Skip to content

Commit

Permalink
Make sure error message shows in image captcha widget (#1430)
Browse files Browse the repository at this point in the history
- [x] error messages in procaptcha widget
- [x] allow `onFailed` to be set by clients
- [x] allow bundle example to run all captcha tests, including the
server verify parts
- [x] adds cypress test for selecting incorrect images and ensures that
custom `onFailed` function is fired
- [x] restrict API admin auth middleware to prosopo API paths in
provider API
- [x] use environment variables in bundle demo instead of hard coded
site keys
- [x] add user and site key logging for tracing errors
- [x] add register site key function to setup script
- [x] add unit test for renderLogic to ensure that callbacks are picked
up from data tags
- [x] add unit tests for errorHandler to make sure parsing errors are
passed through
- [x] add integration tests to make sure new errors are passed back
- [x] changes image captcha process to use `timestamp` signature in line
with pow process
- [x] removes defunct user verify API path
- [x] fixes bug with vite config where `defaultEnvironment` could be set
to something other than [development, staging, production]
- [x] add `reset` function to procaptcha-budle for re-rendering the
procaptcha widgets
- [x] add `onReset` callback
- [x] pass an error JSON object in API errors, using translation keys as
codes
### Invalid Site Key

![image](https://github.com/user-attachments/assets/e3de3885-9325-4dc1-b15a-113569eac7e7)
### Site Key Not Registered

![image](https://github.com/user-attachments/assets/b0590814-f324-46bc-98cf-7381757fe11e)
### Failed to get Dataset

![image](https://github.com/user-attachments/assets/cdc2a176-f62a-41fe-8700-484fdf0d4d46)
  • Loading branch information
forgetso authored Oct 10, 2024
1 parent 4788a1e commit 10e7a55
Show file tree
Hide file tree
Showing 73 changed files with 21,627 additions and 22,483 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name: cypress
on:
pull_request:
branches: [main, dev, staging, release/*]
types:
types:
- opened # when a PR is opened
- synchronize # when a PR is pushed to
- reopened # when a PR is reopened
Expand Down Expand Up @@ -106,6 +106,7 @@ jobs:
cp demos/client-example-server/env.development demos/client-example-server/.env.test
cp demos/client-example/env.development demos/client-example/.env.test
cp demos/client-bundle-example/env.development demos/client-example/.env.test
cp dev/scripts/env.test .env.test
cp dev/scripts/env.test dev/scripts/.env.test
cp dev/scripts/env.test packages/cli/.env.test
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ jobs:
cp demos/client-example-server/env.development demos/client-example-server/.env.test
cp demos/client-example/env.development demos/client-example/.env.test
cp demos/client-bundle-example/env.development demos/client-bundle-example/.env.test
cp dev/scripts/env.test .env.test
cp dev/scripts/env.test dev/scripts/.env.test
cp dev/scripts/env.test packages/cli/.env.test
Expand Down
2 changes: 1 addition & 1 deletion demos/client-bundle-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ docker compose --file ./docker/docker-compose.development.yml up -d && \
npm i && \
npm run build:all && \
npm run setup:all && \
NODE_ENV=production npm -w @prosopo/procaptcha-bundle run bundle && \
NODE_ENV=development npm -w @prosopo/procaptcha-bundle run bundle && \
npm run start:all
```

Expand Down
2 changes: 2 additions & 0 deletions demos/client-bundle-example/env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PROSOPO_SITE_KEY=5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw
PROSOPO_SERVER_URL=http://localhost:9228
2 changes: 2 additions & 0 deletions demos/client-bundle-example/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@prosopo/client-bundle-example",
"main": "index.js",
"type": "module",
"engines": {
"node": ">=20",
"npm": ">=9"
Expand All @@ -14,6 +15,7 @@
},
"version": "2.1.3",
"devDependencies": {
"@prosopo/dotenv": "2.1.3",
"@types/node": "22.5.5",
"@vitest/coverage-v8": "2.1.1",
"concurrently": "9.0.1",
Expand Down
2 changes: 1 addition & 1 deletion demos/client-bundle-example/src/frictionless.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// Get the Element using elementId
const captchaContainer = document.getElementById('procaptcha-container')
render(captchaContainer, {
siteKey: '5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw',
siteKey: import.meta.env.PROSOPO_SITE_KEY,
theme: 'dark',
callback: onCaptchaVerified,
captchaType: 'frictionless',
Expand Down
209 changes: 162 additions & 47 deletions demos/client-bundle-example/src/index.html
Original file line number Diff line number Diff line change
@@ -1,53 +1,168 @@
<!doctype html>
<html lang="en">
<head>
<link href="//cdn.muicss.com/mui-0.10.3/css/mui.min.css" rel="stylesheet" type="text/css" />
<title>Procaptcha demo: Simple page</title>
<script id="procaptchaScript" type="module" src="./assets/procaptcha.bundle.js" async defer></script>
</head>
<body>
<div class="mui-container">
<form action="?" class="mui-form">
<legend>Login</legend>
<div class="mui-textfield mui-textfield--float-label">
<label>Email Address</label>
<input type="email" required />
</div>
<div class="mui-textfield mui-textfield--float-label">
<label>Password</label>
<input type="password" required />
</div>
<div class="mui-textfield mui-textfield--float-label">
<div id="procaptcha-container"></div>
</div>
<div class="mui-textfield mui-textfield--float-label">
<!-- Dev sitekey -->
<div
class="procaptcha"
data-theme="light"
data-sitekey="5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw"
></div>
</div>
<input type="submit" class="mui-btn mui-btn--raised" />
</form>
</div>
<script type="module">
// Pattern to avoid race condition between Procaptcha script loading and Procaptcha render function call
import { render } from './assets/procaptcha.bundle.js'
<head>
<link href="https://cdn.muicss.com/mui-0.10.3/css/mui.min.css" rel="stylesheet" type="text/css"/>
<title>Procaptcha demo: Simple page</title>
<script id="procaptchaScript" type="module" src="./assets/procaptcha.bundle.js" async defer></script>
<script type="text/javascript">
window.onCaptchaFailed = function () {
console.log('The user failed the captcha')
}
</script>
<script type="module">
window.addEventListener('load', () => {

window.setIsError = (isError) => {
const messageContainer = document.getElementById('messageContainer');
messageContainer.style.color = isError ? 'red' : 'black';
messageContainer.style.display = 'block';
};

window.setMessage = (message) => {
document.getElementById('message').innerText = message;
};

window.onLoggedIn = (token) => {
const url = new URL("/private", config.serverUrl).href;
console.log("getting private resource with token ", token, "at", url);
fetch(url, {
method: "GET",
headers: {
Origin: "http://localhost:9232", // TODO: change this to env var
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
})
.then(async (res) => {
try {
const jsonRes = await res.json();
if (res.status === 200) {
setMessage(jsonRes.message);
}
} catch (err) {
console.log(err);
}
})
.catch((err) => {
console.log(err);
});
};

window.onActionHandler = () => {

const procaptchaElements = document.getElementsByName('procaptcha-response');

if (!procaptchaElements.length) {
alert("Must complete captcha");
return
}

const procaptchaToken = procaptchaElements[0].value;

// Define a callback function to be called when the CAPTCHA is verified
function onCaptchaVerified(output) {
console.log('Captcha verified, output: ' + JSON.stringify(output))
const payload = {
email: document.getElementById('email').value,
name: document.getElementById('name').value,
password: document.getElementById('password').value,
"procaptcha-response": procaptchaToken,
};
const url = new URL('signup', import.meta.env.PROSOPO_SERVER_URL).href;
console.log("posting to", url, "with payload", payload);
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
contentType: "application/json",
}).then((response) => {
return new Promise((resolve) => response.json()
.then((json) => resolve({
status: response.status,
ok: response.ok,
json,
})))
})
.then(async ({status, json, ok}) => {
console.log("status", status, "json", json.message, "ok", ok);
console.log("json", json)
try {
if (status !== 200) {
setIsError(true);
setMessage(json.message);
} else {
setIsError(false);
setMessage(json.message);
}
} catch (err) {
console.log(err);
}
})
.catch((err) => {
console.log(err);
setIsError(true);
setMessage("Error: " + err);
});
};
console.log("here")
}
)
;
</script>

</head>
<body>

<div class="mui-container">
<form action="%PROSOPO_SERVER_URL%/signup" method="POST" class="mui-form">
<h1>Example Login Form</h1>
<div class="mui-textfield mui-textfield--float-label">
<label for="name">Name</label>
<input id="name" type="text" name="name" required/>
</div>
<div class="mui-textfield mui-textfield--float-label">
<label for="email">Email Address</label>
<input id="email" type="email" name="email" required/>
</div>
<div class="mui-textfield mui-textfield--float-label">
<label for="password">Password</label>
<input id="password" type="password" name="password" required/>
</div>
<div class="mui-textfield mui-textfield--float-label">
<div id="procaptcha-container"></div>
</div>
<div class="mui-textfield mui-textfield--float-label">
<!-- Dev sitekey -->
<div
class="procaptcha"
data-theme="light"
data-sitekey="%PROSOPO_SITE_KEY%"
data-failed-callback="onCaptchaFailed"
></div>
</div>
<div id="messageContainer" style="display: none; color: black;"><span id="message"></span></div>
<button type="button" class="mui-btn mui-btn--raised" onclick="onActionHandler()">Submit</button>
</form>
</div>
<script type="module">
// Pattern to avoid race condition between Procaptcha script loading and Procaptcha render function call
import {render} from './assets/procaptcha.bundle.js'

// Define a callback function to be called when the CAPTCHA is verified
function onCaptchaVerified(output) {
console.log('Captcha verified, output: ' + JSON.stringify(output))
}

// Get the Element using elementId
const captchaContainer = document.getElementById('procaptcha-container')
// Render the CAPTCHA explicitly on a container with id "procaptcha-container"
render(captchaContainer, {
siteKey: '5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw',
theme: 'dark',
callback: onCaptchaVerified,
})
</script>
</body>
// Get the Element using elementId
const captchaContainer = document.getElementById('procaptcha-container')
// Render the CAPTCHA explicitly on a container with id "procaptcha-container"
render(captchaContainer, {
siteKey: import.meta.env.PROSOPO_SITE_KEY,
theme: 'dark',
callback: onCaptchaVerified,
"failed-callback": function () {
console.log('The user failed the captcha')
}
})
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion demos/client-bundle-example/src/jsBundleTest.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<div
class="procaptcha"
data-theme="light"
data-sitekey="5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw"
data-sitekey="%PROSOPO_SITE_KEY%"
></div>
</form>
</body>
Expand Down
2 changes: 1 addition & 1 deletion demos/client-bundle-example/src/urlParams.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// Get the Element using elementId
const captchaContainer = document.getElementById('procaptcha-container')
render(captchaContainer, {
siteKey: '5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw',
siteKey: import.meta.env.PROSOPO_SITE_KEY,
theme: 'dark',
callback: onCaptchaVerified,
})
Expand Down
6 changes: 5 additions & 1 deletion demos/client-bundle-example/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@
"sourceMap": false
},
"include": ["**/*.ts"],
"references": []
"references": [
{
"path": "../../packages/dotenv"
}
]
}
32 changes: 23 additions & 9 deletions demos/client-bundle-example/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,26 @@
// 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.
export default {
watch: false,
mode: "development",
server: {
https: false,
host: true,
cors: true,
},
};

import { loadEnv } from "@prosopo/dotenv";
import { type UserConfig, defineConfig } from "vite";

export default defineConfig(({ command, mode }) => {
loadEnv();
return {
watch: false,
mode: "development",
server: {
host: true,
cors: true,
},
define: {
"import.meta.env.PROSOPO_SITE_KEY": JSON.stringify(
process.env.PROSOPO_SITE_KEY,
),
"import.meta.env.PROSOPO_SERVER_URL": JSON.stringify(
process.env.PROSOPO_SERVER_URL,
),
},
} as UserConfig;
});
15 changes: 6 additions & 9 deletions demos/client-example-server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,22 @@
"include": ["src", "src/**/*.json"],
"references": [
{
"path": "../../packages/contract"
},
{
"path": "../../packages/server"
"path": "../../packages/common"
},
{
"path": "../../packages/types"
"path": "../../packages/contract"
},
{
"path": "../../packages/common"
"path": "../../packages/dotenv"
},
{
"path": "../../packages/util"
"path": "../../packages/server"
},
{
"path": "../../packages/server"
"path": "../../packages/types"
},
{
"path": "../../packages/dotenv"
"path": "../../packages/util"
}
]
}
Loading

0 comments on commit 10e7a55

Please sign in to comment.