Verified Commit 24c11f62 authored by Rigel Kent's avatar Rigel Kent
Browse files

recaptcha v2 for registration

parents
node_modules
.cache
dist
LICENSE
\ No newline at end of file
This diff is collapsed.
# PeerTube plugin Quickstart
.g-recaptcha {
margin-bottom: 2rem;
}
\ No newline at end of file
import loadjs from "loadjs"
function register({ registerHook, peertubeHelpers }) {
initRC(registerHook, peertubeHelpers).catch(err =>
console.error("Cannot initialize recaptcha plugin", err)
)
}
export { register }
function initRC(registerHook, peertubeHelpers) {
return peertubeHelpers.getSettings().then(async s => {
if (!s || !s["recaptcha-site-key"]) {
console.error(
"Recaptcha plugin lacks a site key set to use the ReCaptcha. Falling back to normal registration."
)
return
}
// add captcha to the first form (user form)
const node = document.getElementsByTagName("form")[0]
const div = document.createElement("div")
div.setAttribute("class", "g-recaptcha")
node.appendChild(div)
// global callback definition is the most flexible way, since
// loadjs's callback triggers too soon: immediately after the
// resource load, when in fact api.js loads other resources
// before it is defining grecaptcha.
window.onReCaptchaLoadCallback = () => {
grecaptcha.render(div, {
callback: () =>
(window.ReCaptchaLoadCallbackResponse = grecaptcha.getResponse()),
sitekey: s["recaptcha-site-key"]
})
}
loadjs(
"https://www.google.com/recaptcha/api.js?onload=onReCaptchaLoadCallback&render=explicit"
)
registerHook({
target: "filter:signup.register.body",
handler: body =>
Object.assign({}, body, {
"g-recaptcha-response": window.ReCaptchaLoadCallbackResponse
})
})
})
}
var _request = require("request")
const request = function(options) {
return new Promise((resolve,reject) => {
_request(options, (error, response, body) => {
if (response) {
return resolve(response)
}
if (error) {
return reject(error)
}
})
})
}
async function register({
registerHook,
registerSetting,
settingsManager
}) {
// see https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do
/*
Test Site key: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
Test Secret key: 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe
They will always return a validated response, and will show a captcha with a warning
*/
registerSetting({
name: 'recaptcha-site-key',
label: 'ReCaptcha Site Key',
type: 'input',
private: false
})
registerSetting({
name: 'recaptcha-secret-key',
label: 'ReCaptcha Secret Key',
type: 'input',
private: true
})
registerHook({
target: "filter:api.user.signup.allowed.result",
handler: (result, params) => verifyCaptcha(result, params, settingsManager)
})
}
async function unregister() {
return
}
module.exports = {
register,
unregister
}
async function verifyCaptcha (result, params, settingsManager) {
// g-recaptcha-response is the key that browser will generate upon form submit.
// if its blank or null means user has not selected the captcha, so return the error.
if (
params.body["g-recaptcha-response"] === undefined ||
params.body["g-recaptcha-response"] === "" ||
params.body["g-recaptcha-response"] === null
) {
return { allowed: false, errorMessage: "Captcha wasn't filled" }
}
const secretKey = await settingsManager.getSetting('recaptcha-secret-key')
if (!secretKey) return result
// params.connection.remoteAddress will provide IP address of connected user.
const verificationUrl =
"https://www.google.com/recaptcha/api/siteverify?secret=" +
secretKey +
"&response=" +
params.body["g-recaptcha-response"] +
"&remoteip=" +
params.connection.remoteAddress
return await request(verificationUrl, (error, response, body) => {
body = JSON.parse(body)
if (body.success !== undefined && !body.success) {
return { allowed: false, errorMessage: "Wrong captcha" }
}
return result
})
}
This diff is collapsed.
{
"name": "peertube-plugin-recaptcha",
"description": "PeerTube plugin adding ReCaptcha v2 to the signup",
"version": "0.0.1",
"author": "Rigel Kent",
"bugs": "https://framagit.org/framasoft/peertube/peertube-plugin-quickstart/issues",
"clientScripts": [
{
"script": "dist/signup-client-plugin.js",
"scopes": [
"signup"
]
}
],
"css": [
"assets/style.css"
],
"dependencies": {
"loadjs": "^4.0.1"
},
"devDependencies": {
"@purtuga/esm-webpack-plugin": "^1.1.1",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10"
},
"engine": {
"peertube": ">=2.1.0"
},
"homepage": "https://framagit.org/framasoft/peertube/peertube-plugin-recaptcha",
"keywords": [
"peertube",
"plugin"
],
"library": "./main.js",
"license": "AGPL-3.0-or-later",
"repository": "https://framagit.org/framasoft/peertube/peertube-plugin-recaptcha",
"scripts": {
"build": "webpack --mode=production"
},
"staticDirs": {},
"translations": {}
}
const path = require("path")
const EsmWebpackPlugin = require("@purtuga/esm-webpack-plugin")
let config = {
entry: "./client/signup-client-plugin.js",
output: {
path: path.resolve(__dirname, "./dist"),
filename: "./signup-client-plugin.js",
library: "script",
libraryTarget: "var"
},
plugins: [new EsmWebpackPlugin()]
}
module.exports = config
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment