Compare commits

...

321 commits

Author SHA1 Message Date
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
realaravinth
9f521fe199
feat: publish mcaptcha bin to dl.mcaptcha.org 2022-08-15 17:03:46 +05:30
realaravinth
8ac1e2b81e
feat: package and sign dist assets 2022-08-15 17:03:46 +05:30
Aravinth Manivannan
5db58d477b
Merge pull request #24 from mCaptcha/dependabot/npm_and_yarn/nanoid-3.3.4
Bump nanoid from 3.1.29 to 3.3.4
2022-08-14 01:32:55 +05:30
Aravinth Manivannan
db03cd3b1f
Merge pull request #34 from mCaptcha/dependabot/npm_and_yarn/terser-5.14.2
chore(deps): bump terser from 5.9.0 to 5.14.2
2022-08-14 01:32:25 +05:30
realaravinth
e5e89bd8a0
chore: bump libmcaptcha, switch to master 2022-08-13 01:58:40 +05:30
Aravinth Manivannan
2dd6f063c5
Merge pull request #40 from Gusted/automate-releases
Automate releases via Github Actions
2022-08-12 18:39:48 +05:30
Gusted
bb81e7fb9b
Automate releases via Github Actions
- Use Github Actions to compile static linked binaries for the three
major OS and upload them to Github Releases.
2022-08-12 14:55:57 +02:00
realaravinth
b3d00c89a6
feat: increase demo test waint time 2022-08-09 17:08:26 +05:30
realaravinth
8c9587ad65
feat: set custom runers and queue length 2022-08-09 16:30:04 +05:30
realaravinth
21825582e5
feat: fallabck to localhost when running tests 2022-08-09 16:29:24 +05:30
realaravinth
f8e6bdf229
feat: bump libmcaptcha 2022-08-09 16:29:05 +05:30
realaravinth
8c576d2b07
feat: queue length and IP runner config 2022-08-09 16:28:30 +05:30
realaravinth
c377cf431e
feat & fix: ip queues 2022-08-09 02:52:17 +05:30
realaravinth
ce1b3b0856
feat: bump libmcaptcha and pow_sha256 2022-08-09 02:51:40 +05:30
Aravinth Manivannan
cd6cecfe4a
Merge pull request #39 from evilsocket/master
fix: fixes broken docker-compose.yml (#38)
2022-08-05 17:40:05 +05:30
Simone Margaritelli
a66d75c3c3 fix: fixes broken docker-compose.yml (#38) 2022-08-05 14:00:40 +02:00
Aravinth Manivannan
3d9056e968
Merge pull request #36 from kianmeng/fix-typos
Fix typos
2022-08-05 14:26:11 +05:30
Kian-Meng Ang
bb42841a66 Fix typos 2022-08-04 23:06:54 +08:00
Aravinth Manivannan
961bb6c5f4
Merge pull request #35 from Gusted/use-full-screen
Let widget use full-screen
2022-07-27 21:35:52 +05:30
Gusted
f56bc6d9e4
Let widget use full-screen
- Instead of using static values for dimensions. Use responsive CSS and
take up the whole screen. Let the user deal with setting the correct
dimensions accordingly.
2022-07-26 22:58:17 +02:00
realaravinth
a040b39558
fix: set db type when overriding with DATABASE_URL 2022-07-23 16:46:49 +05:30
realaravinth
80214b776c
feat: add database_type attr and make db connection parameter descriptions generic 2022-07-23 16:22:51 +05:30
realaravinth
6de9129cd0
feat: add instructions to setup mariadb 2022-07-23 16:17:59 +05:30
realaravinth
1fded38ee8
fix: gh-pages branch CI trigger exclusion 2022-07-23 15:57:24 +05:30
realaravinth
96119fdc71
feat: adapt migrate and sqlx-offline-data to include mariadb support 2022-07-23 15:50:47 +05:30
realaravinth
337a378b08
feat: add checks to verify the DB error situations 2022-07-23 15:50:25 +05:30
realaravinth
d5b17ac00e
fix: mariadb error to lib error conversion 2022-07-23 15:50:01 +05:30
realaravinth
a50763f520
feat: implement get_secret_from_captcha for db-sqlx-mariadb 2022-07-23 15:49:41 +05:30
realaravinth
6f5c09185f
feat: add MARIA_DATABASE_URL to .env_sample and load maria config in CI 2022-07-23 12:04:17 +05:30
realaravinth
249b6461ee
chore: migrate tests to also run with mariadb 2022-07-23 11:59:42 +05:30
realaravinth
912b342e0e
feat: conditionally init postgres/mariadb connection 2022-07-23 11:59:42 +05:30
realaravinth
f9efb062e0
feat: accept alt DB configuration 2022-07-23 11:59:42 +05:30
realaravinth
b8d3b1449a
feat: adapt db/db-migrations to run mariadb migrations 2022-07-23 11:59:42 +05:30
realaravinth
9b5b34a1f8
feat: impl MCDatabase for mariadb 2022-07-23 11:59:42 +05:30
realaravinth
0b2af2f900
feat: setup CI for mariadb support 2022-07-23 11:59:41 +05:30
realaravinth
9371416398
fix: normalize username during login process too
credits: @gusted
2022-07-23 02:24:30 +05:30
realaravinth
9a687f99ee
feat: mv maildev to services 2022-07-23 02:13:12 +05:30
realaravinth
b6afe79a81
fix: initialize DOM elements only when executing methods/in pages that
contain those elements

SUMMARY
    Trying to grab elements globally in a script results in it trying to
    initialize in all pages. When the element is absent, the script
    fails and JavaScript crashes.
2022-07-23 00:48:51 +05:30
realaravinth
b12c30e956
feat: cache-bust when make run is called 2022-07-23 00:48:05 +05:30
realaravinth
c5dc72a83c
fix: don't escape license prefixes and script content 2022-07-23 00:47:44 +05:30
realaravinth
3c3982bad5
feat: CI: publish docker img 2022-07-22 23:42:25 +05:30
realaravinth
c92a35a01f
fix: add sqlx offline compilation data 2022-07-22 20:04:41 +05:30
realaravinth
5410a4657b
feat: add changelog entry to doc change in access token verification
payload
2022-07-22 19:49:07 +05:30
realaravinth
7d0e4c6be4
fix: prevent sitekey abuse with account secret authentication for access token validation
SUMMARY
    At present, sitekey can be abused by installing it on a third-party
    site as verifying the access token returned from CAPTCHA validation
    doesn't require any authentication.

    This fix uses account secret authentication to verify access tokens

credits: by @gusted
2022-07-22 19:44:35 +05:30
realaravinth
85f91cb79b
feat: update libmcaptcha 2022-07-21 18:29:16 +05:30
realaravinth
31978a83f2
fix: docker-compose -d up -> docker-compose up -d 2022-07-20 14:45:25 +05:30
realaravinth
22b312b8c5
fix: services.mcaptcha.depends_on must be a list 2022-07-20 14:44:46 +05:30
dependabot[bot]
8a667ad71f
chore(deps): bump terser from 5.9.0 to 5.14.2
Bumps [terser](https://github.com/terser/terser) from 5.9.0 to 5.14.2.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-20 06:01:46 +00:00
PierreC
2dce6eb2e8
Fixing some docs issues and adding some lines in docker-compose.yml (#33)
* Update README.md

* Update README.md

* Update DEPLOYMENT.md

* Update docker-compose.yml
2022-07-19 15:54:42 +05:30
realaravinth
c7d1bc3191
fix: rename postgres in docker-compose to avoid namespace collision
fixes: https://github.com/mCaptcha/mCaptcha/issues/31
2022-07-18 22:58:02 +05:30
Aravinth Manivannan
37004c7b4f
Merge pull request #30 from felixonmars/patch-1
Correct typos in HACKING.md
2022-07-17 14:37:53 +05:30
Felix Yan
fa9a1a2f4c
Correct typos in HACKING.md 2022-07-17 13:29:21 +08:00
realaravinth
5daeffd6fb
chore: tests to verify mCaptcha counter 2022-05-31 12:46:09 +05:30
realaravinth
be9c6b757e
fix: invert debug flag to set DB logging flag 2022-05-30 16:56:55 +05:30
realaravinth
b30bc67bd4
feat: conditional SQL statements logging for db-sqlx-postgres 2022-05-30 15:48:54 +05:30
realaravinth
a9f8cc24a6
feat: docker build caching with cargo-chef 2022-05-28 16:22:34 +05:30
realaravinth
3710c8f653
feat: fix sqlx offline compilation 2022-05-27 19:06:07 +05:30
realaravinth
629c841e2d
chore: cleanup and addressing clippy lints 2022-05-27 18:37:59 +05:30
realaravinth
d7fd23f565
chore: get rid of direct DB init and use db_* 2022-05-27 18:25:27 +05:30
realaravinth
cd72ae6ffe
feat: migrate fetch captcha config to use db_* 2022-05-27 18:16:47 +05:30
realaravinth
3a535c04a6
feat: impl traits to fetch captcha config sqlx postgres 2022-05-27 18:16:27 +05:30
realaravinth
2212b3b974
feat: def traits to get captcha config 2022-05-27 18:14:51 +05:30
realaravinth
a15d963c3e
feat: migrate get_levels to use db_* 2022-05-27 17:24:40 +05:30
realaravinth
098d0cfc24
feat: migrate fetching stats to use db_* 2022-05-27 17:11:15 +05:30
realaravinth
bc90a51d30
feat: impl fetch captcha stats sqlx postgres 2022-05-27 17:08:55 +05:30
realaravinth
cf66e7efc6
feat: def traits to fetch captcha stats 2022-05-27 17:07:10 +05:30
realaravinth
21dcc2144b
feat: add cmd to run db tests only 2022-05-27 17:07:05 +05:30
realaravinth
bbc8873762
feat: migrate record_stats to use db_* 2022-05-27 16:23:33 +05:30
realaravinth
d28d752a78
feat: impl record stats traits for sqlx postgres 2022-05-27 16:22:45 +05:30
realaravinth
0d395ea67e
feat: def traits to record captcha fetch stats 2022-05-27 16:21:47 +05:30
realaravinth
851874f8cf
feat: load config to make captcha stats optional 2022-05-27 15:25:33 +05:30
realaravinth
4cd4605266
chore: use local app ctx 2022-05-27 15:25:10 +05:30
realaravinth
12edac7915
feat: migrate get_email to use db_* 2022-05-27 03:08:37 +05:30
realaravinth
38d518d843
feat: impl def_email for sqlx postgres 2022-05-26 20:35:38 +05:30
realaravinth
6e45c643b1
feat: def get_email trait 2022-05-26 20:35:25 +05:30
realaravinth
aad49dbb94
feat: migrate notifications add, mark_read and get to use db_* traits 2022-05-26 20:03:05 +05:30
realaravinth
44740535c2
feat: impl traits to add, get and mark read notifications for sqlx
postgres
2022-05-26 19:32:16 +05:30
realaravinth
e9921db55b
feat: def traits for adding, getting notifications and marking them read 2022-05-26 19:31:36 +05:30
realaravinth
e4cf625d48
feat: migrate del traffic pattern to use db_* interface 2022-05-14 18:57:58 +05:30
realaravinth
84a92468a1
feat: impl sqlx postgress interface to del traffic pattern 2022-05-14 18:57:21 +05:30
realaravinth
5270ced600
feat: def interface to del traffic pattern 2022-05-14 18:56:41 +05:30
realaravinth
2dd18897b0
feat: migrate getting traffic pattern to use db_* interface 2022-05-14 18:45:59 +05:30
realaravinth
b983f08884
feat: impl sqlx postgress interface to get traffic pattern 2022-05-14 18:45:42 +05:30
realaravinth
212c03a0e2
feat: def interface to get traffic pattern 2022-05-14 18:45:25 +05:30
realaravinth
a6920f5f36
feat: migrate add user's traffic pattern sqlx postgres to use db_* 2022-05-14 18:22:50 +05:30
realaravinth
dacdd2cb8e
feat: implement interface to add user's traffic pattern sqlx postgres 2022-05-14 18:22:36 +05:30
realaravinth
2132ab5791
feat: define interface to add user's traffic pattern 2022-05-14 18:22:21 +05:30
realaravinth
04b0073d7c
feat: migrate DB migrations to use db_* 2022-05-14 16:44:42 +05:30
realaravinth
d061824660
feat: migrate get captcha cooldown period to use db_* 2022-05-14 16:27:44 +05:30
realaravinth
7daffe767c
feat: implement get captcha cooldown period interface for sqlx postgres 2022-05-14 16:27:28 +05:30
realaravinth
09a8591cb4
feat: define get captcha cooldown period interface 2022-05-14 16:27:15 +05:30
realaravinth
9d7bb3c0be
feat: use cache busting bin and load assets generated by it 2022-05-14 16:00:22 +05:30
realaravinth
0593e254bb
feat: run cache busting via a separate bin 2022-05-14 15:59:40 +05:30
realaravinth
a971d4209d
fix and chore: refactor tests to minimize initializing DB connections
SUMMARY
    The test suite was spinning up way too many database connections that what's
    strictly needed and so the test suite was failing with[0]:
	code: "53300", message: "sorry, too many clients already"

EXPERIMENTS
    Tried sharing database connection pool across all tests with
    async_once[0] but faced:
	- IO errors
	    The connections were probably getting dropped in between tests
	- actix Actor errors
	    The actor was probably not getting initialized before a
	    a reference to the async_once initialized app
	    context(crate::data::Data) is retrieved and used

FIX
    crate::tests was spinning up an App context
    instance(crate::data::Data) for most utility functions, which was
    unnecessarily excessive.

    Each test now creates an instance of the application context at the
    beginning and shared a reference with all test utility functions. So
    number of database connections/app context instance = number of unit
    tests.

[0]: permanently fixes #22
[1]: https://docs.rs/async_once/latest/async_once/
2022-05-14 12:55:56 +05:30
realaravinth
176df3c7a7
feat: migrate get captcha levels to use db_* 2022-05-13 19:09:29 +05:30
realaravinth
ddb6d336f7
feat: implement accountnotfound and captcha notfound err vals for sqlx postgres 2022-05-13 19:09:00 +05:30
realaravinth
3edb2252af
feat: define accountnotfound and captcha notfound err vals 2022-05-13 19:08:14 +05:30
realaravinth
a7590ea14e
feat: implement getting captcha levels for sqlx postgres 2022-05-13 19:07:50 +05:30
realaravinth
04a9bc5cc7
feat: define interface for getting captcha levels 2022-05-13 19:07:27 +05:30
realaravinth
2dff139ae2
feat: migrate update_key to use db_* 2022-05-12 20:22:43 +05:30
realaravinth
b2d32c6113
feat: implement update_captcha_key for sqlx postgres 2022-05-12 20:19:08 +05:30
realaravinth
e2ebae6e2e
feat: define interface for update_captcha_key 2022-05-12 20:18:53 +05:30
realaravinth
aa5bdcf1dc
fix: upload coverage on all branches that run the coverage CI run 2022-05-12 20:18:28 +05:30
realaravinth
add7271531
feat: migrate updating captcha metadata to use db_* 2022-05-12 20:09:56 +05:30
realaravinth
6b10ed6982
feat: implement updating captcha metadata for sqlx postgres 2022-05-12 20:09:40 +05:30
realaravinth
1e6a259d57
feat: define interface for updating captcha metadata 2022-05-12 20:09:18 +05:30
realaravinth
c458e4a233
fix: inject postgres URL while running migrations 2022-05-12 19:57:06 +05:30
realaravinth
b6445000fe
feat: migrate delete captcha to use db_* interface 2022-05-12 19:56:23 +05:30
realaravinth
15c352f6b5
feat: implement delete_captcha_levels and delete_captcha for sqlx postgres 2022-05-12 19:55:51 +05:30
realaravinth
af46a3c54d
feat: define interfaces for delete_captcha_levels and delete_captcha 2022-05-12 19:55:03 +05:30
realaravinth
0c1a82b4c5
feat: migrate tests utils to use db_* interface 2022-05-12 19:33:26 +05:30
realaravinth
81ad030338
feat: migrate captcha exists to use db_* interface 2022-05-12 19:32:08 +05:30
realaravinth
0bb975a230
feat: implement captcha exists interface for sqlx postgres 2022-05-12 19:31:50 +05:30
realaravinth
55518ef650
feat: define captcha_exists interface 2022-05-12 19:31:26 +05:30
realaravinth
2f924607ab
fix: harden failure modes on hotfix test fix 2022-05-12 19:30:13 +05:30
realaravinth
28e9d67fce
fix: load correct env file 2022-05-12 19:29:48 +05:30
realaravinth
bd75fc625c
feat: migrate adding captcha to use db_* interface 2022-05-12 19:10:04 +05:30
realaravinth
79ff7b9917
feat: implement adding captcha for sqlx postgres 2022-05-12 19:09:44 +05:30
realaravinth
277d2bb9e5
feat: define interface for adding captcha 2022-05-12 19:09:25 +05:30
realaravinth
0d3d552ae0
feat: migrate create captcha to use db_* 2022-05-12 18:59:44 +05:30
realaravinth
d64b05c84f
feat: implement create captcha for sqlx postgres 2022-05-12 11:52:53 +05:30
realaravinth
00dca4a069
feat: define interface for creating captcha 2022-05-12 11:50:24 +05:30
realaravinth
049f2b6eea
feat: migrate update secret to use db_* interface 2022-05-12 10:42:55 +05:30
realaravinth
ec6b49c2e1
feat: implement update secret interface for sqlx postgres 2022-05-12 10:21:13 +05:30
realaravinth
d4a080b5fc
feat: define interface for updating user secret 2022-05-12 10:20:41 +05:30
realaravinth
25b3d316db
feat: migrate get password and get secret to use db_* interface 2022-05-11 20:21:55 +05:30
realaravinth
8813cf80ce
feat: implement get secret interface for sqlx postgres 2022-05-11 20:21:33 +05:30
realaravinth
28ddadc5fe
feat: define interface for getting user secret 2022-05-11 20:21:06 +05:30
realaravinth
f165581e17
chore: lints 2022-05-11 20:11:11 +05:30
realaravinth
96995bc068
feat: migrate get password to use db_* interface 2022-05-11 20:11:02 +05:30
realaravinth
39ee2ad221
feat: migrate update username to use db_* interface 2022-05-11 20:02:03 +05:30
realaravinth
f79d159468
feat: implement update username for sqlx postgres 2022-05-11 20:01:48 +05:30
realaravinth
83f6456a59
feat: define interface for updating username 2022-05-11 20:01:32 +05:30
realaravinth
748f48e0d2
feat: migrate update password to use db_* interface 2022-05-11 19:52:20 +05:30
realaravinth
374bbb2403
feat: implement change password for sqlx postgres 2022-05-11 19:51:39 +05:30
realaravinth
f55a383eb5
feat: define interface to change password 2022-05-11 19:51:06 +05:30
realaravinth
f398c4b61c
feat: migrate get password to use db_* interface 2022-05-11 18:54:36 +05:30
realaravinth
5bcf7beddc
fix: return username to store in sessions when getting password 2022-05-11 18:54:17 +05:30
realaravinth
d9b36179d1
feat: implement fetching password with either username or email 2022-05-11 18:30:01 +05:30
realaravinth
7e2be86c12
feat: get password using either username or email 2022-05-11 18:26:35 +05:30
realaravinth
fdf4f0bef9
feat: implement password fetching for sqlx postgres 2022-05-11 15:43:25 +05:30
realaravinth
6377d07dce
feat: define interface for fetching user password 2022-05-11 15:43:03 +05:30
realaravinth
78eac8b6b7
feat: migrate email update to use db_* interface 2022-05-11 15:26:00 +05:30
realaravinth
66226f893a
feat: implement email updates for sqlx postgres 2022-05-11 15:25:43 +05:30
realaravinth
58216f0f63
feat: define interface for updating email of a user 2022-05-11 15:25:25 +05:30
realaravinth
8861201727
feat: run linting and coverage CI runs on db-abstract branch 2022-05-11 13:34:11 +05:30
realaravinth
621e400ea8
feat: migrate email exists to use db_* interface 2022-05-11 13:33:30 +05:30
realaravinth
84671c4a11
feat: implement email exists for sqlx postgres 2022-05-11 13:33:30 +05:30
realaravinth
9595ea232b
feat: define interface for checking if user email exists 2022-05-11 13:33:30 +05:30
realaravinth
136439c97a
feat: add sqlx offline data generation 2022-05-11 13:33:30 +05:30
realaravinth
6ab6df02ed
fix: use db/db-migrations for DB migrations 2022-05-11 13:33:29 +05:30
realaravinth
af36961299
feat: implement postgres migrations 2022-05-11 13:33:29 +05:30
realaravinth
95e7a74559
feat: setup CI to use .env_sample and postgres URI 2022-05-11 13:33:29 +05:30
realaravinth
1cd4ce7318
feat: migrate username exists to use db_* interface 2022-05-11 13:33:29 +05:30
realaravinth
3a80281e86
feat: setup and run tests for sqlx postgres 2022-05-11 13:33:29 +05:30
realaravinth
79cc28bfd8
feat: implement username exists for postgres via sqlx 2022-05-11 13:33:29 +05:30
realaravinth
e244713ad7
feat: implement basic tests 2022-05-11 13:33:29 +05:30
realaravinth
454075a3d9
feat: define username exists endpoint 2022-05-11 13:33:29 +05:30
realaravinth
9e5b54a23d
feat: setup tests on db_* workspaces 2022-05-11 13:33:29 +05:30
realaravinth
5359795ddc
feat: enable CI for db-abstract 2022-05-11 13:33:29 +05:30
realaravinth
9f91854c4d
feat: migrate account deletion to use db_* interface 2022-05-11 13:33:29 +05:30
realaravinth
5dc818a1c1
feat: implemente delete account for postgres via sqlx 2022-05-11 13:33:29 +05:30
realaravinth
4bdbb52d8f
feat: define delete account db interface 2022-05-11 13:33:29 +05:30
realaravinth
4248959b13
feat: migrate user regisration to use db_* 2022-05-11 13:33:29 +05:30
realaravinth
26a0935e5f
feat: implement user registration for postgres via sqlx 2022-05-11 13:33:29 +05:30
realaravinth
8dde022851
feat: define interface for username registration" 2022-05-11 13:33:29 +05:30
realaravinth
43aac949e3
feat: convert db errors to service errors 2022-05-11 13:33:29 +05:30
realaravinth
f337721b25
feat: move health endpoint to use ping from db_* 2022-05-11 13:33:29 +05:30
realaravinth
79506a93b9
feat: load db_* db connection 2022-05-11 13:33:29 +05:30
realaravinth
1d8554cb36
chore: rust fmpt 2022-05-11 13:33:29 +05:30
realaravinth
b7a8716a82
feat: define checking routine 2022-05-11 13:33:29 +05:30
realaravinth
dba1f662a7
feat: init postgres implementation via sqlx 2022-05-11 13:33:29 +05:30
realaravinth
02abffd63a
feat: init and define database ops as interfaces to support multiple DBs 2022-05-11 13:33:29 +05:30
realaravinth
246dcfddb7
feat: mv db migrations to workspace 2022-05-11 13:33:29 +05:30
realaravinth
56225ae2e4
chore: actix-web updates: replace deprecated methods 2022-05-11 13:33:28 +05:30
realaravinth
6550266aef
feat: don't run cache busting routines during debug build 2022-05-11 13:33:28 +05:30
realaravinth
100fb4d5ab
feat: document .env 2022-05-11 13:33:28 +05:30
Aravinth Manivannan
8b7164635d
Merge pull request #26 from ChocoMilkWithoutSugar/master
Update README.md
2022-05-11 12:00:14 +05:30
Aravinth Manivannan
76230eed9e
Update README.md
Formatting default credentials
2022-05-11 06:28:06 +00:00
Luca
e2d126da30 Update README.md
add default credentials
2022-05-10 20:35:09 -03:00
dependabot[bot]
72cff2a470
Bump nanoid from 3.1.29 to 3.3.4
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.29 to 3.3.4.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.29...3.3.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-07 10:54:21 +00:00
561 changed files with 42374 additions and 11707 deletions

View file

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

2
.env_sample Normal file
View file

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

View file

@ -6,69 +6,34 @@ on:
push:
branches:
- master
- db-abstract
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,98 +1,119 @@
name: Coverage
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- master
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
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/setup-node@v2
with:
node-version: "16.x"
- name: start smtp server
run: docker run -d -p 1080:1080 -p 10025:1025 maildev/maildev --incoming-user admin --incoming-pass password
- 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:
DATABASE_URL: postgres://postgres:password@localhost:5432/postgres
- name: build frontend
run: make frontend
- name: Generate coverage file
if: (github.ref == 'refs/heads/master' || github.event_name == 'pull_request')
uses: actions-rs/tarpaulin@v0.1
with:
args: "-t 1200"
env:
DATABASE_URL: postgres://postgres:password@localhost:5432/postgres
# 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.ref == 'refs/heads/master' || 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

@ -8,6 +8,8 @@ on:
push:
branches:
- master
- "*"
- "!gh-pages"
jobs:
build_and_test:
@ -15,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
@ -36,47 +36,72 @@ jobs:
--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@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 == 'mCaptcha/mCaptcha'
run: echo -n "$RELEASE_BOT_GPG_SIGNING_KEY" | gpg --batch --import --pinentry-mode loopback
env:
RELEASE_BOT_GPG_SIGNING_KEY: ${{ secrets.RELEASE_BOT_GPG_SIGNING_KEY }}
- name: load env
run: |
source .env_sample \
&& 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'
node-version: "20.0.0"
- name: start smtp server
run: docker run -d -p 1080:1080 -p 10025:1025 maildev/maildev --incoming-user admin --incoming-pass password
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Install ${{ matrix.version }}
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.version }}-x86_64-unknown-linux-gnu
profile: minimal
override: true
- name: install nightwatch dep
run: sudo apt-get install xvfb
- name: Run migrations
run: make migrate
env:
DATABASE_URL: postgres://postgres:password@localhost:5432/postgres
POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
- name: build
run: make
env:
DATABASE_URL: postgres://postgres:password@localhost:5432/postgres
POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
# - name: build frontend
# run: make frontend
@ -87,13 +112,36 @@ jobs:
- name: run tests
run: make test
env:
DATABASE_URL: postgres://postgres:password@localhost:5432/postgres
POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
- name: run integration tests
run: make test.integration
- name: Login to DockerHub
if: github.ref == 'refs/heads/master' && github.event_name == 'push' && github.repository == 'mCaptcha/mCaptcha'
uses: docker/login-action@v1
with:
username: mcaptcha
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: publish docker images
if: (github.ref == 'refs/heads/master' || github.event_name == 'push') && github.repository == 'mCaptcha/mCaptcha'
run: make docker-publish
- name: publish bins
if: (github.ref == 'refs/heads/master' || github.event_name == 'push') && github.repository == 'mCaptcha/mCaptcha'
run: ./scripts/publish.sh publish master latest $DUMBSERVE_PASSWORD
env:
DUMBSERVE_PASSWORD: ${{ secrets.DUMBSERVE_PASSWORD }}
GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }}
- name: generate documentation
if: matrix.version == 'stable' && (github.repository == 'mCaptcha/mCaptcha')
run: make doc
env:
DATABASE_URL: postgres://postgres:password@localhost:5432/postgres
POSTGRES_DATABASE_URL: "${{ env.POSTGRES_DATABASE_URL }}"
MARIA_DATABASE_URL: "${{ env.MARIA_DATABASE_URL }}"
GIT_HASH: 8e77345f1597e40c2e266cb4e6dee74888918a61 # dummy value
COMPILED_DATE: "2021-07-21"

32
.github/workflows/tagged-release.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: Create binary for release
# Only on tags that start with a "v"
on:
push:
tags:
- "v*"
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-pc-windows-gnu
archive: zip
- target: x86_64-unknown-linux-musl
archive: tar.gz tar.xz
- target: x86_64-apple-darwin
archive: zip
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Compile and release
uses: rust-build/rust-build.action@v1.3.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
RUSTTARGET: ${{ matrix.target }}
ARCHIVE_TYPES: ${{ matrix.archive }}

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,4 +2,21 @@
### Changed
- Rename pow section in settings to captcha and add options to configure([`42544ec42`](https://github.com/mCaptcha/mCaptcha/commit/42544ec421e0c3ec4a8d132e6101ab4069bf0065))
- 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.
> While they can now go abuse it for illegal stuff or other stuff.
> You might decide, oh I don't want this! and terminate a legitimate
> siteKey.
> New request payload:
```json
{
"secret": "<your-users-secret>", // found in /settings in the dashbaord
"token": "<token-presented-by-the-user>",
"key": "<your-sitekey>"
}
```
- ([`42544ec42`](https://github.com/mCaptcha/mCaptcha/commit/42544ec421e0c3ec4a8d132e6101ab4069bf0065)) Rename pow section in settings to captcha and add options to configure

2739
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -13,14 +13,15 @@ build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[workspace]
exclude = ["db/db-migrations", "utils/cache-bust"]
memebers = [".", "db/db-core", "db/db-sqlx-postgres", "db/db-sqlx-maria"]
[[bin]]
name = "mcaptcha"
path = "./src/main.rs"
[[bin]]
name = "tests-migrate"
path = "./src/tests-migrate.rs"
[dependencies]
actix-web = "4.0.1"
actix = "0.13"
@ -29,18 +30,18 @@ actix-http = "3.0.4"
actix-rt = "2"
actix-cors = "0.6.1"
actix-service = "2.0.0"
#my-codegen = {version="0.5.0-beta.5", package = "actix-web-codegen", git ="https://github.com/realaravinth/actix-web"}
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" ] }
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"
@ -58,15 +59,16 @@ log = "0.4"
lazy_static = "1.4"
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"
num_cpus = "1.13.1"
lettre = { version = "0.10.0-rc.3", features = [
"builder",
"tokio1",
@ -74,7 +76,19 @@ 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]
path = "./db/db-core"
[dependencies.db-sqlx-postgres]
path = "./db/db-sqlx-postgres"
[dependencies.db-sqlx-maria]
path = "./db/db-sqlx-maria"
[dependencies.my-codegen]
git = "https://github.com/realaravinth/actix-web"
@ -87,12 +101,10 @@ features = ["actix_identity_backend"]
[build-dependencies]
serde_json = "1"
cache-buster = { version = "0.2.0", git = "https://github.com/realaravinth/cache-buster" }
mime = "0.3.16"
sqlx = { version = "0.5.13", features = [ "runtime-actix-rustls", "postgres", "time", "offline" ] }
sqlx = { version = "0.7", features = [ "runtime-tokio-rustls", "postgres", "time", "mysql" ] }
[dev-dependencies]
pow_sha256 = { version = "0.2.1", git = "https://github.com/mcaptcha/pow_sha256" }
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 \
@ -19,21 +22,14 @@ RUN make frontend
FROM rust:latest as rust
WORKDIR /src
RUN mkdir src && echo "fn main() {}" > src/main.rs
COPY Cargo.toml .
RUN sed -i '/.*build.rs.*/d' Cargo.toml
COPY Cargo.lock .
COPY migrations /src/migrations
COPY sqlx-data.json /src/
COPY src/tests-migrate.rs /src/src/tests-migrate.rs
COPY src/settings.rs /src/src/settings.rs
RUN cargo --version
RUN cargo build --release
COPY . /src
COPY . .
COPY --from=frontend /src/static/cache/bundle/ /src/static/cache/bundle/
RUN cargo build --release
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
FROM debian:bookworm as mCaptcha
LABEL org.opencontainers.image.source https://github.com/mCaptcha/mCaptcha
RUN useradd -ms /bin/bash -u 1001 mcaptcha
WORKDIR /home/mcaptcha

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.

157
Makefile
View file

@ -1,23 +1,98 @@
# 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
cd docs/openapi && yarn install
endef
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
check: ## Check for syntax errors on all workspaces
cargo check --workspace --tests --all-features
cd utils/cache-bust && cargo check --tests --all-features
cd db/db-migrations && cargo check --tests --all-features
cd db/db-sqlx-postgres &&\
DATABASE_URL=${POSTGRES_DATABASE_URL}\
cargo check
cd db/db-sqlx-maria &&\
DATABASE_URL=${MARIA_DATABASE_URL}\
cargo check
cd db/db-core/ && cargo check
cache-bust: ## Run cache buster on static assets
$(call cache_bust)
clean: ## Delete build artifacts
@cargo clean
@yarn cache clean
@-rm $(CLEAN_UP)
coverage: migrate ## Generate code coverage report in HTML format
cargo tarpaulin -t 1200 --out Html
doc: ## Generate documentation
#yarn doc
cargo doc --no-deps --workspace --all-features
@ -33,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)
@ -55,31 +143,70 @@ 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
cargo run --bin tests-migrate
$(call run_migrations)
migrate.dev: ## Run database migrations during development
$(call run_dev_migrations)
release: frontend ## Build app with release optimizations
$(call cache_bust)
cargo build --release
run: frontend ## Run app in debug mode
$(call cache_bust)
cargo run
test: frontend-test frontend ## Run all available tests
./scripts/tests.sh
# cargo test --all-features --no-fail-fast
xml-test-coverage: migrate ## Generate code coverage report in XML format
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
test: frontend ## Run all available tests
$(call test_frontend)
$(call cache_bust)
$(call test_db_sqlx_postgres)
$(call test_db_sqlx_maria)
$(call test_core)
# ./scripts/tests.sh
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

@ -32,18 +32,18 @@ yourself!](https://demo.mcaptcha.org/widget/?sitekey=pHy0AktWyOKuxZDzFfoaewncWec
## How does it work?
mCaptcha uses SHA256 based proof-of-work(PoW) to rate limit users.
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
1. they will have to generate proof-of-work (a bunch of math that will takes
time to compute) and submit it to mCaptcha.
2. We'll validate the proof:
- **if validation is unsuccessful**, they will be prevented from
accessing their target website
- **if validation is successful**, read on,
- **if validation is unsuccessful**, they will be prevented from
accessing their target website
- **if validation is successful**, read on,
3. They will be issued a token that they should submit along
with their request/form submission to the target website.
@ -54,8 +54,8 @@ When a user wants to do something on an mCaptcha-protected website,
The whole process is automated from the user's POV. All they have to do
is click on a button to initiate the process.
mCaptcha makes interacting with websites (computationally)expensive for
the user. A well-behaving user will experience a slight delay(no delay
mCaptcha makes interacting with websites (computationally) expensive for
the user. A well-behaving user will experience a slight delay (no delay
when under moderate load to 2s when under attack; PoW difficulty is
variable) but if someone wants to hammer your site, they will have to do
more work to send requests than your server will have to do to respond
@ -63,14 +63,14 @@ to their request.
## Why use mCaptcha?
- [x] **Free software, privacy focused**
- [x] **Seamless UX** - No more annoying CAPTCHAs!
- [x] **No tracking:** Our CAPTCHA routes are cookie free!
- [x] **IP address independent:** your users are behind a NAT? We got you covered!
- [x] **Resistant to replay attacks:** proof-of-work configurations have
short lifetimes(30s) and can be used only once. If a user submits a
PoW to an already used configuration or an expired one, their proof
will be rejected.
- [x] **Free software, privacy focused**
- [x] **Seamless UX** - No more annoying CAPTCHAs!
- [x] **No tracking:** Our CAPTCHA routes are cookie free!
- [x] **IP address independent:** your users are behind a NAT? We got you covered!
- [x] **Resistant to replay attacks:** proof-of-work configurations have
short lifetimes (30s) and can be used only once. If a user submits a
PoW to an already used configuration or an expired one, their proof
will be rejected.
## Demo
@ -87,15 +87,15 @@ monitor console and network activity.
### Demo servers are available at:
- https://demo.mcaptcha.org/
- https://demo2.mcaptcha.org/ (runs on a Raspberry Pi!)
- https://demo.mcaptcha.org/
- https://demo2.mcaptcha.org/ (runs on a Raspberry Pi!)
> Core functionality is working but it's still very much
> work-in-progress. Since we don't have a stable release yet, hosted
> demo servers might be a few versions behind `master`. Please check footer for
> build commit.
Feel free to provide bogus information while signing up(project under
Feel free to provide bogus information while signing up (project under
development, database frequently wiped).
### Self-hosted:
@ -103,12 +103,18 @@ development, database frequently wiped).
Clone the repo and run the following from the root of the repo:
```bash
$ docker-compose -d up
git clone https://github.com/mCaptcha/mCaptcha.git
docker-compose up -d
```
After the containers are up, visit [http://localhost:7000](http://localhost:7000) and login with the default credentials:
- username: aaronsw
- password: password
It takes a while to build the image so please be patient :)
See [DEPLOYMENT.md](./docs/DEPLOYMET.md) detailed alternate deployment
See [DEPLOYMENT.md](./docs/DEPLOYMENT.md) for detailed alternate deployment
methods.
## Development:
@ -117,8 +123,26 @@ See [HACKING.md](./docs/HACKING.md)
## Deployment:
See [DEPLOYMENT.md](./docs/DEPLOYMET.md)
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,61 +1,22 @@
/*
* 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 cache_buster::{BusterBuilder, NoHashCategory};
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);
cache_bust();
}
fn cache_bust() {
// until APPLICATION_WASM gets added to mime crate
// PR: https://github.com/hyperium/mime/pull/138
// let types = vec![
// mime::IMAGE_PNG,
// mime::IMAGE_SVG,
// mime::IMAGE_JPEG,
// mime::IMAGE_GIF,
// mime::APPLICATION_JAVASCRIPT,
// mime::TEXT_CSS,
// ];
println!("cargo:rerun-if-changed=static/cache");
let no_hash = vec![NoHashCategory::FileExtentions(vec!["wasm"])];
let config = BusterBuilder::default()
.source("./static/cache/")
.result("./assets")
.no_hash(no_hash)
.follow_links(true)
.build()
.unwrap();
config.process().unwrap();
}

View file

@ -11,7 +11,7 @@ cookie_secret = "Zae0OOxf^bOJ#zN^&k7VozgW&QAx%n02TQFXpRMG4cCU0xMzgu3dna@tQ9dvc&T
# The port at which you want authentication to listen to
# takes a number, choose from 1000-10000 if you dont know what you are doing
port = 7000
#IP address. Enter 0.0.0.0 to listen on all availale addresses
#IP address. Enter 0.0.0.0 to listen on all available addresses
ip= "0.0.0.0"
# enter your hostname, eg: example.com
domain = "localhost"
@ -28,6 +28,9 @@ salt = "asdl;kjfhjawehfpa;osdkjasdvjaksndfpoanjdfainsdfaijdsfajlkjdsaf;ajsdfwero
# garbage collection period to manage mCaptcha system
# leave untouched if you don't know what you are doing
gc = 30
runners = 4
queue_length = 2000
enable_stats = true
[captcha.default_difficulty_strategy]
avg_traffic_difficulty = 50000 # almost instant solution
@ -39,15 +42,10 @@ duration = 30 # cooldown period in seconds
# 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
[redis]
@ -68,3 +66,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"

2
db/db-core/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
/Cargo.lock

23
db/db-core/Cargo.toml Normal file
View file

@ -0,0 +1,23 @@
[package]
name = "db-core"
version = "0.1.0"
edition = "2021"
homepage = "https://mcaptcha.org"
repository = "https://github.com/mCaptcha/mCaptcha"
documentation = "https://mcaptcha.org/docs/"
license = "AGPLv3 or later version"
authors = ["realaravinth <realaravinth@batsense.net>"]
[dependencies]
async-trait = "0.1.51"
thiserror = "1.0.30"
serde = { version = "1", features = ["derive"]}
url = { version = "2.2.2", features = ["serde"] }
libmcaptcha = "0.2.4"
[features]
default = []
test = []
[dev-dependencies]
serde_json = "1"

50
db/db-core/src/errors.rs Normal file
View file

@ -0,0 +1,50 @@
// 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;
//use derive_more::{error, Error as DeriveError};
use thiserror::Error;
/// Error data structure grouping various error subtypes
#[derive(Debug, Error)]
pub enum DBError {
/// errors that are specific to a database implementation
#[error("{0}")]
DBError(#[source] BoxDynError),
/// Username is taken
#[error("Username is taken")]
UsernameTaken,
/// Email is taken
#[error("Email is taken")]
EmailTaken,
/// Secret is taken
#[error("Secret is taken")]
SecretTaken,
/// Captcha key is taken
#[error("Captcha key is taken")]
CaptchaKeyTaken,
/// Account not found
#[error("Account not found")]
AccountNotFound,
/// Captcha not found
#[error("Captcha not found")]
CaptchaNotFound,
/// Traffic pattern not found
#[error("Traffic pattern not found")]
TrafficPatternNotFound,
/// Notification not found
#[error("Notification not found")]
NotificationNotFound,
}
/// Convenience type alias for grouping driver-specific errors
pub type BoxDynError = Box<dyn StdError + 'static + Send + Sync>;
/// Generic result data structure
pub type DBResult<V> = std::result::Result<V, DBError>;

446
db/db-core/src/lib.rs Normal file
View file

@ -0,0 +1,446 @@
// 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
//!
//! Traits and datastructures used in mCaptcha to interact with database.
//!
//! To use an unsupported database with mCaptcha, traits present within this crate should be
//! implemented.
//!
//!
//! ## Organisation
//!
//! Database functionality is divided across various modules:
//!
//! - [errors](crate::auth): error data structures used in this crate
//! - [ops](crate::ops): meta operations like connection pool creation, migrations and getting
//! connection from pool
use serde::{Deserialize, Serialize};
pub use libmcaptcha::defense::Level;
pub mod errors;
pub mod ops;
#[cfg(feature = "test")]
pub mod tests;
use dev::*;
pub use ops::GetConnection;
pub mod prelude {
//! useful imports for users working with a supported database
pub use super::errors::*;
pub use super::ops::*;
pub use super::*;
}
pub mod dev {
//! useful imports for supporting a new database
pub use super::prelude::*;
pub use async_trait::async_trait;
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
/// Data required to register a new user
pub struct Register<'a> {
/// username of new user
pub username: &'a str,
/// secret of new user
pub secret: &'a str,
/// hashed password of new use
pub hash: &'a str,
/// Optionally, email of new use
pub email: Option<&'a str>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
/// data required to update them email of a user
pub struct UpdateEmail<'a> {
/// username of the user
pub username: &'a str,
/// new email address of the user
pub new_email: &'a str,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
/// types of credentials used as identifiers during login
pub enum Login<'a> {
/// username as login
Username(&'a str),
/// email as login
Email(&'a str),
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
/// type encapsulating username and hashed password of a user
pub struct NameHash {
/// username
pub username: String,
/// hashed password
pub hash: String,
}
#[async_trait]
/// mCaptcha's database requirements. To implement support for $Database, kindly implement this
/// trait.
pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase {
/// ping DB
async fn ping(&self) -> bool;
/// register a new user
async fn register(&self, p: &Register) -> DBResult<()>;
/// delete a user
async fn delete_user(&self, username: &str) -> DBResult<()>;
/// check if username exists
async fn username_exists(&self, username: &str) -> DBResult<bool>;
/// get user email
async fn get_email(&self, username: &str) -> DBResult<Option<String>>;
/// check if email exists
async fn email_exists(&self, email: &str) -> DBResult<bool>;
/// update a user's email
async fn update_email(&self, p: &UpdateEmail) -> DBResult<()>;
/// get a user's password
async fn get_password(&self, l: &Login) -> DBResult<NameHash>;
/// update user's password
async fn update_password(&self, p: &NameHash) -> DBResult<()>;
/// update username
async fn update_username(&self, current: &str, new: &str) -> DBResult<()>;
/// get a user's secret
async fn get_secret(&self, username: &str) -> DBResult<Secret>;
/// get a user's secret from a captcha key
async fn get_secret_from_captcha(&self, key: &str) -> DBResult<Secret>;
/// update a user's secret
async fn update_secret(&self, username: &str, secret: &str) -> DBResult<()>;
/// create new captcha
async fn create_captcha(&self, username: &str, p: &CreateCaptcha) -> DBResult<()>;
/// Get captcha config
async fn get_captcha_config(&self, username: &str, key: &str) -> DBResult<Captcha>;
/// Get all captchas belonging to user
async fn get_all_user_captchas(&self, username: &str) -> DBResult<Vec<Captcha>>;
/// update captcha metadata; doesn't change captcha key
async fn update_captcha_metadata(
&self,
username: &str,
p: &CreateCaptcha,
) -> DBResult<()>;
/// update captcha key; doesn't change metadata
async fn update_captcha_key(
&self,
username: &str,
old_key: &str,
new_key: &str,
) -> DBResult<()>;
/// Add levels to captcha
async fn add_captcha_levels(
&self,
username: &str,
captcha_key: &str,
levels: &[Level],
) -> DBResult<()>;
/// check if captcha exists
async fn captcha_exists(
&self,
username: Option<&str>,
captcha_key: &str,
) -> DBResult<bool>;
/// Delete all levels of a captcha
async fn delete_captcha_levels(
&self,
username: &str,
captcha_key: &str,
) -> DBResult<()>;
/// Delete captcha
async fn delete_captcha(&self, username: &str, captcha_key: &str) -> DBResult<()>;
/// Get captcha levels
async fn get_captcha_levels(
&self,
username: Option<&str>,
captcha_key: &str,
) -> DBResult<Vec<Level>>;
/// Get captcha's cooldown period
async fn get_captcha_cooldown(&self, captcha_key: &str) -> DBResult<i32>;
/// Add traffic configuration
async fn add_traffic_pattern(
&self,
username: &str,
captcha_key: &str,
pattern: &TrafficPattern,
) -> DBResult<()>;
/// Get traffic configuration
async fn get_traffic_pattern(
&self,
username: &str,
captcha_key: &str,
) -> DBResult<TrafficPattern>;
/// Delete traffic configuration
async fn delete_traffic_pattern(
&self,
username: &str,
captcha_key: &str,
) -> DBResult<()>;
/// create new notification
async fn create_notification(&self, p: &AddNotification) -> DBResult<()>;
/// get all unread notifications
async fn get_all_unread_notifications(
&self,
username: &str,
) -> DBResult<Vec<Notification>>;
/// mark a notification read
async fn mark_notification_read(&self, username: &str, id: i32) -> DBResult<()>;
/// record PoWConfig fetches
async fn record_fetch(&self, key: &str) -> DBResult<()>;
/// record PoWConfig solves
async fn record_solve(&self, key: &str) -> DBResult<()>;
/// record PoWConfig confirms
async fn record_confirm(&self, key: &str) -> DBResult<()>;
/// fetch PoWConfig fetches
async fn fetch_config_fetched(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
/// fetch PoWConfig solves
async fn fetch_solve(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
/// 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)]
/// Captcha statistics with time recorded in UNIX epoch formats
pub struct StatsUnixTimestamp {
/// times at which the configuration were fetched
pub config_fetches: Vec<i64>,
/// times at which the PoW was solved
pub solves: Vec<i64>,
/// times at which the PoW token was verified
pub confirms: Vec<i64>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
/// Represents notification
pub struct Notification {
/// receiver name of the notification
pub name: Option<String>,
/// heading of the notification
pub heading: Option<String>,
/// message of the notification
pub message: Option<String>,
/// when notification was received
pub received: Option<i64>,
/// db assigned ID of the notification
pub id: Option<i32>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
/// Data required to add notification
pub struct AddNotification<'a> {
/// who is the notification addressed to?
pub to: &'a str,
/// notification sender
pub from: &'a str,
/// heading of the notification
pub heading: &'a str,
/// message of the notification
pub message: &'a str,
}
#[derive(Default, PartialEq, Serialize, Deserialize, Clone, Debug)]
/// User's traffic pattern; used in generating a captcha configuration
pub struct TrafficPattern {
/// average traffic of user's website
pub avg_traffic: u32,
/// the peak traffic that the user's website can handle
pub peak_sustainable_traffic: u32,
/// traffic that bought the user's website down; optional
pub broke_my_site_traffic: Option<u32>,
}
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
/// data required to create new captcha
pub struct CreateCaptcha<'a> {
/// cool down duration
pub duration: i32,
/// description of the captcha
pub description: &'a str,
/// secret key of the captcha
pub key: &'a str,
}
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
/// Data representing a captcha
pub struct Captcha {
/// Database assigned ID
pub config_id: i32,
/// cool down duration
pub duration: i32,
/// description of the captcha
pub description: String,
/// secret key of the captcha
pub key: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Default, Serialize)]
/// datastructure representing a user's secret
pub struct Secret {
/// user's secret
pub secret: String,
}
/// Trait to clone MCDatabase
pub trait CloneSPDatabase {
/// clone DB
fn clone_db(&self) -> Box<dyn MCDatabase>;
}
impl<T> CloneSPDatabase for T
where
T: MCDatabase + Clone + 'static,
{
fn clone_db(&self) -> Box<dyn MCDatabase> {
Box::new(self.clone())
}
}
impl Clone for Box<dyn MCDatabase> {
fn clone(&self) -> Self {
(**self).clone_db()
}
}

38
db/db-core/src/ops.rs Normal file
View file

@ -0,0 +1,38 @@
// 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::*;
/// Database operations trait(migrations, pool creation and fetching connection from pool)
pub trait DBOps: GetConnection + Migrate {}
/// Get database connection
#[async_trait]
pub trait GetConnection {
/// database connection type
type Conn;
/// database specific error-type
/// get connection from connection pool
async fn get_conn(&self) -> DBResult<Self::Conn>;
}
/// Create database connection
#[async_trait]
pub trait Connect {
/// database specific pool-type
type Pool: MCDatabase;
/// database specific error-type
/// create connection pool
async fn connect(self) -> DBResult<Self::Pool>;
}
/// database migrations
#[async_trait]
pub trait Migrate: MCDatabase {
/// database specific error-type
/// run migrations
async fn migrate(&self) -> DBResult<()>;
}

461
db/db-core/src/tests.rs Normal file
View file

@ -0,0 +1,461 @@
// 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,
p: &Register<'a>,
c: &CreateCaptcha<'a>,
l: &[Level],
tp: &TrafficPattern,
an: &AddNotification<'a>,
) {
assert!(db.ping().await, "ping test");
if db.username_exists(p.username).await.unwrap() {
db.delete_user(p.username).await.unwrap();
assert!(
!db.username_exists(p.username).await.unwrap(),
"user is deleted so username shouldn't exist"
);
}
assert!(matches!(
db.get_secret(&p.username).await,
Err(DBError::AccountNotFound)
));
db.register(p).await.unwrap();
assert!(matches!(db.register(&p).await, Err(DBError::UsernameTaken)));
// testing get secret
let secret = db.get_secret(p.username).await.unwrap();
assert_eq!(secret.secret, p.secret, "user secret matches");
// testing update secret: setting secret = username
db.update_secret(p.username, p.username).await.unwrap();
let secret = db.get_secret(p.username).await.unwrap();
assert_eq!(
secret.secret, p.username,
"user secret matches username; as set by previous step"
);
// testing get_password
// with username
let name_hash = db.get_password(&Login::Username(p.username)).await.unwrap();
assert_eq!(name_hash.hash, p.hash, "user password matches");
assert_eq!(name_hash.username, p.username, "username matches");
// with email
let mut name_hash = db
.get_password(&Login::Email(p.email.as_ref().unwrap()))
.await
.unwrap();
assert_eq!(name_hash.hash, p.hash, "user password matches");
assert_eq!(name_hash.username, p.username, "username matches");
// testing get_email
assert_eq!(
db.get_email(p.username)
.await
.unwrap()
.as_ref()
.unwrap()
.as_str(),
p.email.unwrap()
);
// testing email exists
assert!(
db.email_exists(p.email.as_ref().unwrap()).await.unwrap(),
"user is registered so email should exist"
);
assert!(
db.username_exists(p.username).await.unwrap(),
"user is registered so username should exist"
);
// update password test. setting password = username
name_hash.hash = name_hash.username.clone();
db.update_password(&name_hash).await.unwrap();
let name_hash = db.get_password(&Login::Username(p.username)).await.unwrap();
assert_eq!(
name_hash.hash, p.username,
"user password matches with changed value"
);
assert_eq!(name_hash.username, p.username, "username matches");
// update username to p.email
assert!(
!db.username_exists(p.email.as_ref().unwrap()).await.unwrap(),
"user with p.email doesn't exist. pre-check to update username to p.email"
);
db.update_username(p.username, p.email.as_ref().unwrap())
.await
.unwrap();
assert!(
db.username_exists(p.email.as_ref().unwrap()).await.unwrap(),
"user with p.email exist post-update"
);
// deleting user for re-registration with email = None
db.delete_user(p.email.as_ref().unwrap()).await.unwrap();
assert!(
!db.username_exists(p.email.as_ref().unwrap()).await.unwrap(),
"user is deleted so username shouldn't exist"
);
// register with email = None
let mut p2 = p.clone();
p2.email = None;
db.register(&p2).await.unwrap();
assert!(
db.username_exists(p2.username).await.unwrap(),
"user is registered so username should exist"
);
assert!(
!db.email_exists(p.email.as_ref().unwrap()).await.unwrap(),
"user registration with email is deleted; so email shouldn't exist"
);
// testing get_email = None
assert_eq!(db.get_email(p.username).await.unwrap(), None);
// testing update email
let update_email = UpdateEmail {
username: p.username,
new_email: p.email.as_ref().unwrap(),
};
db.update_email(&update_email).await.unwrap();
println!(
"null user email: {}",
db.email_exists(p.email.as_ref().unwrap()).await.unwrap()
);
assert!(
db.email_exists(p.email.as_ref().unwrap()).await.unwrap(),
"user was with empty email but email is set; so email should exist"
);
/*
* test notification workflows
* 1. Add notifications: a minimum of two, to mark as read and test if it has affected it
* 2. Get unread notifications
* 3. Mark a notification read, check if it has affected Step #2
*/
// 1. add notification
db.create_notification(an).await.unwrap();
db.create_notification(an).await.unwrap();
// 2. Get notifications
let notifications = db.get_all_unread_notifications(an.to).await.unwrap();
assert_eq!(notifications.len(), 2);
assert_eq!(notifications[0].heading.as_ref().unwrap(), an.heading);
// 3. mark a notification read
db.mark_notification_read(an.to, notifications[0].id.unwrap())
.await
.unwrap();
let new_notifications = db.get_all_unread_notifications(an.to).await.unwrap();
assert_eq!(new_notifications.len(), 1);
// create captcha
db.create_captcha(p.username, c).await.unwrap();
assert!(db.captcha_exists(None, c.key).await.unwrap());
assert!(db.captcha_exists(Some(p.username), c.key).await.unwrap());
// get secret from captcha key
let secret_from_captcha = db.get_secret_from_captcha(&c.key).await.unwrap();
assert_eq!(secret_from_captcha.secret, p.secret, "user secret matches");
// get captcha configuration
let captcha = db.get_captcha_config(p.username, c.key).await.unwrap();
assert_eq!(captcha.key, c.key);
assert_eq!(captcha.duration, c.duration);
assert_eq!(captcha.description, c.description);
// get all captchas that belong to user
let all_user_captchas = db.get_all_user_captchas(p.username).await.unwrap();
assert_eq!(all_user_captchas.len(), 1);
assert_eq!(all_user_captchas[0], captcha);
// get captcha cooldown duration
assert_eq!(db.get_captcha_cooldown(c.key).await.unwrap(), c.duration);
// add traffic pattern
db.add_traffic_pattern(p.username, c.key, tp).await.unwrap();
assert_eq!(
&db.get_traffic_pattern(p.username, c.key).await.unwrap(),
tp
);
// delete traffic pattern
db.delete_traffic_pattern(p.username, c.key).await.unwrap();
assert!(
matches!(
db.get_traffic_pattern(p.username, c.key).await,
Err(DBError::TrafficPatternNotFound)
),
"deletion successful; traffic pattern no longer exists"
);
// add captcha levels
db.add_captcha_levels(p.username, c.key, l).await.unwrap();
// get captcha levels with username
let levels = db
.get_captcha_levels(Some(p.username), c.key)
.await
.unwrap();
assert_eq!(levels, l);
// get captcha levels without username
let levels = db.get_captcha_levels(None, c.key).await.unwrap();
assert_eq!(levels, l);
/*
* Test stats
* 1. record fetch config
* 2. record solve
* 3. record token verify
* 4. fetch config fetches
* 5. fetch solves
* 6. fetch token verify
*/
assert!(db
.fetch_config_fetched(p.username, c.key)
.await
.unwrap()
.is_empty());
assert!(db.fetch_solve(p.username, c.key).await.unwrap().is_empty());
assert!(db
.fetch_confirm(p.username, c.key)
.await
.unwrap()
.is_empty());
db.record_fetch(c.key).await.unwrap();
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)
.await
.unwrap()
.len(),
1
);
assert_eq!(db.fetch_solve(p.username, c.key).await.unwrap().len(), 1);
assert_eq!(db.fetch_confirm(p.username, c.key).await.unwrap().len(), 1);
// update captcha key; set key = username;
db.update_captcha_key(p.username, c.key, p.username)
.await
.unwrap();
// checking for captcha with old key; shouldn't exist
assert!(!db.captcha_exists(Some(p.username), c.key).await.unwrap());
// checking for captcha with new key; shouldn exist
assert!(db
.captcha_exists(Some(p.username), p.username)
.await
.unwrap());
// delete captcha levels
db.delete_captcha_levels(p.username, c.key).await.unwrap();
// update captcha; set description = username and duration *= duration;
let mut c2 = c.clone();
c2.duration *= c2.duration;
c2.description = p.username;
db.update_captcha_metadata(p.username, &c2).await.unwrap();
// delete captcha; updated key = p.username so invoke delete with it
db.delete_captcha(p.username, p.username).await.unwrap();
assert!(!db.captcha_exists(Some(p.username), c.key).await.unwrap());
}

2
db/db-migrations/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
/Cargo.lock

View file

@ -0,0 +1,13 @@
[package]
name = "db-migrations"
version = "0.1.0"
edition = "2021"
homepage = "https://mcaptcha.org"
repository = "https://github.com/mCaptcha/mCaptcha"
documentation = "https://mcaptcha.org/docs/"
license = "AGPLv3 or later version"
authors = ["realaravinth <realaravinth@batsense.net>"]
[dependencies]
actix-rt = "2"
sqlx = { version = "0.7", features = [ "runtime-tokio-rustls", "postgres", "time", "mysql" ] }

View file

@ -0,0 +1,3 @@
{
"db": "PostgreSQL"
}

View file

@ -0,0 +1,45 @@
// 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;
use sqlx::mysql::MySqlPoolOptions;
#[cfg(not(tarpaulin_include))]
#[actix_rt::main]
async fn main() {
//TODO featuregate sqlite and postgres
postgres_migrate().await;
maria_migrate().await;
}
async fn postgres_migrate() {
let db_url = env::var("POSTGRES_DATABASE_URL").expect("set POSTGRES_DATABASE_URL env var");
let db = PgPoolOptions::new()
.max_connections(2)
.connect(&db_url)
.await
.expect("Unable to form database pool");
sqlx::migrate!("../db-sqlx-postgres/migrations/")
.run(&db)
.await
.unwrap();
}
async fn maria_migrate() {
let db_url = env::var("MARIA_DATABASE_URL").expect("set POSTGRES_DATABASE_URL env var");
let db = MySqlPoolOptions::new()
.max_connections(2)
.connect(&db_url)
.await
.expect("Unable to form database pool");
sqlx::migrate!("../db-sqlx-maria/migrations/")
.run(&db)
.await
.unwrap();
}

16
db/db-sqlx-maria/.gitignore vendored Normal file
View file

@ -0,0 +1,16 @@
/target
tarpaulin-report.html
.env
.env
cobertura.xml
prod/
node_modules/
/static-assets/bundle
static/cache/bundle
./templates/**/*.js
/static-assets/bundle/*
src/cache_buster_data.json
coverage
dist
assets
yarn-error.log

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,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

@ -0,0 +1,22 @@
[package]
name = "db-sqlx-maria"
version = "0.1.0"
edition = "2021"
homepage = "https://mcaptcha.org"
repository = "https://github.com/mCaptcha/mCaptcha"
documentation = "https://mcaptcha.org/docs/"
license = "AGPLv3 or later version"
authors = ["realaravinth <realaravinth@batsense.net>"]
[dependencies]
async-trait = "0.1.51"
db-core = {path = "../db-core"}
futures = "0.3.15"
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.7", features = [ "runtime-tokio-rustls", "mysql", "time" ] }
db-core = {path = "../db-core", features = ["test"]}
url = { version = "2.2.2", features = ["serde"] }

View file

@ -0,0 +1,13 @@
-- 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,
email_verified BOOLEAN DEFAULT NULL,
secret varchar(50) NOT NULL UNIQUE,
password TEXT NOT NULL,
ID INT auto_increment,
PRIMARY KEY(ID)
);

View file

@ -0,0 +1,20 @@
-- 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 (
config_id INT auto_increment,
PRIMARY KEY(config_id),
user_id INT NOT NULL,
captcha_key varchar(100) NOT NULL UNIQUE,
name varchar(100) NOT NULL,
duration integer NOT NULL DEFAULT 30,
CONSTRAINT `fk_mcaptcha_user`
FOREIGN KEY (user_id)
REFERENCES mcaptcha_users (ID)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View file

@ -0,0 +1,16 @@
-- 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,
visitor_threshold INTEGER NOT NULL,
level_id INT auto_increment,
PRIMARY KEY(level_id),
CONSTRAINT `fk_mcaptcha_config_id`
FOREIGN KEY (config_id)
REFERENCES mcaptcha_config (config_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View file

@ -0,0 +1,14 @@
-- 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(),
CONSTRAINT `fk_mcaptcha_config_id_pow_fetched_stats`
FOREIGN KEY (config_id)
REFERENCES mcaptcha_config (config_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View file

@ -0,0 +1,13 @@
-- 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(),
CONSTRAINT `fk_mcaptcha_config_id_pow_solved_stats`
FOREIGN KEY (config_id)
REFERENCES mcaptcha_config (config_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View file

@ -0,0 +1,14 @@
-- 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(),
CONSTRAINT `fk_mcaptcha_config_id_pow_confirmed_stats`
FOREIGN KEY (config_id)
REFERENCES mcaptcha_config (config_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View file

@ -0,0 +1,23 @@
-- 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,
PRIMARY KEY(id),
tx INT NOT NULL,
rx INT NOT NULL,
heading varchar(30) NOT NULL,
message varchar(250) NOT NULL,
-- todo: mv read -> read_notification
read_notification BOOLEAN DEFAULT null,
received timestamp NOT NULL DEFAULT now(),
CONSTRAINT `fk_mcaptcha_mcaptcha_user_notifications_tx`
FOREIGN KEY (tx)
REFERENCES mcaptcha_users (ID)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View file

@ -0,0 +1,17 @@
-- 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),
avg_traffic INTEGER DEFAULT NULL,
peak_sustainable_traffic INTEGER DEFAULT NULL,
broke_my_site_traffic INT DEFAULT NULL,
CONSTRAINT `fk_mcaptcha_sitekey_user_provided_avg_trafic_config_id`
FOREIGN KEY (config_id)
REFERENCES mcaptcha_config (config_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

View file

@ -0,0 +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

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

File diff suppressed because it is too large Load diff

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