mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2026-02-11 10:05:41 +00:00
Compare commits
54 Commits
feat-maria
...
nighwatch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5324969bd2 | ||
|
|
43dab030df | ||
|
|
9cc667851c | ||
|
|
90e60b0486 | ||
|
|
58f93cb602 | ||
|
|
fae50b19f8 | ||
|
|
e890ba0f57 | ||
|
|
744d94cf8d | ||
|
|
31d12206aa | ||
|
|
7764eda05d | ||
|
|
f78669955c | ||
|
|
cadc15a7a1 | ||
|
|
c1f6ce3ae2 | ||
|
|
864549cb4c | ||
|
|
5713d4b1ae | ||
|
|
ac502b7c08 | ||
|
|
8dc690ca01 | ||
|
|
a4f9c92b32 | ||
|
|
8826f6df8f | ||
|
|
af35fdb48e | ||
|
|
9fd8ffd666 | ||
|
|
521abd82d6 | ||
|
|
021f2fe5b4 | ||
|
|
b3e0ff6769 | ||
|
|
97abca2520 | ||
|
|
96a6c98c10 | ||
|
|
9d285573d7 | ||
|
|
d506d291c3 | ||
|
|
223e8fb8c2 | ||
|
|
2abf57d16b | ||
|
|
b3ee57d042 | ||
|
|
8c65edd257 | ||
|
|
9f521fe199 | ||
|
|
8ac1e2b81e | ||
|
|
5db58d477b | ||
|
|
db03cd3b1f | ||
|
|
e5e89bd8a0 | ||
|
|
2dd6f063c5 | ||
|
|
bb81e7fb9b | ||
|
|
b3d00c89a6 | ||
|
|
8c9587ad65 | ||
|
|
21825582e5 | ||
|
|
f8e6bdf229 | ||
|
|
8c576d2b07 | ||
|
|
c377cf431e | ||
|
|
ce1b3b0856 | ||
|
|
cd6cecfe4a | ||
|
|
a66d75c3c3 | ||
|
|
3d9056e968 | ||
|
|
bb42841a66 | ||
|
|
961bb6c5f4 | ||
|
|
f56bc6d9e4 | ||
|
|
8a667ad71f | ||
|
|
72cff2a470 |
19
.github/workflows/linux.yml
vendored
19
.github/workflows/linux.yml
vendored
@@ -81,6 +81,12 @@ jobs:
|
||||
target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: configure GPG key
|
||||
if: (github.ref == 'refs/heads/master' || github.event_name == 'push') && github.repository == 'mCaptcha/mCaptcha'
|
||||
run: echo -n "$RELEASE_BOT_GPG_SIGNING_KEY" | gpg --batch --import --pinentry-mode loopback
|
||||
env:
|
||||
RELEASE_BOT_GPG_SIGNING_KEY: ${{ secrets.RELEASE_BOT_GPG_SIGNING_KEY }}
|
||||
|
||||
- name: load env
|
||||
run: |
|
||||
source .env_sample \
|
||||
@@ -98,6 +104,9 @@ jobs:
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
- name: install nightwatch dep
|
||||
run: sudo apt-get install xvfb
|
||||
|
||||
- name: Run migrations
|
||||
run: make migrate
|
||||
env:
|
||||
@@ -122,6 +131,9 @@ jobs:
|
||||
POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
|
||||
MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
|
||||
|
||||
- name: run integration tests
|
||||
run: make test.integration
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: (github.ref == 'refs/heads/master' || github.event_name == 'push') && github.repository == 'mCaptcha/mCaptcha'
|
||||
uses: docker/login-action@v1
|
||||
@@ -133,6 +145,13 @@ 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: generate documentation
|
||||
if: matrix.version == 'stable' && (github.repository == 'mCaptcha/mCaptcha')
|
||||
run: make doc
|
||||
|
||||
32
.github/workflows/tagged-release.yml
vendored
Normal file
32
.github/workflows/tagged-release.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Create binary for release
|
||||
|
||||
# Only on tags that start with a "v"
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-pc-windows-gnu
|
||||
archive: zip
|
||||
- target: x86_64-unknown-linux-musl
|
||||
archive: tar.gz tar.xz
|
||||
- target: x86_64-apple-darwin
|
||||
archive: zip
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Compile and release
|
||||
uses: rust-build/rust-build.action@v1.3.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
RUSTTARGET: ${{ matrix.target }}
|
||||
ARCHIVE_TYPES: ${{ matrix.archive }}
|
||||
419
Cargo.lock
generated
419
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -59,6 +59,7 @@ log = "0.4"
|
||||
lazy_static = "1.4"
|
||||
|
||||
|
||||
#libmcaptcha = { version = "0.2.2", git = "https://github.com/mCaptcha/libmcaptcha", features = ["full"], tag ="0.2.2" }
|
||||
libmcaptcha = { branch = "master", git = "https://github.com/mCaptcha/libmcaptcha", features = ["full"] }
|
||||
#libmcaptcha = { path = "../libmcaptcha", features = ["full"]}
|
||||
|
||||
@@ -68,6 +69,8 @@ sailfish = "0.4.0"
|
||||
|
||||
mime = "0.3.16"
|
||||
|
||||
num_cpus = "1.13.1"
|
||||
|
||||
lettre = { version = "0.10.0-rc.3", features = [
|
||||
"builder",
|
||||
"tokio1",
|
||||
@@ -75,7 +78,7 @@ lettre = { version = "0.10.0-rc.3", features = [
|
||||
"smtp-transport"
|
||||
]}
|
||||
|
||||
openssl = { version = "0.10.29", features = ["vendored"] }
|
||||
openssl = { version = "0.10.48", features = ["vendored"] }
|
||||
|
||||
|
||||
[dependencies.db-core]
|
||||
@@ -101,7 +104,7 @@ serde_json = "1"
|
||||
sqlx = { version = "0.5.13", features = [ "runtime-actix-rustls", "postgres", "time", "offline", "mysql" ] }
|
||||
|
||||
[dev-dependencies]
|
||||
pow_sha256 = { version = "0.2.1", git = "https://github.com/mcaptcha/pow_sha256" }
|
||||
pow_sha256 = { version = "0.3.1", git = "https://github.com/mcaptcha/pow_sha256", tag="0.3.1" }
|
||||
awc = "3.0.0"
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ COPY --from=cacher /src/target target
|
||||
#COPY --from=cacher /src/db/db-migrations/target /src/db/db-migrations/target
|
||||
#COPY --from=cacher /src/utils/cache-bust/target /src/utils/cache-bust/target
|
||||
COPY --from=frontend /src/static/cache/bundle/ /src/static/cache/bundle/
|
||||
COPY --from=frontend /src/docs/openapi/dist/ /src/docs/openapi/dist/
|
||||
RUN cargo --version
|
||||
RUN make cache-bust
|
||||
RUN cargo build --release
|
||||
|
||||
3
Makefile
3
Makefile
@@ -123,6 +123,9 @@ test: frontend-test frontend ## Run all available tests
|
||||
cargo test --no-fail-fast
|
||||
# ./scripts/tests.sh
|
||||
|
||||
test.integration: ## run integration tests with nightwatch.js
|
||||
./scripts/integration.sh
|
||||
|
||||
xml-test-coverage: migrate ## Generate code coverage report in XML format
|
||||
$(call cache_bust)
|
||||
cargo tarpaulin -t 1200 --out Xml
|
||||
|
||||
19
README.md
19
README.md
@@ -112,7 +112,6 @@ After the containers are up, visit [http://localhost:7000](http://localhost:7000
|
||||
- username: aaronsw
|
||||
- password: password
|
||||
|
||||
|
||||
It takes a while to build the image so please be patient :)
|
||||
|
||||
See [DEPLOYMENT.md](./docs/DEPLOYMENT.md) detailed alternate deployment
|
||||
@@ -129,3 +128,21 @@ See [DEPLOYMENT.md](./docs/DEPLOYMENT.md)
|
||||
## Configuration:
|
||||
|
||||
See [CONFIGURATION.md](./docs/CONFIGURATION.md)
|
||||
|
||||
## Funding
|
||||
|
||||
### NLnet
|
||||
|
||||
<div align="center">
|
||||
<img
|
||||
height="150px"
|
||||
alt="NLnet NGIZero logo"
|
||||
src="./docs/third-party/NGIZero-green.hex.svg"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
2023 development is funded through the [NGI0 Entrust
|
||||
Fund](https://nlnet.nl/entrust), via [NLnet](https://nlnet.nl/). Please
|
||||
see [here](https://nlnet.nl/project/mCaptcha/) for more details.
|
||||
|
||||
@@ -11,7 +11,7 @@ cookie_secret = "Zae0OOxf^bOJ#zN^&k7VozgW&QAx%n02TQFXpRMG4cCU0xMzgu3dna@tQ9dvc&T
|
||||
# The port at which you want authentication to listen to
|
||||
# takes a number, choose from 1000-10000 if you dont know what you are doing
|
||||
port = 7000
|
||||
#IP address. Enter 0.0.0.0 to listen on all availale addresses
|
||||
#IP address. Enter 0.0.0.0 to listen on all available addresses
|
||||
ip= "0.0.0.0"
|
||||
# enter your hostname, eg: example.com
|
||||
domain = "localhost"
|
||||
@@ -28,6 +28,8 @@ salt = "asdl;kjfhjawehfpa;osdkjasdvjaksndfpoanjdfainsdfaijdsfajlkjdsaf;ajsdfwero
|
||||
# garbage collection period to manage mCaptcha system
|
||||
# leave untouched if you don't know what you are doing
|
||||
gc = 30
|
||||
runners = 4
|
||||
queue_length = 2000
|
||||
enable_stats = true
|
||||
|
||||
[captcha.default_difficulty_strategy]
|
||||
|
||||
@@ -13,7 +13,8 @@ async-trait = "0.1.51"
|
||||
thiserror = "1.0.30"
|
||||
serde = { version = "1", features = ["derive"]}
|
||||
url = { version = "2.2.2", features = ["serde"] }
|
||||
libmcaptcha = { branch = "master", git = "https://github.com/mCaptcha/libmcaptcha", features = ["minimal"], default-features = false }
|
||||
#libmcaptcha = { version = "0.2.2", git = "https://github.com/mCaptcha/libmcaptcha", features = ["minimal"], default-features = false, tag = "0.2.2"}
|
||||
libmcaptcha = { branch = "master", git = "https://github.com/mCaptcha/libmcaptcha", features = ["full"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
//!
|
||||
//! ## Organisation
|
||||
//!
|
||||
//! Database functionallity is divided accross various modules:
|
||||
//! Database functionality is divided across various modules:
|
||||
//!
|
||||
//! - [errors](crate::auth): error data structures used in this crate
|
||||
//! - [ops](crate::ops): meta operations like connection pool creation, migrations and getting
|
||||
@@ -242,13 +242,13 @@ pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase {
|
||||
/// record PoWConfig confirms
|
||||
async fn record_confirm(&self, key: &str) -> DBResult<()>;
|
||||
|
||||
/// featch PoWConfig fetches
|
||||
/// fetch PoWConfig fetches
|
||||
async fn fetch_config_fetched(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
|
||||
|
||||
/// featch PoWConfig solves
|
||||
/// fetch PoWConfig solves
|
||||
async fn fetch_solve(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
|
||||
|
||||
/// featch PoWConfig confirms
|
||||
/// fetch PoWConfig confirms
|
||||
async fn fetch_confirm(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ pub struct AddNotification<'a> {
|
||||
pub from: &'a str,
|
||||
/// heading of the notification
|
||||
pub heading: &'a str,
|
||||
/// mesage of the notification
|
||||
/// message of the notification
|
||||
pub message: &'a str,
|
||||
}
|
||||
|
||||
@@ -298,12 +298,12 @@ pub struct TrafficPattern {
|
||||
pub avg_traffic: u32,
|
||||
/// the peak traffic that the user's website can handle
|
||||
pub peak_sustainable_traffic: u32,
|
||||
/// trafic that bought the user's website down; optional
|
||||
/// traffic that bought the user's website down; optional
|
||||
pub broke_my_site_traffic: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
|
||||
/// data requried to create new captcha
|
||||
/// data required to create new captcha
|
||||
pub struct CreateCaptcha<'a> {
|
||||
/// cool down duration
|
||||
pub duration: i32,
|
||||
|
||||
@@ -30,7 +30,7 @@ pub trait GetConnection {
|
||||
async fn get_conn(&self) -> DBResult<Self::Conn>;
|
||||
}
|
||||
|
||||
/// Create databse connection
|
||||
/// Create database connection
|
||||
#[async_trait]
|
||||
pub trait Connect {
|
||||
/// database specific pool-type
|
||||
|
||||
@@ -33,7 +33,7 @@ pub async fn database_works<'a, T: MCDatabase>(
|
||||
db.delete_user(p.username).await.unwrap();
|
||||
assert!(
|
||||
!db.username_exists(p.username).await.unwrap(),
|
||||
"user is deleted so username shouldn't exsit"
|
||||
"user is deleted so username shouldn't exist"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -89,11 +89,11 @@ pub async fn database_works<'a, T: MCDatabase>(
|
||||
// testing email exists
|
||||
assert!(
|
||||
db.email_exists(p.email.as_ref().unwrap()).await.unwrap(),
|
||||
"user is registered so email should exsit"
|
||||
"user is registered so email should exist"
|
||||
);
|
||||
assert!(
|
||||
db.username_exists(p.username).await.unwrap(),
|
||||
"user is registered so username should exsit"
|
||||
"user is registered so username should exist"
|
||||
);
|
||||
|
||||
// update password test. setting password = username
|
||||
@@ -124,7 +124,7 @@ pub async fn database_works<'a, T: MCDatabase>(
|
||||
db.delete_user(p.email.as_ref().unwrap()).await.unwrap();
|
||||
assert!(
|
||||
!db.username_exists(p.email.as_ref().unwrap()).await.unwrap(),
|
||||
"user is deleted so username shouldn't exsit"
|
||||
"user is deleted so username shouldn't exist"
|
||||
);
|
||||
|
||||
// register with email = None
|
||||
@@ -133,11 +133,11 @@ pub async fn database_works<'a, T: MCDatabase>(
|
||||
db.register(&p2).await.unwrap();
|
||||
assert!(
|
||||
db.username_exists(p2.username).await.unwrap(),
|
||||
"user is registered so username should exsit"
|
||||
"user is registered so username should exist"
|
||||
);
|
||||
assert!(
|
||||
!db.email_exists(p.email.as_ref().unwrap()).await.unwrap(),
|
||||
"user registration with email is deleted; so email shouldn't exsit"
|
||||
"user registration with email is deleted; so email shouldn't exist"
|
||||
);
|
||||
|
||||
// testing get_email = None
|
||||
@@ -155,7 +155,7 @@ pub async fn database_works<'a, T: MCDatabase>(
|
||||
);
|
||||
assert!(
|
||||
db.email_exists(p.email.as_ref().unwrap()).await.unwrap(),
|
||||
"user was with empty email but email is set; so email should exsit"
|
||||
"user was with empty email but email is set; so email should exist"
|
||||
);
|
||||
|
||||
/*
|
||||
|
||||
@@ -35,7 +35,7 @@ pub struct Database {
|
||||
/// Use an existing database pool
|
||||
pub struct Conn(pub MySqlPool);
|
||||
|
||||
/// Connect to databse
|
||||
/// Connect to database
|
||||
pub enum ConnectionOptions {
|
||||
/// fresh connection
|
||||
Fresh(Fresh),
|
||||
@@ -73,9 +73,6 @@ impl Connect for ConnectionOptions {
|
||||
if fresh.disable_logging {
|
||||
connect_options.disable_statement_logging();
|
||||
}
|
||||
sqlx::mysql::MySqlConnectOptions::from_str(&fresh.url)
|
||||
.unwrap()
|
||||
.disable_statement_logging();
|
||||
fresh
|
||||
.pool_options
|
||||
.connect_with(connect_options)
|
||||
@@ -824,7 +821,7 @@ impl MCDatabase for Database {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// featch PoWConfig fetches
|
||||
/// fetch PoWConfig fetches
|
||||
async fn fetch_config_fetched(&self, user: &str, key: &str) -> DBResult<Vec<i64>> {
|
||||
let records = sqlx::query_as!(
|
||||
Date,
|
||||
@@ -850,7 +847,7 @@ impl MCDatabase for Database {
|
||||
Ok(Date::dates_to_unix(records))
|
||||
}
|
||||
|
||||
/// featch PoWConfig solves
|
||||
/// fetch PoWConfig solves
|
||||
async fn fetch_solve(&self, user: &str, key: &str) -> DBResult<Vec<i64>> {
|
||||
let records = sqlx::query_as!(
|
||||
Date,
|
||||
@@ -874,7 +871,7 @@ impl MCDatabase for Database {
|
||||
Ok(Date::dates_to_unix(records))
|
||||
}
|
||||
|
||||
/// featch PoWConfig confirms
|
||||
/// fetch PoWConfig confirms
|
||||
async fn fetch_confirm(&self, user: &str, key: &str) -> DBResult<Vec<i64>> {
|
||||
let records = sqlx::query_as!(
|
||||
Date,
|
||||
|
||||
@@ -35,7 +35,7 @@ pub struct Database {
|
||||
/// Use an existing database pool
|
||||
pub struct Conn(pub PgPool);
|
||||
|
||||
/// Connect to databse
|
||||
/// Connect to database
|
||||
pub enum ConnectionOptions {
|
||||
/// fresh connection
|
||||
Fresh(Fresh),
|
||||
@@ -73,9 +73,6 @@ impl Connect for ConnectionOptions {
|
||||
if fresh.disable_logging {
|
||||
connect_options.disable_statement_logging();
|
||||
}
|
||||
sqlx::postgres::PgConnectOptions::from_str(&fresh.url)
|
||||
.unwrap()
|
||||
.disable_statement_logging();
|
||||
fresh
|
||||
.pool_options
|
||||
.connect_with(connect_options)
|
||||
@@ -830,7 +827,7 @@ impl MCDatabase for Database {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// featch PoWConfig fetches
|
||||
/// fetch PoWConfig fetches
|
||||
async fn fetch_config_fetched(&self, user: &str, key: &str) -> DBResult<Vec<i64>> {
|
||||
let records = sqlx::query_as!(
|
||||
Date,
|
||||
@@ -856,7 +853,7 @@ impl MCDatabase for Database {
|
||||
Ok(Date::dates_to_unix(records))
|
||||
}
|
||||
|
||||
/// featch PoWConfig solves
|
||||
/// fetch PoWConfig solves
|
||||
async fn fetch_solve(&self, user: &str, key: &str) -> DBResult<Vec<i64>> {
|
||||
let records = sqlx::query_as!(
|
||||
Date,
|
||||
@@ -880,7 +877,7 @@ impl MCDatabase for Database {
|
||||
Ok(Date::dates_to_unix(records))
|
||||
}
|
||||
|
||||
/// featch PoWConfig confirms
|
||||
/// fetch PoWConfig confirms
|
||||
async fn fetch_confirm(&self, user: &str, key: &str) -> DBResult<Vec<i64>> {
|
||||
let records = sqlx::query_as!(
|
||||
Date,
|
||||
|
||||
@@ -7,12 +7,12 @@ services:
|
||||
- 7000:7000
|
||||
environment:
|
||||
DATABASE_URL: postgres://postgres:password@mcaptcha_postgres:5432/postgres # set password at placeholder
|
||||
MCAPTCHA_REDIS_URL: redis://mcaptcha-redis/
|
||||
MCAPTCHA_REDIS_URL: redis://mcaptcha_redis/
|
||||
RUST_LOG: debug
|
||||
PORT: 7000
|
||||
depends_on:
|
||||
- mcaptcha-postgres
|
||||
- mcaptcha-redis
|
||||
- mcaptcha_postgres
|
||||
- mcaptcha_redis
|
||||
|
||||
mcaptcha_postgres:
|
||||
image: postgres:13.2
|
||||
@@ -22,7 +22,7 @@ services:
|
||||
POSTGRES_PASSWORD: password # change password
|
||||
PGDATA: /var/lib/postgresql/data/mcaptcha/
|
||||
|
||||
mcaptcha-redis:
|
||||
mcaptcha_redis:
|
||||
image: mcaptcha/cache:latest
|
||||
|
||||
volumes:
|
||||
|
||||
@@ -107,7 +107,7 @@ I use mariadb also in Docker
|
||||
2. Create create database user:
|
||||
|
||||
```bash
|
||||
docker create
|
||||
docker create \
|
||||
-p 3306:3306 \
|
||||
--name some-mariadb \
|
||||
--env MARIADB_USER=maria \
|
||||
|
||||
@@ -1799,9 +1799,9 @@ minimatch@3.0.4, minimatch@^3.0.4:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||
|
||||
mkdirp@^1.0.4:
|
||||
version "1.0.4"
|
||||
|
||||
103
docs/third-party/NGIZero-green.hex.svg
vendored
Normal file
103
docs/third-party/NGIZero-green.hex.svg
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Ebene_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="165.92125"
|
||||
height="191.45087"
|
||||
viewBox="0 0 165.92125 191.45086"
|
||||
enable-background="new 0 0 198.425 198.425"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="NGIZero-green.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
|
||||
id="metadata4142"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs4140" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1007"
|
||||
id="namedview4138"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.6820179"
|
||||
inkscape:cx="-191.39267"
|
||||
inkscape:cy="54.855534"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Ebene_1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<polygon
|
||||
points="36.911,63.104 36.911,66.116 36.911,132.309 36.911,135.321 39.346,136.825 96.715,169.921 99.273,171.419 101.853,169.921 159.319,136.825 161.938,135.321 161.938,132.309 161.938,66.116 161.938,63.104 159.308,61.6 101.841,28.504 99.234,27.006 96.629,28.504 39.347,61.6 "
|
||||
id="polygon4013"
|
||||
style="fill:#96c00a;fill-opacity:1"
|
||||
transform="matrix(1.3249745,0,0,1.3249745,-48.642464,-35.674938)" />
|
||||
<polygon
|
||||
points="161.712,62.925 161.712,131.589 99.212,167.589 36.712,131.589 36.712,62.925 99.212,26.925 "
|
||||
id="polygon4015"
|
||||
style="fill:#97bf00;fill-opacity:0.91764706"
|
||||
transform="matrix(1.3249745,0,0,1.3249745,-48.642464,-35.674938)" />
|
||||
<polygon
|
||||
stroke-miterlimit="10"
|
||||
points="157.712,65.379 157.712,133.046 99.212,166.88 40.712,133.046 40.712,65.379 99.212,31.546 "
|
||||
id="Outerline"
|
||||
transform="matrix(1.3249745,0,0,1.3249745,-48.642464,-35.674938)"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:2;stroke-miterlimit:10"
|
||||
inkscape:label="#outerline" />
|
||||
|
||||
|
||||
<g
|
||||
id="g4281"
|
||||
transform="matrix(1.3249745,0,0,1.3249745,-47.067006,-23.859001)"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path42"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55783975"
|
||||
d="m 133.45691,60.461638 v 0 c 2.27263,0 4.11462,1.841988 4.11462,4.114628 v 27.330241 c 0,2.27264 -1.84199,4.114628 -4.11462,4.114628 -2.27264,0 -4.11463,-1.841988 -4.11463,-4.114628 V 64.576266 c 0,-2.27264 1.84199,-4.114628 4.11463,-4.114628" /><g
|
||||
transform="matrix(0.55783976,0,0,-0.55783976,120.13631,77.682765)"
|
||||
id="g44"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path46"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 0,0 H -0.506 C -0.57,0 -0.633,-0.008 -0.698,-0.01 -0.762,-0.008 -0.825,0 -0.89,0 h -7.283 c -3.929,0 -7.359,-2.965 -7.613,-6.885 -0.278,-4.296 3.124,-7.867 7.361,-7.867 0.776,0 1.343,-0.754 1.111,-1.494 -0.658,-2.088 -2.341,-3.751 -4.547,-4.333 -2.074,-0.547 -4.276,-0.821 -6.605,-0.821 -4.007,0 -7.574,0.865 -10.7,2.595 -3.127,1.73 -5.57,4.144 -7.331,7.24 -1.761,3.096 -2.641,6.617 -2.641,10.564 0,4.006 0.88,7.558 2.641,10.654 1.761,3.097 4.219,5.493 7.377,7.195 3.156,1.698 6.768,2.549 10.836,2.549 4.681,0 8.865,-1.269 12.55,-3.807 2.341,-1.612 5.524,-1.588 7.757,0.171 3.48,2.741 3.289,8.045 -0.315,10.452 -1.7,1.136 -3.538,2.112 -5.512,2.928 -4.553,1.881 -9.623,2.823 -15.208,2.823 -6.679,0 -12.69,-1.412 -18.03,-4.235 -5.344,-2.822 -9.517,-6.738 -12.522,-11.747 -3.005,-5.008 -4.508,-10.67 -4.508,-16.983 0,-6.315 1.503,-11.975 4.508,-16.984 3.005,-5.009 7.148,-8.924 12.43,-11.747 5.282,-2.824 11.231,-4.235 17.849,-4.235 4.613,0 9.197,0.699 13.751,2.095 0.045,0.014 0.091,0.028 0.136,0.042 7.104,2.202 11.884,8.86 11.884,16.297 v 9.047 C 6.486,-2.904 3.583,0 0,0" /></g><g
|
||||
transform="matrix(0.55783976,0,0,-0.55783976,85.80763,64.525332)"
|
||||
id="g48"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path50"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 0,0 v -49.176 c 0,-4.023 -3.262,-7.285 -7.286,-7.285 h -1.381 c -2.181,0 -4.247,0.977 -5.631,2.662 l -24.229,29.505 c -1.804,2.197 -5.368,0.921 -5.368,-1.922 v -22.96 c 0,-4.023 -3.261,-7.285 -7.285,-7.285 -4.023,0 -7.285,3.262 -7.285,7.285 V 0 c 0,4.024 3.262,7.285 7.285,7.285 h 1.468 c 2.184,0 4.253,-0.979 5.636,-2.669 l 24.135,-29.475 c 1.802,-2.202 5.37,-0.927 5.37,1.918 V 0 c 0,4.024 3.261,7.285 7.285,7.285 C -3.262,7.285 0,4.024 0,0" /></g></g><g
|
||||
aria-label="Z E R O"
|
||||
transform="matrix(0.94681934,0,0,0.94681934,-209.97267,182.03385)"
|
||||
style="font-variant:normal;font-weight:600;font-stretch:normal;font-size:31.76000023px;font-family:'Montserrat SemiBold';-inkscape-font-specification:Montserrat-SemiBold;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:0.7171717;fill-rule:nonzero;stroke:none"
|
||||
id="text56"><path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 243.58117,-73.015206 h 19.46231 v 3.613321 l -12.42176,15.02707 h 12.77844 v 4.512774 h -20.17567 v -3.613321 l 12.42176,-15.02707 h -12.06508 z"
|
||||
id="path2325" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 278.7684,-73.015206 h 16.11262 v 4.512774 h -10.14211 v 4.311172 h 9.5373 v 4.512773 h -9.5373 v 5.303672 h 10.48328 v 4.512774 H 278.7684 Z"
|
||||
id="path2327" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 320.00367,-62.749034 q 1.87645,0 2.68285,-0.697851 0.82192,-0.697852 0.82192,-2.295157 0,-1.581796 -0.82192,-2.26414 -0.8064,-0.682344 -2.68285,-0.682344 h -2.51226 v 5.939492 z m -2.51226,4.125078 v 8.761915 h -5.97051 v -23.153165 h 9.11859 q 4.57481,0 6.69938,1.535274 2.14008,1.535273 2.14008,4.853945 0,2.295156 -1.11657,3.768399 -1.10105,1.473242 -3.33418,2.171093 1.22512,0.279141 2.18661,1.271641 0.97699,0.976992 1.96949,2.9775 l 3.24113,6.575313 h -6.3582 l -2.82242,-5.753399 q -0.85293,-1.736875 -1.73688,-2.372695 -0.86844,-0.635821 -2.32617,-0.635821 z"
|
||||
id="path2329" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 357.57911,-69.107237 q -2.72938,0 -4.23364,2.016016 -1.50425,2.016015 -1.50425,5.675859 0,3.644336 1.50425,5.660352 1.50426,2.016015 4.23364,2.016015 2.74488,0 4.24914,-2.016015 1.50426,-2.016016 1.50426,-5.660352 0,-3.659844 -1.50426,-5.675859 -1.50426,-2.016016 -4.24914,-2.016016 z m 0,-4.32668 q 5.58281,0 8.7464,3.19461 3.1636,3.194609 3.1636,8.823945 0,5.613828 -3.1636,8.808438 -3.16359,3.194609 -8.7464,3.194609 -5.56731,0 -8.74641,-3.194609 -3.16359,-3.19461 -3.16359,-8.808438 0,-5.629336 3.16359,-8.823945 3.1791,-3.19461 8.74641,-3.19461 z"
|
||||
id="path2331" /></g></svg>
|
||||
|
After Width: | Height: | Size: 7.3 KiB |
39
scripts/integration.sh
Executable file
39
scripts/integration.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -Eeuo pipefail
|
||||
trap cleanup SIGINT SIGTERM ERR EXIT
|
||||
|
||||
readonly PROJECT_ROOT=$(realpath $(dirname $(dirname "${BASH_SOURCE[0]}")))
|
||||
|
||||
source $PROJECT_ROOT/scripts/lib.sh
|
||||
|
||||
is_ci(){
|
||||
if [ -z ${CI+x} ];
|
||||
then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
docker-compose down -v --remove-orphans || true
|
||||
docker-compose up -d
|
||||
cd $(mktemp -d)
|
||||
pwd
|
||||
find
|
||||
git clone https://github.com/mCaptcha/integration .
|
||||
|
||||
if is_ci
|
||||
then
|
||||
yarn install
|
||||
xvfb-run --auto-servernum npm run test.chrome
|
||||
xvfb-run --auto-servernum npm run test.firefox
|
||||
else
|
||||
yarn install
|
||||
npx nightwatch ./test/mCaptcha.ts
|
||||
fi
|
||||
|
||||
cd $PROJECT_ROOT
|
||||
docker-compose down -v --remove-orphans || true
|
||||
121
scripts/publish.sh
Executable file
121
scripts/publish.sh
Executable file
@@ -0,0 +1,121 @@
|
||||
#!/bin/bash
|
||||
# Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# publish.sh: grab bin from docker container, pack, sign and upload
|
||||
# $2: binary version
|
||||
# $3: Docker img tag
|
||||
# $4: dumbserve password
|
||||
|
||||
set -xEeuo pipefail
|
||||
|
||||
DUMBSERVE_USERNAME=mcaptcha
|
||||
DUMBSERVE_PASSWORD=$4
|
||||
DUMBSERVE_HOST="https://$DUMBSERVE_USERNAME:$DUMBSERVE_PASSWORD@dl.mcaptcha.org"
|
||||
|
||||
NAME=mcaptcha
|
||||
KEY=0CBABF3084E84E867A76709750BE39D10ECE01FB
|
||||
|
||||
TMP_DIR=$(mktemp -d)
|
||||
FILENAME="$NAME-$2-linux-amd64"
|
||||
TARBALL=$FILENAME.tar.gz
|
||||
TARGET_DIR="$TMP_DIR/$FILENAME/"
|
||||
mkdir -p $TARGET_DIR
|
||||
DOCKER_IMG="mcaptcha/$NAME:$3"
|
||||
|
||||
|
||||
get_bin(){
|
||||
echo "[*] Grabbing binary"
|
||||
container_id=$(docker create $DOCKER_IMG)
|
||||
docker cp $container_id:/usr/local/bin/$NAME $TARGET_DIR/
|
||||
docker rm -v $container_id
|
||||
}
|
||||
|
||||
copy() {
|
||||
echo "[*] Copying dist assets"
|
||||
cp README.md $TARGET_DIR
|
||||
cp LICENSE.md $TARGET_DIR
|
||||
cp CHANGELOG.md $TARGET_DIR
|
||||
cp docker-compose.yml $TARGET_DIR
|
||||
|
||||
mkdir $TARGET_DIR/docs
|
||||
cp docs/DEPLOYMENT.md $TARGET_DIR/docs
|
||||
cp docs/CONFIGURATION.md $TARGET_DIR/docs
|
||||
|
||||
get_bin
|
||||
}
|
||||
|
||||
|
||||
|
||||
pack() {
|
||||
echo "[*] Creating dist tarball"
|
||||
pushd $TMP_DIR
|
||||
tar -cvzf $TARBALL $FILENAME
|
||||
popd
|
||||
}
|
||||
|
||||
checksum() {
|
||||
echo "[*] Generating dist tarball checksum"
|
||||
pushd $TMP_DIR
|
||||
sha256sum $TARBALL > $TARBALL.sha256
|
||||
popd
|
||||
}
|
||||
|
||||
sign() {
|
||||
echo "[*] Signing dist tarball checksum"
|
||||
pushd $TMP_DIR
|
||||
export GPG_TTY=$(tty)
|
||||
gpg --verbose \
|
||||
--pinentry-mode loopback \
|
||||
--batch --yes \
|
||||
--passphrase $GPG_PASSWORD \
|
||||
--local-user $KEY \
|
||||
--output $TARBALL.asc \
|
||||
--sign --detach \
|
||||
--armor $TARBALL
|
||||
popd
|
||||
}
|
||||
|
||||
delete_dir() {
|
||||
curl --location --request DELETE "$DUMBSERVE_HOST/api/v1/files/delete" \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw "{
|
||||
\"path\": \"$1\"
|
||||
}"
|
||||
}
|
||||
|
||||
upload_dist() {
|
||||
upload_dir="mCaptcha/$1"
|
||||
delete_dir $upload_dir
|
||||
|
||||
pushd $TMP_DIR
|
||||
for file in $TARBALL $TARBALL.asc $TARBALL.sha256
|
||||
do
|
||||
curl -v \
|
||||
-F upload=@$file \
|
||||
"$DUMBSERVE_HOST/api/v1/files/upload?path=$upload_dir"
|
||||
done
|
||||
popd
|
||||
}
|
||||
|
||||
publish() {
|
||||
copy
|
||||
pack
|
||||
checksum
|
||||
sign
|
||||
upload_dist $2
|
||||
}
|
||||
|
||||
$1 $@
|
||||
@@ -51,7 +51,7 @@ pub async fn uname_email_exists_works(data: ArcData) {
|
||||
let cookies = get_cookie!(signin_resp);
|
||||
let app = get_app!(data).await;
|
||||
|
||||
// chech if get user secret works
|
||||
// check if get user secret works
|
||||
let resp = test::call_service(
|
||||
&app,
|
||||
test::TestRequest::get()
|
||||
@@ -62,7 +62,7 @@ pub async fn uname_email_exists_works(data: ArcData) {
|
||||
.await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
||||
// chech if get user secret works
|
||||
// check if get user secret works
|
||||
let resp = test::call_service(
|
||||
&app,
|
||||
test::TestRequest::post()
|
||||
@@ -178,7 +178,7 @@ pub async fn email_udpate_password_validation_del_userworks(data: ArcData) {
|
||||
)
|
||||
.await;
|
||||
|
||||
// wrong password while deleteing account
|
||||
// wrong password while deleting account
|
||||
let mut payload = Password {
|
||||
password: NAME.into(),
|
||||
};
|
||||
|
||||
@@ -86,7 +86,7 @@ pub mod runners {
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
/// returns Ok(()) when everything checks out and the user is authenticated. Erros otherwise
|
||||
/// returns Ok(()) when everything checks out and the user is authenticated. Errors otherwise
|
||||
pub async fn login_runner(payload: Login, data: &AppData) -> ServiceResult<String> {
|
||||
use argon2_creds::Config;
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ pub struct TrafficPatternRequest {
|
||||
pub avg_traffic: u32,
|
||||
/// the peak traffic that the user's website can handle
|
||||
pub peak_sustainable_traffic: u32,
|
||||
/// trafic that bought the user's website down; optional
|
||||
/// traffic that bought the user's website down; optional
|
||||
pub broke_my_site_traffic: Option<u32>,
|
||||
/// Captcha description
|
||||
pub description: String,
|
||||
|
||||
@@ -191,7 +191,7 @@ mod tests {
|
||||
let updated_token: MCaptchaDetails =
|
||||
test::read_body_json(update_token_resp).await;
|
||||
|
||||
// get levels with udpated key
|
||||
// get levels with updated key
|
||||
let get_token_resp = test::call_service(
|
||||
&app,
|
||||
post_request!(&updated_token, ROUTES.captcha.get)
|
||||
@@ -199,7 +199,7 @@ mod tests {
|
||||
.to_request(),
|
||||
)
|
||||
.await;
|
||||
// if updated key doesn't exist in databse, a non 200 result will bereturned
|
||||
// if updated key doesn't exist in database, a non 200 result will bereturned
|
||||
assert_eq!(get_token_resp.status(), StatusCode::OK);
|
||||
|
||||
// get stats
|
||||
@@ -211,7 +211,7 @@ mod tests {
|
||||
.to_request(),
|
||||
)
|
||||
.await;
|
||||
// if updated key doesn't exist in databse, a non 200 result will bereturned
|
||||
// if updated key doesn't exist in database, a non 200 result will bereturned
|
||||
assert_eq!(get_statis_resp.status(), StatusCode::OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ pub mod routes {
|
||||
}
|
||||
}
|
||||
|
||||
/// emmits build details of the bninary
|
||||
/// emits build details of the bninary
|
||||
#[my_codegen::get(path = "crate::V1_API_ROUTES.meta.build_details")]
|
||||
async fn build_details() -> impl Responder {
|
||||
let build = BuildDetails {
|
||||
|
||||
@@ -42,7 +42,7 @@ pub async fn add_notification(
|
||||
id: Identity,
|
||||
) -> ServiceResult<impl Responder> {
|
||||
let sender = id.identity().unwrap();
|
||||
// TODO handle error where payload.to doesnt exist
|
||||
// TODO handle error where payload.to doesn't exist
|
||||
|
||||
let p = AddNotification {
|
||||
from: &sender,
|
||||
@@ -98,7 +98,7 @@ pub mod tests {
|
||||
let msg = AddNotificationRequest {
|
||||
to: NAME2.into(),
|
||||
heading: "Test notification".into(),
|
||||
message: "Testeing notifications with a dummy message".into(),
|
||||
message: "Testing notifications with a dummy message".into(),
|
||||
};
|
||||
|
||||
let send_notification_resp = test::call_service(
|
||||
|
||||
@@ -68,7 +68,7 @@ pub async fn get_notification(
|
||||
id: Identity,
|
||||
) -> ServiceResult<impl Responder> {
|
||||
let receiver = id.identity().unwrap();
|
||||
// TODO handle error where payload.to doesnt exist
|
||||
// TODO handle error where payload.to doesn't exist
|
||||
|
||||
let notifications = data.db.get_all_unread_notifications(&receiver).await?;
|
||||
let notifications = NotificationResp::from_notifications(notifications);
|
||||
|
||||
@@ -38,7 +38,7 @@ pub async fn mark_read(
|
||||
id: Identity,
|
||||
) -> ServiceResult<impl Responder> {
|
||||
let receiver = id.identity().unwrap();
|
||||
// TODO handle error where payload.to doesnt exist
|
||||
// TODO handle error where payload.to doesn't exist
|
||||
|
||||
// TODO get payload from path /api/v1/notifications/{id}/read"
|
||||
data.db
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
//! PoW Verification module
|
||||
|
||||
use actix_web::HttpRequest;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use libmcaptcha::pow::Work;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -37,11 +38,21 @@ pub struct ValidationToken {
|
||||
/// if verification is successful
|
||||
#[my_codegen::post(path = "V1_API_ROUTES.pow.verify_pow()")]
|
||||
pub async fn verify_pow(
|
||||
req: HttpRequest,
|
||||
payload: web::Json<Work>,
|
||||
data: AppData,
|
||||
) -> ServiceResult<impl Responder> {
|
||||
#[cfg(not(test))]
|
||||
let ip = req.connection_info().peer_addr().unwrap().to_string();
|
||||
// From actix-web docs:
|
||||
// Will only return None when called in unit tests unless TestRequest::peer_addr is used.
|
||||
//
|
||||
// ref: https://docs.rs/actix-web/latest/actix_web/struct.HttpRequest.html#method.peer_addr
|
||||
#[cfg(test)]
|
||||
let ip = "127.0.1.1".into();
|
||||
|
||||
let key = payload.key.clone();
|
||||
let res = data.captcha.verify_pow(payload.into_inner()).await?;
|
||||
let res = data.captcha.verify_pow(payload.into_inner(), ip).await?;
|
||||
data.stats.record_solve(&data, &key).await?;
|
||||
let payload = ValidationToken { token: res };
|
||||
Ok(HttpResponse::Ok().json(payload))
|
||||
@@ -135,7 +146,7 @@ pub mod tests {
|
||||
// .await;
|
||||
// assert_eq!(pow_config_resp.status(), StatusCode::OK);
|
||||
// I'm not checking for errors because changing work.result triggered
|
||||
// InssuficientDifficulty, which is possible becuase libmcaptcha calculates
|
||||
// InssuficientDifficulty, which is possible because libmcaptcha calculates
|
||||
// difficulty with the submitted result. Besides, this endpoint is merely
|
||||
// propagating errors from libmcaptcha and libmcaptcha has tests covering the
|
||||
// pow aspects ¯\_(ツ)_/¯
|
||||
|
||||
@@ -47,7 +47,7 @@ impl From<VerifyCaptchaResultPayload> for VerifyCaptchaResult {
|
||||
|
||||
// API keys are mcaptcha actor names
|
||||
|
||||
/// route hander that validates a PoW solution token
|
||||
/// route handler that validates a PoW solution token
|
||||
#[my_codegen::post(path = "V1_API_ROUTES.pow.validate_captcha_token()")]
|
||||
pub async fn validate_captcha_token(
|
||||
payload: web::Json<VerifyCaptchaResultPayload>,
|
||||
|
||||
22
src/data.rs
22
src/data.rs
@@ -69,7 +69,7 @@ macro_rules! enum_system_wrapper {
|
||||
|
||||
/// Represents mCaptcha cache and master system.
|
||||
/// When Redis is configured, [SystemGroup::Redis] is used and
|
||||
/// in its absense, [SystemGroup::Embedded] is used
|
||||
/// in its absence, [SystemGroup::Embedded] is used
|
||||
pub enum SystemGroup {
|
||||
Embedded(System<HashCache, EmbeddedMaster>),
|
||||
Redis(System<RedisCache, RedisMaster>),
|
||||
@@ -83,7 +83,12 @@ impl SystemGroup {
|
||||
enum_system_wrapper!(get_pow, String, CaptchaResult<Option<PoWConfig>>);
|
||||
|
||||
// utility function to verify [Work]
|
||||
enum_system_wrapper!(verify_pow, Work, CaptchaResult<String>);
|
||||
pub async fn verify_pow(&self, msg: Work, ip: String) -> CaptchaResult<String> {
|
||||
match self {
|
||||
Self::Embedded(val) => val.verify_pow(msg, ip).await,
|
||||
Self::Redis(val) => val.verify_pow(msg, ip).await,
|
||||
}
|
||||
}
|
||||
|
||||
// utility function to validate verification tokens
|
||||
enum_system_wrapper!(
|
||||
@@ -111,7 +116,18 @@ impl SystemGroup {
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
SystemBuilder::default().pow(pow).cache(c).master(m).build()
|
||||
let runners = if let Some(runners) = s.captcha.runners {
|
||||
runners
|
||||
} else {
|
||||
num_cpus::get_physical()
|
||||
};
|
||||
SystemBuilder::default()
|
||||
.pow(pow)
|
||||
.cache(c)
|
||||
.master(m)
|
||||
.runners(runners)
|
||||
.queue_length(s.captcha.queue_length)
|
||||
.build()
|
||||
}
|
||||
|
||||
// read settings, if Redis is configured then produce a Redis mCaptcha cache
|
||||
|
||||
@@ -111,7 +111,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::tests::*;
|
||||
|
||||
const DURATION: u64 = 5;
|
||||
const DURATION: u64 = 25;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn demo_account_works_pg() {
|
||||
|
||||
@@ -71,7 +71,7 @@ const PAGE: &str = "Notifications";
|
||||
)]
|
||||
pub async fn notifications(data: AppData, id: Identity) -> PageResult<impl Responder> {
|
||||
let receiver = id.identity().unwrap();
|
||||
// TODO handle error where payload.to doesnt exist
|
||||
// TODO handle error where payload.to doesn't exist
|
||||
|
||||
// let mut notifications = runner::get_notification(&data, &receiver).await?;
|
||||
let mut notifications = data.db.get_all_unread_notifications(&receiver).await?;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::{env, fs};
|
||||
|
||||
use config::{Config, ConfigError, Environment, File};
|
||||
use derive_more::Display;
|
||||
@@ -37,6 +37,8 @@ pub struct Server {
|
||||
pub struct Captcha {
|
||||
pub salt: String,
|
||||
pub gc: u64,
|
||||
pub runners: Option<usize>,
|
||||
pub queue_length: usize,
|
||||
pub enable_stats: bool,
|
||||
pub default_difficulty_strategy: DefaultDifficultyStrategy,
|
||||
}
|
||||
@@ -78,7 +80,7 @@ impl Server {
|
||||
//impl DatabaseBuilder {
|
||||
// #[cfg(not(tarpaulin_include))]
|
||||
// fn extract_database_url(url: &Url) -> Self {
|
||||
// debug!("Databse name: {}", url.path());
|
||||
// debug!("Database name: {}", url.path());
|
||||
// let mut path = url.path().split('/');
|
||||
// path.next();
|
||||
// let name = path.next().expect("no database name").to_string();
|
||||
@@ -150,25 +152,34 @@ impl Settings {
|
||||
.expect("unable to set capatcha.enable_stats default config");
|
||||
|
||||
if let Ok(path) = env::var("MCAPTCHA_CONFIG") {
|
||||
s.merge(File::with_name(&path))?;
|
||||
let absolute_path = Path::new(&path).canonicalize().unwrap();
|
||||
log::info!(
|
||||
"Loading config file from {}",
|
||||
absolute_path.to_str().unwrap()
|
||||
);
|
||||
s.merge(File::with_name(absolute_path.to_str().unwrap()))?;
|
||||
} else if Path::new(CURRENT_DIR).exists() {
|
||||
let absolute_path = fs::canonicalize(CURRENT_DIR).unwrap();
|
||||
log::info!(
|
||||
"Loading config file from {}",
|
||||
absolute_path.to_str().unwrap()
|
||||
);
|
||||
// merging default config from file
|
||||
s.merge(File::with_name(CURRENT_DIR))?;
|
||||
s.merge(File::with_name(absolute_path.to_str().unwrap()))?;
|
||||
} else if Path::new(ETC).exists() {
|
||||
log::info!("{}", format!("Loading config file from {}", ETC));
|
||||
s.merge(File::with_name(ETC))?;
|
||||
} else {
|
||||
log::warn!("configuration file not found");
|
||||
log::warn!("Configuration file not found");
|
||||
}
|
||||
|
||||
s.merge(Environment::with_prefix("MCAPTCHA").separator("_"))?;
|
||||
|
||||
check_url(&s);
|
||||
|
||||
match env::var("PORT") {
|
||||
Ok(val) => {
|
||||
if let Ok(val) = env::var("PORT") {
|
||||
s.set("server.port", val).unwrap();
|
||||
}
|
||||
Err(e) => warn!("couldn't interpret PORT: {}", e),
|
||||
log::info!("Overriding [server].port with environment variable");
|
||||
}
|
||||
|
||||
match env::var("DATABASE_URL") {
|
||||
@@ -178,6 +189,7 @@ impl Settings {
|
||||
let database_type = DBType::from_url(&url).unwrap();
|
||||
s.set("database.database_type", database_type.to_string())
|
||||
.unwrap();
|
||||
log::info!("Overriding [database].url and [database].database_type with environment variable");
|
||||
}
|
||||
Err(e) => {
|
||||
set_database_url(&mut s);
|
||||
@@ -213,8 +225,11 @@ fn set_database_url(s: &mut Config) {
|
||||
r"postgres://{}:{}@{}:{}/{}",
|
||||
s.get::<String>("database.username")
|
||||
.expect("Couldn't access database username"),
|
||||
urlencoding::encode(
|
||||
s.get::<String>("database.password")
|
||||
.expect("Couldn't access database password"),
|
||||
.expect("Couldn't access database password")
|
||||
.as_str()
|
||||
),
|
||||
s.get::<String>("database.hostname")
|
||||
.expect("Couldn't access database hostname"),
|
||||
s.get::<String>("database.port")
|
||||
@@ -223,7 +238,7 @@ fn set_database_url(s: &mut Config) {
|
||||
.expect("Couldn't access database name")
|
||||
),
|
||||
)
|
||||
.expect("Couldn't set databse url");
|
||||
.expect("Couldn't set database url");
|
||||
}
|
||||
|
||||
//#[cfg(test)]
|
||||
|
||||
@@ -49,6 +49,7 @@ pub mod pg {
|
||||
pub async fn get_data() -> ArcData {
|
||||
let url = env::var("POSTGRES_DATABASE_URL").unwrap();
|
||||
let mut settings = get_settings();
|
||||
settings.captcha.runners = Some(1);
|
||||
settings.database.url = url.clone();
|
||||
settings.database.database_type = DBType::Postgres;
|
||||
let data = Data::new(&settings).await;
|
||||
@@ -67,6 +68,7 @@ pub mod maria {
|
||||
pub async fn get_data() -> ArcData {
|
||||
let url = env::var("MARIA_DATABASE_URL").unwrap();
|
||||
let mut settings = get_settings();
|
||||
settings.captcha.runners = Some(1);
|
||||
settings.database.url = url.clone();
|
||||
settings.database.database_type = DBType::Maria;
|
||||
let data = Data::new(&settings).await;
|
||||
|
||||
@@ -8,6 +8,16 @@
|
||||
class="auth__logo" alt="mcaptcha logo" />
|
||||
|
||||
|
||||
<. if !crate::SETTINGS.allow_registration { .>
|
||||
<table class="reg-closed__table">
|
||||
<thead class="reg-closed__table-heading">
|
||||
<tr><th colspan="4" class="reg-closed__table-title-text">Registration closed</th></tr>
|
||||
</thead>
|
||||
<tbody class="reg-closed__body">
|
||||
<tr><td class="reg-closed__body-text">This mCaptcha instance is closed for registrations.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<. } else {.>
|
||||
<form
|
||||
method="POST"
|
||||
action="<.= crate::V1_API_ROUTES.auth.register .>"
|
||||
@@ -73,5 +83,6 @@
|
||||
<a href="<.= crate::PAGES.auth.login .>" class="auth__secondary-action__link">Log in</a>
|
||||
</p>
|
||||
<. include!("../demo-user-banner.html"); .>
|
||||
<. } .>
|
||||
</div>
|
||||
<. include!("../../components/footers.html"); .>
|
||||
|
||||
32
templates/auth/register/main.scss
Normal file
32
templates/auth/register/main.scss
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Gusted <postmaster@gusted.xyz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@import '../../components/table/main';
|
||||
|
||||
.reg-closed__table {
|
||||
@include table;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.reg-closed__table-title-text {
|
||||
@include table__title-text;
|
||||
}
|
||||
|
||||
.reg-closed__body-text {
|
||||
display: block;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
@@ -19,11 +19,12 @@
|
||||
<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 wen't wrong</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"
|
||||
@@ -34,10 +35,12 @@
|
||||
</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>
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
@import '../reset';
|
||||
|
||||
.widget__contaienr {
|
||||
max-width: 300px;
|
||||
max-height: 74px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.widget__noscript-container {
|
||||
@@ -49,13 +49,10 @@
|
||||
}
|
||||
|
||||
.widget__verification-container {
|
||||
display: none;
|
||||
/*display: flex; */
|
||||
align-items: center;
|
||||
display: none;
|
||||
line-height: 30px;
|
||||
flex: 2;
|
||||
margin: auto;
|
||||
font-size: 0.99rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.widget__verification-checkbox {
|
||||
@@ -95,15 +92,10 @@
|
||||
}
|
||||
|
||||
.widget__mcaptcha-details {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.widget__mcaptcha-logo-container {
|
||||
flex: 2;
|
||||
padding-top: 3px;
|
||||
margin-left: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.widget__mcaptcha-brand-name {
|
||||
|
||||
69
yarn.lock
69
yarn.lock
@@ -533,6 +533,46 @@
|
||||
"@types/yargs" "^16.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.0":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
|
||||
integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
|
||||
dependencies:
|
||||
"@jridgewell/set-array" "^1.0.1"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@jridgewell/resolve-uri@^3.0.3":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
|
||||
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
|
||||
|
||||
"@jridgewell/set-array@^1.0.1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
||||
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||
|
||||
"@jridgewell/source-map@^0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb"
|
||||
integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==
|
||||
dependencies:
|
||||
"@jridgewell/gen-mapping" "^0.3.0"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.10":
|
||||
version "1.4.14"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
||||
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.9":
|
||||
version "0.3.14"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
|
||||
integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@mcaptcha/core-glue@^0.1.0-alpha-3":
|
||||
version "0.1.0-alpha-3"
|
||||
resolved "https://registry.yarnpkg.com/@mcaptcha/core-glue/-/core-glue-0.1.0-alpha-3.tgz#16c11cb3751b6421999353dc10c032afd08ffa8b"
|
||||
@@ -1079,9 +1119,9 @@ acorn@^7.1.1:
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
|
||||
acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0:
|
||||
version "8.5.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2"
|
||||
integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==
|
||||
version "8.7.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
|
||||
integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
|
||||
|
||||
agent-base@6:
|
||||
version "6.0.2"
|
||||
@@ -3830,9 +3870,9 @@ nanocolors@^0.1.12:
|
||||
integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ==
|
||||
|
||||
nanoid@^3.1.28:
|
||||
version "3.1.29"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.29.tgz#214fb2d7a33e1a5bef4757b779dfaeb6a4e5aeb4"
|
||||
integrity sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg==
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
|
||||
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
@@ -4809,9 +4849,9 @@ source-map-js@^0.6.2:
|
||||
integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
|
||||
|
||||
source-map-support@^0.5.6, source-map-support@~0.5.20:
|
||||
version "0.5.20"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
|
||||
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
|
||||
version "0.5.21"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
|
||||
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
@@ -4826,7 +4866,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
source-map@^0.7.3, source-map@~0.7.2:
|
||||
source-map@^0.7.3:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
@@ -5017,12 +5057,13 @@ terser-webpack-plugin@^5.1.3:
|
||||
terser "^5.7.2"
|
||||
|
||||
terser@^5.7.2:
|
||||
version "5.9.0"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.9.0.tgz#47d6e629a522963240f2b55fcaa3c99083d2c351"
|
||||
integrity sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==
|
||||
version "5.14.2"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10"
|
||||
integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==
|
||||
dependencies:
|
||||
"@jridgewell/source-map" "^0.3.2"
|
||||
acorn "^8.5.0"
|
||||
commander "^2.20.0"
|
||||
source-map "~0.7.2"
|
||||
source-map-support "~0.5.20"
|
||||
|
||||
test-exclude@^6.0.0:
|
||||
|
||||
Reference in New Issue
Block a user