-
Notifications
You must be signed in to change notification settings - Fork 0
Add recaptcha utility methods #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+450
−0
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
8db65b6
Init recaptcha methods with mocha tests.
jonnyg23 d3d5205
Only lint with a single node version.
jonnyg23 ac74b59
Remove mongo service & Rename job.
jonnyg23 15ed165
Fix `getRecaptchaToken`, tests & formatting.
jonnyg23 b2c3422
Add `retries` default value in JSDocs.
jonnyg23 66b667e
Add `delay` default value in JSDocs.
jonnyg23 56ad10b
Update node version to `>=20`.
jonnyg23 ca4928c
Fix method formatting.
jonnyg23 c100abf
Split missing param condition into two conditionals.
jonnyg23 643096e
Format comment.
jonnyg23 b836822
Enable Codecov action.
jonnyg23 5dbeac5
Update for-loop logic.
jonnyg23 f1bd14f
Only run code coverage with node 22.
jonnyg23 dbad013
Fix copyright comments to use lower-case `c`.
jonnyg23 2215d94
Update per review comments.
jonnyg23 baa2609
Remove `emitFn` & Replace `siteKey` with `url`.
jonnyg23 5903955
Abstract out for-loop as `_waitForRecaptcha` & Fix test-case.
jonnyg23 19e83c9
Add default params of an empty object.
jonnyg23 65ab880
Fix eslint configs & Consolidate recaptcha.js to index.js.
jonnyg23 ae0fd47
Change name of GH action job.
jonnyg23 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module.exports = { | ||
root: true, | ||
env: { | ||
browser: true, | ||
node: true | ||
}, | ||
extends: [ | ||
'digitalbazaar', | ||
'digitalbazaar/jsdoc', | ||
'digitalbazaar/module' | ||
], | ||
ignorePatterns: ['node_modules/'], | ||
rules: { | ||
'unicorn/prefer-node-protocol': 'error' | ||
} | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
name: Main CI | ||
|
||
on: [push] | ||
|
||
jobs: | ||
lint: | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 10 | ||
strategy: | ||
matrix: | ||
node-version: [22.x] | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- run: npm install | ||
- name: Run eslint | ||
run: npm run lint | ||
run-tests: | ||
needs: [lint] | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 10 | ||
strategy: | ||
matrix: | ||
node-version: [20.x, 22.x] | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- run: | | ||
npm install | ||
cd test | ||
npm install | ||
- name: Run test with Node.js ${{ matrix.node-version }} and Karma | ||
run: | | ||
cd test | ||
npm test | ||
coverage: | ||
needs: [run-tests] | ||
runs-on: ubuntu-latest | ||
timeout-minutes: 10 | ||
strategy: | ||
matrix: | ||
node-version: [22.x] | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- run: | | ||
npm install | ||
cd test | ||
npm install | ||
- name: Generate coverage report | ||
run: | | ||
cd test | ||
npm run coverage-ci | ||
- name: Upload coverage to Codecov | ||
uses: codecov/codecov-action@v5 | ||
with: | ||
files: ./test/coverage/lcov.info | ||
fail_ci_if_error: true | ||
token: ${{ secrets.CODECOV_TOKEN }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
*.log | ||
*.sw[nop] | ||
*~ | ||
.project | ||
.settings | ||
.vscode | ||
TAGS | ||
coverage | ||
node_modules | ||
reports | ||
.cache | ||
jsdoc | ||
package-lock.json |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# bedrock-web-recaptcha ChangeLog | ||
|
||
## 1.0.0 2025-xx-xx | ||
|
||
- See git history for changes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
Bedrock Non-Commercial License v1.0 | ||
=================================== | ||
|
||
Copyright (c) 2011-2025 Digital Bazaar, Inc. | ||
All rights reserved. | ||
|
||
Summary | ||
======= | ||
|
||
This license allows the licensee to use Bedrock and its software modules | ||
for non-commercial purposes such as self-study, research, personal | ||
projects, or for evaluation purposes. If the licensee uses Bedrock | ||
directly or indirectly to generate revenue, or to provide products or | ||
services to more than 500 people (users), the licensee must immediately | ||
obtain a non-profit or commercial license. | ||
|
||
Examples | ||
======== | ||
|
||
These are examples of cases that are allowed by this license: | ||
|
||
* The licensee is an individual that creates Bedrock-dependent software for | ||
personal use only. | ||
* The licensee is an individual or group of students/researchers that uses | ||
Bedrock to experiment with an idea for a non-commercial project. | ||
* The licensee is a startup company that prototypes a Bedrock-dependent | ||
product before they have cash flow and will be testing the prototype | ||
software with less than 500 users. The service will not generate revenue | ||
of any kind. | ||
* The licensee is a for-profit organization that creates a product or | ||
service that is used by less than 500 users and is built with or | ||
integrates with Bedrock. The service must be exclusively provided for free | ||
and no parent, subsidiary, agent, or affiliate organization may profit | ||
from its use. | ||
|
||
These cases require a non-profit or commercial license: | ||
|
||
* The licensee is a non-profit that receives funding to create and/or run a | ||
Bedrock-dependent service. | ||
* The licensee is a startup company with Bedrock-dependent software that is | ||
funded by another organization. | ||
* The licensee is a startup company that is going into production with | ||
Bedrock-dependent software. | ||
* The licensee has more than 500 users using a Bedrock-dependent service | ||
either directly or indirectly. | ||
* The licensee is a medium to large organization that builds or integrates a | ||
commercial product or service with Bedrock. | ||
|
||
THE LICENSE | ||
=========== | ||
|
||
This section and all subsequent sections of this document constitute the | ||
agreement between the licensee and Digital Bazaar, Inc. | ||
|
||
DEFINITIONS | ||
=========== | ||
|
||
* Product - The Bedrock software and any modules associated with Bedrock | ||
where Digital Bazaar, Inc. owns the copyright. | ||
|
||
CONDITIONS | ||
========== | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted for NON-COMMERCIAL PURPOSES as long as the | ||
following conditions are met: | ||
|
||
1. Any use of the Product must not generate revenue for the licensee or | ||
any parent, subsidiary, agent, or affiliate of the licensee. Use of | ||
Product includes, but is not limited to, interacting with any of the | ||
licensee's Product-dependent products or services over a network. | ||
|
||
2. The aggregate number of individual people (users) of the licensee's | ||
products or services that use Product must be less than 500. | ||
|
||
3. Redistributions of source code must retain the above copyright notice | ||
intact, this list of conditions and the following disclaimer. | ||
|
||
4. Redistributions in binary form must reproduce the above copyright | ||
notice, this license and the following disclaimer in the documentation and | ||
on a web page available via interactive use and/or other materials | ||
provided with the distribution. | ||
|
||
5. Neither the name of the copyright holder, the names of its | ||
contributors, nor any trademarks held by the copyright holder may be used | ||
to endorse or promote products or services built using the Product without | ||
specific prior written permission. | ||
|
||
6. Any modifications are clearly outlined in release documentation and are | ||
specifically mentioned as not being a part of an official Product release. | ||
No additional restrictions to this license may be made when distributing | ||
modifications. | ||
|
||
7. For the avoidance of doubt, this license prohibits sublicensing of the | ||
Product. | ||
|
||
8. Any breach of this license by licensee must be resolved within 30 days. | ||
Failure to do so results in the termination of this license. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR | ||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
|
||
To obtain a non-profit or commercial license for Product, please contact | ||
Digital Bazaar, Inc. at the following email address: | ||
|
||
Digital Bazaar <[email protected]> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
# bedrock-web-recaptcha | ||
|
||
Front-end utilities for recaptcha. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/*! | ||
* Copyright (c) 2025 Digital Bazaar, Inc. All rights reserved. | ||
*/ | ||
|
||
// Helper to wait for the grecaptcha script to land on window | ||
async function _waitForRecaptcha({retries, delay}) { | ||
for(let retry = 0; retry < retries; ++retry) { | ||
if(window.grecaptcha) { | ||
return; | ||
} | ||
await new Promise(r => setTimeout(r, delay)); | ||
} | ||
const error = new Error('reCAPTCHA script failed to load'); | ||
error.name = 'TimeoutError'; | ||
throw error; | ||
} | ||
/** | ||
* Obtains a reCAPTCHA token by loading the grecaptcha script. | ||
* If the max number of `retries` attempts is hit, abort and throw an error. | ||
* | ||
* @param {object} [options] - The options to use. | ||
* @param {string} options.siteKey - ReCAPTCHA site key. | ||
* @param {string} [options.action='login'] - Action name to pass to execute(). | ||
* @param {number} [options.retries=3] - Number of times to retry checking | ||
* `grecaptcha` readiness. | ||
* @param {number} [options.delay=500] - Delay to retry (in ms). | ||
* | ||
* @returns {Promise<string>} Resolves with the reCAPTCHA token. | ||
* @throws {Error} If the script fails to load after retries or execute() | ||
* is rejected. | ||
*/ | ||
export async function getRecaptchaToken({ | ||
siteKey, action = 'login', retries = 3, delay = 500 | ||
} = {}) { | ||
if(typeof siteKey !== 'string') { | ||
throw new TypeError('"siteKey" must be a string.'); | ||
} | ||
if(typeof action !== 'string') { | ||
throw new TypeError('"action" must be a string.'); | ||
} | ||
|
||
await _waitForRecaptcha({retries, delay}); | ||
|
||
try { | ||
await new Promise(resolve => window.grecaptcha.ready(resolve)); | ||
const token = await window.grecaptcha.execute(siteKey, {action}); | ||
return token; | ||
} catch(err) { | ||
throw new Error(`Unable to receive token: ${err.message}`); | ||
} | ||
} | ||
|
||
/** | ||
* Dynamically injects the reCAPTCHA script tag into the document head. | ||
* | ||
* @param {object} options - The options to use. | ||
* @param {string} options.url - ReCAPTCHA API endpoint. | ||
* | ||
* @throws {Error} Wrapped error if the script fails to load. | ||
*/ | ||
export async function loadRecaptchaScript({url}) { | ||
// If already loaded or in progress, return | ||
if(window.grecaptcha || document.getElementById('recaptcha-script')) { | ||
return; | ||
} | ||
|
||
const script = document.createElement('script'); | ||
script.id = 'recaptcha-script'; | ||
script.src = url; | ||
script.async = true; | ||
script.defer = true; | ||
document.head.appendChild(script); | ||
|
||
await new Promise((resolve, reject) => { | ||
script.onload = () => resolve(); | ||
script.onerror = event => { | ||
// capture original error if any | ||
let original; | ||
if(event && event.error instanceof Error) { | ||
original = event.error; | ||
} else { | ||
original = new Error('Unknown error loading reCAPTCHA'); | ||
} | ||
const wrapped = new Error('Failed to load reCAPTCHA script'); | ||
wrapped.cause = original; | ||
reject(wrapped); | ||
}; | ||
}); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "@bedrock/web-recaptcha", | ||
"version": "1.0.0", | ||
"description": "Front-end utilities for recaptcha.", | ||
"type": "module", | ||
"exports": "./lib/index.js", | ||
"files": [ | ||
"lib/**/*.js" | ||
], | ||
"scripts": { | ||
"lint": "eslint ." | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/digitalbazaar/bedrock-web-recaptcha" | ||
}, | ||
"dependencies": { | ||
}, | ||
"devDependencies": { | ||
"eslint": "^8.57.0", | ||
"eslint-config-digitalbazaar": "^5.2.0", | ||
"eslint-plugin-jsdoc": "^48.11.0", | ||
"eslint-plugin-unicorn": "^55.0.0" | ||
}, | ||
"engines": { | ||
"node": ">=20" | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module.exports = { | ||
env: { | ||
mocha: true | ||
}, | ||
globals: { | ||
assertNoError: true, | ||
should: true | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.