From 8769ca1dd9d1cd133c81b9d273d53caa4ccb6667 Mon Sep 17 00:00:00 2001 From: Xaekai Date: Sun, 4 Jun 2017 18:59:36 -0700 Subject: [PATCH 1/4] Basic validation of channel IDs on the registration page --- templates/account-channels.pug | 46 +++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/templates/account-channels.pug b/templates/account-channels.pug index b21a233a..ab0de34f 100644 --- a/templates/account-channels.pug +++ b/templates/account-channels.pug @@ -55,9 +55,49 @@ html(lang="en") input(type="hidden", name="_csrf", value=csrfToken) input(type="hidden", name="action", value="new_channel") .form-group - label.control-label(for="channelname") Channel Name - input#channelname.form-control(type="text", name="name") - button.btn.btn-primary.btn-block(type="submit") Register + label.control-label(for="channelname") Channel URL + span#validation.pull-right + .input-group + span.input-group-addon #{baseUrl}/r/ + input#channelname.form-control(type="text", name="name") + button#register.btn.btn-primary.btn-block(type="submit") Register include footer +footer() + script( type='text/javascript'). + function nameIsInvalid(id){ + if(/\s/.test(id)){ + return 'Channel URLs may not contain spaces'; + } + if(id.length > 30){ + return 'Channel URLs may not be longer than 30 characters'; + } + if(id.length < 1){ + return 'Channel URLs must be at least one character'; + } + if(!/^[\w-]{1,30}$/.test(id)){ + return 'Channel URLs may only consist of a-z, A-Z, 0-9, - and _'; + } + return false; + } + + $("#channelname").keyup(function () { + var box = $(this); + var value = box.val(); + var lastkey = Date.now(); + box.data("lastkey", lastkey); + + setTimeout(function () { + if (box.data("lastkey") !== lastkey || box.val() !== value) { + return; + } + if(nameIsInvalid(value)){ + $('#validation').text(nameIsInvalid(value)); + $('#register').addClass('disabled'); + } else { + $('#validation').text(''); + $('#register').removeClass('disabled'); + } + }, 200); + }); + From 668477d711fbbf4e0c980e6ecefe0277112affae Mon Sep 17 00:00:00 2001 From: Xaekai Date: Sun, 4 Jun 2017 22:04:39 -0700 Subject: [PATCH 2/4] Nice is subjective. --- templates/register.pug | 63 +++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/templates/register.pug b/templates/register.pug index e42ed79f..49d8757a 100644 --- a/templates/register.pug +++ b/templates/register.pug @@ -32,7 +32,7 @@ html(lang="en") input(type="hidden", name="_csrf", value=csrfToken) .form-group label.control-label(for="username") Username - input#username.form-control(type="text", name="name") + input#username.form-control(type="text", name="name", onkeyup="checkUsername()", maxlength="20") .form-group label.control-label(for="password") Password input#password.form-control(type="password", name="password", onkeyup="checkPasswords()") @@ -62,52 +62,59 @@ html(lang="en") return valid; } function checkUsername() { - var name = $("#username").val(); + function createError(text, target){ + target.parent() + .addClass("has-error") + .removeClass("has-success"); + $("

").addClass("text-danger") + .attr("id", "usernameerror") + .text(text) + .insertAfter(target); + } + var target = $("#username"); + var name = target.val(); $("#usernameerror").remove(); if (name === "") { - $("#username").parent().addClass("has-error"); - $("

").addClass("text-danger") - .attr("id", "usernameerror") - .text("Username must not be empty") - .insertAfter($("#username")); + createError('Username must not be empty', target) return false; } else if (!(/^[-\w\u00c0-\u00ff]{1,20}$/).test(name)) { - $("#username").parent().addClass("has-error"); - $("

").addClass("text-danger") - .attr("id", "usernameerror") - .text("Username must consist of 1-20 characters a-Z, A-Z, 0-9 " + - ", -, or _.") - .insertAfter($("#username")); + createError("Username must consist of 1-20 characters" + + " a-Z, A-Z, 0-9, -, or _.", target); return false; } else { - $("#username").parent().removeClass("has-error") + target.parent().removeClass("has-error") .addClass("has-success"); } } function checkPasswords() { - var pw = $("#password").val(); - var pwc = $("#password_confirm").val(); + function createError(text, target, id){ + target.parent() + .addClass("has-error") + .removeClass("has-success"); + $("

").addClass("text-danger") + .attr("id", id) + .text(text) + .insertAfter(target); + } + var target = $("#password"); + var target2 = $("#password_confirm"); + var pw = target.val(); + var pwc = target2.val(); + $("#passwordempty").remove(); $("#passwordmismatch").remove(); if (pw === "") { - $("#password").parent().addClass("has-error"); - $("

").addClass("text-danger") - .attr("id", "passwordempty") - .text("Password must not be empty") - .insertAfter($("#password")); + createError('Password must not be empty', target, 'passwordempty') return false; } else { - $("#password").parent().removeClass("has-error") + target.parent().removeClass("has-error") .addClass("has-success"); if (pw !== pwc) { - $("#password_confirm").parent().addClass("has-error"); - $("

").addClass("text-danger") - .attr("id", "passwordmismatch") - .text("Passwords do not match") - .insertAfter($("#password_confirm")); + createError('Passwords do not match', target2, 'passwordmismatch') return false; } else { - $("#password_confirm").parent().removeClass("has-error") + target2.parent() + .removeClass("has-error") .addClass("has-success"); } } From d42de93d749b4b0b2ad41fffc1b7ac2b8080da3f Mon Sep 17 00:00:00 2001 From: Xaekai Date: Sun, 4 Jun 2017 22:16:40 -0700 Subject: [PATCH 3/4] Round 2. --- src/web/account.js | 1 + templates/account-channels.pug | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/web/account.js b/src/web/account.js index d95582e1..8890ff06 100644 --- a/src/web/account.js +++ b/src/web/account.js @@ -202,6 +202,7 @@ function handleAccountChannelPage(req, res) { db.channels.listUserChannels(req.user.name, function (err, channels) { sendPug(res, "account-channels", { + domain: req.host, channels: channels }); }); diff --git a/templates/account-channels.pug b/templates/account-channels.pug index ab0de34f..0b05e346 100644 --- a/templates/account-channels.pug +++ b/templates/account-channels.pug @@ -56,10 +56,10 @@ html(lang="en") input(type="hidden", name="action", value="new_channel") .form-group label.control-label(for="channelname") Channel URL - span#validation.pull-right + span#validation.text-danger.pull-right .input-group - span.input-group-addon #{baseUrl}/r/ - input#channelname.form-control(type="text", name="name") + span.input-group-addon #{domain}/r/ + input#channelname.form-control(type="text", name="name", maxlength="30", onkeyup="checkChannel()") button#register.btn.btn-primary.btn-block(type="submit") Register include footer @@ -69,11 +69,8 @@ html(lang="en") if(/\s/.test(id)){ return 'Channel URLs may not contain spaces'; } - if(id.length > 30){ - return 'Channel URLs may not be longer than 30 characters'; - } - if(id.length < 1){ - return 'Channel URLs must be at least one character'; + if(id === ''){ + return 'Channel URLs must not be empty'; } if(!/^[\w-]{1,30}$/.test(id)){ return 'Channel URLs may only consist of a-z, A-Z, 0-9, - and _'; @@ -81,8 +78,8 @@ html(lang="en") return false; } - $("#channelname").keyup(function () { - var box = $(this); + function checkChannel(){ + var box = $("#channelname"); var value = box.val(); var lastkey = Date.now(); box.data("lastkey", lastkey); @@ -92,12 +89,15 @@ html(lang="en") return; } if(nameIsInvalid(value)){ - $('#validation').text(nameIsInvalid(value)); + $('#validation').text(nameIsInvalid(value)) + .parent().addClass('has-error').removeClass('has-success'); $('#register').addClass('disabled'); } else { - $('#validation').text(''); + $('#validation').text('') + .parent().addClass('has-success').removeClass('has-error'); $('#register').removeClass('disabled'); } }, 200); - }); + + } From 699aa2abe1f684901a760ed42ff9f756e26593bd Mon Sep 17 00:00:00 2001 From: Xaekai Date: Sun, 4 Jun 2017 23:44:46 -0700 Subject: [PATCH 4/4] Finish validation touchup --- src/web/account.js | 1 - src/web/pug.js | 1 + templates/account-channels.pug | 32 +++++++++++++-------------- templates/register.pug | 40 +++++++++++++++++----------------- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/web/account.js b/src/web/account.js index 8890ff06..d95582e1 100644 --- a/src/web/account.js +++ b/src/web/account.js @@ -202,7 +202,6 @@ function handleAccountChannelPage(req, res) { db.channels.listUserChannels(req.user.name, function (err, channels) { sendPug(res, "account-channels", { - domain: req.host, channels: channels }); }); diff --git a/src/web/pug.js b/src/web/pug.js index b944ed0b..b16e2f95 100644 --- a/src/web/pug.js +++ b/src/web/pug.js @@ -13,6 +13,7 @@ function merge(locals, res) { siteTitle: Config.get("html-template.title"), siteDescription: Config.get("html-template.description"), siteAuthor: "Calvin 'calzoneman' 'cyzon' Montgomery", + domain: res.req.host, loginDomain: Config.get("https.enabled") ? Config.get("https.full-address") : Config.get("http.full-address"), csrfToken: typeof res.req.csrfToken === 'function' ? res.req.csrfToken() : '', diff --git a/templates/account-channels.pug b/templates/account-channels.pug index 0b05e346..123baef6 100644 --- a/templates/account-channels.pug +++ b/templates/account-channels.pug @@ -56,29 +56,29 @@ html(lang="en") input(type="hidden", name="action", value="new_channel") .form-group label.control-label(for="channelname") Channel URL - span#validation.text-danger.pull-right .input-group span.input-group-addon #{domain}/r/ input#channelname.form-control(type="text", name="name", maxlength="30", onkeyup="checkChannel()") + p#validate_channel.text-danger.pull-right button#register.btn.btn-primary.btn-block(type="submit") Register include footer +footer() script( type='text/javascript'). - function nameIsInvalid(id){ - if(/\s/.test(id)){ - return 'Channel URLs may not contain spaces'; - } - if(id === ''){ - return 'Channel URLs must not be empty'; - } - if(!/^[\w-]{1,30}$/.test(id)){ - return 'Channel URLs may only consist of a-z, A-Z, 0-9, - and _'; - } - return false; - } - function checkChannel(){ + function nameIsInvalid(id){ + if(/\s/.test(id)){ + return 'Channel URL may not contain spaces'; + } + if(id === ''){ + return 'Channel URL must not be empty'; + } + if(!/^[\w-]{1,30}$/.test(id)){ + return 'Channel URL may only consist of a-z, A-Z, 0-9, - and _'; + } + return false; + } + var box = $("#channelname"); var value = box.val(); var lastkey = Date.now(); @@ -89,11 +89,11 @@ html(lang="en") return; } if(nameIsInvalid(value)){ - $('#validation').text(nameIsInvalid(value)) + $('#validate_channel').text(nameIsInvalid(value)) .parent().addClass('has-error').removeClass('has-success'); $('#register').addClass('disabled'); } else { - $('#validation').text('') + $('#validate_channel').text('') .parent().addClass('has-success').removeClass('has-error'); $('#register').removeClass('disabled'); } diff --git a/templates/register.pug b/templates/register.pug index 49d8757a..3e8529f1 100644 --- a/templates/register.pug +++ b/templates/register.pug @@ -33,15 +33,19 @@ html(lang="en") .form-group label.control-label(for="username") Username input#username.form-control(type="text", name="name", onkeyup="checkUsername()", maxlength="20") + p#validate_username.text-danger.pull-right .form-group label.control-label(for="password") Password input#password.form-control(type="password", name="password", onkeyup="checkPasswords()") + p#validate_password.text-danger.pull-right .form-group label.control-label(for="password_confirm") Confirm Password input#password_confirm.form-control(type="password", onkeyup="checkPasswords()") + p#validate_confirm.text-danger.pull-right .form-group label.control-label(for="email") Email (optional) input#email.form-control(type="email", name="email") + p#validate_email.text-danger.pull-right p | Providing an email address is optional and will allow you to recover your account via email if you forget your password. strong   If you do not provide an email address, you will not be able to recover a lost account! @@ -62,55 +66,51 @@ html(lang="en") return valid; } function checkUsername() { - function createError(text, target){ + function stateError(text){ target.parent() .addClass("has-error") .removeClass("has-success"); - $("

").addClass("text-danger") - .attr("id", "usernameerror") - .text(text) - .insertAfter(target); + $("#validate_username").text(text); } var target = $("#username"); var name = target.val(); - $("#usernameerror").remove(); if (name === "") { - createError('Username must not be empty', target) + stateError('Username must not be empty') return false; } else if (!(/^[-\w\u00c0-\u00ff]{1,20}$/).test(name)) { - createError("Username must consist of 1-20 characters" + - " a-Z, A-Z, 0-9, -, or _.", target); + stateError("Username must consist of 1-20 characters" + + " a-Z, A-Z, 0-9, -, or _."); return false; } else { - target.parent().removeClass("has-error") + target.parent() + .removeClass("has-error") .addClass("has-success"); + $("#validate_username").text(''); } } function checkPasswords() { - function createError(text, target, id){ + function stateError(text, target, validator){ target.parent() .addClass("has-error") .removeClass("has-success"); - $("

").addClass("text-danger") - .attr("id", id) - .text(text) - .insertAfter(target); + $(`#${validator}`).text(text); } var target = $("#password"); var target2 = $("#password_confirm"); var pw = target.val(); var pwc = target2.val(); - $("#passwordempty").remove(); - $("#passwordmismatch").remove(); + $("#validate_password").text(''); + $("#validate_confirm").text(''); if (pw === "") { - createError('Password must not be empty', target, 'passwordempty') + stateError('Password must not be empty', target, 'validate_password') return false; } else { - target.parent().removeClass("has-error") + target.parent() + .removeClass("has-error") .addClass("has-success"); if (pw !== pwc) { - createError('Passwords do not match', target2, 'passwordmismatch') + stateError('Passwords do not match', target2, 'validate_confirm') return false; } else { target2.parent()