Compare commits
No commits in common. "master" and "upload-to-survey" have entirely different histories.
master
...
upload-to-
66 changed files with 7321 additions and 3901 deletions
|
@ -1,2 +1,2 @@
|
|||
export POSTGRES_DATABASE_URL="postgres://postgres:password@localhost:5432/postgres"
|
||||
export MARIA_DATABASE_URL="mysql://root:password@localhost:3306/maria"
|
||||
export MARIA_DATABASE_URL="mysql://maria:password@localhost:3306/maria"
|
||||
|
|
2
.github/workflows/clippy-fmt.yml
vendored
2
.github/workflows/clippy-fmt.yml
vendored
|
@ -30,7 +30,7 @@ jobs:
|
|||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "20.0.0"
|
||||
node-version: "18.0.0"
|
||||
|
||||
- name: Build frontend
|
||||
run: make frontend
|
||||
|
|
14
.github/workflows/linux.yml
vendored
14
.github/workflows/linux.yml
vendored
|
@ -84,7 +84,7 @@ jobs:
|
|||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "20.0.0"
|
||||
node-version: "18.0.0"
|
||||
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
|
||||
|
@ -129,12 +129,12 @@ jobs:
|
|||
if: (github.ref == 'refs/heads/master' || github.event_name == 'push') && github.repository == 'mCaptcha/mCaptcha'
|
||||
run: make docker-publish
|
||||
|
||||
- name: publish bins
|
||||
if: (github.ref == 'refs/heads/master' || github.event_name == 'push') && github.repository == 'mCaptcha/mCaptcha'
|
||||
run: ./scripts/publish.sh publish master latest $DUMBSERVE_PASSWORD
|
||||
env:
|
||||
DUMBSERVE_PASSWORD: ${{ secrets.DUMBSERVE_PASSWORD }}
|
||||
GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }}
|
||||
# - name: publish bins
|
||||
# if: (github.ref == 'refs/heads/master' || github.event_name == 'push') && github.repository == 'mCaptcha/mCaptcha'
|
||||
# run: ./scripts/publish.sh publish master latest $DUMBSERVE_PASSWORD
|
||||
# env:
|
||||
# DUMBSERVE_PASSWORD: ${{ secrets.DUMBSERVE_PASSWORD }}
|
||||
# GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }}
|
||||
|
||||
- name: generate documentation
|
||||
if: matrix.version == 'stable' && (github.repository == 'mCaptcha/mCaptcha')
|
||||
|
|
2
.nvmrc
2
.nvmrc
|
@ -1 +1 @@
|
|||
20
|
||||
18
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
FROM node:20 as frontend
|
||||
FROM node:18.0.0 as frontend
|
||||
RUN set -ex; \
|
||||
apt-get update; \
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
|
|
|
@ -292,32 +292,6 @@ pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase {
|
|||
|
||||
/// Get all psuedo IDs
|
||||
async fn analytics_get_all_psuedo_ids(&self, page: usize) -> DBResult<Vec<String>>;
|
||||
|
||||
/// Track maximum nonce received against captcha levels
|
||||
async fn update_max_nonce_for_level(
|
||||
&self,
|
||||
captcha_key: &str,
|
||||
difficulty_factor: u32,
|
||||
latest_nonce: u32,
|
||||
) -> DBResult<()>;
|
||||
|
||||
/// Get maximum nonce tracked so far for captcha levels
|
||||
async fn get_max_nonce_for_level(
|
||||
&self,
|
||||
captcha_key: &str,
|
||||
difficulty_factor: u32,
|
||||
) -> DBResult<u32>;
|
||||
|
||||
/// Get number of analytics entries that are under a certain duration
|
||||
async fn stats_get_num_logs_under_time(&self, duration: u32) -> DBResult<usize>;
|
||||
|
||||
/// Get the entry at a location in the list of analytics entires under a certain time limit
|
||||
/// and sorted in ascending order
|
||||
async fn stats_get_entry_at_location_for_time_limit_asc(
|
||||
&self,
|
||||
duration: u32,
|
||||
location: u32,
|
||||
) -> DBResult<Option<usize>>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
|
||||
|
|
|
@ -7,29 +7,6 @@
|
|||
use crate::errors::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
/// easy traffic pattern
|
||||
pub const TRAFFIC_PATTERN: TrafficPattern = TrafficPattern {
|
||||
avg_traffic: 500,
|
||||
peak_sustainable_traffic: 5_000,
|
||||
broke_my_site_traffic: Some(10_000),
|
||||
};
|
||||
|
||||
/// levels for complex captcha config
|
||||
pub const LEVELS: [Level; 3] = [
|
||||
Level {
|
||||
difficulty_factor: 1,
|
||||
visitor_threshold: 1,
|
||||
},
|
||||
Level {
|
||||
difficulty_factor: 2,
|
||||
visitor_threshold: 2,
|
||||
},
|
||||
Level {
|
||||
difficulty_factor: 3,
|
||||
visitor_threshold: 3,
|
||||
},
|
||||
];
|
||||
|
||||
/// test all database functions
|
||||
pub async fn database_works<'a, T: MCDatabase>(
|
||||
db: &T,
|
||||
|
@ -273,6 +250,7 @@ pub async fn database_works<'a, T: MCDatabase>(
|
|||
db.record_confirm(c.key).await.unwrap();
|
||||
|
||||
// analytics start
|
||||
|
||||
db.analytics_create_psuedo_id_if_not_exists(c.key)
|
||||
.await
|
||||
.unwrap();
|
||||
|
@ -304,31 +282,11 @@ pub async fn database_works<'a, T: MCDatabase>(
|
|||
);
|
||||
|
||||
let analytics = CreatePerformanceAnalytics {
|
||||
time: 1,
|
||||
difficulty_factor: 1,
|
||||
time: 0,
|
||||
difficulty_factor: 0,
|
||||
worker_type: "wasm".into(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
db.stats_get_num_logs_under_time(analytics.time)
|
||||
.await
|
||||
.unwrap(),
|
||||
0
|
||||
);
|
||||
|
||||
db.analysis_save(c.key, &analytics).await.unwrap();
|
||||
assert_eq!(
|
||||
db.stats_get_num_logs_under_time(analytics.time)
|
||||
.await
|
||||
.unwrap(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
db.stats_get_num_logs_under_time(analytics.time - 1)
|
||||
.await
|
||||
.unwrap(),
|
||||
0
|
||||
);
|
||||
let limit = 50;
|
||||
let mut offset = 0;
|
||||
let a = db.analytics_fetch(c.key, limit, offset).await.unwrap();
|
||||
|
@ -347,82 +305,11 @@ pub async fn database_works<'a, T: MCDatabase>(
|
|||
.unwrap();
|
||||
assert_eq!(db.analytics_fetch(c.key, 1000, 0).await.unwrap().len(), 0);
|
||||
assert!(!db.analytics_captcha_is_published(c.key).await.unwrap());
|
||||
|
||||
let rest_analytics = [
|
||||
CreatePerformanceAnalytics {
|
||||
time: 2,
|
||||
difficulty_factor: 2,
|
||||
worker_type: "wasm".into(),
|
||||
},
|
||||
CreatePerformanceAnalytics {
|
||||
time: 3,
|
||||
difficulty_factor: 3,
|
||||
worker_type: "wasm".into(),
|
||||
},
|
||||
CreatePerformanceAnalytics {
|
||||
time: 4,
|
||||
difficulty_factor: 4,
|
||||
worker_type: "wasm".into(),
|
||||
},
|
||||
CreatePerformanceAnalytics {
|
||||
time: 5,
|
||||
difficulty_factor: 5,
|
||||
worker_type: "wasm".into(),
|
||||
},
|
||||
];
|
||||
for a in rest_analytics.iter() {
|
||||
db.analysis_save(c.key, &a).await.unwrap();
|
||||
}
|
||||
assert!(db
|
||||
.stats_get_entry_at_location_for_time_limit_asc(1, 2)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none());
|
||||
assert_eq!(
|
||||
db.stats_get_entry_at_location_for_time_limit_asc(2, 1)
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(2)
|
||||
);
|
||||
assert_eq!(
|
||||
db.stats_get_entry_at_location_for_time_limit_asc(3, 2)
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(3)
|
||||
);
|
||||
|
||||
db.analytics_delete_all_records_for_campaign(c.key)
|
||||
.await
|
||||
.unwrap();
|
||||
// analytics end
|
||||
|
||||
// nonce tracking start
|
||||
assert_eq!(
|
||||
db.get_max_nonce_for_level(c.key, l[0].difficulty_factor)
|
||||
.await
|
||||
.unwrap(),
|
||||
0
|
||||
);
|
||||
db.update_max_nonce_for_level(c.key, l[0].difficulty_factor, 1000)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
db.get_max_nonce_for_level(c.key, l[0].difficulty_factor)
|
||||
.await
|
||||
.unwrap(),
|
||||
1000
|
||||
);
|
||||
db.update_max_nonce_for_level(c.key, l[0].difficulty_factor, 10_000)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
db.get_max_nonce_for_level(c.key, l[0].difficulty_factor)
|
||||
.await
|
||||
.unwrap(),
|
||||
10_000
|
||||
);
|
||||
// nonce tracking end
|
||||
|
||||
assert_eq!(db.fetch_solve(p.username, c.key).await.unwrap().len(), 1);
|
||||
assert_eq!(
|
||||
db.fetch_config_fetched(p.username, c.key)
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "INSERT INTO\n mcaptcha_track_nonce (level_id, nonce)\n VALUES ((\n SELECT\n level_id\n FROM\n mcaptcha_levels\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?)\n AND\n difficulty_factor = ?\n AND\n visitor_threshold = ?\n ), ?);",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 4
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "216478d53870d7785cd0be43f030883ab79eaafb558d9197d09aea3adbd7b0bc"
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "UPDATE mcaptcha_track_nonce SET nonce = ?\n WHERE level_id = (\n SELECT\n level_id\n FROM\n mcaptcha_levels\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?)\n AND\n difficulty_factor = ?\n )\n AND nonce <= ?;",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 4
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "349ba17ff197aca7ee9fbd43e227d181c27ae04702fd6bdb6ddc32aab3bcb1ea"
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "SELECT\n COUNT(difficulty_factor) AS count\n FROM\n mcaptcha_pow_analytics\n WHERE time <= ?;",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count",
|
||||
"type_info": {
|
||||
"type": "LongLong",
|
||||
"flags": "NOT_NULL | BINARY",
|
||||
"char_set": 63,
|
||||
"max_size": 21
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "9bae79667a8cc631541879321e72a40f20cf812584aaf44418089bc7a51e07c4"
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "INSERT INTO\n mcaptcha_track_nonce (level_id, nonce)\n VALUES ((\n SELECT\n level_id\n FROM\n mcaptcha_levels\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key =?)\n AND\n difficulty_factor = ?\n ), ?);",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 3
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "9def82dcec9c8d477824182bb2f71044cc264cf2073ab4f60a0000b435ed0f0b"
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "SELECT nonce FROM mcaptcha_track_nonce\n WHERE level_id = (\n SELECT\n level_id\n FROM\n mcaptcha_levels\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?)\n AND\n difficulty_factor = ?\n );",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "nonce",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 11
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "b739ec4cfab1ec60947106c8112e931510c3a50a1606facdde0c0ebb540d5beb"
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "SELECT\n difficulty_factor\n FROM\n mcaptcha_pow_analytics\n WHERE\n time <= ?\n ORDER BY difficulty_factor ASC LIMIT 1 OFFSET ?;",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "difficulty_factor",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
|
||||
"char_set": 63,
|
||||
"max_size": 11
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "c4d6ad934e38218931e74ae1c31c6712cbadb40f31bb12e160c9d333c7e3835c"
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
-- Add migration script here
|
||||
CREATE TABLE IF NOT EXISTS mcaptcha_track_nonce (
|
||||
level_id INTEGER NOT NULL,
|
||||
nonce INTEGER NOT NULL DEFAULT 0,
|
||||
ID INT auto_increment,
|
||||
PRIMARY KEY(ID),
|
||||
CONSTRAINT `fk_mcaptcha_track_nonce_level_id`
|
||||
FOREIGN KEY (level_id)
|
||||
REFERENCES mcaptcha_levels (level_id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE
|
||||
);
|
|
@ -433,39 +433,6 @@ impl MCDatabase for Database {
|
|||
futs.push(fut);
|
||||
}
|
||||
|
||||
try_join_all(futs)
|
||||
.await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
||||
let mut futs = Vec::with_capacity(levels.len());
|
||||
|
||||
for level in levels.iter() {
|
||||
let difficulty_factor = level.difficulty_factor as i32;
|
||||
let visitor_threshold = level.visitor_threshold as i32;
|
||||
let fut = sqlx::query!(
|
||||
"INSERT INTO
|
||||
mcaptcha_track_nonce (level_id, nonce)
|
||||
VALUES ((
|
||||
SELECT
|
||||
level_id
|
||||
FROM
|
||||
mcaptcha_levels
|
||||
WHERE
|
||||
config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?)
|
||||
AND
|
||||
difficulty_factor = ?
|
||||
AND
|
||||
visitor_threshold = ?
|
||||
), ?);",
|
||||
&captcha_key,
|
||||
difficulty_factor,
|
||||
visitor_threshold,
|
||||
0,
|
||||
)
|
||||
.execute(&self.pool);
|
||||
futs.push(fut);
|
||||
}
|
||||
|
||||
try_join_all(futs)
|
||||
.await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
@ -1120,160 +1087,6 @@ impl MCDatabase for Database {
|
|||
|
||||
Ok(res.drain(0..).map(|r| r.psuedo_id).collect())
|
||||
}
|
||||
|
||||
/// Track maximum nonce received against captcha levels
|
||||
async fn update_max_nonce_for_level(
|
||||
&self,
|
||||
captcha_key: &str,
|
||||
difficulty_factor: u32,
|
||||
latest_nonce: u32,
|
||||
) -> DBResult<()> {
|
||||
let latest_nonce = latest_nonce as i64;
|
||||
sqlx::query!(
|
||||
"UPDATE mcaptcha_track_nonce SET nonce = ?
|
||||
WHERE level_id = (
|
||||
SELECT
|
||||
level_id
|
||||
FROM
|
||||
mcaptcha_levels
|
||||
WHERE
|
||||
config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?)
|
||||
AND
|
||||
difficulty_factor = ?
|
||||
)
|
||||
AND nonce <= ?;",
|
||||
latest_nonce,
|
||||
&captcha_key,
|
||||
difficulty_factor as i64,
|
||||
latest_nonce
|
||||
)
|
||||
.execute(&self.pool).await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get maximum nonce tracked so far for captcha levels
|
||||
async fn get_max_nonce_for_level(
|
||||
&self,
|
||||
captcha_key: &str,
|
||||
difficulty_factor: u32,
|
||||
) -> DBResult<u32> {
|
||||
struct X {
|
||||
nonce: i32,
|
||||
}
|
||||
|
||||
async fn inner_get_max_nonce(
|
||||
pool: &MySqlPool,
|
||||
captcha_key: &str,
|
||||
difficulty_factor: u32,
|
||||
) -> DBResult<X> {
|
||||
sqlx::query_as!(
|
||||
X,
|
||||
"SELECT nonce FROM mcaptcha_track_nonce
|
||||
WHERE level_id = (
|
||||
SELECT
|
||||
level_id
|
||||
FROM
|
||||
mcaptcha_levels
|
||||
WHERE
|
||||
config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?)
|
||||
AND
|
||||
difficulty_factor = ?
|
||||
);",
|
||||
&captcha_key,
|
||||
difficulty_factor as i32,
|
||||
)
|
||||
.fetch_one(pool).await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))
|
||||
}
|
||||
|
||||
let res = inner_get_max_nonce(&self.pool, captcha_key, difficulty_factor).await;
|
||||
if let Err(DBError::CaptchaNotFound) = res {
|
||||
sqlx::query!(
|
||||
"INSERT INTO
|
||||
mcaptcha_track_nonce (level_id, nonce)
|
||||
VALUES ((
|
||||
SELECT
|
||||
level_id
|
||||
FROM
|
||||
mcaptcha_levels
|
||||
WHERE
|
||||
config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key =?)
|
||||
AND
|
||||
difficulty_factor = ?
|
||||
), ?);",
|
||||
&captcha_key,
|
||||
difficulty_factor as i32,
|
||||
0,
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
||||
let res =
|
||||
inner_get_max_nonce(&self.pool, captcha_key, difficulty_factor).await?;
|
||||
Ok(res.nonce as u32)
|
||||
} else {
|
||||
let res = res?;
|
||||
Ok(res.nonce as u32)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get number of analytics entries that are under a certain duration
|
||||
async fn stats_get_num_logs_under_time(&self, duration: u32) -> DBResult<usize> {
|
||||
struct Count {
|
||||
count: Option<i64>,
|
||||
}
|
||||
|
||||
//"SELECT COUNT(*) FROM (SELECT difficulty_factor FROM mcaptcha_pow_analytics WHERE time <= ?) as count",
|
||||
let count = sqlx::query_as!(
|
||||
Count,
|
||||
"SELECT
|
||||
COUNT(difficulty_factor) AS count
|
||||
FROM
|
||||
mcaptcha_pow_analytics
|
||||
WHERE time <= ?;",
|
||||
duration as i32,
|
||||
)
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
||||
Ok(count.count.unwrap_or_else(|| 0) as usize)
|
||||
}
|
||||
|
||||
/// Get the entry at a location in the list of analytics entires under a certain time limited
|
||||
/// and sorted in ascending order
|
||||
async fn stats_get_entry_at_location_for_time_limit_asc(
|
||||
&self,
|
||||
duration: u32,
|
||||
location: u32,
|
||||
) -> DBResult<Option<usize>> {
|
||||
struct Difficulty {
|
||||
difficulty_factor: Option<i32>,
|
||||
}
|
||||
|
||||
match sqlx::query_as!(
|
||||
Difficulty,
|
||||
"SELECT
|
||||
difficulty_factor
|
||||
FROM
|
||||
mcaptcha_pow_analytics
|
||||
WHERE
|
||||
time <= ?
|
||||
ORDER BY difficulty_factor ASC LIMIT 1 OFFSET ?;",
|
||||
duration as i32,
|
||||
location as i64 - 1,
|
||||
)
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
{
|
||||
Ok(res) => Ok(Some(res.difficulty_factor.unwrap() as usize)),
|
||||
Err(sqlx::Error::RowNotFound) => Ok(None),
|
||||
Err(e) => Err(map_row_not_found_err(e, DBError::CaptchaNotFound)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
|
||||
#![cfg(test)]
|
||||
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
use std::env;
|
||||
|
||||
use sqlx::{migrate::MigrateDatabase, mysql::MySqlPoolOptions};
|
||||
use url::Url;
|
||||
|
||||
use crate::*;
|
||||
|
||||
use db_core::tests::*;
|
||||
|
@ -28,6 +26,28 @@ async fn everyting_works() {
|
|||
const HEADING: &str = "testing notifications get db mariadb";
|
||||
const MESSAGE: &str = "testing notifications get message db mariadb";
|
||||
|
||||
// easy traffic pattern
|
||||
const TRAFFIC_PATTERN: TrafficPattern = TrafficPattern {
|
||||
avg_traffic: 500,
|
||||
peak_sustainable_traffic: 5_000,
|
||||
broke_my_site_traffic: Some(10_000),
|
||||
};
|
||||
|
||||
const LEVELS: [Level; 3] = [
|
||||
Level {
|
||||
difficulty_factor: 1,
|
||||
visitor_threshold: 1,
|
||||
},
|
||||
Level {
|
||||
difficulty_factor: 2,
|
||||
visitor_threshold: 2,
|
||||
},
|
||||
Level {
|
||||
difficulty_factor: 3,
|
||||
visitor_threshold: 3,
|
||||
},
|
||||
];
|
||||
|
||||
const ADD_NOTIFICATION: AddNotification = AddNotification {
|
||||
from: NAME,
|
||||
to: NAME,
|
||||
|
@ -36,20 +56,10 @@ async fn everyting_works() {
|
|||
};
|
||||
|
||||
let url = env::var("MARIA_DATABASE_URL").unwrap();
|
||||
|
||||
let mut parsed = Url::parse(&url).unwrap();
|
||||
parsed.set_path("db_maria_test");
|
||||
let url = parsed.to_string();
|
||||
|
||||
if sqlx::MySql::database_exists(&url).await.unwrap() {
|
||||
sqlx::MySql::drop_database(&url).await.unwrap();
|
||||
}
|
||||
sqlx::MySql::create_database(&url).await.unwrap();
|
||||
|
||||
let pool_options = MySqlPoolOptions::new().max_connections(2);
|
||||
let connection_options = ConnectionOptions::Fresh(Fresh {
|
||||
pool_options,
|
||||
url: url.clone(),
|
||||
url,
|
||||
disable_logging: false,
|
||||
});
|
||||
let db = connection_options.connect().await.unwrap();
|
||||
|
@ -68,6 +78,4 @@ async fn everyting_works() {
|
|||
description: CAPTCHA_DESCRIPTION,
|
||||
};
|
||||
database_works(&db, &p, &c, &LEVELS, &TRAFFIC_PATTERN, &ADD_NOTIFICATION).await;
|
||||
drop(db);
|
||||
sqlx::MySql::drop_database(&url).await.unwrap();
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO\n mcaptcha_track_nonce (level_id, nonce)\n VALUES ((\n SELECT\n level_id\n FROM\n mcaptcha_levels\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE key = ($1))\n AND\n difficulty_factor = $2\n AND\n visitor_threshold = $3\n ), $4);",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Int4",
|
||||
"Int4",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "133ee23ab5ac7c664a86b6edfaa8da79281b6d1f5ba33c642a6ea1b0682fe0b0"
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT nonce FROM mcaptcha_track_nonce\n WHERE level_id = (\n SELECT\n level_id\n FROM\n mcaptcha_levels\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE key = ($1))\n AND\n difficulty_factor = $2\n );",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "nonce",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "96f1f1e45144d5add6c4ba4cd2df8eda6043bc8cd6952787f92a687fef778a6e"
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT COUNT(difficulty_factor) FROM mcaptcha_pow_analytics WHERE time <= $1;",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "count",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "c08c1dd4bfcb6cbd0359c79cc3be79526a012b006ce9deb80bceb4e1a04c835d"
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT\n difficulty_factor\n FROM\n mcaptcha_pow_analytics\n WHERE\n time <= $1\n ORDER BY difficulty_factor ASC LIMIT 1 OFFSET $2;",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "difficulty_factor",
|
||||
"type_info": "Int4"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "c67aec0c3d5786fb495b6ed60fa106437d8e5034d3a40bf8face2ca7c12f2694"
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO\n mcaptcha_track_nonce (level_id, nonce)\n VALUES ((\n SELECT\n level_id\n FROM\n mcaptcha_levels\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE key = ($1))\n AND\n difficulty_factor = $2\n ), $3);",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Int4",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "e0088cf77c1c3a0184f35d1899a6168023fba021adf281cf1c8f9e8ccfe3a03e"
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "UPDATE mcaptcha_track_nonce SET nonce = $3\n WHERE level_id = (\n SELECT\n level_id\n FROM\n mcaptcha_levels\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE key = ($1))\n AND\n difficulty_factor = $2\n )\n AND nonce <= $3;",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Int4",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "e33ee14cf76cd09d9a157b8784a3fe25b89eaca105aa30e479d31b756cd5c88b"
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
-- Add migration script here
|
||||
CREATE TABLE IF NOT EXISTS mcaptcha_track_nonce (
|
||||
nonce INTEGER NOT NULL DEFAULT 0,
|
||||
level_id INTEGER references mcaptcha_levels(level_id) ON DELETE CASCADE,
|
||||
ID SERIAL PRIMARY KEY NOT NULL
|
||||
);
|
|
@ -445,38 +445,6 @@ impl MCDatabase for Database {
|
|||
futs.push(fut);
|
||||
}
|
||||
|
||||
try_join_all(futs)
|
||||
.await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
||||
let mut futs = Vec::with_capacity(levels.len());
|
||||
for level in levels.iter() {
|
||||
let difficulty_factor = level.difficulty_factor as i32;
|
||||
let visitor_threshold = level.visitor_threshold as i32;
|
||||
let fut = sqlx::query!(
|
||||
"INSERT INTO
|
||||
mcaptcha_track_nonce (level_id, nonce)
|
||||
VALUES ((
|
||||
SELECT
|
||||
level_id
|
||||
FROM
|
||||
mcaptcha_levels
|
||||
WHERE
|
||||
config_id = (SELECT config_id FROM mcaptcha_config WHERE key = ($1))
|
||||
AND
|
||||
difficulty_factor = $2
|
||||
AND
|
||||
visitor_threshold = $3
|
||||
), $4);",
|
||||
&captcha_key,
|
||||
difficulty_factor,
|
||||
visitor_threshold,
|
||||
0,
|
||||
)
|
||||
.execute(&self.pool);
|
||||
futs.push(fut);
|
||||
}
|
||||
|
||||
try_join_all(futs)
|
||||
.await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
@ -1129,154 +1097,6 @@ impl MCDatabase for Database {
|
|||
|
||||
Ok(res.drain(0..).map(|r| r.psuedo_id).collect())
|
||||
}
|
||||
|
||||
/// Track maximum nonce received against captcha levels
|
||||
async fn update_max_nonce_for_level(
|
||||
&self,
|
||||
captcha_key: &str,
|
||||
difficulty_factor: u32,
|
||||
latest_nonce: u32,
|
||||
) -> DBResult<()> {
|
||||
sqlx::query!(
|
||||
"UPDATE mcaptcha_track_nonce SET nonce = $3
|
||||
WHERE level_id = (
|
||||
SELECT
|
||||
level_id
|
||||
FROM
|
||||
mcaptcha_levels
|
||||
WHERE
|
||||
config_id = (SELECT config_id FROM mcaptcha_config WHERE key = ($1))
|
||||
AND
|
||||
difficulty_factor = $2
|
||||
)
|
||||
AND nonce <= $3;",
|
||||
&captcha_key,
|
||||
difficulty_factor as i32,
|
||||
latest_nonce as i32,
|
||||
)
|
||||
.execute(&self.pool).await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get maximum nonce tracked so far for captcha levels
|
||||
async fn get_max_nonce_for_level(
|
||||
&self,
|
||||
captcha_key: &str,
|
||||
difficulty_factor: u32,
|
||||
) -> DBResult<u32> {
|
||||
struct X {
|
||||
nonce: i32,
|
||||
}
|
||||
|
||||
async fn inner_get_max_nonce(
|
||||
pool: &PgPool,
|
||||
captcha_key: &str,
|
||||
difficulty_factor: u32,
|
||||
) -> DBResult<X> {
|
||||
sqlx::query_as!(
|
||||
X,
|
||||
"SELECT nonce FROM mcaptcha_track_nonce
|
||||
WHERE level_id = (
|
||||
SELECT
|
||||
level_id
|
||||
FROM
|
||||
mcaptcha_levels
|
||||
WHERE
|
||||
config_id = (SELECT config_id FROM mcaptcha_config WHERE key = ($1))
|
||||
AND
|
||||
difficulty_factor = $2
|
||||
);",
|
||||
&captcha_key,
|
||||
difficulty_factor as i32,
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))
|
||||
}
|
||||
|
||||
let res = inner_get_max_nonce(&self.pool, captcha_key, difficulty_factor).await;
|
||||
if let Err(DBError::CaptchaNotFound) = res {
|
||||
sqlx::query!(
|
||||
"INSERT INTO
|
||||
mcaptcha_track_nonce (level_id, nonce)
|
||||
VALUES ((
|
||||
SELECT
|
||||
level_id
|
||||
FROM
|
||||
mcaptcha_levels
|
||||
WHERE
|
||||
config_id = (SELECT config_id FROM mcaptcha_config WHERE key = ($1))
|
||||
AND
|
||||
difficulty_factor = $2
|
||||
), $3);",
|
||||
&captcha_key,
|
||||
difficulty_factor as i32,
|
||||
0,
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
||||
let res =
|
||||
inner_get_max_nonce(&self.pool, captcha_key, difficulty_factor).await?;
|
||||
Ok(res.nonce as u32)
|
||||
} else {
|
||||
let res = res?;
|
||||
Ok(res.nonce as u32)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get number of analytics entries that are under a certain duration
|
||||
async fn stats_get_num_logs_under_time(&self, duration: u32) -> DBResult<usize> {
|
||||
struct Count {
|
||||
count: Option<i64>,
|
||||
}
|
||||
|
||||
let count = sqlx::query_as!(
|
||||
Count,
|
||||
"SELECT COUNT(difficulty_factor) FROM mcaptcha_pow_analytics WHERE time <= $1;",
|
||||
duration as i32,
|
||||
)
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
.map_err(|e| map_row_not_found_err(e, DBError::CaptchaNotFound))?;
|
||||
|
||||
Ok(count.count.unwrap_or_else(|| 0) as usize)
|
||||
}
|
||||
|
||||
/// Get the entry at a location in the list of analytics entires under a certain time limit
|
||||
/// and sorted in ascending order
|
||||
async fn stats_get_entry_at_location_for_time_limit_asc(
|
||||
&self,
|
||||
duration: u32,
|
||||
location: u32,
|
||||
) -> DBResult<Option<usize>> {
|
||||
struct Difficulty {
|
||||
difficulty_factor: Option<i32>,
|
||||
}
|
||||
|
||||
match sqlx::query_as!(
|
||||
Difficulty,
|
||||
"SELECT
|
||||
difficulty_factor
|
||||
FROM
|
||||
mcaptcha_pow_analytics
|
||||
WHERE
|
||||
time <= $1
|
||||
ORDER BY difficulty_factor ASC LIMIT 1 OFFSET $2;",
|
||||
duration as i32,
|
||||
location as i64 - 1,
|
||||
)
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
{
|
||||
Ok(res) => Ok(Some(res.difficulty_factor.unwrap() as usize)),
|
||||
Err(sqlx::Error::RowNotFound) => Ok(None),
|
||||
Err(e) => Err(map_row_not_found_err(e, DBError::CaptchaNotFound)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -5,11 +5,8 @@
|
|||
|
||||
#![cfg(test)]
|
||||
|
||||
use std::env;
|
||||
|
||||
use sqlx::migrate::MigrateDatabase;
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use url::Url;
|
||||
use std::env;
|
||||
|
||||
use crate::*;
|
||||
|
||||
|
@ -29,6 +26,28 @@ async fn everyting_works() {
|
|||
const HEADING: &str = "testing notifications get db postgres";
|
||||
const MESSAGE: &str = "testing notifications get message db postgres";
|
||||
|
||||
// easy traffic pattern
|
||||
const TRAFFIC_PATTERN: TrafficPattern = TrafficPattern {
|
||||
avg_traffic: 500,
|
||||
peak_sustainable_traffic: 5_000,
|
||||
broke_my_site_traffic: Some(10_000),
|
||||
};
|
||||
|
||||
const LEVELS: [Level; 3] = [
|
||||
Level {
|
||||
difficulty_factor: 1,
|
||||
visitor_threshold: 1,
|
||||
},
|
||||
Level {
|
||||
difficulty_factor: 2,
|
||||
visitor_threshold: 2,
|
||||
},
|
||||
Level {
|
||||
difficulty_factor: 3,
|
||||
visitor_threshold: 3,
|
||||
},
|
||||
];
|
||||
|
||||
const ADD_NOTIFICATION: AddNotification = AddNotification {
|
||||
from: NAME,
|
||||
to: NAME,
|
||||
|
@ -37,20 +56,10 @@ async fn everyting_works() {
|
|||
};
|
||||
|
||||
let url = env::var("POSTGRES_DATABASE_URL").unwrap();
|
||||
|
||||
let mut parsed = Url::parse(&url).unwrap();
|
||||
parsed.set_path("db_postgres_test");
|
||||
let url = parsed.to_string();
|
||||
|
||||
if sqlx::Postgres::database_exists(&url).await.unwrap() {
|
||||
sqlx::Postgres::drop_database(&url).await.unwrap();
|
||||
}
|
||||
sqlx::Postgres::create_database(&url).await.unwrap();
|
||||
|
||||
let pool_options = PgPoolOptions::new().max_connections(2);
|
||||
let connection_options = ConnectionOptions::Fresh(Fresh {
|
||||
pool_options,
|
||||
url: url.clone(),
|
||||
url,
|
||||
disable_logging: false,
|
||||
});
|
||||
let db = connection_options.connect().await.unwrap();
|
||||
|
@ -69,6 +78,4 @@ async fn everyting_works() {
|
|||
description: CAPTCHA_DESCRIPTION,
|
||||
};
|
||||
database_works(&db, &p, &c, &LEVELS, &TRAFFIC_PATTERN, &ADD_NOTIFICATION).await;
|
||||
drop(db);
|
||||
sqlx::Postgres::drop_database(&url).await.unwrap();
|
||||
}
|
||||
|
|
4654
docs/openapi/package-lock.json
generated
4654
docs/openapi/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -17,6 +17,6 @@
|
|||
},
|
||||
"homepage": "https://github.com/mCaptcha/mCaptcha#readme",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "^1.4.0"
|
||||
"@redocly/cli": "^1.0.0-beta.129"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
34
package.json
34
package.json
|
@ -10,35 +10,35 @@
|
|||
"test": "jest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.6",
|
||||
"@types/jsdom": "^21.1.4",
|
||||
"@types/node": "^20.8.9",
|
||||
"@types/sinon": "^10.0.20",
|
||||
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
||||
"@typescript-eslint/parser": "^6.9.0",
|
||||
"@types/jest": "^29.5.2",
|
||||
"@types/jsdom": "^21.1.1",
|
||||
"@types/node": "^20.3.3",
|
||||
"@types/sinon": "^10.0.15",
|
||||
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
||||
"@typescript-eslint/parser": "^5.60.1",
|
||||
"@wasm-tool/wasm-pack-plugin": "^1.7.0",
|
||||
"css-loader": "^6.8.1",
|
||||
"css-minimizer-webpack-plugin": "^5.0.1",
|
||||
"eslint": "^8.52.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"eslint": "^8.44.0",
|
||||
"jest": "^29.5.0",
|
||||
"jest-environment-jsdom": "^29.5.0",
|
||||
"jest-fetch-mock": "^3.0.3",
|
||||
"jsdom": "^22.1.0",
|
||||
"mini-css-extract-plugin": "^2.7.6",
|
||||
"sass": "^1.69.5",
|
||||
"sass": "^1.63.6",
|
||||
"sass-loader": "^13.3.2",
|
||||
"sinon": "^17.0.0",
|
||||
"sinon": "^15.2.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"ts-loader": "^9.5.0",
|
||||
"ts-loader": "^9.4.4",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2",
|
||||
"webpack": "^5.89.0",
|
||||
"typescript": "^5.1.6",
|
||||
"webpack": "^5.88.1",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^4.15.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mcaptcha/pow_sha256-polyfill": "^0.1.0-rc2",
|
||||
"@mcaptcha/vanilla-glue": "^0.1.0-rc1",
|
||||
"@mcaptcha/pow-wasm": "^0.1.0-rc2"
|
||||
"@mcaptcha/pow_sha256-polyfill": "^0.1.0-alpha-1",
|
||||
"@mcaptcha/pow-wasm": "^0.1.0-alpha-1",
|
||||
"@mcaptcha/vanilla-glue": "^0.1.0-alpha-3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ DUMBSERVE_PASSWORD=$4
|
|||
DUMBSERVE_HOST="https://$DUMBSERVE_USERNAME:$DUMBSERVE_PASSWORD@dl.mcaptcha.org"
|
||||
|
||||
NAME=mcaptcha
|
||||
KEY=73DAC973A9ADBB9ADCB5CDC4595A08135BA9FF73
|
||||
KEY=0CBABF3084E84E867A76709750BE39D10ECE01FB
|
||||
|
||||
TMP_DIR=$(mktemp -d)
|
||||
FILENAME="$NAME-$2-linux-amd64"
|
||||
|
|
|
@ -14,7 +14,6 @@ pub mod meta;
|
|||
pub mod notifications;
|
||||
pub mod pow;
|
||||
mod routes;
|
||||
pub mod stats;
|
||||
pub mod survey;
|
||||
|
||||
pub use routes::ROUTES;
|
||||
|
@ -27,7 +26,6 @@ pub fn services(cfg: &mut ServiceConfig) {
|
|||
mcaptcha::services(cfg);
|
||||
notifications::services(cfg);
|
||||
survey::services(cfg);
|
||||
stats::services(cfg);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
//use actix::prelude::*;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use libmcaptcha::pow::PoWConfig;
|
||||
use libmcaptcha::{
|
||||
defense::LevelBuilder, master::messages::AddSiteBuilder, DefenseBuilder,
|
||||
MCaptchaBuilder,
|
||||
|
@ -22,13 +21,7 @@ pub struct GetConfigPayload {
|
|||
pub key: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct ApiPoWConfig {
|
||||
pub string: String,
|
||||
pub difficulty_factor: u32,
|
||||
pub salt: String,
|
||||
pub max_recorded_nonce: u32,
|
||||
}
|
||||
// API keys are mcaptcha actor names
|
||||
|
||||
/// get PoW configuration for an mcaptcha key
|
||||
#[my_codegen::post(path = "V1_API_ROUTES.pow.get_config()")]
|
||||
|
@ -42,34 +35,52 @@ pub async fn get_config(
|
|||
}
|
||||
let payload = payload.into_inner();
|
||||
|
||||
let config: ServiceResult<PoWConfig> =
|
||||
match data.captcha.get_pow(payload.key.clone()).await {
|
||||
Ok(Some(config)) => Ok(config),
|
||||
Ok(None) => {
|
||||
init_mcaptcha(&data, &payload.key).await?;
|
||||
let config = data
|
||||
.captcha
|
||||
.get_pow(payload.key.clone())
|
||||
.await
|
||||
.expect("mcaptcha should be initialized and ready to go");
|
||||
Ok(config.unwrap())
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
};
|
||||
let config = config?;
|
||||
let max_nonce = data
|
||||
.db
|
||||
.get_max_nonce_for_level(&payload.key, config.difficulty_factor)
|
||||
.await?;
|
||||
data.stats.record_fetch(&data, &payload.key).await?;
|
||||
match data.captcha.get_pow(payload.key.clone()).await {
|
||||
Ok(Some(config)) => {
|
||||
data.stats.record_fetch(&data, &payload.key).await?;
|
||||
Ok(HttpResponse::Ok().json(config))
|
||||
}
|
||||
Ok(None) => {
|
||||
init_mcaptcha(&data, &payload.key).await?;
|
||||
let config = data
|
||||
.captcha
|
||||
.get_pow(payload.key.clone())
|
||||
.await
|
||||
.expect("mcaptcha should be initialized and ready to go");
|
||||
// background it. would require data::Data to be static
|
||||
// to satidfy lifetime
|
||||
data.stats.record_fetch(&data, &payload.key).await?;
|
||||
Ok(HttpResponse::Ok().json(config))
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
|
||||
let config = ApiPoWConfig {
|
||||
string: config.string,
|
||||
difficulty_factor: config.difficulty_factor,
|
||||
salt: config.salt,
|
||||
max_recorded_nonce: max_nonce,
|
||||
};
|
||||
Ok(HttpResponse::Ok().json(config))
|
||||
// match res.exists {
|
||||
// Some(true) => {
|
||||
// match data.captcha.get_pow(payload.key.clone()).await {
|
||||
// Ok(Some(config)) => {
|
||||
// record_fetch(&payload.key, &data.db).await;
|
||||
// Ok(HttpResponse::Ok().json(config))
|
||||
// }
|
||||
// Ok(None) => {
|
||||
// init_mcaptcha(&data, &payload.key).await?;
|
||||
// let config = data
|
||||
// .captcha
|
||||
// .get_pow(payload.key.clone())
|
||||
// .await
|
||||
// .expect("mcaptcha should be initialized and ready to go");
|
||||
// // background it. would require data::Data to be static
|
||||
// // to satidfy lifetime
|
||||
// record_fetch(&payload.key, &data.db).await;
|
||||
// Ok(HttpResponse::Ok().json(config))
|
||||
// }
|
||||
// Err(e) => Err(e.into()),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Some(false) => Err(ServiceError::TokenNotFound),
|
||||
// None => Err(ServiceError::TokenNotFound),
|
||||
// }
|
||||
}
|
||||
/// Call this when [MCaptcha][libmcaptcha::MCaptcha] is not in master.
|
||||
///
|
||||
|
|
|
@ -65,7 +65,6 @@ pub async fn verify_pow(
|
|||
let payload = payload.into_inner();
|
||||
let worker_type = payload.worker_type.clone();
|
||||
let time = payload.time;
|
||||
let nonce = payload.nonce;
|
||||
let (res, difficulty_factor) = data.captcha.verify_pow(payload.into(), ip).await?;
|
||||
data.stats.record_solve(&data, &key).await?;
|
||||
if let (Some(time), Some(worker_type)) = (time, worker_type) {
|
||||
|
@ -76,9 +75,6 @@ pub async fn verify_pow(
|
|||
};
|
||||
data.db.analysis_save(&key, &analytics).await?;
|
||||
}
|
||||
data.db
|
||||
.update_max_nonce_for_level(&key, difficulty_factor, nonce as u32)
|
||||
.await?;
|
||||
let payload = ValidationToken { token: res };
|
||||
Ok(HttpResponse::Ok().json(payload))
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ use super::mcaptcha::routes::Captcha;
|
|||
use super::meta::routes::Meta;
|
||||
use super::notifications::routes::Notifications;
|
||||
use super::pow::routes::PoW;
|
||||
use super::stats::routes::Stats;
|
||||
use super::survey::routes::Survey;
|
||||
|
||||
pub const ROUTES: Routes = Routes::new();
|
||||
|
@ -24,7 +23,6 @@ pub struct Routes {
|
|||
pub pow: PoW,
|
||||
pub survey: Survey,
|
||||
pub notifications: Notifications,
|
||||
pub stats: Stats,
|
||||
}
|
||||
|
||||
impl Routes {
|
||||
|
@ -37,7 +35,6 @@ impl Routes {
|
|||
pow: PoW::new(),
|
||||
notifications: Notifications::new(),
|
||||
survey: Survey::new(),
|
||||
stats: Stats::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,252 +0,0 @@
|
|||
// Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use derive_builder::Builder;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::errors::*;
|
||||
use crate::AppData;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Builder, Serialize)]
|
||||
pub struct BuildDetails {
|
||||
pub version: &'static str,
|
||||
pub git_commit_hash: &'static str,
|
||||
}
|
||||
|
||||
pub mod routes {
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Stats {
|
||||
pub percentile_benches: &'static str,
|
||||
}
|
||||
|
||||
impl Stats {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
percentile_benches: "/api/v1/stats/analytics/percentile",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get difficulty factor with max time limit for percentile of stats
|
||||
#[my_codegen::post(path = "crate::V1_API_ROUTES.stats.percentile_benches")]
|
||||
async fn percentile_benches(
|
||||
data: AppData,
|
||||
payload: web::Json<PercentileReq>,
|
||||
) -> ServiceResult<impl Responder> {
|
||||
let count = data.db.stats_get_num_logs_under_time(payload.time).await?;
|
||||
|
||||
if count == 0 {
|
||||
return Ok(HttpResponse::Ok().json(PercentileResp {
|
||||
difficulty_factor: None,
|
||||
}));
|
||||
}
|
||||
|
||||
if count < 2 {
|
||||
return Ok(HttpResponse::Ok().json(PercentileResp {
|
||||
difficulty_factor: None,
|
||||
}));
|
||||
}
|
||||
|
||||
let location = ((count - 1) as f64 * (payload.percentile / 100.00)) + 1.00;
|
||||
let fraction = location - location.floor();
|
||||
|
||||
if fraction > 0.00 {
|
||||
if let (Some(base), Some(ceiling)) = (
|
||||
data.db
|
||||
.stats_get_entry_at_location_for_time_limit_asc(
|
||||
payload.time,
|
||||
location.floor() as u32,
|
||||
)
|
||||
.await?,
|
||||
data.db
|
||||
.stats_get_entry_at_location_for_time_limit_asc(
|
||||
payload.time,
|
||||
location.floor() as u32 + 1,
|
||||
)
|
||||
.await?,
|
||||
) {
|
||||
let res = base as u32 + ((ceiling - base) as f64 * fraction).floor() as u32;
|
||||
|
||||
return Ok(HttpResponse::Ok().json(PercentileResp {
|
||||
difficulty_factor: Some(res),
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
if let Some(base) = data
|
||||
.db
|
||||
.stats_get_entry_at_location_for_time_limit_asc(
|
||||
payload.time,
|
||||
location.floor() as u32,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
let res = base as u32;
|
||||
|
||||
return Ok(HttpResponse::Ok().json(PercentileResp {
|
||||
difficulty_factor: Some(res),
|
||||
}));
|
||||
}
|
||||
};
|
||||
Ok(HttpResponse::Ok().json(PercentileResp {
|
||||
difficulty_factor: None,
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Builder, Serialize)]
|
||||
/// Health check return datatype
|
||||
pub struct PercentileReq {
|
||||
time: u32,
|
||||
percentile: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Builder, Serialize)]
|
||||
/// Health check return datatype
|
||||
pub struct PercentileResp {
|
||||
difficulty_factor: Option<u32>,
|
||||
}
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(percentile_benches);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use actix_web::{http::StatusCode, test, App};
|
||||
|
||||
use super::*;
|
||||
use crate::api::v1::services;
|
||||
use crate::*;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn stats_bench_work_pg() {
|
||||
let data = crate::tests::pg::get_data().await;
|
||||
stats_bench_work(data).await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn stats_bench_work_maria() {
|
||||
let data = crate::tests::maria::get_data().await;
|
||||
stats_bench_work(data).await;
|
||||
}
|
||||
|
||||
async fn stats_bench_work(data: ArcData) {
|
||||
use crate::tests::*;
|
||||
|
||||
const NAME: &str = "benchstatsuesr";
|
||||
const EMAIL: &str = "benchstatsuesr@testadminuser.com";
|
||||
const PASSWORD: &str = "longpassword2";
|
||||
|
||||
const DEVICE_USER_PROVIDED: &str = "foo";
|
||||
const DEVICE_SOFTWARE_RECOGNISED: &str = "Foobar.v2";
|
||||
const THREADS: i32 = 4;
|
||||
|
||||
let data = &data;
|
||||
{
|
||||
delete_user(&data, NAME).await;
|
||||
}
|
||||
|
||||
register_and_signin(data, NAME, EMAIL, PASSWORD).await;
|
||||
// create captcha
|
||||
let (_, _signin_resp, key) = add_levels_util(data, NAME, PASSWORD).await;
|
||||
let app = get_app!(data).await;
|
||||
|
||||
let page = 1;
|
||||
let tmp_id = uuid::Uuid::new_v4();
|
||||
let download_rotue = V1_API_ROUTES
|
||||
.survey
|
||||
.get_download_route(&tmp_id.to_string(), page);
|
||||
|
||||
let download_req = test::call_service(
|
||||
&app,
|
||||
test::TestRequest::get().uri(&download_rotue).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(download_req.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
data.db
|
||||
.analytics_create_psuedo_id_if_not_exists(&key.key)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let psuedo_id = data
|
||||
.db
|
||||
.analytics_get_psuedo_id_from_capmaign_id(&key.key)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
for i in 1..6 {
|
||||
println!("[{i}] Saving analytics");
|
||||
let analytics = db_core::CreatePerformanceAnalytics {
|
||||
time: i,
|
||||
difficulty_factor: i,
|
||||
worker_type: "wasm".into(),
|
||||
};
|
||||
data.db.analysis_save(&key.key, &analytics).await.unwrap();
|
||||
}
|
||||
|
||||
let msg = PercentileReq {
|
||||
time: 1,
|
||||
percentile: 99.00,
|
||||
};
|
||||
let resp = test::call_service(
|
||||
&app,
|
||||
post_request!(&msg, V1_API_ROUTES.stats.percentile_benches).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let resp: PercentileResp = test::read_body_json(resp).await;
|
||||
|
||||
assert!(resp.difficulty_factor.is_none());
|
||||
|
||||
let msg = PercentileReq {
|
||||
time: 1,
|
||||
percentile: 100.00,
|
||||
};
|
||||
|
||||
let resp = test::call_service(
|
||||
&app,
|
||||
post_request!(&msg, V1_API_ROUTES.stats.percentile_benches).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let resp: PercentileResp = test::read_body_json(resp).await;
|
||||
|
||||
assert!(resp.difficulty_factor.is_none());
|
||||
|
||||
let msg = PercentileReq {
|
||||
time: 2,
|
||||
percentile: 100.00,
|
||||
};
|
||||
|
||||
let resp = test::call_service(
|
||||
&app,
|
||||
post_request!(&msg, V1_API_ROUTES.stats.percentile_benches).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let resp: PercentileResp = test::read_body_json(resp).await;
|
||||
|
||||
assert_eq!(resp.difficulty_factor.unwrap(), 2);
|
||||
|
||||
let msg = PercentileReq {
|
||||
time: 5,
|
||||
percentile: 90.00,
|
||||
};
|
||||
|
||||
let resp = test::call_service(
|
||||
&app,
|
||||
post_request!(&msg, V1_API_ROUTES.stats.percentile_benches).to_request(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let resp: PercentileResp = test::read_body_json(resp).await;
|
||||
|
||||
assert_eq!(resp.difficulty_factor.unwrap(), 4);
|
||||
delete_user(&data, NAME).await;
|
||||
}
|
||||
}
|
|
@ -29,9 +29,6 @@ pub fn get_settings() -> Settings {
|
|||
pub mod pg {
|
||||
use std::env;
|
||||
|
||||
use sqlx::migrate::MigrateDatabase;
|
||||
|
||||
use crate::api::v1::mcaptcha::get_random;
|
||||
use crate::data::Data;
|
||||
use crate::settings::*;
|
||||
use crate::survey::SecretsStore;
|
||||
|
@ -41,16 +38,6 @@ pub mod pg {
|
|||
|
||||
pub async fn get_data() -> ArcData {
|
||||
let url = env::var("POSTGRES_DATABASE_URL").unwrap();
|
||||
|
||||
let mut parsed = url::Url::parse(&url).unwrap();
|
||||
parsed.set_path(&get_random(16));
|
||||
let url = parsed.to_string();
|
||||
|
||||
if sqlx::Postgres::database_exists(&url).await.unwrap() {
|
||||
sqlx::Postgres::drop_database(&url).await.unwrap();
|
||||
}
|
||||
sqlx::Postgres::create_database(&url).await.unwrap();
|
||||
|
||||
let mut settings = get_settings();
|
||||
settings.captcha.runners = Some(1);
|
||||
settings.database.url = url.clone();
|
||||
|
@ -63,9 +50,6 @@ pub mod pg {
|
|||
pub mod maria {
|
||||
use std::env;
|
||||
|
||||
use sqlx::migrate::MigrateDatabase;
|
||||
|
||||
use crate::api::v1::mcaptcha::get_random;
|
||||
use crate::data::Data;
|
||||
use crate::settings::*;
|
||||
use crate::survey::SecretsStore;
|
||||
|
@ -75,16 +59,6 @@ pub mod maria {
|
|||
|
||||
pub async fn get_data() -> ArcData {
|
||||
let url = env::var("MARIA_DATABASE_URL").unwrap();
|
||||
|
||||
let mut parsed = url::Url::parse(&url).unwrap();
|
||||
parsed.set_path(&get_random(16));
|
||||
let url = parsed.to_string();
|
||||
|
||||
if sqlx::MySql::database_exists(&url).await.unwrap() {
|
||||
sqlx::MySql::drop_database(&url).await.unwrap();
|
||||
}
|
||||
sqlx::MySql::create_database(&url).await.unwrap();
|
||||
|
||||
let mut settings = get_settings();
|
||||
settings.captcha.runners = Some(1);
|
||||
settings.database.url = url.clone();
|
||||
|
|
29
static/openapi/.gitignore
vendored
29
static/openapi/.gitignore
vendored
|
@ -1,29 +0,0 @@
|
|||
node_modules
|
||||
.idea
|
||||
.vscode
|
||||
.deps_check
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.nyc_output
|
||||
npm-debug.log*
|
||||
.eslintcache
|
||||
*.iml
|
||||
selenium-debug.log
|
||||
chromedriver.log
|
||||
test/e2e/db.json
|
||||
docs/_book
|
||||
dev-helpers/examples
|
||||
|
||||
# dist
|
||||
flavors/**/dist/*
|
||||
/lib
|
||||
/es
|
||||
dist/log*
|
||||
/swagger-ui-*.tgz
|
||||
|
||||
# Cypress
|
||||
test/e2e-cypress/screenshots
|
||||
test/e2e-cypress/videos
|
|
@ -1,5 +1,5 @@
|
|||
<!-- HTML for static distribution bundle build -->
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
@ -25,22 +25,22 @@
|
|||
<script src="./swagger-ui-bundle.js" charset="UTF-8"></script>
|
||||
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"></script>
|
||||
<script src="./swagger-initializer.js" charset="UTF-8"></script>
|
||||
|
||||
<script>
|
||||
window.onload = function () {
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "./openapi.yaml",
|
||||
dom_id: "#swagger-ui",
|
||||
deepLinking: true,
|
||||
presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
|
||||
plugins: [SwaggerUIBundle.plugins.DownloadUrl],
|
||||
layout: "StandaloneLayout",
|
||||
});
|
||||
// End Swagger UI call region
|
||||
|
||||
window.ui = ui;
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
window.onload = function () {
|
||||
// Begin Swagger UI call region
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "/docs/openapi.yaml",
|
||||
dom_id: "#swagger-ui",
|
||||
deepLinking: true,
|
||||
presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
|
||||
plugins: [SwaggerUIBundle.plugins.DownloadUrl],
|
||||
layout: "StandaloneLayout",
|
||||
});
|
||||
// End Swagger UI call region
|
||||
|
||||
window.ui = ui;
|
||||
};
|
||||
</script>
|
||||
</html>
|
||||
|
|
|
@ -1,283 +1,99 @@
|
|||
.pnpm/ramda@0.29.1: 361.78 KB (5.90%)
|
||||
ramda: 361.78 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/ramda-adjunct@4.1.1_ramda@0.29.1: 257.62 KB (4.20%)
|
||||
ramda-adjunct: 257.62 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/lodash@4.17.21: 253.56 KB (4.14%)
|
||||
lodash: 253.56 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@swagger-api+apidom-ns-openapi-3-0@0.80.0: 203.35 KB (3.32%)
|
||||
@swagger-api/apidom-ns-openapi-3-0: 203.35 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/autolinker@3.16.2: 203.32 KB (3.32%)
|
||||
autolinker: 203.32 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/swagger-client@3.23.1: 166.55 KB (2.72%)
|
||||
swagger-client: 166.55 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@swagger-api+apidom-ns-openapi-3-1@0.80.0: 151.35 KB (2.47%)
|
||||
@swagger-api/apidom-ns-openapi-3-1: 151.35 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/immutable@3.8.2: 139.01 KB (2.27%)
|
||||
immutable: 139.01 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/remarkable@2.0.1: 125.56 KB (2.05%)
|
||||
remarkable: 125.56 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/react-dom@17.0.2_react@17.0.2: 119.19 KB (1.94%)
|
||||
react-dom: 119.19 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/highlight.js@10.7.3: 111.85 KB (1.82%)
|
||||
highlight.js: 111.85 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/js-yaml@4.1.0: 105.01 KB (1.71%)
|
||||
js-yaml: 105.01 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/readable-stream@3.6.2: 96.66 KB (1.58%)
|
||||
readable-stream: 96.66 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/core-js-pure@3.33.1: 82.98 KB (1.35%)
|
||||
core-js-pure: 82.98 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@swagger-api+apidom-reference@0.80.0: 81.46 KB (1.33%)
|
||||
@swagger-api/apidom-reference: 81.46 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/dompurify@3.0.6: 62.88 KB (1.03%)
|
||||
dompurify: 62.88 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/minim@0.23.8: 57.35 KB (0.935%)
|
||||
minim: 57.35 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/buffer@6.0.3: 56.99 KB (0.929%)
|
||||
buffer: 56.99 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@swagger-api+apidom-ns-json-schema-draft-4@0.80.0: 54.6 KB (0.890%)
|
||||
@swagger-api/apidom-ns-json-schema-draft-4: 54.6 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/react-redux@8.1.3_react-dom@17.0.2_react@17.0.2_redux@4.2.1: 48.26 KB (0.787%)
|
||||
react-redux: 48.26 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@swagger-api+apidom-core@0.80.0: 48.12 KB (0.785%)
|
||||
@swagger-api/apidom-core: 48.12 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@swagger-api+apidom-ast@0.80.0: 46.52 KB (0.759%)
|
||||
@swagger-api/apidom-ast: 46.52 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/react-syntax-highlighter@15.5.0_react@17.0.2: 40.15 KB (0.655%)
|
||||
react-syntax-highlighter: 40.15 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/fast-json-patch@3.1.1: 31.89 KB (0.520%)
|
||||
fast-json-patch: 31.89 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/redux@4.2.1: 26.64 KB (0.434%)
|
||||
redux: 26.64 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/qs@6.11.2: 26.23 KB (0.428%)
|
||||
qs: 26.23 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/short-unique-id@5.0.3: 18.88 KB (0.308%)
|
||||
short-unique-id: 18.88 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/sha.js@2.4.11: 18.57 KB (0.303%)
|
||||
sha.js: 18.57 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/object-inspect@1.13.1: 18.45 KB (0.301%)
|
||||
object-inspect: 18.44 KB (99.9%)
|
||||
<self>: 15 B (0.0794%)
|
||||
.pnpm/url-parse@1.5.10: 16.23 KB (0.265%)
|
||||
url-parse: 16.23 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/tslib@2.6.2: 15.87 KB (0.259%)
|
||||
tslib: 15.87 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/events@3.3.0: 14.54 KB (0.237%)
|
||||
events: 14.54 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/get-intrinsic@1.2.2: 13.01 KB (0.212%)
|
||||
get-intrinsic: 13.01 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/zenscroll@4.0.2: 12.31 KB (0.201%)
|
||||
zenscroll: 12.31 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/react-debounce-input@3.3.0_react@17.0.2: 11.95 KB (0.195%)
|
||||
react-debounce-input: 11.95 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/react-immutable-proptypes@2.2.0_immutable@3.8.2: 11.82 KB (0.193%)
|
||||
react-immutable-proptypes: 11.82 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/ret@0.2.2: 10.82 KB (0.176%)
|
||||
ret: 10.82 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/lodash.debounce@4.0.8: 10.53 KB (0.172%)
|
||||
lodash.debounce: 10.53 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/unraw@3.0.0: 9.9 KB (0.161%)
|
||||
unraw: 9.9 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/string_decoder@1.3.0: 9.24 KB (0.151%)
|
||||
string_decoder: 9.24 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/reselect@4.1.8: 8.85 KB (0.144%)
|
||||
reselect: 8.85 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/xml@1.0.1: 7.39 KB (0.121%)
|
||||
xml: 7.39 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/react-copy-to-clipboard@5.1.0_react@17.0.2: 7.33 KB (0.120%)
|
||||
react-copy-to-clipboard: 7.33 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/traverse@0.6.7: 7.15 KB (0.117%)
|
||||
traverse: 7.15 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/react@17.0.2: 6.48 KB (0.106%)
|
||||
react: 6.48 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@swagger-api+apidom-json-pointer@0.80.0: 6.39 KB (0.104%)
|
||||
@swagger-api/apidom-json-pointer: 6.39 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/randexp@0.5.3: 6.15 KB (0.100%)
|
||||
randexp: 6.15 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/react-immutable-pure-component@2.2.2_immutable@3.8.2_react-dom@17.0.2_react@17.0.2: 6.01 KB (0.0980%)
|
||||
react-immutable-pure-component: 6.01 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/redux-immutable@4.0.0_immutable@3.8.2: 5.43 KB (0.0886%)
|
||||
redux-immutable: 5.43 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/process@0.11.10: 5.29 KB (0.0863%)
|
||||
process: 5.29 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@babel+runtime@7.23.2: 5.1 KB (0.0833%)
|
||||
@babel/runtime: 5.1 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/cookie@0.5.0: 5.1 KB (0.0832%)
|
||||
cookie: 5.1 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/scheduler@0.20.2: 4.91 KB (0.0801%)
|
||||
scheduler: 4.91 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/drange@1.1.1: 4.8 KB (0.0783%)
|
||||
drange: 4.8 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/lowlight@1.20.0: 4.42 KB (0.0721%)
|
||||
lowlight: 4.42 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/deep-extend@0.6.0: 4.19 KB (0.0684%)
|
||||
deep-extend: 4.19 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/deepmerge@4.3.1: 3.95 KB (0.0645%)
|
||||
deepmerge: 3.95 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/base64-js@1.5.1: 3.84 KB (0.0626%)
|
||||
base64-js: 3.84 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/stream-browserify@3.0.0: 3.76 KB (0.0613%)
|
||||
stream-browserify: 3.76 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@swagger-api+apidom-error@0.80.0: 3.49 KB (0.0570%)
|
||||
@swagger-api/apidom-error: 3.49 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/side-channel@1.0.4: 3.31 KB (0.0540%)
|
||||
side-channel: 3.31 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/copy-to-clipboard@3.3.3: 3.29 KB (0.0536%)
|
||||
copy-to-clipboard: 3.29 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/format@0.2.2: 3.26 KB (0.0531%)
|
||||
format: 3.26 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/stampit@4.3.2: 3.16 KB (0.0515%)
|
||||
stampit: 3.16 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/css.escape@1.5.1: 3.08 KB (0.0502%)
|
||||
css.escape: 3.08 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/serialize-error@8.1.0: 2.93 KB (0.0477%)
|
||||
serialize-error: 2.93 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/define-data-property@1.1.1: 2.77 KB (0.0452%)
|
||||
define-data-property: 2.77 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/hoist-non-react-statics@3.3.2: 2.68 KB (0.0437%)
|
||||
hoist-non-react-statics: 2.68 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/prop-types@15.8.1: 2.6 KB (0.0424%)
|
||||
prop-types: 2.6 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/use-sync-external-store@1.2.0_react@17.0.2: 2.59 KB (0.0423%)
|
||||
use-sync-external-store: 2.59 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/querystringify@2.2.0: 2.5 KB (0.0408%)
|
||||
querystringify: 2.5 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/xml-but-prettier@1.0.1: 2.17 KB (0.0353%)
|
||||
xml-but-prettier: 2.17 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/has-symbols@1.0.3: 2.13 KB (0.0347%)
|
||||
has-symbols: 2.13 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/function-bind@1.1.2: 2.12 KB (0.0345%)
|
||||
function-bind: 2.12 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/ieee754@1.2.1: 2.1 KB (0.0343%)
|
||||
ieee754: 2.1 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/object-assign@4.1.1: 2.06 KB (0.0336%)
|
||||
object-assign: 2.06 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/call-bind@1.0.5: 1.59 KB (0.0259%)
|
||||
call-bind: 1.59 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/util-deprecate@1.0.2: 1.58 KB (0.0257%)
|
||||
util-deprecate: 1.58 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@braintree+sanitize-url@6.0.4: 1.56 KB (0.0255%)
|
||||
@braintree/sanitize-url: 1.56 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/randombytes@2.1.0: 1.54 KB (0.0251%)
|
||||
randombytes: 1.54 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/js-file-download@0.4.12: 1.52 KB (0.0248%)
|
||||
js-file-download: 1.52 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/classnames@2.3.2: 1.38 KB (0.0226%)
|
||||
classnames: 1.38 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/repeat-string@1.6.1: 1.18 KB (0.0193%)
|
||||
repeat-string: 1.18 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/set-function-length@1.1.1: 1.14 KB (0.0186%)
|
||||
set-function-length: 1.14 KB (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/@babel+runtime-corejs3@7.23.2: 878 B (0.0140%)
|
||||
@babel/runtime-corejs3: 878 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/has-property-descriptors@1.0.1: 817 B (0.0130%)
|
||||
has-property-descriptors: 817 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/toggle-selection@1.0.6: 780 B (0.0124%)
|
||||
toggle-selection: 780 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/is-plain-object@5.0.0: 758 B (0.0121%)
|
||||
is-plain-object: 758 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/inherits@2.0.4: 753 B (0.0120%)
|
||||
inherits: 753 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/requires-port@1.0.0: 753 B (0.0120%)
|
||||
requires-port: 753 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/fault@1.0.4: 691 B (0.0110%)
|
||||
fault: 691 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/gopd@1.0.1: 263 B (0.00419%)
|
||||
gopd: 263 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/hasown@2.0.0: 234 B (0.00373%)
|
||||
hasown: 234 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
.pnpm/has-proto@1.0.1: 197 B (0.00314%)
|
||||
has-proto: 197 B (100%)
|
||||
<self>: 0 B (0.00%)
|
||||
<self>: 2.74 MB (45.8%)
|
||||
ramda: 361.65 KB (6.14%)
|
||||
core-js-pure: 300.89 KB (5.11%)
|
||||
ramda-adjunct: 255.42 KB (4.34%)
|
||||
lodash: 253.56 KB (4.30%)
|
||||
@swagger-api/apidom-ns-openapi-3-0: 204.6 KB (3.47%)
|
||||
autolinker: 203.32 KB (3.45%)
|
||||
swagger-client: 159.41 KB (2.71%)
|
||||
is-plain-object: 758 B (0.464%)
|
||||
<self>: 158.67 KB (99.5%)
|
||||
@swagger-api/apidom-ns-openapi-3-1: 154.72 KB (2.63%)
|
||||
immutable: 139.01 KB (2.36%)
|
||||
remarkable: 125.56 KB (2.13%)
|
||||
react-dom: 119.19 KB (2.02%)
|
||||
highlight.js: 111.85 KB (1.90%)
|
||||
js-yaml: 105.01 KB (1.78%)
|
||||
readable-stream: 96.66 KB (1.64%)
|
||||
@swagger-api/apidom-reference: 84.72 KB (1.44%)
|
||||
dompurify: 61.27 KB (1.04%)
|
||||
@swagger-api/apidom-ns-json-schema-draft-4: 58.11 KB (0.987%)
|
||||
minim: 57.35 KB (0.974%)
|
||||
buffer: 56.99 KB (0.967%)
|
||||
@swagger-api/apidom-core: 47.72 KB (0.810%)
|
||||
@swagger-api/apidom-ast: 44.47 KB (0.755%)
|
||||
react-redux: 43.7 KB (0.742%)
|
||||
react-syntax-highlighter: 38.01 KB (0.645%)
|
||||
url: 37.24 KB (0.632%)
|
||||
punycode: 14.33 KB (38.5%)
|
||||
<self>: 22.92 KB (61.5%)
|
||||
fast-json-patch: 31.89 KB (0.541%)
|
||||
redux: 27.59 KB (0.468%)
|
||||
qs: 26.61 KB (0.452%)
|
||||
sha.js: 18.57 KB (0.315%)
|
||||
object-inspect: 18.15 KB (0.308%)
|
||||
url-parse: 16.23 KB (0.276%)
|
||||
events: 14.54 KB (0.247%)
|
||||
cross-fetch: 14.31 KB (0.243%)
|
||||
tslib: 14.21 KB (0.241%)
|
||||
@babel/runtime-corejs3: 13.24 KB (0.225%)
|
||||
get-intrinsic: 13.01 KB (0.221%)
|
||||
reselect: 12.51 KB (0.212%)
|
||||
zenscroll: 12.31 KB (0.209%)
|
||||
react-debounce-input: 11.95 KB (0.203%)
|
||||
react-immutable-proptypes: 11.82 KB (0.201%)
|
||||
ret: 10.82 KB (0.184%)
|
||||
lodash.debounce: 10.53 KB (0.179%)
|
||||
unraw: 10.27 KB (0.174%)
|
||||
string_decoder: 9.24 KB (0.157%)
|
||||
short-unique-id: 8.29 KB (0.141%)
|
||||
xml: 7.39 KB (0.125%)
|
||||
react-copy-to-clipboard: 7.33 KB (0.124%)
|
||||
traverse: 7.15 KB (0.121%)
|
||||
react: 6.48 KB (0.110%)
|
||||
@babel/runtime: 6.29 KB (0.107%)
|
||||
randexp: 6.15 KB (0.104%)
|
||||
react-immutable-pure-component: 6.01 KB (0.102%)
|
||||
redux-immutable: 5.43 KB (0.0922%)
|
||||
process: 5.29 KB (0.0898%)
|
||||
cookie: 5.1 KB (0.0866%)
|
||||
scheduler: 4.91 KB (0.0834%)
|
||||
drange: 4.8 KB (0.0815%)
|
||||
lowlight: 4.42 KB (0.0751%)
|
||||
deep-extend: 4.19 KB (0.0712%)
|
||||
deepmerge: 3.95 KB (0.0671%)
|
||||
base64-js: 3.84 KB (0.0652%)
|
||||
stream-browserify: 3.76 KB (0.0638%)
|
||||
@swagger-api/apidom-json-pointer: 3.68 KB (0.0625%)
|
||||
side-channel: 3.31 KB (0.0562%)
|
||||
copy-to-clipboard: 3.29 KB (0.0558%)
|
||||
format: 3.26 KB (0.0553%)
|
||||
stampit: 3.16 KB (0.0536%)
|
||||
css.escape: 3.08 KB (0.0523%)
|
||||
serialize-error: 2.93 KB (0.0497%)
|
||||
hoist-non-react-statics: 2.68 KB (0.0455%)
|
||||
prop-types: 2.6 KB (0.0441%)
|
||||
use-sync-external-store: 2.59 KB (0.0440%)
|
||||
querystringify: 2.5 KB (0.0425%)
|
||||
react-is: 2.48 KB (0.0422%)
|
||||
xml-but-prettier: 2.17 KB (0.0368%)
|
||||
has-symbols: 2.13 KB (0.0362%)
|
||||
ieee754: 2.1 KB (0.0357%)
|
||||
object-assign: 2.06 KB (0.0349%)
|
||||
call-bind: 1.68 KB (0.0285%)
|
||||
safe-buffer: 1.63 KB (0.0277%)
|
||||
util-deprecate: 1.58 KB (0.0268%)
|
||||
function-bind: 1.55 KB (0.0263%)
|
||||
randombytes: 1.54 KB (0.0261%)
|
||||
js-file-download: 1.52 KB (0.0258%)
|
||||
classnames: 1.38 KB (0.0235%)
|
||||
@braintree/sanitize-url: 1.38 KB (0.0234%)
|
||||
repeat-string: 1.18 KB (0.0201%)
|
||||
toggle-selection: 780 B (0.0129%)
|
||||
inherits: 753 B (0.0125%)
|
||||
requires-port: 753 B (0.0125%)
|
||||
fault: 691 B (0.0115%)
|
||||
formdata-node: 259 B (0.00429%)
|
||||
has-proto: 197 B (0.00327%)
|
||||
has: 129 B (0.00214%)
|
||||
object-inspect|.: 15 B (0.000249%)
|
||||
<self>: 2.26 MB (39.2%)
|
||||
|
|
16
static/openapi/log.es-bundle-core-sizes.swagger-ui.txt
Normal file
16
static/openapi/log.es-bundle-core-sizes.swagger-ui.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
readable-stream: 96.66 KB (7.62%)
|
||||
buffer: 56.99 KB (4.49%)
|
||||
core-js-pure: 25.99 KB (2.05%)
|
||||
sha.js: 18.57 KB (1.46%)
|
||||
events: 14.54 KB (1.15%)
|
||||
string_decoder: 9.24 KB (0.728%)
|
||||
xml: 7.39 KB (0.582%)
|
||||
process: 5.29 KB (0.417%)
|
||||
deep-extend: 4.19 KB (0.330%)
|
||||
stream-browserify: 3.76 KB (0.296%)
|
||||
safe-buffer: 1.63 KB (0.129%)
|
||||
util-deprecate: 1.58 KB (0.124%)
|
||||
randombytes: 1.54 KB (0.121%)
|
||||
inherits: 753 B (0.0579%)
|
||||
@babel/runtime-corejs3: 71 B (0.00546%)
|
||||
<self>: 1020.83 KB (80.4%)
|
99
static/openapi/log.es-bundle-sizes.swagger-ui.txt
Normal file
99
static/openapi/log.es-bundle-sizes.swagger-ui.txt
Normal file
|
@ -0,0 +1,99 @@
|
|||
ramda: 361.65 KB (6.14%)
|
||||
core-js-pure: 300.89 KB (5.11%)
|
||||
ramda-adjunct: 255.42 KB (4.34%)
|
||||
lodash: 253.56 KB (4.30%)
|
||||
@swagger-api/apidom-ns-openapi-3-0: 204.6 KB (3.47%)
|
||||
autolinker: 203.32 KB (3.45%)
|
||||
swagger-client: 159.41 KB (2.71%)
|
||||
is-plain-object: 758 B (0.464%)
|
||||
<self>: 158.67 KB (99.5%)
|
||||
@swagger-api/apidom-ns-openapi-3-1: 154.72 KB (2.63%)
|
||||
immutable: 139.01 KB (2.36%)
|
||||
remarkable: 125.56 KB (2.13%)
|
||||
react-dom: 119.19 KB (2.02%)
|
||||
highlight.js: 111.85 KB (1.90%)
|
||||
js-yaml: 105.01 KB (1.78%)
|
||||
readable-stream: 96.66 KB (1.64%)
|
||||
@swagger-api/apidom-reference: 84.72 KB (1.44%)
|
||||
dompurify: 61.27 KB (1.04%)
|
||||
@swagger-api/apidom-ns-json-schema-draft-4: 58.11 KB (0.987%)
|
||||
minim: 57.35 KB (0.974%)
|
||||
buffer: 56.99 KB (0.967%)
|
||||
@swagger-api/apidom-core: 47.72 KB (0.810%)
|
||||
@swagger-api/apidom-ast: 44.47 KB (0.755%)
|
||||
react-redux: 43.7 KB (0.742%)
|
||||
react-syntax-highlighter: 38.01 KB (0.645%)
|
||||
url: 37.24 KB (0.632%)
|
||||
punycode: 14.33 KB (38.5%)
|
||||
<self>: 22.92 KB (61.5%)
|
||||
fast-json-patch: 31.89 KB (0.541%)
|
||||
redux: 27.59 KB (0.468%)
|
||||
qs: 26.61 KB (0.452%)
|
||||
sha.js: 18.57 KB (0.315%)
|
||||
object-inspect: 18.15 KB (0.308%)
|
||||
url-parse: 16.23 KB (0.276%)
|
||||
events: 14.54 KB (0.247%)
|
||||
cross-fetch: 14.31 KB (0.243%)
|
||||
tslib: 14.21 KB (0.241%)
|
||||
@babel/runtime-corejs3: 13.24 KB (0.225%)
|
||||
get-intrinsic: 13.01 KB (0.221%)
|
||||
reselect: 12.51 KB (0.212%)
|
||||
zenscroll: 12.31 KB (0.209%)
|
||||
react-debounce-input: 11.95 KB (0.203%)
|
||||
react-immutable-proptypes: 11.82 KB (0.201%)
|
||||
ret: 10.82 KB (0.184%)
|
||||
lodash.debounce: 10.53 KB (0.179%)
|
||||
unraw: 10.27 KB (0.174%)
|
||||
string_decoder: 9.24 KB (0.157%)
|
||||
short-unique-id: 8.29 KB (0.141%)
|
||||
xml: 7.39 KB (0.125%)
|
||||
react-copy-to-clipboard: 7.33 KB (0.124%)
|
||||
traverse: 7.15 KB (0.121%)
|
||||
react: 6.48 KB (0.110%)
|
||||
@babel/runtime: 6.29 KB (0.107%)
|
||||
randexp: 6.15 KB (0.104%)
|
||||
react-immutable-pure-component: 6.01 KB (0.102%)
|
||||
redux-immutable: 5.43 KB (0.0922%)
|
||||
process: 5.29 KB (0.0898%)
|
||||
cookie: 5.1 KB (0.0866%)
|
||||
scheduler: 4.91 KB (0.0834%)
|
||||
drange: 4.8 KB (0.0815%)
|
||||
lowlight: 4.42 KB (0.0751%)
|
||||
deep-extend: 4.19 KB (0.0712%)
|
||||
deepmerge: 3.95 KB (0.0671%)
|
||||
base64-js: 3.84 KB (0.0652%)
|
||||
stream-browserify: 3.76 KB (0.0638%)
|
||||
@swagger-api/apidom-json-pointer: 3.68 KB (0.0625%)
|
||||
side-channel: 3.31 KB (0.0562%)
|
||||
copy-to-clipboard: 3.29 KB (0.0558%)
|
||||
format: 3.26 KB (0.0553%)
|
||||
stampit: 3.16 KB (0.0536%)
|
||||
css.escape: 3.08 KB (0.0523%)
|
||||
serialize-error: 2.93 KB (0.0497%)
|
||||
hoist-non-react-statics: 2.68 KB (0.0455%)
|
||||
prop-types: 2.6 KB (0.0441%)
|
||||
use-sync-external-store: 2.59 KB (0.0440%)
|
||||
querystringify: 2.5 KB (0.0425%)
|
||||
react-is: 2.48 KB (0.0422%)
|
||||
xml-but-prettier: 2.17 KB (0.0368%)
|
||||
has-symbols: 2.13 KB (0.0362%)
|
||||
ieee754: 2.1 KB (0.0357%)
|
||||
object-assign: 2.06 KB (0.0349%)
|
||||
call-bind: 1.68 KB (0.0285%)
|
||||
safe-buffer: 1.63 KB (0.0277%)
|
||||
util-deprecate: 1.58 KB (0.0268%)
|
||||
function-bind: 1.55 KB (0.0263%)
|
||||
randombytes: 1.54 KB (0.0261%)
|
||||
js-file-download: 1.52 KB (0.0258%)
|
||||
classnames: 1.38 KB (0.0235%)
|
||||
@braintree/sanitize-url: 1.38 KB (0.0234%)
|
||||
repeat-string: 1.18 KB (0.0201%)
|
||||
toggle-selection: 780 B (0.0129%)
|
||||
inherits: 753 B (0.0125%)
|
||||
requires-port: 753 B (0.0125%)
|
||||
fault: 691 B (0.0115%)
|
||||
formdata-node: 259 B (0.00429%)
|
||||
has-proto: 197 B (0.00327%)
|
||||
has: 129 B (0.00214%)
|
||||
object-inspect|.: 15 B (0.000249%)
|
||||
<self>: 2.26 MB (39.2%)
|
File diff suppressed because one or more lines are too long
138
static/openapi/swagger-ui-bundle.js.LICENSE.txt
Normal file
138
static/openapi/swagger-ui-bundle.js.LICENSE.txt
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
Copyright (c) 2018 Jed Watson.
|
||||
Licensed under the MIT License (MIT), see
|
||||
http://jedwatson.github.io/classnames
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @description Recursive object extending
|
||||
* @author Viacheslav Lotsmanov <lotsmanov89@gmail.com>
|
||||
* @license MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2018 Viacheslav Lotsmanov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* The buffer module from node.js, for the browser.
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* cookie
|
||||
* Copyright(c) 2012-2014 Roman Shtylman
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/*!
|
||||
* https://github.com/Starcounter-Jack/JSON-Patch
|
||||
* (c) 2017-2021 Joachim Wester
|
||||
* MIT license
|
||||
*/
|
||||
|
||||
/*!
|
||||
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
|
||||
*
|
||||
* Copyright (c) 2014-2017, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* repeat-string <https://github.com/jonschlinkert/repeat-string>
|
||||
*
|
||||
* Copyright (c) 2014-2015, Jon Schlinkert.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
/*! @license DOMPurify 3.0.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.3/LICENSE */
|
||||
|
||||
/*! https://mths.be/punycode v1.4.1 by @mathias */
|
||||
|
||||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */
|
||||
|
||||
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim/with-selector.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v0.20.2
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
35
static/openapi/swagger-ui-es-bundle-core.js.LICENSE.txt
Normal file
35
static/openapi/swagger-ui-es-bundle-core.js.LICENSE.txt
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*!
|
||||
* @description Recursive object extending
|
||||
* @author Viacheslav Lotsmanov <lotsmanov89@gmail.com>
|
||||
* @license MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2018 Viacheslav Lotsmanov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* The buffer module from node.js, for the browser.
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
138
static/openapi/swagger-ui-es-bundle.js.LICENSE.txt
Normal file
138
static/openapi/swagger-ui-es-bundle.js.LICENSE.txt
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
Copyright (c) 2018 Jed Watson.
|
||||
Licensed under the MIT License (MIT), see
|
||||
http://jedwatson.github.io/classnames
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @description Recursive object extending
|
||||
* @author Viacheslav Lotsmanov <lotsmanov89@gmail.com>
|
||||
* @license MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2018 Viacheslav Lotsmanov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* The buffer module from node.js, for the browser.
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* cookie
|
||||
* Copyright(c) 2012-2014 Roman Shtylman
|
||||
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/*!
|
||||
* https://github.com/Starcounter-Jack/JSON-Patch
|
||||
* (c) 2017-2021 Joachim Wester
|
||||
* MIT license
|
||||
*/
|
||||
|
||||
/*!
|
||||
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
|
||||
*
|
||||
* Copyright (c) 2014-2017, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* repeat-string <https://github.com/jonschlinkert/repeat-string>
|
||||
*
|
||||
* Copyright (c) 2014-2015, Jon Schlinkert.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
/*! @license DOMPurify 3.0.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.3/LICENSE */
|
||||
|
||||
/*! https://mths.be/punycode v1.4.1 by @mathias */
|
||||
|
||||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */
|
||||
|
||||
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim/with-selector.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v0.20.2
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
27
static/openapi/swagger-ui-standalone-preset.js.LICENSE.txt
Normal file
27
static/openapi/swagger-ui-standalone-preset.js.LICENSE.txt
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* The buffer module from node.js, for the browser.
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */
|
||||
|
||||
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -52,7 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|||
<. } .>
|
||||
|
||||
<label class="sitekey-form__label" for="publish_benchmarks">
|
||||
Anonymously publish CAPTCHA performance statistics to help other webmasters. <a href="https://mcaptcha.org/blog/introducing-mcaptcha-net">Please see here for more info</a>.
|
||||
Anonymously publish CAPTCHA performance statistics to help other webmasters
|
||||
<input
|
||||
class="sitekey-form__input"
|
||||
type="checkbox"
|
||||
|
|
|
@ -76,7 +76,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|||
|
||||
|
||||
<label class="sitekey-form__label" for="publish_benchmarks">
|
||||
Anonymously publish CAPTCHA performance statistics to help other webmasters. <a href="https://mcaptcha.org/blog/introducing-mcaptcha-net">Please see here for more info</a>.
|
||||
Anonymously publish CAPTCHA performance statistics to help other webmasters
|
||||
<input
|
||||
class="sitekey-form__input"
|
||||
type="checkbox"
|
||||
|
|
|
@ -6,54 +6,51 @@ SPDX-License-Identifier: MIT OR Apache-2.0
|
|||
|
||||
<. include!("../components/headers/widget-headers.html"); .>
|
||||
<body>
|
||||
<main class="widget__container">
|
||||
<form class="widget__inner-container">
|
||||
<noscript>
|
||||
<div class="widget__noscript-container">
|
||||
<span class="widget__noscript-warning">
|
||||
Please enable JavaScript to receive mCaptcha challenge
|
||||
</span>
|
||||
<a class="widget__source-code" href="https://github.com/mCaptcha">
|
||||
Read our source code
|
||||
</a>
|
||||
</div>
|
||||
</noscript>
|
||||
<label class="widget__verification-container" for="widget__verification-checkbox">
|
||||
<input
|
||||
id="widget__verification-checkbox"
|
||||
class="widget__verification-checkbox"
|
||||
type="checkbox" />
|
||||
<span id="widget__verification-text--before">I'm not a robot</span>
|
||||
<span id="widget__verification-text--during">Processing...</span>
|
||||
<span id="widget__verification-text--after">Verified!</span>
|
||||
<span id="widget__verification-text--error">Something went wrong</span>
|
||||
</label>
|
||||
<div class="widget__mcaptcha-details">
|
||||
<a href="<.= crate::PKG_HOMEPAGE .>"
|
||||
class="widget__mcaptcha-logo-container"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
class="widget__mcaptcha-logo"
|
||||
src="<.= crate::FILES.get("./static/cache/img/icon-trans.png").unwrap().>"
|
||||
alt="mCaptcha logo"
|
||||
/>
|
||||
<p class="widget__mcaptcha-brand-name">mCaptcha</p>
|
||||
<form class="widget__contaienr">
|
||||
<noscript>
|
||||
<div class="widget__noscript-container">
|
||||
<span class="widget__noscript-warning">
|
||||
Please enable JavaScript to receive mCaptcha challenge
|
||||
</span>
|
||||
<a class="widget__source-code" href="https://github.com/mCaptcha">
|
||||
Read our source code
|
||||
</a>
|
||||
</div>
|
||||
</noscript>
|
||||
<label class="widget__verification-container" for="widget__verification-checkbox">
|
||||
<input
|
||||
id="widget__verification-checkbox"
|
||||
class="widget__verification-checkbox"
|
||||
type="checkbox" />
|
||||
<span id="widget__verification-text--before">I'm not a robot</span>
|
||||
<span id="widget__verification-text--during">Processing...</span>
|
||||
<span id="widget__verification-text--after">Verified!</span>
|
||||
<span id="widget__verification-text--error">Something went wrong</span>
|
||||
</label>
|
||||
<div class="widget__mcaptcha-details">
|
||||
<a href="<.= crate::PKG_HOMEPAGE .>"
|
||||
class="widget__mcaptcha-logo-container"
|
||||
target="_blank"
|
||||
>
|
||||
<img
|
||||
class="widget__mcaptcha-logo"
|
||||
src="<.= crate::FILES.get("./static/cache/img/icon-trans.png").unwrap().>"
|
||||
alt="mCaptcha logo"
|
||||
/>
|
||||
<p class="widget__mcaptcha-brand-name">mCaptcha</p>
|
||||
</a>
|
||||
<div class="widget__mcaptcha-info-container">
|
||||
<a class="widget__mcaptcha-info-link"
|
||||
target="_blank"
|
||||
href="<.= crate::PKG_HOMEPAGE .><.= crate::PAGES.privacy .>">
|
||||
Privacy
|
||||
</a>
|
||||
<a class="widget__mcaptcha-info-link"
|
||||
target="_blank"
|
||||
href="<.= crate::PKG_HOMEPAGE .><.= crate::PAGES.security .>">
|
||||
Terms
|
||||
</a>
|
||||
<div class="widget__mcaptcha-info-container">
|
||||
<a class="widget__mcaptcha-info-link"
|
||||
target="_blank"
|
||||
href="<.= crate::PKG_HOMEPAGE .><.= crate::PAGES.privacy .>">
|
||||
Privacy
|
||||
</a>
|
||||
<a class="widget__mcaptcha-info-link"
|
||||
target="_blank"
|
||||
href="<.= crate::PKG_HOMEPAGE .><.= crate::PAGES.security .>">
|
||||
Terms
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="progress__bar"><div class="progress__fill"></div></div>
|
||||
</main>
|
||||
</div>
|
||||
</form>
|
||||
<.include!("./footer.html"); .>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
import { Work, ServiceWorkerMessage } from "./types";
|
||||
import { Work, ServiceWorkerWork } from "./types";
|
||||
import fetchPoWConfig from "./fetchPoWConfig";
|
||||
import sendWork from "./sendWork";
|
||||
import sendToParent from "./sendToParent";
|
||||
|
@ -24,9 +24,6 @@ export const registerVerificationEventHandler = (): void => {
|
|||
};
|
||||
|
||||
export const solveCaptchaRunner = async (e: Event): Promise<void> => {
|
||||
const PROGRESS_FILL = <HTMLElement>document.querySelector(".progress__fill");
|
||||
let width = 0;
|
||||
|
||||
if (LOCK) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
@ -35,8 +32,6 @@ export const solveCaptchaRunner = async (e: Event): Promise<void> => {
|
|||
try {
|
||||
LOCK = true;
|
||||
if (CONST.btn().checked == false) {
|
||||
width = 0;
|
||||
PROGRESS_FILL.style.width = `${width}%`;
|
||||
CONST.messageText().before();
|
||||
LOCK = false;
|
||||
return;
|
||||
|
@ -48,49 +43,32 @@ export const solveCaptchaRunner = async (e: Event): Promise<void> => {
|
|||
CONST.messageText().during();
|
||||
// 1. get config
|
||||
const config = await fetchPoWConfig();
|
||||
const max_recorded_nonce = config.max_recorded_nonce;
|
||||
// 2. prove work
|
||||
worker.postMessage(config);
|
||||
|
||||
worker.onmessage = async (event: MessageEvent) => {
|
||||
const resp: ServiceWorkerMessage = event.data;
|
||||
const resp: ServiceWorkerWork = event.data;
|
||||
console.log(
|
||||
`Proof generated. Difficuly: ${config.difficulty_factor} Duration: ${resp.work.time}`
|
||||
);
|
||||
|
||||
if (resp.type === "work") {
|
||||
width = 80;
|
||||
PROGRESS_FILL.style.width = `${width}%`;
|
||||
console.log(
|
||||
`Proof generated. Difficuly: ${config.difficulty_factor} Duration: ${resp.value.work.time}`
|
||||
);
|
||||
const proof: Work = {
|
||||
key: CONST.sitekey(),
|
||||
string: config.string,
|
||||
nonce: resp.work.nonce,
|
||||
result: resp.work.result,
|
||||
time: Math.trunc(resp.work.time),
|
||||
worker_type: resp.work.worker_type,
|
||||
};
|
||||
|
||||
const proof: Work = {
|
||||
key: CONST.sitekey(),
|
||||
string: config.string,
|
||||
nonce: resp.value.work.nonce,
|
||||
result: resp.value.work.result,
|
||||
time: Math.trunc(resp.value.work.time),
|
||||
worker_type: resp.value.work.worker_type,
|
||||
};
|
||||
|
||||
width = 90;
|
||||
PROGRESS_FILL.style.width = `${width}%`;
|
||||
// 3. submit work
|
||||
const token = await sendWork(proof);
|
||||
// 4. send token
|
||||
sendToParent(token);
|
||||
// 5. mark checkbox checked
|
||||
CONST.btn().checked = true;
|
||||
width = 100;
|
||||
PROGRESS_FILL.style.width = `${width}%`;
|
||||
CONST.messageText().after();
|
||||
LOCK = false;
|
||||
}
|
||||
if (resp.type === "progress") {
|
||||
if (width < 80) {
|
||||
width = (resp.nonce / max_recorded_nonce) * 100;
|
||||
PROGRESS_FILL.style.width = `${width}%`;
|
||||
}
|
||||
console.log(`received nonce ${resp.nonce}`);
|
||||
}
|
||||
// 3. submit work
|
||||
const token = await sendWork(proof);
|
||||
// 4. send token
|
||||
sendToParent(token);
|
||||
// 5. mark checkbox checked
|
||||
CONST.btn().checked = true;
|
||||
CONST.messageText().after();
|
||||
LOCK = false;
|
||||
};
|
||||
} catch (e) {
|
||||
CONST.messageText().error();
|
||||
|
|
|
@ -7,138 +7,106 @@
|
|||
|
||||
@import "../reset";
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.widget__container {
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
margin: auto 0;
|
||||
}
|
||||
|
||||
.widget__inner-container {
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.widget__contaienr {
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.widget__noscript-container {
|
||||
display: flex;
|
||||
font-size: 0.7rem;
|
||||
line-height: 20px;
|
||||
flex-direction: column;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
font-size: 0.7rem;
|
||||
line-height: 20px;
|
||||
flex-direction: column;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.widget__noscript-warning {
|
||||
display: block;
|
||||
margin: auto;
|
||||
flex: 2;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
display: block;
|
||||
margin: auto;
|
||||
flex: 2;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.widget__source-code {
|
||||
display: block;
|
||||
flex: 1;
|
||||
display: block;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.widget__verification-container {
|
||||
align-items: center;
|
||||
display: none;
|
||||
line-height: 30px;
|
||||
font-size: 1rem;
|
||||
align-items: center;
|
||||
display: none;
|
||||
line-height: 30px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.widget__verification-checkbox {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin: 0 10px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
#widget__verification-text--during {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#widget__verification-text--after {
|
||||
display: none;
|
||||
color: green;
|
||||
display: none;
|
||||
color: green;
|
||||
}
|
||||
|
||||
#widget__verification-text--error {
|
||||
display: none;
|
||||
color: red;
|
||||
display: none;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.widget__verification-checkbox:checked ~ #widget__verification-text--before {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.widget__verification-checkbox:checked ~ #widget__verification-text--during {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.widget__verification-checkbox:checked ~ #widget__verification-text--error {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.widget__verification-checkbox:checked ~ #widget__verification-text--after {
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.widget__mcaptcha-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: auto;
|
||||
margin-right: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.widget__mcaptcha-brand-name {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.widget__mcaptcha-logo {
|
||||
display: block;
|
||||
width: 35px;
|
||||
margin: auto;
|
||||
display: block;
|
||||
width: 35px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.widget__mcaptcha-info-container {
|
||||
display: flex;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.widget__mcaptcha-info-link {
|
||||
font-size: 0.5rem;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
/* progress bar courtesy of https://codepen.io/Bizzy-Coding/pen/poOymVJ?editors=1111 */
|
||||
.progress__bar {
|
||||
position: relative;
|
||||
height: 5px;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.progress__fill {
|
||||
background: #65a2e0;
|
||||
border-radius: 15px;
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
font-size: 0.5rem;
|
||||
margin: 2px;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
import { stepped_gen_pow } from "@mcaptcha/pow-wasm";
|
||||
import { gen_pow } from "@mcaptcha/pow-wasm";
|
||||
import * as p from "@mcaptcha/pow_sha256-polyfill";
|
||||
import { WasmWork, PoWConfig, SubmitWork } from "./types";
|
||||
|
||||
|
@ -12,25 +12,19 @@ import { WasmWork, PoWConfig, SubmitWork } from "./types";
|
|||
* @param {PoWConfig} config - the proof-of-work configuration using which
|
||||
* work needs to be computed
|
||||
* */
|
||||
const prove = async (
|
||||
config: PoWConfig,
|
||||
progress: (nonce: number) => void
|
||||
): Promise<SubmitWork> => {
|
||||
const prove = async (config: PoWConfig): Promise<SubmitWork> => {
|
||||
const WASM = "wasm";
|
||||
const JS = "js";
|
||||
const STEPS = 5000;
|
||||
if (WasmSupported) {
|
||||
let proof: WasmWork = null;
|
||||
let res: SubmitWork = null;
|
||||
let time: number = null;
|
||||
|
||||
const t0 = performance.now();
|
||||
const proofString = stepped_gen_pow(
|
||||
const proofString = gen_pow(
|
||||
config.salt,
|
||||
config.string,
|
||||
config.difficulty_factor,
|
||||
STEPS,
|
||||
progress
|
||||
config.difficulty_factor
|
||||
);
|
||||
const t1 = performance.now();
|
||||
time = t1 - t0;
|
||||
|
@ -53,12 +47,10 @@ const prove = async (
|
|||
|
||||
const t0 = performance.now();
|
||||
|
||||
proof = await p.stepped_generate_work(
|
||||
proof = await p.generate_work(
|
||||
config.salt,
|
||||
config.string,
|
||||
config.difficulty_factor,
|
||||
STEPS,
|
||||
progress
|
||||
config.difficulty_factor
|
||||
);
|
||||
const t1 = performance.now();
|
||||
time = t1 - t0;
|
||||
|
|
|
@ -6,31 +6,17 @@
|
|||
import log from "../logger";
|
||||
|
||||
import prove from "./prove";
|
||||
import { PoWConfig, ServiceWorkerMessage, ServiceWorkerWork } from "./types";
|
||||
import { PoWConfig, ServiceWorkerWork } from "./types";
|
||||
|
||||
log.log("worker registered");
|
||||
onmessage = async (e) => {
|
||||
console.debug("message received at worker");
|
||||
const config: PoWConfig = e.data;
|
||||
|
||||
const progressCallback = (nonce: number) => {
|
||||
const res: ServiceWorkerMessage = {
|
||||
type: "progress",
|
||||
nonce: nonce,
|
||||
};
|
||||
|
||||
postMessage(res);
|
||||
};
|
||||
|
||||
const work = await prove(config, progressCallback);
|
||||
const w: ServiceWorkerWork = {
|
||||
const work = await prove(config);
|
||||
const res: ServiceWorkerWork = {
|
||||
work,
|
||||
};
|
||||
|
||||
const res: ServiceWorkerMessage = {
|
||||
type: "work",
|
||||
value: w,
|
||||
};
|
||||
|
||||
postMessage(res);
|
||||
};
|
||||
|
|
|
@ -32,13 +32,8 @@ export type PoWConfig = {
|
|||
string: string;
|
||||
difficulty_factor: number;
|
||||
salt: string;
|
||||
max_recorded_nonce: number;
|
||||
};
|
||||
|
||||
export type Token = {
|
||||
token: string;
|
||||
};
|
||||
|
||||
export type ServiceWorkerMessage =
|
||||
| { type: "work"; value: ServiceWorkerWork }
|
||||
| { type: "progress"; nonce: number };
|
||||
|
|
Loading…
Add table
Reference in a new issue