Compare commits

..

178 Commits

Author SHA1 Message Date
Aravinth Manivannan
3a7e71b499 fix: exit loop when paginated DB query returns empty array
fixes: https://github.com/mCaptcha/mCaptcha/issues/154
2024-03-24 08:40:52 +05:30
Aravinth Manivannan
91955501e2 feat: enable easy PoW configuration auto-enhance by default 2024-03-24 08:37:26 +05:30
Aravinth Manivannan
cb72b0adfa Merge pull request #152 from mCaptcha/fix-151
fix: difficulty factor for "broke my site" should be greater than peak sustainable traffic"
2024-03-23 13:55:28 +05:30
Aravinth Manivannan
c1fe45d409 fix: difficulty factor for "broke my site" should be greater than "peak sustainable traffic"
fixes: #151
2024-03-23 13:31:49 +05:30
Aravinth Manivannan
59e339f287 Merge pull request #150 from mCaptcha/fix-144
feat: add curl to the final image to aid in healthchecks
2024-03-15 18:01:12 +05:30
Aravinth Manivannan
ddcde9cf18 Merge pull request #146 from 15aura35/master
Update .env.docker-compose to use port 7000 instead of 7001
2024-03-15 18:00:17 +05:30
Aravinth Manivannan
65c92ee96e feat: add curl to the final image to aid in healthchecks
closes: https://github.com/mCaptcha/mCaptcha/issues/144
2024-03-14 20:52:37 +05:30
Aravinth Manivannan
40766ff44f Merge pull request #147 from mitallast/master
Fix: ensuring worker is ready
2024-03-12 19:41:49 +05:30
mitallast
ddc3008009 await worker is ready 2024-03-05 13:42:10 +03:00
mitallast
cba056aba6 fix wasm bigint progress handler 2024-03-05 13:13:47 +03:00
15aura35
16c975d2ec Update .env.docker-compose 2024-03-01 21:53:32 +00:00
Aravinth Manivannan
f67fdf917e Merge pull request #142 from mCaptcha/release-ci
feat: publish tagged docker images and bins
2024-02-23 15:51:56 +05:30
Aravinth Manivannan
e1746223c8 feat: publish tagged docker images and bins 2024-02-23 15:40:45 +05:30
Aravinth Manivannan
ae08c09702 fix: tmp disable bin publication 2024-02-23 15:40:27 +05:30
Aravinth Manivannan
1c9e242d7e Merge pull request #140 from mCaptcha/fix-134
fix: typecast BigInt to number in progress computation
2024-02-22 19:21:03 +05:30
Aravinth Manivannan
3cb0ca38ec fix: typecast BigInt to number in progress computation
closes: https://github.com/mCaptcha/mCaptcha/issues/134
2024-02-22 18:40:38 +05:30
Aravinth Manivannan
3cd38511fa Merge pull request #135 from SebastianGode/widget-dark
Added automatic dark mode to the widget
2024-02-19 20:13:58 +05:30
Sebastian Gode
d765bd7491 Added dark mode to widget 2024-02-13 13:30:14 +00:00
Sebastian Gode
8e33e75659 Added dark mode to widget 2024-02-13 12:59:20 +00:00
Aravinth Manivannan
c00857dd28 Merge pull request #133 from mCaptcha/aria-labels
feat: add aria labels to widget progress bar and checkbox
2024-02-04 01:09:09 +05:30
Aravinth Manivannan
9cf0eb596a feat: add aria labels to widget progress bar and checkbox 2024-02-03 19:33:45 +05:30
Aravinth Manivannan
d010a1cbd4 Merge pull request #131 from mCaptcha/fix-upload-config-file
fix: publish config file in tarball
2024-01-08 00:21:52 +05:30
Aravinth Manivannan
453be36201 fix: publish config file in tarball 2024-01-08 00:14:14 +05:30
Aravinth Manivannan
d4967626ee Merge pull request #130 from mCaptcha/document-configuration-parameters
feat: list all env vars and load in docker-compose
2024-01-07 23:52:49 +05:30
Aravinth Manivannan
2ee0a0ae5f feat: list all env vars and load in docker-compose 2024-01-07 23:35:31 +05:30
Aravinth Manivannan
5722a5327c Merge pull request #128 from mCaptcha/feat-auto-captcha
Use time (in seconds) instead of difficulty factor to describe PoW
2024-01-05 01:25:19 +05:30
Aravinth Manivannan
239e0bfd47 feat: easy captcha update job runner 2024-01-05 01:03:38 +05:30
Aravinth Manivannan
790fd8f393 feat: create runner method for updating easy captchas 2024-01-05 01:03:13 +05:30
Aravinth Manivannan
c70a30e640 feat: fetch username of owner and description in easy captcha method 2024-01-05 01:02:27 +05:30
Aravinth Manivannan
3b8051159d feat: use time for easy captcha when option is configured by admin 2024-01-04 23:29:20 +05:30
Aravinth Manivannan
91c235b3f4 feat: add database method to get all easy captcha configurations with pagination 2024-01-04 23:28:50 +05:30
Aravinth Manivannan
9bcf6af3ab feat: add options to use time for easy captcha configuration 2024-01-04 23:28:04 +05:30
Aravinth Manivannan
e0d6188853 fix: terminate demo user job cleanly 2024-01-04 23:24:36 +05:30
Aravinth Manivannan
1b2096d955 Merge pull request #127 from mCaptcha/feat-auto-captcha
feat: new dashboard page to show percentile scores on PoW performance analysis records
2024-01-04 18:47:44 +05:30
Aravinth Manivannan
13c3066b86 fix: unused import 2024-01-04 17:22:10 +05:30
Aravinth Manivannan
da934f5ba7 feat: new dashboard page to show percentile scores on PoW performance analysis records 2024-01-04 01:58:19 +05:30
Aravinth Manivannan
26ad05d284 Merge pull request #125 from mCaptcha/fix-embedded-cache-health
fix: health endpoint crashing with embedded cache usage
2023-12-09 01:32:21 +05:30
Aravinth Manivannan
b6326603d1 fix: health endpoint crashing with embedded cache usage 2023-12-09 01:15:25 +05:30
Aravinth Manivannan
8bed3cb352 Merge pull request #121 from mCaptcha/feat-percentile
compute percentile on analytics records
2023-11-04 20:32:28 +00:00
Aravinth Manivannan
8e03290fda feat: expose percentile scores for all analyis records through API
endpoint
2023-11-05 01:20:49 +05:30
Aravinth Manivannan
321fd2e89b feat: create individual databases for each test 2023-11-05 01:17:42 +05:30
Aravinth Manivannan
36600e2f13 feat: database methods to compute percentiles on analysis records 2023-11-05 00:48:26 +05:30
Aravinth Manivannan
606d22cc9d Merge pull request #120 from mCaptcha/feat-help-text-in-publishing-data
feat: link to mCaptcha net blog post from the captcha creation form
2023-11-02 10:42:11 +00:00
Aravinth Manivannan
4426057fbc feat: link to mCaptcha net blog post from the captcha creation form 2023-11-02 04:33:32 +05:30
Aravinth Manivannan
1f23999c10 fix: re-enable bin publishing with 73DAC973A9ADBB9ADCB5CDC4595A08135BA9FF73 GPG key 2023-10-30 09:29:48 +05:30
Aravinth Manivannan
0a3d93453e Merge pull request #119 from mCaptcha/fix-progress-bar
fix: create max_recorded nonce for existing captcha configs
2023-10-29 13:03:57 +00:00
Aravinth Manivannan
939fb5f8b9 fix: create max_recorded nonce for existing captcha configs 2023-10-29 18:11:06 +05:30
Aravinth Manivannan
3a787a6592 Merge pull request #118 from mCaptcha/feat-progress-bar
Feat progress bar
2023-10-29 01:20:04 +00:00
Aravinth Manivannan
9dfb0713ad feat: progress bar and incremental PoW generation 2023-10-29 06:28:21 +05:30
Aravinth Manivannan
ad4582cc16 feat: record and fetch max recorded nonces 2023-10-29 06:27:58 +05:30
Aravinth Manivannan
77e4a9c473 feat: use node@v20 2023-10-29 06:27:15 +05:30
Aravinth Manivannan
b6497882d7 feat: track maximum recorded nonce for captcha levels to render progress bar 2023-10-29 06:18:01 +05:30
Aravinth Manivannan
49a8757ead chore: CI: update base node version 2023-10-29 03:32:06 +05:30
Aravinth Manivannan
1107d3fc05 Merge pull request #116 from mCaptcha/update-deps-js
Update deps js
2023-10-28 13:21:12 +00:00
Aravinth Manivannan
072a997ff0 chore: update JS deps 2023-10-28 15:00:27 +05:30
Aravinth Manivannan
d30b53f4ee chore: update base node version 2023-10-28 15:00:25 +05:30
Aravinth Manivannan
b3021c500e chore: update redoc openapi spec compiler 2023-10-28 15:00:08 +05:30
Aravinth Manivannan
79006f1e64 chore: update swagger UI 2023-10-28 14:59:44 +05:30
Aravinth Manivannan
a45840d259 Merge pull request #92 from mCaptcha/upload-to-survey
Upload PoW performance to mCaptcha/survey
2023-10-20 02:20:04 +05:30
Aravinth Manivannan
960283324d feat: schedule mCaptcha/survey registration and uploads 2023-10-20 01:48:59 +05:30
Aravinth Manivannan
74364c4e17 chore: lint 2023-10-20 01:47:24 +05:30
Aravinth Manivannan
3d02f55241 fix: create psuedo id and setup publishing for those tht have opted in 2023-10-20 01:39:19 +05:30
Aravinth Manivannan
eab146b121 gc: get public hostname as config parameter 2023-10-20 01:38:22 +05:30
Aravinth Manivannan
d4534c1c43 feat: define db method to get all psuedo IDs with pagination 2023-10-20 00:18:29 +05:30
Aravinth Manivannan
d5617c7ec7 feat: upload secret route 2023-10-19 09:59:30 +05:30
Aravinth Manivannan
f933a30e7e feat: load survey keystore 2023-10-19 09:59:29 +05:30
Aravinth Manivannan
87785b38be feat: bootstrap survey upload job runner 2023-10-19 09:59:29 +05:30
Aravinth Manivannan
52c2c6e598 feat: bootstrap survey uploader's endpoints 2023-10-19 09:59:29 +05:30
Aravinth Manivannan
b6a6705449 feat: read survey uploader's settings 2023-10-19 09:59:29 +05:30
Aravinth Manivannan
c56b04fa5a feat: download published pow performance analytics 2023-10-19 09:59:29 +05:30
Aravinth Manivannan
ccb9278d67 Merge pull request #115 from mCaptcha/hotfix-env-vars
hotfix: read soon-to-be deprecated env vars to avoid breakages like #114
2023-10-18 17:52:51 +05:30
Aravinth Manivannan
eb69e9aedc hotfix: read soon-to-be deprecated env vars to avoid breakages like #114 2023-10-18 17:38:42 +05:30
Aravinth Manivannan
1310c22bed fix: update env var names in docker-compose with the latest names 2023-10-18 13:27:59 +05:30
Aravinth Manivannan
b300d2caac fix: typo in env var names 2023-10-18 13:23:50 +05:30
Aravinth Manivannan
5d03682c45 fix: CI: disable docker container uploads for branch!=master 2023-10-18 13:22:17 +05:30
Aravinth Manivannan
61729c5fae fix: set logging var, only if one is not provided 2023-10-18 13:21:33 +05:30
Aravinth Manivannan
8ec5122f87 hotfix: CI: disable tarpaulin run until it is fixed 2023-10-18 12:41:02 +05:30
Aravinth Manivannan
6bd66e6d00 Merge pull request #113 from mCaptcha/update-deps3
chore: use libmcaptcha and libcachebust from crates.io
2023-10-17 16:48:08 +05:30
Aravinth Manivannan
8e3fb9d8ec hotfix: disable uploads to dl.mcaptcha.org 2023-10-17 16:14:06 +05:30
Aravinth Manivannan
c67b7ac686 fix: cache busting metadata is stored in libcachebust_data.json 2023-10-17 15:47:15 +05:30
Aravinth Manivannan
cb7245d577 feat: use libmCaptcha from crates.io 2023-10-17 15:38:40 +05:30
Aravinth Manivannan
4739c697b7 Merge pull request #107 from jfly/patch-1
Change license
2023-10-17 14:06:18 +05:30
Aravinth Manivannan
561a847bd7 chore: use libmcaptcha and libcachebust from crates.io 2023-10-17 01:04:44 +05:30
Aravinth Manivannan
9e77eec657 Merge pull request #111 from mCaptcha/update-sqlx
Update sqlx
2023-10-16 22:53:10 +05:30
Aravinth Manivannan
30dc51e8e1 debug: allow warnings 2023-10-16 22:04:34 +05:30
Aravinth Manivannan
4e2758f415 chore: clippy lints 2023-10-16 21:50:53 +05:30
Aravinth Manivannan
0e75a22beb chore: bump sqlx to 0.7 2023-10-16 21:15:44 +05:30
Aravinth Manivannan
0d2c02348b feat: document environment variable name changes 2023-10-16 21:15:15 +05:30
Aravinth Manivannan
98efe3ae56 feat: manually read configuration from environment variables 2023-10-16 21:15:15 +05:30
Aravinth Manivannan
060291d174 chore: bump config version 2023-10-16 21:15:15 +05:30
Aravinth Manivannan
65c3b9ad67 feat: use nvm to manage node versions 2023-10-16 21:15:15 +05:30
Aravinth Manivannan
d3e08ff49e chore: update sailfish
NOTE: Updating to 0.8 causes memory leak during compilation
2023-10-16 21:15:15 +05:30
Aravinth Manivannan
431463a397 Merge pull request #110 from mCaptcha/fix-docker-img
fix: get rid of docker caching
2023-10-16 21:14:23 +05:30
Aravinth Manivannan
342d03b58b fix: CI: port actions actionx-rust-lang and checkout@v4 2023-10-16 20:30:41 +05:30
Aravinth Manivannan
765be413c4 debug: rm GH actions caching 2023-10-16 20:17:00 +05:30
Aravinth Manivannan
e0203c660d fix: get rid of caching 2023-10-16 20:04:19 +05:30
Jeremy Fleischman
ce73d29792 Change license
`AGPL3` isn't a valid SPDX identifier, but `AGPL-3.0-or-later` is. See https://spdx.org/licenses/
2023-09-27 23:31:21 -07:00
Aravinth Manivannan
f337ee0643 Merge pull request #90 from mCaptcha/wip-reuse
feat: init reuse tool
2023-07-04 16:03:55 +05:30
Aravinth Manivannan
19d07489f0 fix: run make sqlx to update offline data with license header modification 2023-07-04 15:37:52 +05:30
Aravinth Manivannan
78d85ab9a9 feat: annotate license headers using reuse on text source files 2023-07-03 23:19:51 +05:30
Aravinth Manivannan
d707a2265c feat: init reuse tool 2023-07-03 23:19:38 +05:30
Aravinth Manivannan
376a9348cb Merge pull request #96 from mCaptcha/update-deps
chore: update swagger ui
2023-07-03 20:12:48 +05:30
Aravinth Manivannan
6b94708935 chore: temporarily disable OPENAPI testing
TODO: fix tests
2023-07-03 19:30:55 +05:30
Aravinth Manivannan
0094bac559 feat: use redocly instead of the possibly deprecated swagger-cli 2023-07-03 19:30:36 +05:30
Aravinth Manivannan
04cb724df1 Merge pull request #95 from mCaptcha/fix-integration
debug: first run firefox tests
2023-07-03 19:09:27 +05:30
Aravinth Manivannan
461020d413 chore: update swagger ui 2023-07-03 19:09:03 +05:30
Aravinth Manivannan
c8e6b81d6e debug: first run firefox tests 2023-07-03 17:56:30 +05:30
Aravinth Manivannan
71ef95e4c4 Merge pull request #94 from mCaptcha/update-deps
Update deps
2023-07-03 00:08:53 +05:30
Aravinth Manivannan
b2f373dffd Merge pull request #93 from mCaptcha/pow-live-stats
Pow live stats
2023-07-02 23:22:05 +05:30
Aravinth Manivannan
c3ab7f8b0e chore: use node v18.0.0 2023-07-02 22:05:23 +05:30
Aravinth Manivannan
c4a286454b chore: update rust and js deps 2023-07-02 22:05:23 +05:30
Aravinth Manivannan
4a25f7f3a6 fix: truncate pow compute time before submitting 2023-07-02 22:05:23 +05:30
Aravinth Manivannan
32762cf6b5 fix: linting 2023-07-02 22:04:42 +05:30
Aravinth Manivannan
43024f1940 fix: CI: update make command 2023-07-02 21:54:42 +05:30
Aravinth Manivannan
1e0aedad61 chore: linting 2023-07-02 21:51:24 +05:30
Aravinth Manivannan
1b05cdc391 fix: truncate pow compute time before submitting 2023-07-02 20:27:03 +05:30
Aravinth Manivannan
3e5936cb83 fix: CI: pin mariadb to version 10 2023-07-02 18:37:38 +05:30
Aravinth Manivannan
2ca49cffe4 feat: see publication status in sitekey view page 2023-06-30 16:50:04 +05:30
Aravinth Manivannan
468752f691 feat: advance siteey create now allows setting publication status 2023-06-30 16:49:35 +05:30
Aravinth Manivannan
22edb04ce2 feat: advance sitekey edit now allows modifying publication status 2023-06-30 16:48:53 +05:30
Aravinth Manivannan
6834e555d8 chore: use db util method to check publication status 2023-06-30 16:33:20 +05:30
Aravinth Manivannan
3c6b13f947 feat: utility method to check if captcha is published 2023-06-30 16:15:44 +05:30
Aravinth Manivannan
99db889867 chore: refactor test (coverage and frontend) subroutines in Makefile 2023-06-30 07:55:53 +05:30
Aravinth Manivannan
56dba7b77f feat: option to publish pow performance numbers. Can un/publish from edit page too. 2023-06-30 07:55:12 +05:30
Aravinth Manivannan
1c4ee5b622 feat: upload pow performance benchmarks 2023-06-30 07:54:54 +05:30
Aravinth Manivannan
d8a145cf87 chore: refactor test workflows in Makefile 2023-06-30 07:28:13 +05:30
Aravinth Manivannan
8ca48d85ff fix: worker_type should not be unique 2023-06-30 07:18:34 +05:30
Aravinth Manivannan
2b82af9a0c feat: update novice captcha creation form to include publish_benchmarks
preference
2023-06-30 03:20:57 +05:30
Aravinth Manivannan
2cf5e48d8e feat: log pow performance stats while pow verification 2023-06-30 03:19:38 +05:30
Aravinth Manivannan
679a35216c feat: delete analytics when webmaster updates publishing status 2023-06-30 03:16:43 +05:30
Aravinth Manivannan
68b59ade8c feat: add psuedo ID support to publish campaign IDs 2023-06-30 01:48:24 +05:30
Aravinth Manivannan
8af09939ff feat: pagination on performance logs fetches 2023-06-28 22:54:18 +05:30
Aravinth Manivannan
dc380adfcf chore: bump libmcaptcha 2023-06-28 22:49:08 +05:30
Aravinth Manivannan
f8e3b720de fix: ignore failures when creating dependency containers.
Failures happen when containers already exist, so ignoring is alright
2023-06-28 11:59:26 +05:30
Aravinth Manivannan
5ae3b1f26e feat: store pow performance statistics against statistics 2023-06-27 19:47:04 +05:30
Aravinth Manivannan
2a1bda653d feat: run migrations using sqlx also 2023-06-27 19:46:54 +05:30
Aravinth Manivannan
b0db04f26a feat: make: deploy dependencies 2023-06-27 15:14:08 +05:30
Aravinth Manivannan
746748f98c Merge pull request #84 from Timwi/patch-1
Typo in README.md
2023-06-07 10:12:23 +05:30
Timwi
003ed983cb Typo in README.md 2023-05-30 12:47:41 +02:00
Aravinth Manivannan
78de0b266f Merge pull request #77 from mCaptcha/nighwatch
Integration testing using Nighwatch (firefox + chromium)
2023-05-25 21:23:37 +05:30
Aravinth Manivannan
6ede578ad5 Merge pull request #83 from Benjamin-Loison/master
Correct a typo and add necessary spaces in `README.md`
2023-05-25 21:08:10 +05:30
Aravinth Manivannan
efed5f5f93 Merge pull request #82 from Supernova3339/patch-1
🐛 Typo fix in Documentation
2023-05-25 21:05:08 +05:30
Benjamin Loison
4a6850631a Correct a typo and add necessary spaces in README.md 2023-05-23 15:08:55 +02:00
SuperDev
0adbb0aa2f Update CONFIGURATION.md
FIx typo in documentation
2023-05-18 12:44:39 -05:00
Aravinth Manivannan
8f3faaa279 Merge pull request #75 from WizardTales/licensefix
fix(license): accidential AGPL in MIT licensed files
2023-05-01 16:02:58 +05:30
Aravinth Manivannan
5324969bd2 feat: install selenium drivers 2023-04-30 23:46:58 +05:30
Aravinth Manivannan
43dab030df feat: run nightwatch integration tests on CI 2023-04-30 20:18:47 +05:30
Aravinth Manivannan
9cc667851c feat: run integration tests using nightwatch js 2023-04-30 20:17:51 +05:30
Tobias Gurtzick
9fc7c31083 fix(license): accidential AGPL in MIT licensed files
fixes #69

Signed-off-by: Tobias Gurtzick <magic@wizardtales.com>
2023-04-18 11:20:12 +02:00
Aravinth Manivannan
90e60b0486 Merge pull request #70 from mCaptcha/fix-53
fix: update libmcaptcha to use connection manager
2023-03-31 17:29:58 +05:30
Aravinth Manivannan
58f93cb602 fix: update libmcaptcha to use connection manager
closes: https://github.com/mCaptcha/mCaptcha/issues/53
2023-03-31 16:20:13 +05:30
Aravinth Manivannan
fae50b19f8 Merge pull request #67 from mCaptcha/dependabot/cargo/openssl-0.10.48
chore(deps): bump openssl from 0.10.41 to 0.10.48
2023-03-25 11:43:57 +05:30
dependabot[bot]
e890ba0f57 chore(deps): bump openssl from 0.10.41 to 0.10.48
Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.41 to 0.10.48.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.41...openssl-v0.10.48)

---
updated-dependencies:
- dependency-name: openssl
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-25 05:03:34 +00:00
Aravinth Manivannan
744d94cf8d Merge pull request #66 from mCaptcha/dependabot/npm_and_yarn/docs/openapi/minimist-1.2.8
chore(deps): bump minimist from 1.2.5 to 1.2.8 in /docs/openapi
2023-03-25 10:33:03 +05:30
Aravinth Manivannan
31d12206aa feat: add NLnet funding details 2023-03-08 17:08:39 +05:30
dependabot[bot]
7764eda05d chore(deps): bump minimist from 1.2.5 to 1.2.8 in /docs/openapi
Bumps [minimist](https://github.com/minimistjs/minimist) from 1.2.5 to 1.2.8.
- [Release notes](https://github.com/minimistjs/minimist/releases)
- [Changelog](https://github.com/minimistjs/minimist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/minimistjs/minimist/compare/v1.2.5...v1.2.8)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-06 12:38:56 +00:00
Aravinth Manivannan
f78669955c Merge pull request #60 from mCaptcha/fix-59
fix: copy OpenAPI build from build container to final container
2023-01-17 04:26:20 +05:30
Aravinth Manivannan
cadc15a7a1 fix: copy OpenAPI build from build container to final container
fixes: https://github.com/mCaptcha/mCaptcha/issues/59
2023-01-17 03:54:54 +05:30
Aravinth Manivannan
c1f6ce3ae2 Merge pull request #52 from Gusted/close-register-page
Hide register page when registrations are closed
2022-11-07 13:39:34 +05:30
Gusted
864549cb4c Fix copyright 2022-11-06 19:42:22 +01:00
Gusted
5713d4b1ae Hide register page when registrations are closed
- Improve UX for "private" instances.
2022-10-24 22:47:07 +02:00
Aravinth Manivannan
ac502b7c08 Merge pull request #51 from Gusted/fix-compiling
Fix compiling
2022-10-24 21:22:34 +05:30
Gusted
8dc690ca01 Remove redunant format 2022-10-24 16:22:10 +02:00
Gusted
a4f9c92b32 Update cargo 2022-10-22 21:53:18 +02:00
Gusted
8826f6df8f Fix compiling
- I made some mistakes while checking my two previous PRs(Seems like I
don't understand Rust that great after all).
- Do the url encoding only on the password part, not only the whole URL.
- Fix `temporary value dropped while borrowed` compile error.
2022-10-22 21:28:58 +02:00
Aravinth Manivannan
af35fdb48e Merge pull request #46 from Gusted/relax-port-env
Allow `PORT` environment to be not set
2022-10-18 15:51:22 +05:30
Gusted
9fd8ffd666 Add more logging for configuration/env 2022-10-17 19:49:42 +02:00
Aravinth Manivannan
521abd82d6 Merge pull request #47 from Gusted/encode-url-postgres
Encode connection URL to database
2022-10-17 15:42:02 +05:30
Gusted
021f2fe5b4 Encode connection URL to database
- If you have a database password that contains characters like `#` or `*`, sqlx
will error about a InvalidPort, this is due to not encoding the url.
[See issue on sqlx](https://github.com/launchbadge/sqlx/issues/1624).
- Removed useless statements.
2022-10-16 23:37:24 +02:00
Gusted
b3e0ff6769 Allow PORT environment to be not set
- It's quite weird to require the `PORT` environment to be set, when it
already can be set via the config file.
2022-10-16 23:07:10 +02:00
Aravinth Manivannan
97abca2520 Merge pull request #45 from DarianAnjuhal/master
feat: open mail link with target=_blank
2022-10-12 15:28:13 +05:30
Daniel Antlinger
96a6c98c10 feat: open mail link with target=_blank 2022-10-12 11:50:55 +02:00
realaravinth
9d285573d7 fix: typo in widget 2022-09-26 16:40:40 +05:30
Aravinth Manivannan
d506d291c3 Merge pull request #43 from DarianAnjuhal/master
feat: open links from widget in new pages target=_blank
2022-09-07 23:31:56 +05:30
Daniel Antlinger
223e8fb8c2 feat: open links from widget in new pages target=_blank 2022-09-07 14:05:25 +02:00
realaravinth
2abf57d16b fix: set correct upload dir 2022-08-15 18:01:41 +05:30
realaravinth
b3ee57d042 fix: configure gpg key 2022-08-15 17:37:48 +05:30
realaravinth
8c65edd257 fix: upload path 2022-08-15 17:25:22 +05:30
480 changed files with 35579 additions and 11272 deletions

View File

@@ -12,3 +12,4 @@ src/cache_buster_data.json
browser/target
browser/cobertura.xml
browser/docs
**/target

43
.env.docker-compose Normal file
View 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=7000
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_peak_sustainable_traffic_difficulty=3000000 # greater than 3.5s
MCAPTCHA_captcha_DEFAULT_DIFFICULTY_STRATEGY_broke_my_site_traffic_difficulty=5000000 # roughly 1.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=

View File

@@ -1,2 +1,2 @@
export POSTGRES_DATABASE_URL="postgres://postgres:password@localhost:5432/postgres"
export MARIA_DATABASE_URL="mysql://maria:password@localhost:3306/maria"
export MARIA_DATABASE_URL="mysql://root:password@localhost:3306/maria"

View File

@@ -12,64 +12,28 @@ jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: ⚡ Cache
uses: actions/cache@v2
- uses: actions/checkout@v4
# Ensure rustfmt is installed and setup problem matcher
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
path: |
~/.cargo/registry
~/.cargo/git
node_modules
./docs/openapi/node_modules
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: rustfmt
- name: Check with rustfmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: Rustfmt Check
uses: actions-rust-lang/rustfmt@v1
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: ⚡ Cache
uses: actions/cache@v2
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
with:
path: |
~/.cargo/registry
~/.cargo/git
node_modules
./docs/openapi/node_modules
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: clippy
override: true
- uses: actions/setup-node@v2
with:
node-version: "14.x"
node-version: "20.0.0"
- name: Build frontend
run: make frontend
- name: Check with Clippy
uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --tests --all-features
- name: clippy Check
run: cargo clippy --workspace --tests --all-features

View File

@@ -1,135 +1,119 @@
name: Coverage
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- master
- db-abstract
jobs:
build_and_test:
strategy:
fail-fast: false
matrix:
version:
- stable
#- 1.51.0
name: ${{ matrix.version }} - 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
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@v2
- name: ⚡ Cache
uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
node_modules
./docs/openapi/node_modules
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- 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: "16.x"
- name: Install ${{ matrix.version }}
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.version }}-x86_64-unknown-linux-gnu
profile: minimal
override: true
- name: Build frontend
run: make frontend
- name: Run the frontend tests
run: make frontend-test
- name: Run migrations
run: make migrate
env:
POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
- name: build frontend
run: make frontend
- name: Generate coverage file
if: github.event_name == 'pull_request'
#if: (github.ref == 'refs/heads/master' || github.event_name == 'pull_request')
uses: actions-rs/tarpaulin@v0.1
with:
args: "-t 1200"
env:
POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
# GIT_HASH is dummy value. I guess build.rs is skipped in tarpaulin
# execution so this value is required for preventing meta tests from
# panicking
GIT_HASH: 8e77345f1597e40c2e266cb4e6dee74888918a61
CACHE_BUSTER_FILE_MAP: '{"map":{"./static/bundle/main.js":"./prod/bundle/main.1417115E59909BE0A01040A45A398ADB09D928DF89CCF038FA44B14850442096.js"},"base_dir":"./prod"}'
COMPILED_DATE: "2021-07-21"
- name: Upload to Codecov
if: github.event_name == 'pull_request'
uses: codecov/codecov-action@v2
#name: Coverage
#
#on:
# pull_request:
# types: [opened, synchronize, reopened]
# push:
# branches:
# - master
# - db-abstract
#
#jobs:
# build_and_test:
# strategy:
# fail-fast: false
# matrix:
# version:
# - stable
# #- 1.51.0
#
# name: ${{ matrix.version }} - 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: 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: "18.0.0"
#
# - uses: actions-rust-lang/setup-rust-toolchain@v1
#
# - name: Build frontend
# run: make frontend
#
# - name: Run the frontend tests
# run: make test.frontend
#
# - name: Run migrations
# run: make migrate
# env:
# POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
# MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
#
# - name: build frontend
# run: make frontend
#
# - name: Generate coverage file
# if: github.event_name == 'pull_request'
# #if: (github.ref == 'refs/heads/master' || github.event_name == 'pull_request')
# uses: actions-rs/tarpaulin@v0.1
# with:
# args: "-t 1200"
# env:
# POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
# MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
# # GIT_HASH is dummy value. I guess build.rs is skipped in tarpaulin
# # execution so this value is required for preventing meta tests from
# # panicking
# GIT_HASH: 8e77345f1597e40c2e266cb4e6dee74888918a61
# CACHE_BUSTER_FILE_MAP: '{"map":{"./static/bundle/main.js":"./prod/bundle/main.1417115E59909BE0A01040A45A398ADB09D928DF89CCF038FA44B14850442096.js"},"base_dir":"./prod"}'
# COMPILED_DATE: "2021-07-21"
#
# - name: Upload to Codecov
# if: github.event_name == 'pull_request'
# uses: codecov/codecov-action@v2

View File

@@ -9,7 +9,7 @@ on:
branches:
- master
- "*"
- '!gh-pages'
- "!gh-pages"
jobs:
build_and_test:
@@ -17,9 +17,7 @@ jobs:
fail-fast: false
matrix:
version:
#- 1.51.0
- stable
# - nightly
name: ${{ matrix.version }} - x86_64-unknown-linux-gnu
runs-on: ubuntu-latest
@@ -54,7 +52,7 @@ jobs:
- 10025:1025
maria:
image: mariadb
image: mariadb:10
env:
MARIADB_USER: "maria"
MARIADB_PASSWORD: "password"
@@ -69,20 +67,11 @@ jobs:
- 3306:3306
steps:
- uses: actions/checkout@v2
- name: ⚡ Cache
uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
node_modules
./docs/openapi/node_modules
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- uses: actions/checkout@v4
- name: configure GPG key
if: (github.ref == 'refs/heads/master' || github.event_name == 'push') && github.repository == 'realaravinth/dumbserve'
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 }}
@@ -95,14 +84,12 @@ jobs:
- uses: actions/setup-node@v2
with:
node-version: "16.x"
node-version: "20.0.0"
- name: Install ${{ matrix.version }}
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.version }}-x86_64-unknown-linux-gnu
profile: minimal
override: true
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: install nightwatch dep
run: sudo apt-get install xvfb
- name: Run migrations
run: make migrate
@@ -128,8 +115,11 @@ 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'
if: github.ref == 'refs/heads/master' && github.event_name == 'push' && github.repository == 'mCaptcha/mCaptcha'
uses: docker/login-action@v1
with:
username: mcaptcha

125
.github/workflows/release.yml vendored Normal file
View 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 }}

View File

@@ -1,32 +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 }}
#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 }}

4
.gitignore vendored
View File

@@ -14,3 +14,7 @@ coverage
dist
assets
yarn-error.log
src/cache_buster_data.json.license
**/**/target
src/libcachebust_data.json
utils/cache-bust/src/libcachebust_data.json

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
20

10
.reuse/dep5 Normal file
View File

@@ -0,0 +1,10 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: mCaptcha
Upstream-Contact: Aravinth Manivannan <realaravinth@batsense.net>
Source: https://mcaptcha.org
# Sample paragraph, commented out:
#
# Files: src/*
# Copyright: $YEAR $NAME <$CONTACT>
# License: ...

View File

@@ -2,6 +2,9 @@
### Changed
- 2023-10-18: Environment variable names have changed, please see
[CONFIGURATION.md](docs/CONFIGURATION.md) for the names of environment
variables.
- ([`7d0e4c6`](https://github.com/mCaptcha/mCaptcha/commit/7d0e4c6be4b0769921cda7681858ebe16ec9a07b)) Add `secret` parameter to token verification request payload(`/api/v1/pow/siteverify`) to mitigate a security issue that @gusted found:
> ...A malicious user could grab the sitekey
> and use that sitekey with mcaptcha to use it for their own server.

2620
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -33,15 +33,15 @@ actix-service = "2.0.0"
async-trait = "0.1.51"
mime_guess = "2.0.3"
rust-embed = "6.4.0"
cache-buster = { git = "https://github.com/realaravinth/cache-buster" }
libcachebust = "0.3.0"
futures = "0.3.15"
tokio = { version = "1.14", features = ["sync"]}
sqlx = { version = "0.5.13", features = [ "runtime-actix-rustls", "postgres", "time", "offline", "mysql"] }
sqlx = { version = "0.7", features = [ "runtime-tokio-rustls", "postgres", "time", "mysql"] }
argon2-creds = { branch = "master", git = "https://github.com/realaravinth/argon2-creds"}
#argon2-creds = { version="*", path = "../../argon2-creds/" }
config = "0.11"
config = "0.13"
validator = { version = "0.15", features = ["derive"]}
derive_builder = "0.11"
@@ -59,13 +59,11 @@ 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"]}
libmcaptcha = "0.2.4"
rand = "0.8"
sailfish = "0.4.0"
sailfish = "0.7.0"
mime = "0.3.16"
@@ -78,7 +76,9 @@ lettre = { version = "0.10.0-rc.3", features = [
"smtp-transport"
]}
openssl = { version = "0.10.29", features = ["vendored"] }
openssl = { version = "0.10.48", features = ["vendored"] }
uuid = { version = "1.4.0", features = ["v4", "serde"] }
reqwest = { version = "0.11.18", features = ["json", "gzip"] }
[dependencies.db-core]
@@ -101,10 +101,10 @@ features = ["actix_identity_backend"]
[build-dependencies]
serde_json = "1"
sqlx = { version = "0.5.13", features = [ "runtime-actix-rustls", "postgres", "time", "offline", "mysql" ] }
sqlx = { version = "0.7", features = [ "runtime-tokio-rustls", "postgres", "time", "mysql" ] }
[dev-dependencies]
pow_sha256 = { version = "0.3.1", git = "https://github.com/mcaptcha/pow_sha256", tag="0.3.1" }
mcaptcha_pow_sha256 = "0.4"
awc = "3.0.0"

View File

@@ -1,4 +1,7 @@
FROM node:16.0.0 as frontend
# SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
FROM node:20 as frontend
RUN set -ex; \
apt-get update; \
DEBIAN_FRONTEND=noninteractive \
@@ -17,33 +20,21 @@ COPY Makefile /src/
COPY scripts /src/scripts
RUN make frontend
FROM rust:latest as planner
RUN cargo install cargo-chef
WORKDIR /src
COPY . /src/
RUN cargo chef prepare --recipe-path recipe.json
FROM rust:latest as cacher
WORKDIR /src/
RUN cargo install cargo-chef
COPY --from=planner /src/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json
FROM rust:latest as rust
WORKDIR /src
COPY . .
COPY --from=cacher /src/target target
#COPY --from=cacher /src/db/db-core/target /src/db/db-core/target
#COPY --from=cacher /src/db/db-sqlx-postgres/target /src/db/db-sqlx-postgres/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
FROM debian:bullseye as mCaptcha
FROM debian:bookworm as mCaptcha
LABEL org.opencontainers.image.source https://github.com/mCaptcha/mCaptcha
RUN set -ex; \
apt-get update; \
DEBIAN_FRONTEND=noninteractive \
apt-get install -y --no-install-recommends curl
RUN useradd -ms /bin/bash -u 1001 mcaptcha
WORKDIR /home/mcaptcha
COPY --from=rust /src/target/release/mcaptcha /usr/local/bin/

View File

@@ -0,0 +1,235 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software.
A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public.
The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version.
An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based on the Program.
To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work.
A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices".
c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
"Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph.
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements.
You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see <http://www.gnu.org/licenses/>.

73
LICENSES/Apache-2.0.txt Normal file
View File

@@ -0,0 +1,73 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

9
LICENSES/MIT.txt Normal file
View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) <year> <copyright holders>
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.

13
LICENSES/X11.txt Normal file
View File

@@ -0,0 +1,13 @@
X11 License
Copyright (C) 1996 X Consortium
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 X CONSORTIUM 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.
Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium.
X Window System is a trademark of X Consortium, Inc.

137
Makefile
View File

@@ -1,6 +1,42 @@
# SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
BUNDLE = static/cache/bundle
OPENAPI = docs/openapi
CLEAN_UP = $(BUNDLE) src/cache_buster_data.json assets
CLEAN_UP = $(BUNDLE) src/libcachebust_data.json assets
define deploy_dependencies ## deploy dependencies
@-docker create --name ${db} \
-e POSTGRES_PASSWORD=password \
-p 5432:5432 \
postgres
@-docker create \
-p 3306:3306 \
--name ${mdb} \
--env MARIADB_USER=maria \
--env MARIADB_PASSWORD=password \
--env MARIADB_ROOT_PASSWORD=password \
--env MARIADB_DATABASE=maria \
mariadb:latest
@-docker create \
-p 6379:6379 \
--name mcaptcha-cache \
mcaptcha/cache:latest
docker start ${db}
docker start ${mdb}
docker start mcaptcha-cache
endef
define run_migrations ## run database migrations
cd db/db-migrations/ && cargo run
endef
define run_dev_migrations ## run database migrations
cd db/db-sqlx-maria/ && \
DATABASE_URL=${MARIA_DATABASE_URL} sqlx migrate run cd db/db-sqlx-postgres/ && \
DATABASE_URL=${POSTGRES_DATABASE_URL} sqlx migrate run
endef
define frontend_env ## install frontend deps
yarn install
@@ -11,6 +47,28 @@ define cache_bust ## run cache_busting program
cd utils/cache-bust && cargo run
endef
define test_frontend ## run frontend tests
yarn test
# cd $(OPENAPI)&& yarn test
endef
define test_db_sqlx_postgres
cd db/db-sqlx-postgres &&\
DATABASE_URL=${POSTGRES_DATABASE_URL}\
cargo test --no-fail-fast
endef
define test_db_sqlx_maria
cd db/db-sqlx-maria &&\
DATABASE_URL=${MARIA_DATABASE_URL}\
cargo test --no-fail-fast
endef
define test_core
cargo test --no-fail-fast --jobs=4
endef
default: frontend ## Build app in debug mode
$(call cache_bust)
cargo build
@@ -35,10 +93,6 @@ clean: ## Delete build artifacts
@yarn cache clean
@-rm $(CLEAN_UP)
coverage: migrate ## Generate code coverage report in HTML format
$(call cache_bust)
cargo tarpaulin -t 1200 --out Html
doc: ## Generate documentation
#yarn doc
cargo doc --no-deps --workspace --all-features
@@ -54,6 +108,19 @@ env: ## Setup development environtment
cargo fetch
$(call frontend_env)
env.db: ## Deploy dependencies
$(call deploy_dependencies)
sleep 5
$(call run_migrations)
env.db.recreate: ## Deploy dependencies from scratch
@-docker rm -f ${db}
@-docker rm -f ${mdb}
@-docker rm -f mcaptcha-cache
$(call deploy_dependencies)
sleep 5
$(call run_migrations)
frontend-env: ## Install frontend deps
$(call frontend_env)
@@ -76,18 +143,17 @@ frontend: ## Build frontend
@./scripts/librejs.sh
@./scripts/cachebust.sh
frontend-test: ## Run frontend tests
cd $(OPENAPI)&& yarn test
yarn test
lint: ## Lint codebase
cargo fmt -v --all -- --emit files
cargo clippy --workspace --tests --all-features
yarn lint
cd $(OPENAPI)&& yarn test
#cd $(OPENAPI)&& yarn test
migrate: ## Run database migrations
cd db/db-migrations/ && cargo run
$(call run_migrations)
migrate.dev: ## Run database migrations during development
$(call run_dev_migrations)
release: frontend ## Build app with release optimizations
$(call cache_bust)
@@ -98,34 +164,49 @@ run: frontend ## Run app in debug mode
cargo run
sqlx-offline-data: ## prepare sqlx offline data
db.sqlx.offline: ## prepare sqlx offline data
cd db/db-sqlx-postgres && cargo sqlx prepare \
--database-url=${POSTGRES_DATABASE_URL} -- \
--all-features
cd db/db-sqlx-maria && cargo sqlx prepare \
--database-url=${MARIA_DATABASE_URL} -- \
--all-features
# cd db/db-sqlx-sqlite/ \
# && DATABASE_URL=${SQLITE_DATABASE_URL} cargo sqlx prepare
test-db: ## run tests on database
cd db/db-sqlx-postgres &&\
DATABASE_URL=${POSTGRES_DATABASE_URL}\
cargo test --no-fail-fast
test: frontend-test frontend ## Run all available tests
test: frontend ## Run all available tests
$(call test_frontend)
$(call cache_bust)
cd db/db-sqlx-postgres &&\
DATABASE_URL=${POSTGRES_DATABASE_URL}\
cargo test --no-fail-fast
cd db/db-sqlx-maria &&\
DATABASE_URL=${MARIA_DATABASE_URL}\
cargo test --no-fail-fast
cargo test --no-fail-fast
$(call test_db_sqlx_postgres)
$(call test_db_sqlx_maria)
$(call test_core)
# ./scripts/tests.sh
xml-test-coverage: migrate ## Generate code coverage report in XML format
test.cov.html: migrate ## Generate code coverage report in HTML format
$(call cache_bust)
cargo tarpaulin -t 1200 --out Html
test.cov.xml: migrate ## Generate code coverage report in XML format
$(call cache_bust)
cargo tarpaulin -t 1200 --out Xml
test.core: ## Run all core tests
$(call test_core)
test.db: ## Run all database driver tests
$(call test_db_sqlx_postgres)
$(call test_db_sqlx_maria)
test.db.pg: ## Run Postgres database driver tests
$(call test_db_sqlx_postgres)
test.db.maria: ## Run Maria database driver tests
$(call test_db_sqlx_maria)
test.frontend: ## Run frontend tests
$(call test_frontend)
test.integration: ## run integration tests with nightwatch.js
./scripts/integration.sh
help: ## Prints help for targets with comments
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-].+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

View File

@@ -34,7 +34,7 @@ yourself!](https://demo.mcaptcha.org/widget/?sitekey=pHy0AktWyOKuxZDzFfoaewncWec
mCaptcha uses SHA256 based proof-of-work (PoW) to rate limit users.
When a user wants to do something on an mCaptcha-protected website,
When a user wants to do something on a mCaptcha-protected website,
1. they will have to generate proof-of-work (a bunch of math that will takes
time to compute) and submit it to mCaptcha.
@@ -112,10 +112,9 @@ 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
See [DEPLOYMENT.md](./docs/DEPLOYMENT.md) for detailed alternate deployment
methods.
## Development:
@@ -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.

View File

@@ -1,19 +1,8 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// 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 std::process::Command;
use sqlx::types::time::OffsetDateTime;
@@ -21,12 +10,13 @@ use sqlx::types::time::OffsetDateTime;
fn main() {
// note: add error checking yourself.
let output = Command::new("git")
.args(&["rev-parse", "HEAD"])
.args(["rev-parse", "HEAD"])
.output()
.unwrap();
let git_hash = String::from_utf8(output.stdout).unwrap();
println!("cargo:rustc-env=GIT_HASH={}", git_hash);
let now = OffsetDateTime::now_utc().format("%y-%m-%d");
let now = OffsetDateTime::now_utc();
let now = format!("{}{}{}", now.year(), now.month(), now.date());
println!("cargo:rustc-env=COMPILED_DATE={}", &now);
}

View File

@@ -34,25 +34,22 @@ enable_stats = true
[captcha.default_difficulty_strategy]
avg_traffic_difficulty = 50000 # almost instant solution
avg_traffic_time = 1 # almost instant solution
peak_sustainable_traffic_difficulty = 3000000 # roughly 1.5s
peak_sustainable_traffic_time = 3
broke_my_site_traffic_difficulty = 5000000 # greater than 3.5s
broke_my_site_traffic_time = 5
duration = 30 # cooldown period in seconds
[database]
# This section deals with the database location and how to access it
# Please note that at the moment, we have support for only postgresqa.
# Example, if you are Batman, your config would be:
# hostname = "batcave.org"
# port = "5432"
# username = "batman"
# password = "somereallycomplicatedBatmanpassword"
hostname = "localhost"
port = "5432"
username = "postgres"
password = "password"
name = "postgres"
# url = "postgres://batman:password@batcave.org:5432/batcave"
# database_type = "postgres"
# pool = 4
url = "postgres://example.org" # hack for tests to run successfully
pool = 4
database_type="postgres" # "postgres", "maria"
[redis]
# This section deals with the database location and how to access it
@@ -72,3 +69,8 @@ url = "127.0.0.1"
port = 10025
username = "admin"
password = "password"
#[survey]
#nodes = ["http://localhost:7001"]
#rate_limit = 10 # upload every hour
#instance_root_url = "http://localhost:7000"

View File

@@ -13,8 +13,7 @@ async-trait = "0.1.51"
thiserror = "1.0.30"
serde = { version = "1", features = ["derive"]}
url = { version = "2.2.2", features = ["serde"] }
#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"] }
libmcaptcha = "0.2.4"
[features]
default = []

View File

@@ -1,19 +1,8 @@
/*
* 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/>.
*/
// Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! represents all the ways a trait can fail using this crate
use std::error::Error as StdError;

View File

@@ -1,19 +1,7 @@
/*
* 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/>.
*/
// Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
#![warn(missing_docs)]
//! # `mCaptcha` database operations
@@ -214,6 +202,13 @@ pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase {
captcha_key: &str,
) -> DBResult<TrafficPattern>;
/// Get all easy captcha configurations on instance
async fn get_all_easy_captchas(
&self,
limit: usize,
offset: usize,
) -> DBResult<Vec<EasyCaptcha>>;
/// Delete traffic configuration
async fn delete_traffic_pattern(
&self,
@@ -250,6 +245,110 @@ pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase {
/// fetch PoWConfig confirms
async fn fetch_confirm(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
/// record PoW timing
async fn analysis_save(
&self,
captcha_id: &str,
d: &CreatePerformanceAnalytics,
) -> DBResult<()>;
/// fetch PoW analytics
async fn analytics_fetch(
&self,
captcha_id: &str,
limit: usize,
offset: usize,
) -> DBResult<Vec<PerformanceAnalytics>>;
/// Create psuedo ID against campaign ID to publish analytics
async fn analytics_create_psuedo_id_if_not_exists(
&self,
captcha_id: &str,
) -> DBResult<()>;
/// Get psuedo ID from campaign ID
async fn analytics_get_psuedo_id_from_capmaign_id(
&self,
captcha_id: &str,
) -> DBResult<String>;
/// Get campaign ID from psuedo ID
async fn analytics_get_capmaign_id_from_psuedo_id(
&self,
psuedo_id: &str,
) -> DBResult<String>;
/// Delete all records for campaign
async fn analytics_delete_all_records_for_campaign(
&self,
campaign_id: &str,
) -> DBResult<()>;
/// Get publishing status of pow analytics for captcha ID/ campaign ID
async fn analytics_captcha_is_published(&self, campaign_id: &str) -> DBResult<bool> {
match self
.analytics_get_psuedo_id_from_capmaign_id(campaign_id)
.await
{
Ok(_) => Ok(true),
Err(errors::DBError::CaptchaNotFound) => Ok(false),
Err(e) => Err(e),
}
}
/// 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)]
/// Log Proof-of-Work CAPTCHA performance analytics
pub struct CreatePerformanceAnalytics {
/// time taken to generate proof
pub time: u32,
/// difficulty factor for which the proof was generated
pub difficulty_factor: u32,
/// worker/client type: wasm, javascript, python, etc.
pub worker_type: String,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
/// Proof-of-Work CAPTCHA performance analytics
pub struct PerformanceAnalytics {
/// log ID
pub id: usize,
/// time taken to generate proof
pub time: u32,
/// difficulty factor for which the proof was generated
pub difficulty_factor: u32,
/// worker/client type: wasm, javascript, python, etc.
pub worker_type: String,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
@@ -291,6 +390,19 @@ pub struct AddNotification<'a> {
pub message: &'a str,
}
#[derive(Default, PartialEq, Serialize, Deserialize, Clone, Debug)]
/// Represents Easy captcha configuration
pub struct EasyCaptcha {
/// traffic pattern of easy captcha
pub traffic_pattern: TrafficPattern,
/// captcha key/sitekey
pub key: String,
/// captcha description
pub description: String,
/// Owner of the captcha configuration
pub username: String,
}
#[derive(Default, PartialEq, Serialize, Deserialize, Clone, Debug)]
/// User's traffic pattern; used in generating a captcha configuration
pub struct TrafficPattern {
@@ -332,7 +444,6 @@ pub struct Secret {
/// user's secret
pub secret: String,
}
/// Trait to clone MCDatabase
pub trait CloneSPDatabase {
/// clone DB

View File

@@ -1,19 +1,8 @@
/*
* 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/>.
*/
// Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! meta operations like migration and connecting to a database
use crate::dev::*;

View File

@@ -1,23 +1,35 @@
/*
* 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/>.
*/
// Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Test utilities
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,
@@ -211,6 +223,11 @@ pub async fn database_works<'a, T: MCDatabase>(
tp
);
// get all traffic patterns
let patterns = db.get_all_easy_captchas(10, 0).await.unwrap();
assert_eq!(patterns.get(0).as_ref().unwrap().key, c.key);
assert_eq!(&patterns.get(0).unwrap().traffic_pattern, tp);
// delete traffic pattern
db.delete_traffic_pattern(p.username, c.key).await.unwrap();
assert!(
@@ -260,6 +277,157 @@ pub async fn database_works<'a, T: MCDatabase>(
db.record_solve(c.key).await.unwrap();
db.record_confirm(c.key).await.unwrap();
// analytics start
db.analytics_create_psuedo_id_if_not_exists(c.key)
.await
.unwrap();
let psuedo_id = db
.analytics_get_psuedo_id_from_capmaign_id(c.key)
.await
.unwrap();
assert_eq!(
vec![psuedo_id.clone()],
db.analytics_get_all_psuedo_ids(0).await.unwrap()
);
assert!(db.analytics_get_all_psuedo_ids(1).await.unwrap().is_empty());
db.analytics_create_psuedo_id_if_not_exists(c.key)
.await
.unwrap();
assert_eq!(
psuedo_id,
db.analytics_get_psuedo_id_from_capmaign_id(c.key)
.await
.unwrap()
);
assert_eq!(
c.key,
db.analytics_get_capmaign_id_from_psuedo_id(&psuedo_id)
.await
.unwrap()
);
let analytics = CreatePerformanceAnalytics {
time: 1,
difficulty_factor: 1,
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();
assert_eq!(a[0].time, analytics.time);
assert_eq!(a[0].difficulty_factor, analytics.difficulty_factor);
assert_eq!(a[0].worker_type, analytics.worker_type);
offset += 1;
assert!(db
.analytics_fetch(c.key, limit, offset)
.await
.unwrap()
.is_empty());
db.analytics_delete_all_records_for_campaign(c.key)
.await
.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)

View File

@@ -10,4 +10,4 @@ authors = ["realaravinth <realaravinth@batsense.net>"]
[dependencies]
actix-rt = "2"
sqlx = { version = "0.5.13", features = [ "runtime-actix-rustls", "postgres", "time", "offline", "mysql" ] }
sqlx = { version = "0.7", features = [ "runtime-tokio-rustls", "postgres", "time", "mysql" ] }

View File

@@ -1,19 +1,8 @@
/*
* 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/>.
*/
// Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
use std::env;
use sqlx::postgres::PgPoolOptions;

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT time FROM mcaptcha_pow_confirmed_stats \n WHERE \n config_id = (\n SELECT config_id FROM mcaptcha_config \n WHERE \n captcha_key = ?\n AND\n user_id = (\n SELECT \n ID FROM mcaptcha_users WHERE name = ?))\n ORDER BY time DESC",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "time",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | UNSIGNED | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false
]
},
"hash": "1367dceb151a766a901b5dd771d0b75d0bc61d2fef17a94a90c8ffa0065e2c44"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT\n captcha_key\n FROM\n mcaptcha_config\n WHERE\n config_id = (\n SELECT\n config_id\n FROM\n mcaptcha_psuedo_campaign_id\n WHERE\n psuedo_id = ?\n );",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "captcha_key",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "14dc89b2988b221fd24e4f319b1d48f5e6c65c760c30d11c9c29087f09cee23a"
}

View File

@@ -0,0 +1,12 @@
{
"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"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "INSERT INTO mcaptcha_sitekey_user_provided_avg_traffic (\n config_id,\n avg_traffic,\n peak_sustainable_traffic,\n broke_my_site_traffic\n ) VALUES ( \n (SELECT config_id FROM mcaptcha_config where captcha_key= (?)\n AND user_id = (SELECT ID FROM mcaptcha_users WHERE name = ?)\n ), ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 5
},
"nullable": []
},
"hash": "22e697114c3ed5b0156cdceab11a398f1ef3a804f482e1cd948bc615ef95fc92"
}

View File

@@ -0,0 +1,12 @@
{
"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"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "INSERT INTO mcaptcha_pow_confirmed_stats \n (config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config where captcha_key= ?), ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "34b29417f9ff3f4d5987df0ce81023b1985eb84e560602b36182f55de6cd9d83"
}

View File

@@ -0,0 +1,58 @@
{
"db_name": "MySQL",
"query": "SELECT captcha_key, name, config_id, duration FROM mcaptcha_config WHERE\n user_id = (SELECT ID FROM mcaptcha_users WHERE name = ?) ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "captcha_key",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
},
{
"ordinal": 1,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
},
{
"ordinal": 2,
"name": "config_id",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 3,
"name": "duration",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 11
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false
]
},
"hash": "3812693a9ae4402d900bcbf680981e6194073bd1937af11a77daa3776fb4c873"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "UPDATE mcaptcha_config SET name = ?, duration = ?\n WHERE user_id = (SELECT ID FROM mcaptcha_users WHERE name = ?)\n AND captcha_key = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 4
},
"nullable": []
},
"hash": "3a8381eb0f0542a492d9dd51368e769e2b313e0576a1873e5c7630011e463daf"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT email FROM mcaptcha_users WHERE name = ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "email",
"type_info": {
"type": "VarString",
"flags": "UNIQUE_KEY",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
true
]
},
"hash": "413ea53cea8b8f114fc009bad527b054a68a94477dfcc50d860d45bbd864d4f1"
}

View File

@@ -0,0 +1,69 @@
{
"db_name": "MySQL",
"query": "-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>\n--\n-- SPDX-License-Identifier: AGPL-3.0-or-later\n\n-- gets all unread notifications a user has\nSELECT \n mcaptcha_notifications.id,\n mcaptcha_notifications.heading,\n mcaptcha_notifications.message,\n mcaptcha_notifications.received,\n mcaptcha_users.name\nFROM\n mcaptcha_notifications \nINNER JOIN \n mcaptcha_users \nON \n mcaptcha_notifications.tx = mcaptcha_users.id\nWHERE \n mcaptcha_notifications.rx = (\n SELECT \n id \n FROM \n mcaptcha_users\n WHERE\n name = ?\n )\nAND \n mcaptcha_notifications.read_notification IS NULL;\n",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 1,
"name": "heading",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
},
{
"ordinal": 2,
"name": "message",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1000
}
},
{
"ordinal": 3,
"name": "received",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | UNSIGNED | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 4,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false
]
},
"hash": "42d967d6e080efd3cff8d4df13ea4d2ff38f3093da5c97000349dfc23c4d4eb3"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "INSERT INTO mcaptcha_pow_fetched_stats \n (config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config where captcha_key= ?), ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "598a8202942771eff460faa6f09bd3fb1fc910d5fab7edb07c49dadbbaeb1cb8"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT psuedo_id FROM\n mcaptcha_psuedo_campaign_id\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key = (?));\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "psuedo_id",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "5ad1ef722a961183228d851813b9f50284520bf8cc8118c765b72c108daaf6fb"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "INSERT INTO mcaptcha_users \n (name , password, secret) VALUES (?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "5d5a106981345e9f62bc2239c00cdc683d3aaaa820d63da300dc51e3f6f363d3"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\n DELETE FROM\n mcaptcha_pow_analytics\n WHERE\n config_id = (\n SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?\n ) ",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "6094468b7fa20043b0da90e366b7f1fa29a8c748e163b6712725440b25ae9361"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT config_id FROM mcaptcha_config\n WHERE\n captcha_key = ? \n AND user_id = (SELECT ID FROM mcaptcha_users WHERE name = ?)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "config_id",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
"char_set": 63,
"max_size": 11
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false
]
},
"hash": "66ec7df10484f8e0206f3c97afc9136021589556c38dbbed341d6574487f79f2"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "UPDATE mcaptcha_users set name = ?\n WHERE name = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "676a9f1761c3b63cf16d7d4dd6261507cc7707feb32d458f4b946ed9caa53721"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "DELETE FROM mcaptcha_users WHERE name = (?)",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "6d1b6e5e58ca2ba285cab7b050bbdc43de1f3e46cf7d420bc95c124a1c7c9d1f"
}

View File

@@ -0,0 +1,36 @@
{
"db_name": "MySQL",
"query": "SELECT difficulty_factor, visitor_threshold FROM mcaptcha_levels WHERE\n config_id = (\n SELECT config_id FROM mcaptcha_config where captcha_key= (?)\n ) ORDER BY difficulty_factor ASC;",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "difficulty_factor",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 1,
"name": "visitor_threshold",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false
]
},
"hash": "6d43e6ceb54a0ff8a803bd96dd9134b15da01d48776ac0cf3d66a2997dadce5e"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "INSERT INTO mcaptcha_levels (\n difficulty_factor, \n visitor_threshold,\n config_id) VALUES (\n ?, ?, (\n SELECT config_id FROM mcaptcha_config WHERE\n captcha_key = (?) AND user_id = (\n SELECT ID FROM mcaptcha_users WHERE name = ?\n )));",
"describe": {
"columns": [],
"parameters": {
"Right": 4
},
"nullable": []
},
"hash": "74d68a86f852d3d85957e94ed04e8acd8e6144744f7b13e383ebcb2bcf3360ae"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "UPDATE mcaptcha_users set secret = ?\n WHERE name = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "7838ade4a48068e25c6f117ee8e38f088b867b1ab08a7dd0269b76891266ace6"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "DELETE FROM mcaptcha_levels \n WHERE config_id = (\n SELECT config_id FROM mcaptcha_config where captcha_key= (?) \n AND user_id = (\n SELECT ID from mcaptcha_users WHERE name = ?\n )\n )",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "7894dda54cd65559fe3b81bab7df8cc848e21ed5c7f5e88951bf1c98c78ed820"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "INSERT INTO mcaptcha_notifications (\n heading, message, tx, rx, received)\n VALUES (\n ?, ?,\n (SELECT ID FROM mcaptcha_users WHERE name = ?),\n (SELECT ID FROM mcaptcha_users WHERE name = ?),\n ?\n );",
"describe": {
"columns": [],
"parameters": {
"Right": 5
},
"nullable": []
},
"hash": "89386c46668a2653a54687e65958af5cf7a8da268339a1f5a379ede47b3c6d2a"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT duration FROM mcaptcha_config \n where captcha_key= ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "duration",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 11
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "8acbf84d4801e86221d8f6324ae50488a0986182d66b20ad414bce4e2ac18eca"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "UPDATE mcaptcha_config SET captcha_key = ? \n WHERE captcha_key = ? AND user_id = (SELECT ID FROM mcaptcha_users WHERE name = ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "8e6026abf7c0e8ab90ee8eb7ada9f66962ab6999d3127944b058d6f96346e72f"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "insert into mcaptcha_users \n (name , password, email, secret) values (?, ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 4
},
"nullable": []
},
"hash": "8ec8bbde0c02a99f74d12e6778f123a973283e6d56b6861b30f559768617848a"
}

View File

@@ -0,0 +1,25 @@
{
"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"
}

View File

@@ -0,0 +1,58 @@
{
"db_name": "MySQL",
"query": "SELECT `config_id`, `duration`, `name`, `captcha_key` from mcaptcha_config WHERE\n `captcha_key` = ? AND\n user_id = (SELECT ID FROM mcaptcha_users WHERE name = ?) ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "config_id",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 1,
"name": "duration",
"type_info": {
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 2,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
},
{
"ordinal": 3,
"name": "captcha_key",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
false
]
},
"hash": "9c435148ed5655e79dd1e73e3566ce23b7c6d38edcedbb988c95813c5da893ed"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "UPDATE mcaptcha_users set email = ?\n WHERE name = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "9cb416de904872d66af90baa0024f382ce6f8344464c607fe6e6c2572816dfc2"
}

View File

@@ -0,0 +1,12 @@
{
"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"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\n INSERT INTO\n mcaptcha_psuedo_campaign_id (config_id, psuedo_id)\n VALUES (\n (SELECT config_id FROM mcaptcha_config WHERE captcha_key = (?)),\n ?\n );",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "9e45969a0f79eab8caba41b0d91e5e3b85a1a68a49136f89fc90793c38f00041"
}

View File

@@ -0,0 +1,58 @@
{
"db_name": "MySQL",
"query": "SELECT\n id, time, difficulty_factor, worker_type\n FROM\n mcaptcha_pow_analytics\n WHERE\n config_id = (\n SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?\n ) \n ORDER BY ID\n LIMIT ? OFFSET ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 1,
"name": "time",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 2,
"name": "difficulty_factor",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 3,
"name": "worker_type",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 3
},
"nullable": [
false,
false,
false,
false
]
},
"hash": "9f10afb0f242f11c58389803c5e85e244cc59102b8929a21e3fcaa852d57a52c"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT config_id from mcaptcha_config WHERE captcha_key = ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "config_id",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
"char_set": 63,
"max_size": 11
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "a89c066db044cddfdebee6a0fd0d80a5a26dcb7ecc00a9899f5634b72ea0a952"
}

View File

@@ -0,0 +1,25 @@
{
"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"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT secret FROM mcaptcha_users WHERE ID = (\n SELECT user_id FROM mcaptcha_config WHERE captcha_key = ?\n )",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "secret",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 200
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "b9258c2494d95701d19703cf5cd05a222057a0ccad943192138b1a4a94bf823b"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "DELETE FROM mcaptcha_config where captcha_key= (?)\n AND\n user_id = (SELECT ID FROM mcaptcha_users WHERE name = ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "b95e5a60a202cb646d5e76df8c7395e4bf881a6dd14e28e6f2e8b93e0536b331"
}

View File

@@ -0,0 +1,25 @@
{
"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"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT name from mcaptcha_users WHERE email = ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "caa1638ee510ef62b86817e5d2baeaca8dfa432c23d7630c0e70737211a4680b"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "UPDATE mcaptcha_users set password = ?\n WHERE name = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "cad5b403470f26c565e74a1dca19b7dee066141dec0f708070067e34d5bf72cc"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "INSERT INTO mcaptcha_config\n (`captcha_key`, `user_id`, `duration`, `name`)\n VALUES (?, (SELECT ID FROM mcaptcha_users WHERE name = ?), ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 4
},
"nullable": []
},
"hash": "d05b84966f4e70c53789221f961bf3637f404f3ba45e880115e97ed1ba5a2809"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT time FROM mcaptcha_pow_solved_stats \n WHERE config_id = (\n SELECT config_id FROM mcaptcha_config \n WHERE \n captcha_key = ?\n AND\n user_id = (\n SELECT \n ID FROM mcaptcha_users WHERE name = ?)) \n ORDER BY time DESC",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "time",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | UNSIGNED | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false
]
},
"hash": "d4b92e8099cd29cfdb99aadeeada739bb6858667fc65f528ec484e98a9da21bc"
}

View File

@@ -0,0 +1,80 @@
{
"db_name": "MySQL",
"query": "SELECT \n mcaptcha_sitekey_user_provided_avg_traffic.avg_traffic, \n mcaptcha_sitekey_user_provided_avg_traffic.peak_sustainable_traffic, \n mcaptcha_sitekey_user_provided_avg_traffic.broke_my_site_traffic,\n mcaptcha_config.name,\n mcaptcha_users.name as username,\n mcaptcha_config.captcha_key\n FROM \n mcaptcha_sitekey_user_provided_avg_traffic \n INNER JOIN\n mcaptcha_config\n ON\n mcaptcha_config.config_id = mcaptcha_sitekey_user_provided_avg_traffic.config_id\n INNER JOIN\n mcaptcha_users\n ON\n mcaptcha_config.user_id = mcaptcha_users.ID\n ORDER BY mcaptcha_config.config_id\n LIMIT ? OFFSET ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "avg_traffic",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 1,
"name": "peak_sustainable_traffic",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 2,
"name": "broke_my_site_traffic",
"type_info": {
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 3,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
},
{
"ordinal": 4,
"name": "username",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
},
{
"ordinal": 5,
"name": "captcha_key",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
true,
false,
false,
false
]
},
"hash": "d587844217f202c23d29c3cb4c819551bc204dd459c956c41024fa74aadbba64"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT time FROM mcaptcha_pow_fetched_stats\n WHERE \n config_id = (\n SELECT \n config_id FROM mcaptcha_config \n WHERE \n captcha_key = ?\n AND\n user_id = (\n SELECT \n ID FROM mcaptcha_users WHERE name = ?))\n ORDER BY time DESC",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "time",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | UNSIGNED | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false
]
},
"hash": "daac5e937aeac2f106eb89154b431fa8bd1bd7baa95e51704fdcdf50bd970a1d"
}

View File

@@ -0,0 +1,36 @@
{
"db_name": "MySQL",
"query": "SELECT name, password FROM mcaptcha_users WHERE name = ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
},
{
"ordinal": 1,
"name": "password",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false
]
},
"hash": "dd5ff10b88fa6f374e105b6bed9e34e0870ac8dd7ce36dfb09d13a1b7005b2eb"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT secret FROM mcaptcha_users WHERE name = ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "secret",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 200
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "dd9b4dec39405ff19af21faabb6a7c3bb3207e7e785fe15357146b88c6c27f01"
}

View File

@@ -0,0 +1,36 @@
{
"db_name": "MySQL",
"query": "SELECT difficulty_factor, visitor_threshold FROM mcaptcha_levels WHERE\n config_id = (\n SELECT config_id FROM mcaptcha_config where captcha_key= (?)\n AND user_id = (SELECT ID from mcaptcha_users WHERE name = ?)\n )\n ORDER BY difficulty_factor ASC;",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "difficulty_factor",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 1,
"name": "visitor_threshold",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false
]
},
"hash": "df6de3b96afcfb7f364f98954995e506b19e80e7f88204405d970c360ad5e1a0"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "INSERT INTO mcaptcha_pow_solved_stats \n (config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config where captcha_key= ?), ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "e2b0b85f2afac1cbca43ce684641bf75ef070e44ce3d00404fc6151d2f4d7bcf"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "\n SELECT\n psuedo_id\n FROM\n mcaptcha_psuedo_campaign_id\n ORDER BY ID ASC LIMIT ? OFFSET ?;",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "psuedo_id",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false
]
},
"hash": "e2c30dafa790b388a193ad8785c0a7d88d8e7a7558775e238fe009f478003e46"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\n DELETE FROM\n mcaptcha_psuedo_campaign_id\n WHERE config_id = (\n SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?\n );",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "e4d9bf156a368dcee1433dd5ced9f1991aa15f84e0ade916433aada40f68f0aa"
}

View File

@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "SELECT name from mcaptcha_users WHERE name = ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "e6569a6064d0e07abea4c0bd4686cdfdaac64f0109ac40efaed06a744a2eaf5e"
}

View File

@@ -0,0 +1,47 @@
{
"db_name": "MySQL",
"query": "SELECT \n avg_traffic, \n peak_sustainable_traffic, \n broke_my_site_traffic \n FROM \n mcaptcha_sitekey_user_provided_avg_traffic \n WHERE \n config_id = (\n SELECT \n config_id \n FROM \n mcaptcha_config \n WHERE \n captcha_key = ? \n AND user_id = (\n SELECT \n id \n FROM \n mcaptcha_users \n WHERE \n NAME = ?\n )\n )\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "avg_traffic",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 1,
"name": "peak_sustainable_traffic",
"type_info": {
"type": "Long",
"flags": "NOT_NULL | NO_DEFAULT_VALUE",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 2,
"name": "broke_my_site_traffic",
"type_info": {
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 11
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
true
]
},
"hash": "e91116ebce127833488130cf1060e0817e5677f39588632452b8d621688c405a"
}

View File

@@ -0,0 +1,36 @@
{
"db_name": "MySQL",
"query": "SELECT name, password FROM mcaptcha_users WHERE email = ?",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 400
}
},
{
"ordinal": 1,
"name": "password",
"type_info": {
"type": "Blob",
"flags": "NOT_NULL | BLOB | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 262140
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false
]
},
"hash": "ed943cbf7e16536d81010255ce2f5beb207b2b9d44cb859fa9f2233405b80ae0"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "INSERT INTO mcaptcha_pow_analytics \n (config_id, time, difficulty_factor, worker_type)\n VALUES ((SELECT config_id FROM mcaptcha_config where captcha_key= ?), ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 4
},
"nullable": []
},
"hash": "f987c4568ab28271d87af47f473b18cf41130a483333e81d5f50199758cbb98b"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>\n--\n-- SPDX-License-Identifier: AGPL-3.0-or-later\n\n-- mark a notification as read\nUPDATE mcaptcha_notifications\n SET read_notification = TRUE\nWHERE \n mcaptcha_notifications.id = ?\nAND\n mcaptcha_notifications.rx = (\n SELECT\n id\n FROM\n mcaptcha_users\n WHERE\n name = ?\n );\n",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "f9f2ed1b2f47828d5d976d2e470e106d54b8a2357f9d525ef0cdb1f7965aa61c"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "DELETE FROM mcaptcha_sitekey_user_provided_avg_traffic\n WHERE config_id = (\n SELECT config_id \n FROM \n mcaptcha_config \n WHERE\n captcha_key = ?\n AND \n user_id = (SELECT ID FROM mcaptcha_users WHERE name = ?)\n );",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "fc717ff0827ccfaa1cc61a71cc7f71c348ebb03d35895c54b011c03121ad2385"
}

View File

@@ -12,10 +12,11 @@ authors = ["realaravinth <realaravinth@batsense.net>"]
async-trait = "0.1.51"
db-core = {path = "../db-core"}
futures = "0.3.15"
sqlx = { version = "0.5.13", features = [ "runtime-actix-rustls", "mysql", "time", "offline" ] }
sqlx = { version = "0.7", features = [ "runtime-tokio-rustls", "mysql", "time"] }
uuid = { version = "1.4.0", features = ["v4", "serde"] }
[dev-dependencies]
actix-rt = "2"
sqlx = { version = "0.5.13", features = [ "runtime-actix-rustls", "mysql", "time", "offline" ] }
sqlx = { version = "0.7", features = [ "runtime-tokio-rustls", "mysql", "time" ] }
db-core = {path = "../db-core", features = ["test"]}
url = { version = "2.2.2", features = ["serde"] }

View File

@@ -1,3 +1,7 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
CREATE TABLE IF NOT EXISTS mcaptcha_users (
name VARCHAR(100) NOT NULL UNIQUE,
email VARCHAR(100) UNIQUE DEFAULT NULL,

View File

@@ -1,3 +1,7 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
-- TODO: changed key -> captcha_key
CREATE TABLE IF NOT EXISTS mcaptcha_config (

View File

@@ -1,3 +1,7 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
CREATE TABLE IF NOT EXISTS mcaptcha_levels (
config_id INTEGER NOT NULL,
difficulty_factor INTEGER NOT NULL,

View File

@@ -1,3 +1,7 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
CREATE TABLE IF NOT EXISTS mcaptcha_pow_fetched_stats (
config_id INTEGER NOT NULL,
time timestamp NOT NULL DEFAULT now(),

View File

@@ -1,3 +1,7 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
CREATE TABLE IF NOT EXISTS mcaptcha_pow_solved_stats (
config_id INTEGER NOT NULL,
time timestamp NOT NULL DEFAULT now(),

View File

@@ -1,3 +1,7 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
CREATE TABLE IF NOT EXISTS mcaptcha_pow_confirmed_stats (
config_id INTEGER NOT NULL,
time timestamp NOT NULL DEFAULT now(),

View File

@@ -1,3 +1,7 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
-- Add migration script here
CREATE TABLE IF NOT EXISTS mcaptcha_notifications (
id INT auto_increment,

View File

@@ -1,3 +1,7 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
CREATE TABLE IF NOT EXISTS mcaptcha_sitekey_user_provided_avg_traffic (
config_id INT NOT NULL,
PRIMARY KEY(config_id),

View File

@@ -1,3 +1,7 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
ALTER TABLE mcaptcha_sitekey_user_provided_avg_traffic
MODIFY avg_traffic INTEGER NOT NULL,
MODIFY peak_sustainable_traffic INTEGER NOT NULL;

View File

@@ -1,2 +1,6 @@
-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
-- Add migration script here
ALTER TABLE mcaptcha_notifications MODIFY heading varchar(100) NOT NULL;

View File

@@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS mcaptcha_pow_analytics (
ID INT auto_increment,
PRIMARY KEY(ID),
config_id INTEGER NOT NULL,
time INTEGER NOT NULL,
difficulty_factor INTEGER NOT NULL,
worker_type VARCHAR(100) NOT NULL,
CONSTRAINT `fk_mcaptcha_config_id_pow_analytics`
FOREIGN KEY (config_id)
REFERENCES mcaptcha_config (config_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View File

@@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS mcaptcha_psuedo_campaign_id (
ID INT auto_increment,
PRIMARY KEY(ID),
psuedo_id varchar(100) NOT NULL UNIQUE,
config_id INT NOT NULL,
CONSTRAINT `fk_mcaptcha_psuedo_campaign_id_config_id`
FOREIGN KEY (config_id)
REFERENCES mcaptcha_config (config_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View File

@@ -0,0 +1,12 @@
-- 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
);

View File

@@ -25,6 +25,31 @@
},
"query": "SELECT time FROM mcaptcha_pow_confirmed_stats \n WHERE \n config_id = (\n SELECT config_id FROM mcaptcha_config \n WHERE \n captcha_key = ?\n AND\n user_id = (\n SELECT \n ID FROM mcaptcha_users WHERE name = ?))\n ORDER BY time DESC"
},
"14dc89b2988b221fd24e4f319b1d48f5e6c65c760c30d11c9c29087f09cee23a": {
"describe": {
"columns": [
{
"name": "captcha_key",
"ordinal": 0,
"type_info": {
"char_set": 224,
"flags": {
"bits": 4101
},
"max_size": 400,
"type": "VarString"
}
}
],
"nullable": [
false
],
"parameters": {
"Right": 1
}
},
"query": "SELECT\n captcha_key\n FROM\n mcaptcha_config\n WHERE\n config_id = (\n SELECT\n config_id\n FROM\n mcaptcha_psuedo_campaign_id\n WHERE\n psuedo_id = ?\n );"
},
"22e697114c3ed5b0156cdceab11a398f1ef3a804f482e1cd948bc615ef95fc92": {
"describe": {
"columns": [],
@@ -144,6 +169,83 @@
},
"query": "SELECT email FROM mcaptcha_users WHERE name = ?"
},
"42d967d6e080efd3cff8d4df13ea4d2ff38f3093da5c97000349dfc23c4d4eb3": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": {
"char_set": 63,
"flags": {
"bits": 515
},
"max_size": 11,
"type": "Long"
}
},
{
"name": "heading",
"ordinal": 1,
"type_info": {
"char_set": 224,
"flags": {
"bits": 4097
},
"max_size": 400,
"type": "VarString"
}
},
{
"name": "message",
"ordinal": 2,
"type_info": {
"char_set": 224,
"flags": {
"bits": 4097
},
"max_size": 1000,
"type": "VarString"
}
},
{
"name": "received",
"ordinal": 3,
"type_info": {
"char_set": 63,
"flags": {
"bits": 1185
},
"max_size": 19,
"type": "Timestamp"
}
},
{
"name": "name",
"ordinal": 4,
"type_info": {
"char_set": 224,
"flags": {
"bits": 4101
},
"max_size": 400,
"type": "VarString"
}
}
],
"nullable": [
false,
false,
false,
false,
false
],
"parameters": {
"Right": 1
}
},
"query": "-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>\n--\n-- SPDX-License-Identifier: AGPL-3.0-or-later\n\n-- gets all unread notifications a user has\nSELECT \n mcaptcha_notifications.id,\n mcaptcha_notifications.heading,\n mcaptcha_notifications.message,\n mcaptcha_notifications.received,\n mcaptcha_users.name\nFROM\n mcaptcha_notifications \nINNER JOIN \n mcaptcha_users \nON \n mcaptcha_notifications.tx = mcaptcha_users.id\nWHERE \n mcaptcha_notifications.rx = (\n SELECT \n id \n FROM \n mcaptcha_users\n WHERE\n name = ?\n )\nAND \n mcaptcha_notifications.read_notification IS NULL;\n"
},
"598a8202942771eff460faa6f09bd3fb1fc910d5fab7edb07c49dadbbaeb1cb8": {
"describe": {
"columns": [],
@@ -154,6 +256,31 @@
},
"query": "INSERT INTO mcaptcha_pow_fetched_stats \n (config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config where captcha_key= ?), ?)"
},
"5ad1ef722a961183228d851813b9f50284520bf8cc8118c765b72c108daaf6fb": {
"describe": {
"columns": [
{
"name": "psuedo_id",
"ordinal": 0,
"type_info": {
"char_set": 224,
"flags": {
"bits": 4101
},
"max_size": 400,
"type": "VarString"
}
}
],
"nullable": [
false
],
"parameters": {
"Right": 1
}
},
"query": "SELECT psuedo_id FROM\n mcaptcha_psuedo_campaign_id\n WHERE\n config_id = (SELECT config_id FROM mcaptcha_config WHERE captcha_key = (?));\n "
},
"5d5a106981345e9f62bc2239c00cdc683d3aaaa820d63da300dc51e3f6f363d3": {
"describe": {
"columns": [],
@@ -164,6 +291,16 @@
},
"query": "INSERT INTO mcaptcha_users \n (name , password, secret) VALUES (?, ?, ?)"
},
"6094468b7fa20043b0da90e366b7f1fa29a8c748e163b6712725440b25ae9361": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 1
}
},
"query": "\n DELETE FROM\n mcaptcha_pow_analytics\n WHERE\n config_id = (\n SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?\n ) "
},
"66ec7df10484f8e0206f3c97afc9136021589556c38dbbed341d6574487f79f2": {
"describe": {
"columns": [
@@ -406,6 +543,80 @@
},
"query": "UPDATE mcaptcha_users set email = ?\n WHERE name = ?"
},
"9e45969a0f79eab8caba41b0d91e5e3b85a1a68a49136f89fc90793c38f00041": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 2
}
},
"query": "\n INSERT INTO\n mcaptcha_psuedo_campaign_id (config_id, psuedo_id)\n VALUES (\n (SELECT config_id FROM mcaptcha_config WHERE captcha_key = (?)),\n ?\n );"
},
"9f10afb0f242f11c58389803c5e85e244cc59102b8929a21e3fcaa852d57a52c": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": {
"char_set": 63,
"flags": {
"bits": 515
},
"max_size": 11,
"type": "Long"
}
},
{
"name": "time",
"ordinal": 1,
"type_info": {
"char_set": 63,
"flags": {
"bits": 4097
},
"max_size": 11,
"type": "Long"
}
},
{
"name": "difficulty_factor",
"ordinal": 2,
"type_info": {
"char_set": 63,
"flags": {
"bits": 4097
},
"max_size": 11,
"type": "Long"
}
},
{
"name": "worker_type",
"ordinal": 3,
"type_info": {
"char_set": 224,
"flags": {
"bits": 4097
},
"max_size": 400,
"type": "VarString"
}
}
],
"nullable": [
false,
false,
false,
false
],
"parameters": {
"Right": 3
}
},
"query": "SELECT\n id, time, difficulty_factor, worker_type\n FROM\n mcaptcha_pow_analytics\n WHERE\n config_id = (\n SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?\n ) \n ORDER BY ID\n LIMIT ? OFFSET ?"
},
"a89c066db044cddfdebee6a0fd0d80a5a26dcb7ecc00a9899f5634b72ea0a952": {
"describe": {
"columns": [
@@ -466,83 +677,6 @@
},
"query": "DELETE FROM mcaptcha_config where captcha_key= (?)\n AND\n user_id = (SELECT ID FROM mcaptcha_users WHERE name = ?)"
},
"b9b0c63380bc0dfdea8aae092dcefceb316fe94667d74f53d53063810cdd2ba8": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": {
"char_set": 63,
"flags": {
"bits": 515
},
"max_size": 11,
"type": "Long"
}
},
{
"name": "heading",
"ordinal": 1,
"type_info": {
"char_set": 224,
"flags": {
"bits": 4097
},
"max_size": 400,
"type": "VarString"
}
},
{
"name": "message",
"ordinal": 2,
"type_info": {
"char_set": 224,
"flags": {
"bits": 4097
},
"max_size": 1000,
"type": "VarString"
}
},
{
"name": "received",
"ordinal": 3,
"type_info": {
"char_set": 63,
"flags": {
"bits": 1185
},
"max_size": 19,
"type": "Timestamp"
}
},
{
"name": "name",
"ordinal": 4,
"type_info": {
"char_set": 224,
"flags": {
"bits": 4101
},
"max_size": 400,
"type": "VarString"
}
}
],
"nullable": [
false,
false,
false,
false,
false
],
"parameters": {
"Right": 1
}
},
"query": "-- gets all unread notifications a user has\nSELECT \n mcaptcha_notifications.id,\n mcaptcha_notifications.heading,\n mcaptcha_notifications.message,\n mcaptcha_notifications.received,\n mcaptcha_users.name\nFROM\n mcaptcha_notifications \nINNER JOIN \n mcaptcha_users \nON \n mcaptcha_notifications.tx = mcaptcha_users.id\nWHERE \n mcaptcha_notifications.rx = (\n SELECT \n id \n FROM \n mcaptcha_users\n WHERE\n name = ?\n )\nAND \n mcaptcha_notifications.read_notification IS NULL;\n"
},
"caa1638ee510ef62b86817e5d2baeaca8dfa432c23d7630c0e70737211a4680b": {
"describe": {
"columns": [
@@ -578,16 +712,6 @@
},
"query": "UPDATE mcaptcha_users set password = ?\n WHERE name = ?"
},
"cf333541509213f11a9bf7119dcb3289bb77abf1482fc1d47e7f5bb27bdc8d97": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 2
}
},
"query": "-- mark a notification as read\nUPDATE mcaptcha_notifications\n SET read_notification = TRUE\nWHERE \n mcaptcha_notifications.id = ?\nAND\n mcaptcha_notifications.rx = (\n SELECT\n id\n FROM\n mcaptcha_users\n WHERE\n name = ?\n );\n"
},
"d05b84966f4e70c53789221f961bf3637f404f3ba45e880115e97ed1ba5a2809": {
"describe": {
"columns": [],
@@ -759,6 +883,16 @@
},
"query": "INSERT INTO mcaptcha_pow_solved_stats \n (config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config where captcha_key= ?), ?)"
},
"e4d9bf156a368dcee1433dd5ced9f1991aa15f84e0ade916433aada40f68f0aa": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 1
}
},
"query": "\n DELETE FROM\n mcaptcha_psuedo_campaign_id\n WHERE config_id = (\n SELECT config_id FROM mcaptcha_config WHERE captcha_key = ?\n );"
},
"e6569a6064d0e07abea4c0bd4686cdfdaac64f0109ac40efaed06a744a2eaf5e": {
"describe": {
"columns": [
@@ -873,6 +1007,26 @@
},
"query": "SELECT name, password FROM mcaptcha_users WHERE email = ?"
},
"f987c4568ab28271d87af47f473b18cf41130a483333e81d5f50199758cbb98b": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 4
}
},
"query": "INSERT INTO mcaptcha_pow_analytics \n (config_id, time, difficulty_factor, worker_type)\n VALUES ((SELECT config_id FROM mcaptcha_config where captcha_key= ?), ?, ?, ?)"
},
"f9f2ed1b2f47828d5d976d2e470e106d54b8a2357f9d525ef0cdb1f7965aa61c": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Right": 2
}
},
"query": "-- SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>\n--\n-- SPDX-License-Identifier: AGPL-3.0-or-later\n\n-- mark a notification as read\nUPDATE mcaptcha_notifications\n SET read_notification = TRUE\nWHERE \n mcaptcha_notifications.id = ?\nAND\n mcaptcha_notifications.rx = (\n SELECT\n id\n FROM\n mcaptcha_users\n WHERE\n name = ?\n );\n"
},
"fc717ff0827ccfaa1cc61a71cc7f71c348ebb03d35895c54b011c03121ad2385": {
"describe": {
"columns": [],

View File

@@ -1,19 +1,7 @@
/*
* 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/>.
*/
// Copyright (C) 2022 Aravinth Manivannan <realaravinth@batsense.net>
// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//! Error-handling utilities
use std::borrow::Cow;

Some files were not shown because too many files have changed in this diff Show More