feat: add python example server

This commit is contained in:
Aravinth Manivannan 2024-01-07 23:01:12 +05:30
commit 51802bc4f8
Signed by: realaravinth
GPG key ID: F8F50389936984FF
7 changed files with 343 additions and 0 deletions

133
.gitignore vendored Normal file
View file

@ -0,0 +1,133 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
.env
.env.local
tmp/

3
python/.env_sample Normal file
View file

@ -0,0 +1,3 @@
SITEKEY=
SECRET=
INSTANCE_URL=

1
python/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
__pycache__/

40
python/README.md Normal file
View file

@ -0,0 +1,40 @@
# Example Server with mCaptcha protection
The example server shows a dummy form with the mCaptcha widget. When the
form is submitted, it validates the [authorization
token](https://mcaptcha.org/docs/webmasters/terminology#authorization-token)
presented by the visitor against the mCaptcha instance that the server
is configured with.
The example server is built with the Flask webframework and uses the
[Python API library for mCaptcha](https://pypi.org/project/mcaptcha-api/0.1.0/) for validation.
## 1. Configuration
Before running, please configure the server:
```bash
cp .env_sample .env
```
And fill in the configuration parameters in `.env` file with:
1. [Sitekey](https://mcaptcha.org/docs/webmasters/terminology#sitekey)
2. Account secret: Available in the settings page on the mCaptcha
dashboard
3. Instance URL
## 2. Install dependencies
```bash
virtualenv venv && . venv/bin/activate && pip install -r ./requirements.txt
```
## 3. Launch server
```bash
flask --app server run
```
If all configuration parameters are properly filled in, the example server must
work.

13
python/requirements.txt Normal file
View file

@ -0,0 +1,13 @@
blinker==1.7.0
certifi==2023.11.17
charset-normalizer==3.3.2
click==8.1.7
Flask==3.0.0
idna==3.6
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
mcaptcha_api==0.1.0
requests==2.31.0
urllib3==2.1.0
Werkzeug==3.0.1

43
python/server.py Normal file
View file

@ -0,0 +1,43 @@
import os
from flask import Flask, render_template, request
from mcaptcha_api import MCaptcha
app = Flask(__name__)
sitekey = os.environ["SITEKEY"]
secret = os.environ["SECRET"]
instance_url = os.environ["INSTANCE_URL"]
if len(sitekey) == 0:
print("please enter sitekey")
exit(-1)
if len(secret) == 0:
print("please enter secret")
exit(-1)
if len(instance_url) == 0:
print("please enter instance url")
exit(-1)
@app.route("/")
def index():
return render_template(
"index.html.j2", widget_link=f"{instance_url}/widget?sitekey={sitekey}"
)
mcaptcha = MCaptcha(instance_url=instance_url, sitekey=sitekey, secret=secret)
@app.route("/login", methods=["POST"])
def login_page():
username = request.form["username"]
token = request.form["mcaptcha__token"]
if mcaptcha.verify(token=token):
return "<p> Success. Click <a href="/">here</a> to retry</p>"
else:
return '<p> Failed. Click <a href="/">here</a> to retry</p>'

View file

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Home | mCaptcha Example SErver</title>
<meta name="referrer" content="no-referrer-when-downgrade" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="mCaptcha is an AGPL'd, privacy focued, proof-of-work based CAPTCHA System"
/>
</head>
<body>
<form action="/" method="post">
<h1>Demo Form</h1>
<label for="name">
Name
<input type="text" name="name" id="name" />
</label>
<label for="comment">
Comment
<input type="password" name="comment" id="comment" />
</label>
<label
for="mcaptcha__token"
data-mcaptcha_url="{{ widget_link }}"
id="mcaptcha__token-label"
>
mCaptcha authorization token.
<a
href="https://mcaptcha.org/docs/user-manual/how-to-mcaptcha-without-js/"
>Instructions</a
>.
<input type="text" name="mcaptcha__token" id="mcaptcha__token" />
</label>
<div id="mcaptcha__widget-container"></div>
<script src="https://unpkg.com/@mcaptcha/vanilla-glue@0.1.0-rc2/dist/index.js"></script>
<button type="submit">Register</button>
</form>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
height: 100vh;
justify-content: space-around;
}
* {
padding: 0;
margin: 0;
}
form {
display: flex;
flex-direction: column;
margin: auto;
}
label {
display: block;
width: 100%;
margin: 5px 0;
}
input {
display: block;
width: 100%;
margin: 5px 0 auto;
height: 26px;
}
/*
#mcaptcha__token {
display: none;
}
*/
button {
background: none;
border: none;
background: green;
color: #fff;
height: 26px;
border-radius: 5px;
margin: 5px 0 auto;
}
h1 {
text-align: center;
align-self: center;
margin: 40px auto;
}
#mcaptcha__widget-container {
height: 78px;
width: 100%;
margin: 10px 0;
}
</style>
</body>
</html>