feat: add gdpr privacy and terms
This commit is contained in:
@ -99,6 +99,10 @@
|
|||||||
"twitter": {
|
"twitter": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"acceptedPrivacyTerms": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"sendQuincyEmail": {
|
"sendQuincyEmail": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
|
@ -51,6 +51,20 @@ module.exports = function enableAuthentication(app) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/accept-privacy-terms',
|
||||||
|
ifNoUserRedirectHome,
|
||||||
|
(req, res) => {
|
||||||
|
const { user } = req;
|
||||||
|
if (user && !user.acceptedPrivacyTerms) {
|
||||||
|
return res.render('account/accept-privacy-terms', {
|
||||||
|
title: 'Privacy Policy and Terms of Service'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return res.redirect('/settings');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const defaultErrorMsg = dedent`
|
const defaultErrorMsg = dedent`
|
||||||
Oops, something is not right,
|
Oops, something is not right,
|
||||||
please request a fresh link to sign in / sign up.
|
please request a fresh link to sign in / sign up.
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { check } from 'express-validator/check';
|
import { check } from 'express-validator/check';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ifNoUser401,
|
ifNoUser401,
|
||||||
createValidatorErrorHandler
|
createValidatorErrorHandler
|
||||||
@ -147,6 +146,36 @@ export default function settingsController(app) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updatePrivacyTerms = (req, res, next) => {
|
||||||
|
const {
|
||||||
|
user,
|
||||||
|
body: { quincyemails }
|
||||||
|
} = req;
|
||||||
|
const update = {
|
||||||
|
acceptedPrivacyTerms: true,
|
||||||
|
sendQuincyEmail: !!quincyemails
|
||||||
|
};
|
||||||
|
return user.update$(update)
|
||||||
|
.do(() => {
|
||||||
|
req.user = Object.assign(req.user, update);
|
||||||
|
})
|
||||||
|
.subscribe(
|
||||||
|
() => {
|
||||||
|
res.status(200).json({
|
||||||
|
message: 'We have updated your preferences. ' +
|
||||||
|
'You can now continue using freeCodeCamp.'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
next
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
api.post(
|
||||||
|
'/update-privacy-terms',
|
||||||
|
ifNoUser401,
|
||||||
|
updatePrivacyTerms
|
||||||
|
);
|
||||||
|
|
||||||
api.post(
|
api.post(
|
||||||
'/refetch-user-completed-challenges',
|
'/refetch-user-completed-challenges',
|
||||||
ifNoUser401,
|
ifNoUser401,
|
||||||
|
@ -57,7 +57,8 @@
|
|||||||
"./middlewares/csp": {},
|
"./middlewares/csp": {},
|
||||||
"./middlewares/jade-helpers": {},
|
"./middlewares/jade-helpers": {},
|
||||||
"./middlewares/flash-cheaters": {},
|
"./middlewares/flash-cheaters": {},
|
||||||
"./middlewares/passport-login": {}
|
"./middlewares/passport-login": {},
|
||||||
|
"./middlewares/privacy-terms-notice": {}
|
||||||
},
|
},
|
||||||
"files": {},
|
"files": {},
|
||||||
"final:after": {
|
"final:after": {
|
||||||
|
22
server/middlewares/privacy-terms-notice.js
Normal file
22
server/middlewares/privacy-terms-notice.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
const ALLOWED_METHODS = ['GET'];
|
||||||
|
const EXCLUDED_PATHS = [
|
||||||
|
'/api/flyers/findOne',
|
||||||
|
'/signout',
|
||||||
|
'/accept-privacy-terms'
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function privacyTermsNotAcceptedNotice() {
|
||||||
|
return function(req, res, next) {
|
||||||
|
if (
|
||||||
|
ALLOWED_METHODS.indexOf(req.method) !== -1 &&
|
||||||
|
EXCLUDED_PATHS.indexOf(req.path) === -1
|
||||||
|
) {
|
||||||
|
const { user } = req;
|
||||||
|
if (user && user.acceptedPrivacyTerms !== true) {
|
||||||
|
res.redirect('/accept-privacy-terms');
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
}
|
123
server/views/account/accept-privacy-terms.jade
Normal file
123
server/views/account/accept-privacy-terms.jade
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
extends ../layout
|
||||||
|
block content
|
||||||
|
.container
|
||||||
|
.row.flashMessage.negative-30
|
||||||
|
.col-sm-6.col-sm-offset-3
|
||||||
|
#flash-board.alert.fade.in(style='display: none;')
|
||||||
|
button.close(type='button', data-dismiss='alert')
|
||||||
|
span.ion-close-circled#flash-close
|
||||||
|
#flash-content
|
||||||
|
.col-xs-12
|
||||||
|
#accept-privacy-terms
|
||||||
|
.row
|
||||||
|
.text-center
|
||||||
|
h3 Please review our privacy policy and the terms of service.
|
||||||
|
br
|
||||||
|
.row
|
||||||
|
.col-sm-6.col-sm-offset-3
|
||||||
|
form(method='POST', action='/update-privacy-terms')
|
||||||
|
input(type='hidden', name='_csrf', value=_csrf)
|
||||||
|
.checkbox
|
||||||
|
label
|
||||||
|
input(id='terms', name='privacy', type='checkbox')
|
||||||
|
span.cr
|
||||||
|
i.cr-icon.fa.fa-check
|
||||||
|
| I accept the
|
||||||
|
a(href='https://www.freecodecamp.org/terms' target='_blank') terms of service
|
||||||
|
| (required).
|
||||||
|
.checkbox
|
||||||
|
label
|
||||||
|
input(id='privacy', name='privacy', type='checkbox')
|
||||||
|
span.cr
|
||||||
|
i.cr-icon.fa.fa-check
|
||||||
|
| I accept the
|
||||||
|
a(href='https://www.freecodecamp.org/privacy' target='_blank') privacy policy
|
||||||
|
| (required).
|
||||||
|
.checkbox
|
||||||
|
label
|
||||||
|
input(id='quincyemails', name='quincyemails', type='checkbox')
|
||||||
|
span.cr
|
||||||
|
i.cr-icon.fa.fa-check
|
||||||
|
| I want weekly emails from Quincy (freeCodeCamp.org's founder)
|
||||||
|
.button-spacer
|
||||||
|
button.btn.btn-primary.btn-lg.btn-block(id='submit-button', type='submit')
|
||||||
|
.row
|
||||||
|
.col-sm-6.col-sm-offset-3
|
||||||
|
a.btn.btn-primary.btn-lg.btn-block(id='continue-button', href='/', style='display: none;')
|
||||||
|
| Continue to freeCodeCamp
|
||||||
|
|
||||||
|
script.
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
var checkedBoxCount = 0;
|
||||||
|
function disableContinueButtonForAgreement(isLaunched) {
|
||||||
|
if (isLaunched) {
|
||||||
|
$('#submit-button').prop('disabled', true).html(
|
||||||
|
'<span style="color:#E0E0E0;">Submit<\/span>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLaunched && checkedBoxCount === 2){
|
||||||
|
$('#submit-button').prop('disabled', false).html(
|
||||||
|
'<span>Submit<\/span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disableContinueButtonForAgreement(true);
|
||||||
|
|
||||||
|
$('#terms').click(function() {
|
||||||
|
if (this.checked) {
|
||||||
|
checkedBoxCount++;
|
||||||
|
disableContinueButtonForAgreement(false);
|
||||||
|
} else {
|
||||||
|
checkedBoxCount--;
|
||||||
|
disableContinueButtonForAgreement(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#privacy').click(function() {
|
||||||
|
if (this.checked) {
|
||||||
|
checkedBoxCount++;
|
||||||
|
disableContinueButtonForAgreement(false);
|
||||||
|
} else {
|
||||||
|
checkedBoxCount--;
|
||||||
|
disableContinueButtonForAgreement(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('form').submit(function(event){
|
||||||
|
event.preventDefault();
|
||||||
|
$('#flash-board').hide();
|
||||||
|
var $form = $(event.target);
|
||||||
|
$.ajax({
|
||||||
|
type : 'POST',
|
||||||
|
url : $form.attr('action'),
|
||||||
|
data : $form.serialize(),
|
||||||
|
dataType : 'json',
|
||||||
|
encode : true,
|
||||||
|
xhrFields : { withCredentials: true }
|
||||||
|
})
|
||||||
|
.fail(error => {
|
||||||
|
if (error.responseText){
|
||||||
|
var data = JSON.parse(error.responseText);
|
||||||
|
if(data.message)
|
||||||
|
$('#flash-content').html(data.message);
|
||||||
|
$('#flash-board')
|
||||||
|
.removeClass('alert-success')
|
||||||
|
.addClass('alert-info')
|
||||||
|
.fadeIn();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.done(data =>{
|
||||||
|
if(data && data.message){
|
||||||
|
$('#flash-content').html(data.message);
|
||||||
|
$('#flash-board')
|
||||||
|
.removeClass('alert-info')
|
||||||
|
.addClass('alert-success')
|
||||||
|
.fadeIn();
|
||||||
|
|
||||||
|
$('#accept-privacy-terms').hide();
|
||||||
|
$('#continue-button').show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user