Skip to content

Commit

Permalink
HCaptcha, Favicon (#26)
Browse files Browse the repository at this point in the history
1. Out with Recaptcha, in with HCaptcha
2. Rip out a bunch of network data we don't use
3. Add new favicons
4. Update READMEs 
Closes #17 
Closes #18 

Co-authored-by: Aramik <[email protected]>
  • Loading branch information
shannonwells and aramikm authored Sep 24, 2024
1 parent a1c9b77 commit 6d9f72a
Show file tree
Hide file tree
Showing 42 changed files with 231 additions and 481 deletions.
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# See src/networkData for available configuration networks.
SMF_CONFIG_NETWORK="frequencyPaseo"
#SMF_CONFIG_NETWORK="localhost"

SMF_CONFIG_PORT=5555
SMF_CONFIG_DEPLOYED_REF=local
Expand All @@ -24,4 +26,5 @@ SMF_CONFIG_DEPLOYED_REF=local
SMF_CONFIG_FAUCET_ACCOUNT_MNEMONIC="//Alice"

# Only used with external access
SMF_CONFIG_RECAPTCHA_SECRET="6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe" # Public testing secret, will accept all tokens.
# HCaptcha Test secret, see https://docs.hcaptcha.com/#integration-testing-test-keys
SMF_CONFIG_CAPTCHA_SECRET=0x0000000000000000000000000000000000000000
2 changes: 1 addition & 1 deletion .github/workflows/deploy-site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- run: yarn run test
- run: yarn run build
env:
PUBLIC_CAPTCHA_KEY: 6LesXHomAAAAAGVVTCgc467t8hvBbmK7IlYZCc8O
PUBLIC_CAPTCHA_KEY: 0f68a804-860e-4f9a-962a-39789afc8792
GITHUB_PAGES: "/${{ github.event.repository.name }}"
STATIC: true
- uses: actions/upload-artifact@v4
Expand Down
92 changes: 29 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,101 +2,67 @@

Fork of [paritytech/polkadot-testnet-faucet](https://github.com/paritytech/polkadot-testnet-faucet)

## Development
E2E tests don't work right now, and the fork has diverged significantly and stopped being synched around v3.4

#### Setup dependencies and git hooks
To test, follow instructions to launch the Faucet Server, then head over to the Faucet Client README and launch that.

## Faucet Client Development
See [Faucet Client README](https://github.com/frequency-chain/testnet-faucet/blob/main/client/README.md)

## Faucet Server Development
### 1. Install packages.
```bash
yarn install
yarn simple-git-hooks
```

#### start local database:
### 2. start local database:

Uses sqlite file, no start needed.

#### run migrations:
### 3. run migrations:
```bash
yarn migrations:run
```

#### creating migrations:
* update entities in `src/db/entity`
* run `yarn migrations:generate src/db/migration/<migration_name>`
* import generated migration to `src/db/dataSource.ts`

#### To launch a hot-reloading dev environment

```bash
yarn dev
```

## Environment variables
### 4. Configure environment variables

Definition with explanation is in `./env.faucet.config.json`

Copy example file to real env and change its values:
```bash
$ cp example.env .env
$ cp .env.example .env
```

## End-to-end tests
### 5. launch a hot-reloading dev environment (faucet server only)

Please refer to the [E2E Readme](./e2e/README.md).
```bash
yarn dev
```

Example requests:
## POST request testing
For testing, you can use the public, [testing hCaptcha values](https://docs.hcaptcha.com/#integration-testing-test-keys).

Example request using the test hCaptcha token:
```bash
curl -X POST \
localhost:5555/drip/web \
-H "Content-Type: application/json" \
-d '{"address": "xxx", "parachain_id": "1002", "recaptcha": "captcha_token"}'
-d '{"address": "xxx", "captcha": "10000000-aaaa-bbbb-cccc-000000000001"}'
```

In React:

```tsx
import ReCAPTCHA from "react-google-recaptcha";

(...)

const [captcha, setCaptcha] = useState<string | null>(null)

(...)

<ReCAPTCHA
sitekey="xxx"
onChange={setCaptcha}
/>

(...)

const request = async () => {
const body = {
address: "xxx",
parachain_id: "1002",
recaptcha: captcha_token
}

const fetchResult = await fetch("http://localhost:5555/drip/web", {
method: "POST", body: JSON.stringify(body), headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
})
const result = await fetchResult.json()
}
## Other stuff
There are git hooks you can set up by running
```shell
yarn simple-git-hooks
```
#### creating migrations:
* update entities in `src/db/entity`
* run `yarn migrations:generate src/db/migration/<migration_name>`
* import generated migration to `src/db/dataSource.ts`

Where the `captcha_token` is a recaptcha token created with a `sitekey`
is matching the recaptcha secret specified in `SMF_BACKEND_RECAPTCHA_SECRET`.

For testing, you can use a public, testing recaptcha secret which will allow any captcha token to pass.
## End-to-end tests

```shell
# Public testing secret, will accept all tokens.
SMF_BACKEND_RECAPTCHA_SECRET="6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"
```
Please refer to the [E2E Readme](./e2e/README.md). They don't run.

### Helm chart

Expand Down
35 changes: 18 additions & 17 deletions client/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
# Web Faucet

Web Client to access the faucet. Powered by Catpcha v2

## Why?

The objective of this project is to simplify the use of the Faucet through a standalone webpage and open ability to share it via social networks & google search.

Two current options are to [access Matrix and contact a bot](https://wiki.polkadot.network/docs/learn-DOT#getting-tokens-on-the-rococo-testnet) or [ink! documentation](https://use.ink/faucet).
Web Client to access the Frequency Paseo Testnet faucet. Powered by SvelteKit and hCaptcha.

## Development
Set up the following variables:
- `PUBLIC_CAPTCHA_KEY`: The hCaptcha v2 site key. Test values on the [hCaptcha Development documentation](https://docs.hcaptcha.com/#integration-testing-test-keys)
- `PUBLIC_FAUCET_URL`: The endpoint to contact the faucet server. Keep unset to run client-side code with production backend. Set to `http://localhost:5555/drip/web` to use a local instance of the faucet server.
- `PUBLIC_DEMO_MODE`: for testing only the front end. It will not try to contact any faucet server. Leave blank if you want to test end-to-end.

To develop you need two env variables:

- `PUBLIC_CAPTCHA_KEY`: The [reCaptcha v2 site key](https://www.google.com/u/0/recaptcha/admin).
- `PUBLIC_FAUCET_URL`: The endpoint to contact the faucet backend. Keep unset to run client-side code with production backend.
The other environment variables don't need to change, typically.

The reason for which these variables have `PUBLIC_` as a prefix is a security measure to not upload any unnecessary data. [More info here](https://kit.svelte.dev/docs/modules#$env-static-public)

If you wish to only interact with the flow but do not wish to contact the faucet, you can set the following env variable to true `PUBLIC_DEMO_MODE`.
This will show that the application is running on Demo mode and will not contact the faucet but simulate the flow.

## Scripts

- `yarn run dev`: To deploy a development instance of the project
### Quick start / testing
from `src/client`:
```shell
yarn install
cp env.sample .env
```
Edit the .env file as desired and launch the client in watch mode:
```shell
yarn dev
```

## Other Scripts
- `yarn run build`: To build the project in the `build` directory
- `yarn run check`: To lint the project of unnecessary code

Expand Down
7 changes: 5 additions & 2 deletions client/env.sample
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# leave blank to turn off demo mode
PUBLIC_DEMO_MODE=
PUBLIC_CAPTCHA_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
# test key for hcaptcha, see https://docs.hcaptcha.com/#integration-testing-test-keys
PUBLIC_CAPTCHA_KEY=10000000-ffff-ffff-ffff-000000000001

# Direct requests to local instance
# Direct requests to local instance. Leave blank to use external default
# PUBLIC_FAUCET_URL=http://localhost:5555/drip/web/
PUBLIC_FAUCET_URL=

# No need to edit these.
PUBLIC_ISSUE_LINK=https://github.com/frequency-chain/testnet-faucet/issues/new/choose
PUBLIC_FORUM="https://discord.com/channels/969001918460469250/969308337864867840"
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"postcss-load-config": "^6.0.1",
"svelte": "^4.2.19",
"svelte-check": "^4.0.2",
"svelte-hcaptcha": "^0.1.1",
"svelte-markdown": "^0.4.1",
"svelte-meta-tags": "^3.1.4",
"svelte-preprocess": "^6.0.2",
Expand Down
4 changes: 1 addition & 3 deletions client/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ const config: PlaywrightTestConfig = {
command: "npm run build && npm run preview",
port: 4173,
env: {
PUBLIC_CAPTCHA_KEY: "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI",
PUBLIC_DEMO_MODE: "",
PUBLIC_CAPTCHA_KEY: "10000000-ffff-ffff-ffff-000000000001",
PUBLIC_FAUCET_URL: "https://example.com/test",
PUBLIC_FORUM: "",
},
},
testDir: "tests",
Expand Down
2 changes: 1 addition & 1 deletion client/src/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ declare global {
}

declare interface Window {
grecaptcha?: Captcha;
captcha?: Captcha;
captchaLoaded: () => void;
onToken: (token: string) => void;
onExpiredToken: () => void;
Expand Down
2 changes: 1 addition & 1 deletion client/src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/x-icon" href="%sveltekit.assets%/favicon-frequency.png" />
<link rel="icon" type="image/x-icon" href="%sveltekit.assets%/favicon-192.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
Expand Down
4 changes: 2 additions & 2 deletions client/src/lib/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 25 additions & 49 deletions client/src/lib/components/CaptchaV2.svelte
Original file line number Diff line number Diff line change
@@ -1,66 +1,42 @@
<script lang="ts">
import { createEventDispatcher, onMount } from "svelte";
import { createEventDispatcher } from "svelte";
import Cross from "./icons/Cross.svelte";
// @ts-ignore
import HCaptcha from 'svelte-hcaptcha';
import { PUBLIC_CAPTCHA_KEY } from '$env/static/public';
export let captchaKey: string;
const siteKey = PUBLIC_CAPTCHA_KEY;
const dispatch = createEventDispatcher<{ token: string }>();
const dispatch = createEventDispatcher();
const captchaId = "captcha_element";
let captchaError: boolean = false;
export let theme: "dark" | "light" | "auto" = "auto";
let captchaError = false;
let captchaKey = '';
let componentMounted: boolean;
onMount(() => {
window.captchaLoaded = () => {
const colorTheme =
theme === "auto"
? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: theme;
const mobileScreen = window.innerHeight > window.innerWidth;
if (!window.grecaptcha) {
captchaError = true;
throw new Error("grecaptcha is undefined!");
}
window.grecaptcha.render(captchaId, {
sitekey: captchaKey,
theme: colorTheme,
callback: "onToken",
size: mobileScreen ? "compact" : "normal",
"expired-callback": "onExpiredToken",
});
};
window.onToken = (token) => {
dispatch("token", token);
};
// clean the token so the form becomes invalid
window.onExpiredToken = () => {
dispatch("token", "");
};
// once we have mounted all the required methods, we import the script
componentMounted = true;
const handleSuccess = (payload: { detail?: {token: string}}) => {
const token = payload?.detail?.token || '';
dispatch("token", token);
captchaError = false;
});
</script>
}
<svelte:head>
{#if componentMounted}
<script src="https://www.google.com/recaptcha/api.js?onload=captchaLoaded&render=explicit" async defer></script>
{/if}
</svelte:head>
const handleError = (error: Error) => {
captchaError = true;
console.error(error)
}
</script>
<HCaptcha
sitekey={siteKey}
bind:this={captchaKey}
theme=dark
on:success={handleSuccess}
on:error={handleError}
/>

{#if captchaError}
<div class="alert alert-error shadow-lg" data-testid="error">
<div>
<Cross />
<span>Error loading Google Captcha. Please reload the page.</span>
<span>Error loading HCaptcha. Please reload the page.</span>
</div>
</div>
{/if}
Expand Down
5 changes: 2 additions & 3 deletions client/src/lib/components/Form.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<script lang="ts">
import { PUBLIC_CAPTCHA_KEY } from "$env/static/public";
import type { NetworkData } from "$lib/utils/networkData";
import { operation, testnet } from "$lib/utils/stores";
import { request as faucetRequest } from "../utils";
import CaptchaV2 from "./CaptchaV2.svelte";
import NetworkDropdown from "./NetworkDropdown.svelte";
import NetworkInput from "./NetworkInput.svelte";
import NetworkInput from "./ChainDropdown.svelte";
import {validateAddress} from "@polkadot/util-crypto";
let address: string = "";
Expand Down Expand Up @@ -74,7 +73,7 @@
</div>
{#if !webRequest}
<div class="grid place-items-center">
<CaptchaV2 captchaKey={PUBLIC_CAPTCHA_KEY ?? ""} on:token={onToken} theme="dark" />
<CaptchaV2 on:token={onToken} />
</div>
<button class="submit-btn" type="submit" data-testid="submit-button" disabled={!formValid}>
Get some {$testnet.currency}s
Expand Down
Loading

0 comments on commit 6d9f72a

Please sign in to comment.