mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2026-02-11 10:05:41 +00:00
Compare commits
13 Commits
fix-upload
...
v0.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f67fdf917e | ||
|
|
e1746223c8 | ||
|
|
ae08c09702 | ||
|
|
1c9e242d7e | ||
|
|
3cb0ca38ec | ||
|
|
3cd38511fa | ||
|
|
d765bd7491 | ||
|
|
8e33e75659 | ||
|
|
c00857dd28 | ||
|
|
9cf0eb596a | ||
|
|
d010a1cbd4 | ||
|
|
d4967626ee | ||
|
|
2ee0a0ae5f |
43
.env.docker-compose
Normal file
43
.env.docker-compose
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
MCAPTCHA_debug=false
|
||||||
|
MCAPTCHA_commercial=false
|
||||||
|
MCAPTCHA_source_code=https://github.com/mCaptcha/mCaptcha
|
||||||
|
MCAPTCHA_allow_registration=false
|
||||||
|
MCAPTCHA_allow_demo=false
|
||||||
|
|
||||||
|
# database
|
||||||
|
DATABASE_URL=postgres://postgres:password@mcaptcha_postgres:5432/postgres
|
||||||
|
MCAPTCHA_database_POOL=4
|
||||||
|
|
||||||
|
# redis
|
||||||
|
MCAPTCHA_redis_URL=redis://mcaptcha_redis
|
||||||
|
MCAPTCHA_redis_POOL=4
|
||||||
|
|
||||||
|
# server
|
||||||
|
PORT=7001
|
||||||
|
MCAPTCHA_server_DOMAIN=localhost
|
||||||
|
MCAPTCHA__server_COOKIE_SECRET=pleasereplacethiswithrandomstring # PLEASE SET RANDOM STRING. MIN LENGTH=32
|
||||||
|
MCAPTCHA__server_IP= 0.0.0.0
|
||||||
|
|
||||||
|
|
||||||
|
# captcha
|
||||||
|
MCAPTCHA_captcha_SALT=pleasereplacethiswithrandomstring # PLEASE SET RANDOM STRING. MIN LENGTH=32
|
||||||
|
MCAPTCHA_captcha_GC=30
|
||||||
|
MCAPTCHA_captcha_RUNNERS=4
|
||||||
|
MCAPTCHA_captcha_QUEUE_LENGTH=2000
|
||||||
|
MCAPTCHA_captcha_ENABLE_STATS=true
|
||||||
|
MCAPTCHA_captcha_DEFAULT_DIFFICULTY_STRATEGY_avg_traffic_difficulty=50000 # almost instant solution
|
||||||
|
MCAPTCHA_captcha_DEFAULT_DIFFICULTY_STRATEGY_broke_my_site_traffic_difficulty=3000000 # roughly 1.5s
|
||||||
|
MCAPTCHA_captcha_DEFAULT_DIFFICULTY_STRATEGY_peak_sustainable_traffic_difficulty=5000000 # greater than 3.5s
|
||||||
|
MCAPTCHA_captcha_DEFAULT_DIFFICULTY_STRATEGY_duration=30 # cooldown period in seconds
|
||||||
|
MCAPTCHA_captcha_DEFAULT_DIFFICULTY_STRATEGY_avg_traffic_time=1 # almost instant solution
|
||||||
|
MCAPTCHA_captcha_DEFAULT_DIFFICULTY_STRATEGY_peak_sustainable_traffic_time=3
|
||||||
|
MCAPTCHA_captcha_DEFAULT_DIFFICULTY_STRATEGY_broke_my_site_traffic_time=5
|
||||||
|
|
||||||
|
|
||||||
|
# SMTP
|
||||||
|
#MCAPTCHA_smtp_FROM=
|
||||||
|
#MCAPTCHA_smtp_REPLY=
|
||||||
|
#MCAPTCHA_smtp_URL=
|
||||||
|
#MCAPTCHA_smtp_USERNAME=
|
||||||
|
#MCAPTCHA_smtp_PASSWORD=
|
||||||
|
#MCAPTCHA_smtp_PORT=
|
||||||
125
.github/workflows/release.yml
vendored
Normal file
125
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
name: Publish release
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
type: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_and_test:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
name: x86_64-unknown-linux-gnu
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres
|
||||||
|
env:
|
||||||
|
POSTGRES_PASSWORD: password
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_DB: postgres
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
|
||||||
|
mcaptcha-redis:
|
||||||
|
image: mcaptcha/cache
|
||||||
|
ports:
|
||||||
|
- 6379:6379
|
||||||
|
mcaptcha-smtp:
|
||||||
|
image: maildev/maildev
|
||||||
|
env:
|
||||||
|
MAILDEV_WEB_PORT: "1080"
|
||||||
|
MAILDEV_INCOMING_USER: "admin"
|
||||||
|
MAILDEV_INCOMING_PASS: "password"
|
||||||
|
ports:
|
||||||
|
- 1080:1080
|
||||||
|
- 10025:1025
|
||||||
|
|
||||||
|
maria:
|
||||||
|
image: mariadb:10
|
||||||
|
env:
|
||||||
|
MARIADB_USER: "maria"
|
||||||
|
MARIADB_PASSWORD: "password"
|
||||||
|
MARIADB_ROOT_PASSWORD: "password"
|
||||||
|
MARIADB_DATABASE: "maria"
|
||||||
|
options: >-
|
||||||
|
--health-cmd="mysqladmin ping"
|
||||||
|
--health-interval=10s
|
||||||
|
--health-timeout=5s
|
||||||
|
--health-retries=10
|
||||||
|
ports:
|
||||||
|
- 3306:3306
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: configure GPG key
|
||||||
|
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: Set release version
|
||||||
|
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: load env
|
||||||
|
run: |
|
||||||
|
source .env_sample \
|
||||||
|
&& echo "POSTGRES_DATABASE_URL=$POSTGRES_DATABASE_URL" >> $GITHUB_ENV \
|
||||||
|
&& echo "MARIA_DATABASE_URL=$MARIA_DATABASE_URL" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: "20.0.0"
|
||||||
|
|
||||||
|
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
|
|
||||||
|
- name: install nightwatch dep
|
||||||
|
run: sudo apt-get install xvfb
|
||||||
|
|
||||||
|
- name: Run migrations
|
||||||
|
run: make migrate
|
||||||
|
env:
|
||||||
|
POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
|
||||||
|
MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
|
||||||
|
|
||||||
|
- name: build
|
||||||
|
run: make
|
||||||
|
env:
|
||||||
|
POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
|
||||||
|
MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
|
||||||
|
|
||||||
|
- name: lint frontend
|
||||||
|
run: yarn lint
|
||||||
|
|
||||||
|
- name: run tests
|
||||||
|
run: make test
|
||||||
|
env:
|
||||||
|
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
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: mcaptcha
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: build docker images
|
||||||
|
run: docker build -t mcaptcha/mcaptcha:${RELEASE_VERSION} .
|
||||||
|
|
||||||
|
- name: publish docker images
|
||||||
|
run: docker push mcaptcha/mcaptcha:${RELEASE_VERSION}
|
||||||
|
|
||||||
|
- name: publish bins
|
||||||
|
run: ./scripts/publish.sh publish $RELEASE_VERSION latest $DUMBSERVE_PASSWORD
|
||||||
|
env:
|
||||||
|
DUMBSERVE_PASSWORD: ${{ secrets.DUMBSERVE_PASSWORD }}
|
||||||
|
GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }}
|
||||||
64
.github/workflows/tagged-release.yml
vendored
64
.github/workflows/tagged-release.yml
vendored
@@ -1,32 +1,32 @@
|
|||||||
name: Create binary for release
|
#name: Create binary for release
|
||||||
|
#
|
||||||
# Only on tags that start with a "v"
|
## Only on tags that start with a "v"
|
||||||
on:
|
#on:
|
||||||
push:
|
# push:
|
||||||
tags:
|
# tags:
|
||||||
- "v*"
|
# - "v*"
|
||||||
|
#
|
||||||
jobs:
|
#jobs:
|
||||||
build:
|
# build:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
strategy:
|
# strategy:
|
||||||
fail-fast: false
|
# fail-fast: false
|
||||||
matrix:
|
# matrix:
|
||||||
include:
|
# include:
|
||||||
- target: x86_64-pc-windows-gnu
|
# - target: x86_64-pc-windows-gnu
|
||||||
archive: zip
|
# archive: zip
|
||||||
- target: x86_64-unknown-linux-musl
|
# - target: x86_64-unknown-linux-musl
|
||||||
archive: tar.gz tar.xz
|
# archive: tar.gz tar.xz
|
||||||
- target: x86_64-apple-darwin
|
# - target: x86_64-apple-darwin
|
||||||
archive: zip
|
# archive: zip
|
||||||
steps:
|
# steps:
|
||||||
- name: Checkout
|
# - name: Checkout
|
||||||
uses: actions/checkout@v3
|
# uses: actions/checkout@v3
|
||||||
|
#
|
||||||
- name: Compile and release
|
# - name: Compile and release
|
||||||
uses: rust-build/rust-build.action@v1.3.2
|
# uses: rust-build/rust-build.action@v1.3.2
|
||||||
env:
|
# env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
# with:
|
||||||
RUSTTARGET: ${{ matrix.target }}
|
# RUSTTARGET: ${{ matrix.target }}
|
||||||
ARCHIVE_TYPES: ${{ matrix.archive }}
|
# ARCHIVE_TYPES: ${{ matrix.archive }}
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ services:
|
|||||||
image: mcaptcha/mcaptcha:latest
|
image: mcaptcha/mcaptcha:latest
|
||||||
ports:
|
ports:
|
||||||
- 7000:7000
|
- 7000:7000
|
||||||
environment:
|
env_file:
|
||||||
DATABASE_URL: postgres://postgres:password@mcaptcha_postgres:5432/postgres # set password at placeholder
|
- .env.docker-compose
|
||||||
MCAPTCHA_redis_URL: "redis://mcaptcha_redis/"
|
|
||||||
RUST_LOG: "debug"
|
|
||||||
PORT: 7000
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- mcaptcha_postgres
|
- mcaptcha_postgres
|
||||||
- mcaptcha_redis
|
- mcaptcha_redis
|
||||||
|
|||||||
@@ -56,53 +56,41 @@ type messageTextReturn = {
|
|||||||
error: () => void;
|
error: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const messageText = (): messageTextReturn => {
|
export const BEFORE = "I'm not a robot";
|
||||||
const beforeID = "widget__verification-text--before";
|
export const DURING = "Processing...";
|
||||||
const duringID = "widget__verification-text--during";
|
export const AFTER = "Verified!";
|
||||||
const errorID = "widget__verification-text--error";
|
export const ERROR = "Something went wrong";
|
||||||
const afterID = "widget__verification-text--after";
|
|
||||||
|
|
||||||
const before = new LazyElement(beforeID);
|
export const messageText = (): messageTextReturn => {
|
||||||
const after = new LazyElement(afterID);
|
const conatinerID = "widget__verification-text";
|
||||||
const during = new LazyElement(duringID);
|
|
||||||
const error = new LazyElement(errorID);
|
const container = new LazyElement(conatinerID);
|
||||||
|
|
||||||
/** runner fn to display HTMLElement **/
|
/** runner fn to display HTMLElement **/
|
||||||
const showMsg = (e: HTMLElement) => (e.style.display = "block");
|
const showMsg = (value: string) => {
|
||||||
/** runner fn to hide HTMLElement **/
|
container.get().innerText = value;
|
||||||
const hideMsg = (e: HTMLElement) => (e.style.display = "none");
|
btn().ariaValueText = value;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
/** display "before" message **/
|
/** display "before" message **/
|
||||||
before: () => {
|
before: () => {
|
||||||
showMsg(before.get());
|
showMsg(BEFORE);
|
||||||
hideMsg(after.get());
|
|
||||||
hideMsg(during.get());
|
|
||||||
hideMsg(error.get());
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/** display "after" message **/
|
/** display "after" message **/
|
||||||
after: () => {
|
after: () => {
|
||||||
hideMsg(before.get());
|
showMsg(AFTER);
|
||||||
showMsg(after.get());
|
|
||||||
hideMsg(during.get());
|
|
||||||
hideMsg(error.get());
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/** display "during" message **/
|
/** display "during" message **/
|
||||||
during: () => {
|
during: () => {
|
||||||
hideMsg(before.get());
|
showMsg(DURING);
|
||||||
hideMsg(after.get());
|
|
||||||
showMsg(during.get());
|
|
||||||
hideMsg(error.get());
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/** display "error" message **/
|
/** display "error" message **/
|
||||||
error: () => {
|
error: () => {
|
||||||
hideMsg(before.get());
|
showMsg(ERROR);
|
||||||
hideMsg(after.get());
|
|
||||||
hideMsg(during.get());
|
|
||||||
showMsg(error.get());
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,14 +19,15 @@ SPDX-License-Identifier: MIT OR Apache-2.0
|
|||||||
</div>
|
</div>
|
||||||
</noscript>
|
</noscript>
|
||||||
<label class="widget__verification-container" for="widget__verification-checkbox">
|
<label class="widget__verification-container" for="widget__verification-checkbox">
|
||||||
|
<span id="widget__verification-text"
|
||||||
|
>I'm not a robot</span>
|
||||||
<input
|
<input
|
||||||
id="widget__verification-checkbox"
|
id="widget__verification-checkbox"
|
||||||
|
aria-valuenow="I'm not a robot"
|
||||||
|
aria-checked="false"
|
||||||
|
role="checkbox"
|
||||||
class="widget__verification-checkbox"
|
class="widget__verification-checkbox"
|
||||||
type="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>
|
</label>
|
||||||
<div class="widget__mcaptcha-details">
|
<div class="widget__mcaptcha-details">
|
||||||
<a href="<.= crate::PKG_HOMEPAGE .>"
|
<a href="<.= crate::PKG_HOMEPAGE .>"
|
||||||
@@ -54,6 +55,8 @@ SPDX-License-Identifier: MIT OR Apache-2.0
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="progress__bar"><div class="progress__fill"></div></div>
|
<div class="progress__bar"><div
|
||||||
|
aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"
|
||||||
|
role="progressbar" class="progress__fill"></div></div>
|
||||||
</main>
|
</main>
|
||||||
<.include!("./footer.html"); .>
|
<.include!("./footer.html"); .>
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ export const registerVerificationEventHandler = (): void => {
|
|||||||
|
|
||||||
export const solveCaptchaRunner = async (e: Event): Promise<void> => {
|
export const solveCaptchaRunner = async (e: Event): Promise<void> => {
|
||||||
const PROGRESS_FILL = <HTMLElement>document.querySelector(".progress__fill");
|
const PROGRESS_FILL = <HTMLElement>document.querySelector(".progress__fill");
|
||||||
|
|
||||||
|
const setWidth = (width: number) => {
|
||||||
|
PROGRESS_FILL.style.width = `${width}%`;
|
||||||
|
PROGRESS_FILL.ariaValueNow = <any>parseInt(<any>width);
|
||||||
|
};
|
||||||
|
|
||||||
let width = 0;
|
let width = 0;
|
||||||
|
|
||||||
if (LOCK) {
|
if (LOCK) {
|
||||||
@@ -36,8 +42,9 @@ export const solveCaptchaRunner = async (e: Event): Promise<void> => {
|
|||||||
LOCK = true;
|
LOCK = true;
|
||||||
if (CONST.btn().checked == false) {
|
if (CONST.btn().checked == false) {
|
||||||
width = 0;
|
width = 0;
|
||||||
PROGRESS_FILL.style.width = `${width}%`;
|
setWidth(width);
|
||||||
CONST.messageText().before();
|
CONST.messageText().before();
|
||||||
|
CONST.btn().ariaChecked = <any>false;
|
||||||
LOCK = false;
|
LOCK = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -57,7 +64,7 @@ export const solveCaptchaRunner = async (e: Event): Promise<void> => {
|
|||||||
|
|
||||||
if (resp.type === "work") {
|
if (resp.type === "work") {
|
||||||
width = 80;
|
width = 80;
|
||||||
PROGRESS_FILL.style.width = `${width}%`;
|
setWidth(width);
|
||||||
console.log(
|
console.log(
|
||||||
`Proof generated. Difficuly: ${config.difficulty_factor} Duration: ${resp.value.work.time}`
|
`Proof generated. Difficuly: ${config.difficulty_factor} Duration: ${resp.value.work.time}`
|
||||||
);
|
);
|
||||||
@@ -72,22 +79,23 @@ export const solveCaptchaRunner = async (e: Event): Promise<void> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
width = 90;
|
width = 90;
|
||||||
PROGRESS_FILL.style.width = `${width}%`;
|
setWidth(width);
|
||||||
// 3. submit work
|
// 3. submit work
|
||||||
const token = await sendWork(proof);
|
const token = await sendWork(proof);
|
||||||
// 4. send token
|
// 4. send token
|
||||||
sendToParent(token);
|
sendToParent(token);
|
||||||
// 5. mark checkbox checked
|
// 5. mark checkbox checked
|
||||||
CONST.btn().checked = true;
|
CONST.btn().checked = true;
|
||||||
|
CONST.btn().ariaChecked = <any>true;
|
||||||
width = 100;
|
width = 100;
|
||||||
PROGRESS_FILL.style.width = `${width}%`;
|
setWidth(width);
|
||||||
CONST.messageText().after();
|
CONST.messageText().after();
|
||||||
LOCK = false;
|
LOCK = false;
|
||||||
}
|
}
|
||||||
if (resp.type === "progress") {
|
if (resp.type === "progress") {
|
||||||
if (width < 80) {
|
if (width < 80) {
|
||||||
width = (resp.nonce / max_recorded_nonce) * 100;
|
width = Number(resp.nonce / max_recorded_nonce) * 100;
|
||||||
PROGRESS_FILL.style.width = `${width}%`;
|
setWidth(width);
|
||||||
}
|
}
|
||||||
console.log(`received nonce ${resp.nonce}`);
|
console.log(`received nonce ${resp.nonce}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ body {
|
|||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
border: 2px solid #e5e5e5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.widget__noscript-container {
|
.widget__noscript-container {
|
||||||
@@ -56,7 +58,8 @@ body {
|
|||||||
|
|
||||||
.widget__verification-container {
|
.widget__verification-container {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: none;
|
display: flex;
|
||||||
|
flex-direction: row-reverse;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
@@ -67,36 +70,6 @@ body {
|
|||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#widget__verification-text--during {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#widget__verification-text--after {
|
|
||||||
display: none;
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
|
|
||||||
#widget__verification-text--error {
|
|
||||||
display: none;
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.widget__verification-checkbox:checked ~ #widget__verification-text--before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.widget__verification-checkbox:checked ~ #widget__verification-text--during {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.widget__verification-checkbox:checked ~ #widget__verification-text--error {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.widget__verification-checkbox:checked ~ #widget__verification-text--after {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.widget__mcaptcha-details {
|
.widget__mcaptcha-details {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -127,6 +100,29 @@ body {
|
|||||||
margin: 2px;
|
margin: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.widget__container {
|
||||||
|
background-color: #1c1c1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget__inner-container {
|
||||||
|
background-color: #1c1c1c;
|
||||||
|
border: 2px solid #656569;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget__verification-container {
|
||||||
|
color: rgb(232, 230, 227);
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget__mcaptcha-brand-name {
|
||||||
|
color: #7d94f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget__mcaptcha-info-link {
|
||||||
|
color: #7d94f9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* progress bar courtesy of https://codepen.io/Bizzy-Coding/pen/poOymVJ?editors=1111 */
|
/* progress bar courtesy of https://codepen.io/Bizzy-Coding/pen/poOymVJ?editors=1111 */
|
||||||
.progress__bar {
|
.progress__bar {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -142,3 +138,9 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 0%;
|
width: 0%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.progress__bar {
|
||||||
|
background: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import * as CONST from "../const";
|
import * as CONST from "../const";
|
||||||
|
|
||||||
import {getBaseHtml, sitekey, checkbox} from "./setupTests";
|
import { getBaseHtml, sitekey, checkbox } from "./setupTests";
|
||||||
import * as TESTElements from "./setupTests";
|
import * as TESTElements from "./setupTests";
|
||||||
|
|
||||||
it("const works", () => {
|
it("const works", () => {
|
||||||
@@ -17,29 +17,17 @@ it("const works", () => {
|
|||||||
|
|
||||||
// display after
|
// display after
|
||||||
CONST.messageText().after();
|
CONST.messageText().after();
|
||||||
expect(TESTElements.afterMsg.style.display).toBe("block");
|
expect(TESTElements.Msg.innerText).toBe(CONST.AFTER);
|
||||||
expect(TESTElements.beforeMsg.style.display).toBe("none");
|
|
||||||
expect(TESTElements.duringMsg.style.display).toBe("none");
|
|
||||||
expect(TESTElements.errorMsg.style.display).toBe("none");
|
|
||||||
|
|
||||||
// display before
|
// display before
|
||||||
CONST.messageText().before();
|
CONST.messageText().before();
|
||||||
expect(TESTElements.afterMsg.style.display).toBe("none");
|
expect(TESTElements.Msg.innerText).toBe(CONST.BEFORE);
|
||||||
expect(TESTElements.beforeMsg.style.display).toBe("block");
|
|
||||||
expect(TESTElements.duringMsg.style.display).toBe("none");
|
|
||||||
expect(TESTElements.errorMsg.style.display).toBe("none");
|
|
||||||
|
|
||||||
// display during
|
// display during
|
||||||
CONST.messageText().during();
|
CONST.messageText().during();
|
||||||
expect(TESTElements.afterMsg.style.display).toBe("none");
|
expect(TESTElements.Msg.innerText).toBe(CONST.DURING);
|
||||||
expect(TESTElements.beforeMsg.style.display).toBe("none");
|
|
||||||
expect(TESTElements.duringMsg.style.display).toBe("block");
|
|
||||||
expect(TESTElements.errorMsg.style.display).toBe("none");
|
|
||||||
|
|
||||||
// display error
|
// display error
|
||||||
CONST.messageText().error();
|
CONST.messageText().error();
|
||||||
expect(TESTElements.afterMsg.style.display).toBe("none");
|
expect(TESTElements.Msg.innerText).toBe(CONST.ERROR);
|
||||||
expect(TESTElements.beforeMsg.style.display).toBe("none");
|
|
||||||
expect(TESTElements.duringMsg.style.display).toBe("none");
|
|
||||||
expect(TESTElements.errorMsg.style.display).toBe("block");
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,25 +11,19 @@ export const checkbox = <HTMLInputElement>document.createElement("input");
|
|||||||
checkbox.type = "checkbox";
|
checkbox.type = "checkbox";
|
||||||
checkbox.id = CONST.btnId;
|
checkbox.id = CONST.btnId;
|
||||||
|
|
||||||
const getMessages = (state: string) => {
|
const getMessages = () => {
|
||||||
const msg = <HTMLElement>document.createElement("span");
|
const msg = <HTMLElement>document.createElement("span");
|
||||||
msg.id = `widget__verification-text--${state}`;
|
msg.id = "widget__verification-text";
|
||||||
|
msg.innerText = "I'm not a robot";
|
||||||
return msg;
|
return msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const beforeMsg = getMessages("before");
|
export const Msg = getMessages();
|
||||||
export const afterMsg = getMessages("after");
|
|
||||||
export const duringMsg = getMessages("during");
|
|
||||||
export const errorMsg = getMessages("error");
|
|
||||||
|
|
||||||
/** get base HTML with empty mCaptcha container */
|
/** get base HTML with empty mCaptcha container */
|
||||||
export const getBaseHtml = (): HTMLFormElement => {
|
export const getBaseHtml = (): HTMLFormElement => {
|
||||||
const form = <HTMLFormElement>document.createElement("form");
|
const form = <HTMLFormElement>document.createElement("form");
|
||||||
form.appendChild(checkbox);
|
form.appendChild(checkbox);
|
||||||
form.appendChild(beforeMsg);
|
form.appendChild(Msg);
|
||||||
form.appendChild(duringMsg);
|
|
||||||
form.appendChild(afterMsg);
|
|
||||||
form.appendChild(errorMsg);
|
|
||||||
|
|
||||||
return form;
|
return form;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user