-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
228 additions
and
10 deletions.
There are no files selected for viewing
This file contains 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,167 @@ | ||
/** | ||
@licence | ||
Copyright (c) 2020 Alan Chandler, all rights reserved | ||
This file is part of Football-Mobile. | ||
Football-Mobile is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
Football-Mobile is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with Football-Mobile. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
import { LitElement, html } from '../libs/lit-element.js'; | ||
import api from '../modules/api.js'; | ||
|
||
let instance = 1; | ||
|
||
const recaptcha = new Promise(function (resolve, reject) { | ||
window.recaptchaElementCallback = function () { | ||
resolve(window.grecaptcha); //grecaptcha is a global object that the script element I am about to add delivers | ||
}; | ||
|
||
const head = document.getElementsByTagName('head')[0]; | ||
const script = document.createElement('script'); | ||
script.setAttribute('async', ''); | ||
script.setAttribute('id', 'grecaptchaLibrary'); | ||
script.setAttribute('defer', ''); | ||
script.setAttribute('src', 'https://www.google.com/recaptcha/api.js?onload=recaptchaElementCallback&render=explicit'); | ||
head.appendChild(script); | ||
}); | ||
|
||
|
||
/* | ||
<re-captcha> | ||
*/ | ||
class ReCaptcha extends LitElement { | ||
static get styles() { | ||
return []; | ||
} | ||
static get properties() { | ||
return { | ||
theme: {type: String}, | ||
invalid: {type: Boolean}, //failed to provide capture response | ||
message: {type: String} //Error message to display when invalid | ||
}; | ||
} | ||
constructor() { | ||
super(); | ||
this.theme = 'light'; | ||
this.invalid = false; | ||
this.captureCompleted = false; | ||
this.message = 'Captcha Not Completed'; | ||
this._setLocationOfBodyFloat = this._setLocationOfBodyFloat.bind(this); | ||
this._scroll = this._scroll.bind(this); | ||
this._captured = this._captured.bind(this); | ||
this.isScrolling = false; | ||
this.resizeObserver = new ResizeObserver(this._setLocationOfBodyFloat); | ||
|
||
} | ||
connectedCallback() { | ||
super.connectedCallback(); | ||
|
||
//append an absolute div to the body in which to render our div. | ||
this.float = document.createElement('div'); | ||
const captchaId = `captcha_${instance++}`; | ||
this.float.setAttribute('id', this.captchaId) | ||
this.float.style = 'position:absolute;'; | ||
document.body.appendChild(this.float); | ||
recaptcha.then(grepcaptcha => grepcaptcha.render(this.captureId,{ | ||
'sitekey': global.recaptchaKey, | ||
'theme': this.theme, | ||
'callback': this._captured | ||
})); | ||
if (this.reserver !== undefined) { | ||
this.resizeObserver.observe(this.reserve); | ||
} | ||
let parent = this; | ||
while (parent = parent.parentNode) { | ||
parent.addEventListener('scroll', this._scroll); | ||
} | ||
|
||
} | ||
disconnectedCallback() { | ||
super.disconnectedCallback(); | ||
this.float.remove(); //take our recapture element away | ||
this.isScrolling = false; | ||
this.captureCompleted = false; | ||
this.resizeObserver.unobserve(this.reserve); | ||
let parent = this; | ||
while (parent = parent.parentNode) { | ||
parent.removeEventListener('scroll', this._scroll); | ||
} | ||
} | ||
update(changed) { | ||
super.update(changed); | ||
} | ||
firstUpdated() { | ||
this.reserve = this.shadowRoot.querySelector('#reserve'); | ||
this.resizeObserver.observe(this.reserve); | ||
|
||
} | ||
updated(changed) { | ||
super.updated(changed); | ||
} | ||
render() { | ||
return html` | ||
<style> | ||
#reserve { | ||
width: 398px; | ||
height: 98px; | ||
} | ||
</style> | ||
<div class="error">${this.invalid? this.message: ' '}</div> | ||
<!-- we reserve space in the dom for this --> | ||
<div id="reserve"></div> | ||
`; | ||
} | ||
validate() { | ||
if (!this.captureCompleted) { | ||
this.invalid = false; | ||
} | ||
return !this.invalid; | ||
} | ||
_captured(token) { | ||
console.log('captured called with token', token); | ||
//I don't want the client to see my secret key, so I am going to send the token to my server, and it can do the validation | ||
api('session/recaptcha_verify',{token:token}).then(response => { | ||
if (response.success) { | ||
this.captureCompleted = true; | ||
this.invalid = false; | ||
} else { | ||
this.invalid = true; | ||
window.grecaptcha.reset(this.captchaId); | ||
} | ||
}) | ||
} | ||
_scroll() { | ||
if (this.isScrolling) return; | ||
this.isScrolling = true; | ||
requestAnimationFrame(() => { | ||
this._setLocationOfBodyFloat(); | ||
this.isScrolling = false; | ||
}); | ||
|
||
} | ||
_setLocationOfBodyFloat() { | ||
if (this.reserve !== undefined) { | ||
const rect = this.reserve.getBoundingClientRect(); | ||
this.float.style.left = rect.left + 'px'; | ||
this.float.style.top = rect.top + 'px'; | ||
this.float.style.width = rect.width + 'px'; | ||
this.float.style.height = rect.height + 'px'; | ||
} | ||
} | ||
} | ||
customElements.define('re-captcha', ReCaptcha); | ||
|
||
|
||
|
||
|
This file contains 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
This file contains 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
This file contains 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 |
---|---|---|
|
@@ -393,20 +393,19 @@ INSERT INTO settings (name,value) VALUES('version',14); --version of this config | |
|
||
INSERT INTO settings (name,value) VALUES('client_log',''); --if none empty string should specify colon separated function areas client should log or 'all' for every thing. | ||
INSERT INTO settings (name,value) VALUES('client_log_uid',0); --if non zero limit client logging to that uid. | ||
INSERT INTO settings (name,value) VALUES('cookie_visit_name','FMVISIT'); --name used for a cookie to record a visit where the user logged on. | ||
|
||
INSERT INTO settings (name,value) VALUES('main_menu_icon','menu'); --character from material icon font to use as the main menu. | ||
INSERT INTO settings (name,value) VALUES('webmaster','[email protected]'); --site webmaster. | ||
INSERT INTO settings (name,value) VALUES('site_logo','/appimages/site_logo.png'); --url of the site_logo image to be used on info pages and in mail | ||
INSERT INTO settings (name,value) VALUES('min_pass_len', 6); --minimum password length | ||
INSERT INTO settings (name,value) VALUES('dwell_time', 2000); --time to elapse before new urls get to be pushed to the history stack | ||
|
||
INSERT INTO settings (name,value) VALUES('recaptcha_key',''); --stardard recaptcha key for the recapcha element | ||
--values for server config | ||
INSERT INTO settings (name,value) VALUES('cache_age',0);--cache age before invalid (in hours), 0 is infinite | ||
INSERT INTO settings (name,value) VALUES('server_port', 2040); --port the api server should listen on. | ||
INSERT INTO settings (name,value) VALUES('cookie_name', 'FOOTBALL'); --name used for our main cookie | ||
INSERT INTO settings (name,value) VALUES('cookie_key', 'newCookieKey'); --key used to encrypt/decrypt cookie token | ||
INSERT INTO settings (name,value) VALUES('cookie_expires', 720); --hours until expire for standard logged on token | ||
INSERT INTO settings (name,value) VALUES('recaptch_secret',''); -- secret key or verification of recaptcha. | ||
INSERT INTO settings (name,value) VALUES('verify_expires', 24); --hours until expire for verification tokens. | ||
INSERT INTO settings (name,value) VALUES('rate_limit', 30); --minutes that must elapse by verification emails | ||
INSERT INTO settings (name,value) VALUES('email_from', '[email protected]'); --email address that mail comes from (do not reply) | ||
|
@@ -454,7 +453,8 @@ INSERT INTO styles (name,style) VALUES('pw-input-length','100px'); --input field | |
-- UPDATE settings SET value = '/images/signature.png;Joe Bloggs' WHERE name = 'mail_signature'; --NOTE, site specific images should be in a different directory | ||
-- UPDATE settings SET value = '/images/site_logo.png' WHERE name = 'site_logo'; --As above. | ||
-- UPDATE settings SET value = 'newCookieKey' WHERE name = 'cookie_key'; | ||
|
||
-- UPDATE settings SET value = 'recaptcha_key' WHERE name = 'recaptcha_key'; | ||
-- UPDATE settings SET value = 'recaptcha_secret_key' WHERE name = 'recaptcha_secret'; | ||
COMMIT; | ||
VACUUM; | ||
-- set it all up as Write Ahead Log for max performance and minimum contention with other users. | ||
|
This file contains 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 |
---|---|---|
|
@@ -236,17 +236,18 @@ INSERT INTO settings (name,value) VALUES('version',14); --version of this config | |
|
||
INSERT INTO settings (name,value) VALUES('client_log',''); --if none empty string should specify colon separated function areas client should log or 'all' for every thing. | ||
INSERT INTO settings (name,value) VALUES('client_log_uid',0); --if non zero limit client logging to that uid. | ||
INSERT INTO settings (name,value) VALUES('cookie_visit_name','FMVISIT'); --name used for a cookie to record a visit where the user logged on. | ||
INSERT INTO settings (name,value) VALUES('webmaster','[email protected]'); --site webmaster. | ||
INSERT INTO settings (name,value) VALUES('site_logo','/appimages/site_logo.png'); --url of the site_logo image to be used on info pages and in mail | ||
INSERT INTO settings (name,value) VALUES('min_pass_len', 6); --minimum password length | ||
INSERT INTO settings (name,value) VALUES('dwell_time', 2000); --time to elapse before new urls get to be pushed to the history stack | ||
INSERT INTO settings (name,value) VALUES('recaptcha_key',''); --standard recaptcha key for the recapcha element | ||
--values for server config | ||
INSERT INTO settings (name,value) VALUES('cache_age',0);--cache age before invalid (in hours), 0 is infinite | ||
INSERT INTO settings (name,value) VALUES('server_port', 2040); --port the api server should listen on. | ||
INSERT INTO settings (name,value) VALUES('cookie_name', 'MBBall'); --name used for our main cookie | ||
INSERT INTO settings (name,value) VALUES('cookie_key', 'newCookieKey'); --key used to encrypt/decrypt cookie token | ||
INSERT INTO settings (name,value) VALUES('cookie_expires', 720); --hours until expire for standard logged on token | ||
INSERT INTO settings (name,value) VALUES('recaptch_secret',''); -- secret key or verification of recaptcha. | ||
INSERT INTO settings (name,value) VALUES('verify_expires', 24); --hours until expire for verification tokens. | ||
INSERT INTO settings (name,value) VALUES('rate_limit', 30); --minutes that must elapse by verification emails | ||
INSERT INTO settings (name,value) VALUES('email_from', '[email protected]'); --email address that mail comes from (do not reply) | ||
|
This file contains 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,50 @@ | ||
/** | ||
@licence | ||
Copyright (c) 2020 Alan Chandler, all rights reserved | ||
This file is part of Football Mobile. | ||
Football Mobile is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
Football Mobile is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with Football Mobile. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
(function() { | ||
'use strict'; | ||
|
||
const debug = require('debug')('football:api:recaptcha'); | ||
const db = require('../utils/database'); | ||
const secret = db.prepare('SELECT value FROM settings WHERE name = ?').pluck().get('recaptcha_secret'); | ||
https = require('https'); | ||
|
||
|
||
module.exports = async function(params) { | ||
debug('new request with token', params.token); | ||
return new Promise((accept, reject) => { | ||
https.request({`https://www.google.com/recaptcha/api/siteverify?secret=${secret}&response=${params.token}`,{ | ||
method: 'POST', | ||
}, (resp) => { | ||
let data = ''; | ||
resp.on('data', (chunk) => { | ||
data += chunk; | ||
}); | ||
// The whole response has been received. Print out the result. | ||
resp.on('end', () => { | ||
accept(JSON.parse(data)); | ||
}); | ||
|
||
}).on("error", (err) => { | ||
reject(err); | ||
}); | ||
}); | ||
}; | ||
})(); |