#52 Added server-side uniqueness checks
parent
a43568a009
commit
3bdaf1b034
|
@ -51,8 +51,8 @@ const userSchema = new mongoose.Schema({
|
|||
// For an example
|
||||
|
||||
// Create email confirmation token
|
||||
userSchema.methods.createEmailToken = function(next){// next(err,hash)
|
||||
console.log('user.createEmailToken() called');
|
||||
userSchema.methods.createEmailToken = function(next){ // next(err,token)
|
||||
//console.log('user.createEmailToken() called');
|
||||
var user = this;
|
||||
|
||||
crypto.randomBytes(16, (err,buf)=>{
|
||||
|
@ -60,12 +60,56 @@ const userSchema = new mongoose.Schema({
|
|||
if (buf){
|
||||
//console.log(`Buffer ${buf.toString('hex')} created`);
|
||||
user.emailToken = buf.toString('hex');
|
||||
user.save();
|
||||
return next(null,user.emailToken);
|
||||
user.save()
|
||||
.then( ()=>{
|
||||
return next(null,user.emailToken);
|
||||
})
|
||||
.catch( (err)=>{
|
||||
return next(err,null);
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// Create password reset token
|
||||
userSchema.methods.createPassToken = function(next){ // next(err,token,expires)
|
||||
var user = this;
|
||||
|
||||
// Reuse old token, resetting clock
|
||||
if ( user.auth.passTokenExpires >= Date.now() ){
|
||||
console.log(`Reusing old password token...`);
|
||||
user.auth.passTokenExpires = Date.now() + 3600000; // 1 hour
|
||||
user.save()
|
||||
.then( ()=>{
|
||||
return next(null,user.auth.passToken,user.auth.passTokenExpires);
|
||||
})
|
||||
.catch( (err)=>{
|
||||
return next(err,null,null);
|
||||
});
|
||||
}
|
||||
|
||||
// Create new token
|
||||
else {
|
||||
console.log(`Creating new password token...`);
|
||||
crypto.randomBytes(16, (err,buf)=>{
|
||||
if (err){ return next(err,null,null); }
|
||||
if (buf) {
|
||||
user.auth.passToken = buf.toString('hex');
|
||||
user.auth.passTokenExpires = Date.now() + 3600000; // 1 hour
|
||||
user.save()
|
||||
.then( ()=>{
|
||||
return next(null,user.auth.passToken,user.auth.passTokenExpires);
|
||||
})
|
||||
.catch( (err)=>{
|
||||
return next(err,null,null);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Generate hash for new password
|
||||
userSchema.methods.generateHash = function(password,next){
|
||||
|
@ -77,37 +121,6 @@ const userSchema = new mongoose.Schema({
|
|||
.catch( (err)=>{ return next(err,null); });
|
||||
};
|
||||
|
||||
// Create password reset token
|
||||
userSchema.methods.createPassToken = function(next){
|
||||
var user = this;
|
||||
|
||||
// Reuse old token, resetting clock
|
||||
if ( user.auth.passTokenExpires <= Date.now() ){
|
||||
user.auth.passTokenExpires = Date.now() + 3600000; // 1 hour
|
||||
user.save()
|
||||
.then( ()=>{
|
||||
return next(null,user.auth.passToken);
|
||||
})
|
||||
.catch( (err)=>{
|
||||
return next(err,user.auth.passToken);
|
||||
});
|
||||
}
|
||||
|
||||
// Create new token
|
||||
else {
|
||||
crypto.randomBytes(16, (err,buf)=>{
|
||||
if (err){ return next(err,null); }
|
||||
if (buf) {
|
||||
user.auth.passToken = buf.toString('hex');
|
||||
user.auth.passTokenExpires = Date.now() + 3600000; // 1 hour
|
||||
user.save();
|
||||
return next(null,user.passToken);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Check for valid password
|
||||
userSchema.methods.validPassword = function(password,next){
|
||||
bcrypt.compare(password, this.auth.password, next);
|
||||
|
|
|
@ -40,7 +40,7 @@ module.exports = router
|
|||
})
|
||||
|
||||
// Endpoint to validate forms
|
||||
.get('/validate', (req,res)=>{
|
||||
.get('/validate', (req,res,next)=>{
|
||||
|
||||
// Validate unique slug
|
||||
if (req.query.slug) {
|
||||
|
@ -51,7 +51,10 @@ module.exports = router
|
|||
}
|
||||
else { res.sendStatus(200); }
|
||||
})
|
||||
.catch( (err)=>{ mw.throwErr(err,req); });
|
||||
.catch( (err)=>{
|
||||
console.error(err);
|
||||
res.sendStatus(500);
|
||||
});
|
||||
}
|
||||
|
||||
// Validate unique email
|
||||
|
@ -63,7 +66,10 @@ module.exports = router
|
|||
}
|
||||
else { res.sendStatus(200); }
|
||||
})
|
||||
.catch( (err)=>{ mw.throwErr(err,req); });
|
||||
.catch( (err)=>{
|
||||
console.error(err);
|
||||
res.sendStatus(500);
|
||||
});
|
||||
}
|
||||
|
||||
// Create slug
|
||||
|
@ -71,10 +77,14 @@ module.exports = router
|
|||
res.send(slug(xss(req.query.slugify)));
|
||||
}
|
||||
|
||||
// Sanitize for XSS
|
||||
else if (req.query.xss) {
|
||||
res.send(xss(req.query.xss));
|
||||
}
|
||||
|
||||
// 404
|
||||
else { next(); }
|
||||
|
||||
})
|
||||
|
||||
// Link to androidapp in play store
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
'use strict';
|
||||
//TODO: Use promises
|
||||
|
||||
const router = require('express').Router(),
|
||||
mw = require('../middleware.js'),
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
const slug = require('slug'),
|
||||
xss = require('xss'),
|
||||
mellt = require('mellt'),
|
||||
moment = require('moment'),
|
||||
mw = require('../middleware.js'),
|
||||
User = require('../models.js').user,
|
||||
mail = require('../mail.js'),
|
||||
|
@ -34,7 +35,6 @@ router.route('/')
|
|||
|
||||
// Set values
|
||||
req.user.name = xss(req.body.name);
|
||||
req.user.slug = slug(xss(req.body.slug));
|
||||
req.user.settings = {
|
||||
units: req.body.units,
|
||||
defaultMap: req.body.map,
|
||||
|
@ -72,41 +72,101 @@ router.route('/')
|
|||
|
||||
else {
|
||||
|
||||
// Email changed
|
||||
if (req.user.email!==req.body.email) {
|
||||
//console.log(`Email changed to ${req.body.email}`);
|
||||
req.user.newEmail = req.body.email;
|
||||
// Check if email changed
|
||||
let checkEmailChanged = new Promise( (resolve,reject)=>{
|
||||
|
||||
// Create token
|
||||
//console.log(`Creating email token...`);
|
||||
req.user.createEmailToken((err,token)=>{
|
||||
if (err){
|
||||
mw.throwErr(err,req);
|
||||
res.redirect(req.session.next||'/settings');
|
||||
}
|
||||
// Email changed
|
||||
if (req.user.email!==req.body.email) {
|
||||
//console.log(`Email changed to ${req.body.email}`);
|
||||
|
||||
// Send token to user by email
|
||||
//console.log(`Mailing new email token to ${req.body.email}...`);
|
||||
mail.send({
|
||||
to: `"${req.user.name}" <${req.body.email}>`,
|
||||
from: mail.from,
|
||||
subject: 'Confirm your new email address for Tracman',
|
||||
text: mail.text(`A request has been made to change your Tracman email address. If you did not initiate this request, please disregard it. \n\nTo confirm your email, follow this link:\n${env.url}/settings/email/${token}. `),
|
||||
html: mail.html(`<p>A request has been made to change your Tracman email address. If you did not initiate this request, please disregard it. </p><p>To confirm your email, follow this link:<br><a href="${env.url}/settings/email/${token}">${env.url}/settings/email/${token}</a>. </p>`)
|
||||
// Check uniqueness
|
||||
User.findOne({ email: req.body.email })
|
||||
.then( (existingUser)=>{
|
||||
|
||||
// Not unique!
|
||||
if (existingUser && existingUser.id!==req.user.id) {
|
||||
//console.log("Email not unique!");
|
||||
req.flash('warning', `That email, <u>${req.body.email}</u>, is already in use by another user! `);
|
||||
}
|
||||
|
||||
// It's unique
|
||||
else {
|
||||
//console.log("Email is unique");
|
||||
req.user.newEmail = req.body.email;
|
||||
|
||||
// Create token
|
||||
//console.log(`Creating email token...`);
|
||||
req.user.createEmailToken((err,token)=>{
|
||||
if (err){ reject(err); }
|
||||
|
||||
// Send token to user by email
|
||||
//console.log(`Mailing new email token to ${req.body.email}...`);
|
||||
mail.send({
|
||||
to: `"${req.user.name}" <${req.body.email}>`,
|
||||
from: mail.from,
|
||||
subject: 'Confirm your new email address for Tracman',
|
||||
text: mail.text(`A request has been made to change your Tracman email address. If you did not initiate this request, please disregard it. \n\nTo confirm your email, follow this link:\n${env.url}/settings/email/${token}. `),
|
||||
html: mail.html(`<p>A request has been made to change your Tracman email address. If you did not initiate this request, please disregard it. </p><p>To confirm your email, follow this link:<br><a href="${env.url}/settings/email/${token}">${env.url}/settings/email/${token}</a>. </p>`)
|
||||
})
|
||||
.then( ()=>{
|
||||
req.flash('warning',`An email has been sent to <u>${req.body.email}</u>. Check your inbox to confirm your new email address. `);
|
||||
})
|
||||
.catch( (err)=>{
|
||||
reject(err);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
.then( ()=>{
|
||||
req.flash('warning',`An email has been sent to <u>${req.body.email}</u>. Check your inbox to confirm your new email address. `);
|
||||
setSettings();
|
||||
})
|
||||
.catch( (err)=>{
|
||||
.then(resolve)
|
||||
.catch( (err)=>{
|
||||
mw.throwErr(err,req);
|
||||
res.redirect('/settings');
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
} else { resolve(); }
|
||||
});
|
||||
|
||||
// Email not changed
|
||||
else { setSettings(); }
|
||||
// Check if slug changed
|
||||
let checkSlugChanged = new Promise( (resolve,reject)=>{
|
||||
|
||||
// Slug changed
|
||||
if (req.user.slug!==req.body.slug) {
|
||||
|
||||
// Check uniqueness
|
||||
User.findOne({ slug: req.body.slug })
|
||||
.then( (existingUser)=>{
|
||||
|
||||
// Not unique!
|
||||
if (existingUser && existingUser.id!==req.user.id) {
|
||||
req.flash('warning', `That slug, <u>${req.body.slug}</u>, is already in use by another user! `);
|
||||
}
|
||||
|
||||
// It's unique
|
||||
else {
|
||||
req.user.slug = slug(xss(req.body.slug));
|
||||
}
|
||||
|
||||
})
|
||||
.then(resolve)
|
||||
.catch( (err)=>{
|
||||
mw.throwErr(err,req);
|
||||
res.redirect('/settings');
|
||||
});
|
||||
|
||||
} else { resolve(); }
|
||||
|
||||
});
|
||||
|
||||
// Set settings when done
|
||||
Promise.all([checkEmailChanged, checkSlugChanged])
|
||||
.then(setSettings)
|
||||
.catch( (err)=>{
|
||||
mw.throwErr(err,req);
|
||||
res.redirect('/settings');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
@ -115,8 +175,6 @@ router.route('/')
|
|||
// Delete user account
|
||||
.delete( (req,res,next)=>{
|
||||
|
||||
//TODO: Reenter password?
|
||||
|
||||
User.findByIdAndRemove(req.user)
|
||||
.then( ()=>{
|
||||
req.flash('success', 'Your account has been deleted. ');
|
||||
|
@ -174,28 +232,33 @@ router.route('/password')
|
|||
.get( (req,res,next)=>{
|
||||
|
||||
// Create token for password change
|
||||
req.user.createPassToken( (err,token)=>{
|
||||
req.user.createPassToken( (err,token,expires)=>{
|
||||
if (err){
|
||||
mw.throwErr(err,req);
|
||||
res.redirect(req.session.next||'/settings');
|
||||
res.redirect((req.user)?'/settings':'/login');
|
||||
}
|
||||
|
||||
// Figure out expiration time
|
||||
let expirationTimeString = (req.query.tz)?
|
||||
moment(expires).utcOffset(req.query.tz).toDate().toLocaleTimeString(req.acceptsLanguages[0]):
|
||||
moment(expires).toDate().toLocaleTimeString(req.acceptsLanguages[0])+" UTC";
|
||||
|
||||
// Confirm password change request by email.
|
||||
mail.send({
|
||||
to: mail.to(req.user),
|
||||
from: mail.from,
|
||||
subject: 'Request to change your Tracman password',
|
||||
text: mail.text(`A request has been made to change your tracman password. If you did not initiate this request, please contact support at keith@tracman.org. \n\nTo change your password, follow this link:\n${env.url}/settings/password/${token}. \n\nThis request will expire in 1 hour. `),
|
||||
html: mail.html(`<p>A request has been made to change your tracman password. If you did not initiate this request, please contact support at <a href="mailto:keith@tracman.org">keith@tracman.org</a>. </p><p>To change your password, follow this link:<br><a href="${env.url}/settings/password/${token}">${env.url}/settings/password/${token}</a>. </p><p>This request will expire in 1 hour. </p>`)
|
||||
text: mail.text(`A request has been made to change your tracman password. If you did not initiate this request, please contact support at keith@tracman.org. \n\nTo change your password, follow this link:\n${env.url}/settings/password/${token}. \n\nThis request will expire at ${expirationTimeString}. `),
|
||||
html: mail.html(`<p>A request has been made to change your tracman password. If you did not initiate this request, please contact support at <a href="mailto:keith@tracman.org">keith@tracman.org</a>. </p><p>To change your password, follow this link:<br><a href="${env.url}/settings/password/${token}">${env.url}/settings/password/${token}</a>. </p><p>This request will expire at ${expirationTimeString}. </p>`)
|
||||
})
|
||||
.then( ()=>{
|
||||
// Alert user to check email.
|
||||
req.flash('success',`An email has been sent to <u>${req.user.email}</u>. Check your inbox to complete your password change. `);
|
||||
res.redirect('/login#login');
|
||||
req.flash('success',`An link has been sent to <u>${req.user.email}</u>. Click on the link to complete your password change. This link will expire in one hour (${expirationTimeString}). `);
|
||||
res.redirect((req.user)?'/settings':'/login');
|
||||
})
|
||||
.catch( (err)=>{
|
||||
mw.throwErr(err,req);
|
||||
res.redirect('/login#login');
|
||||
res.redirect((req.user)?'/settings':'/login');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
// Imports
|
||||
const mw = require('./middleware.js'),
|
||||
User = require('./models.js').user;
|
||||
const User = require('./models.js').user;
|
||||
|
||||
// Check for tracking clients
|
||||
function checkForUsers(io, user) {
|
||||
|
@ -10,10 +9,14 @@ function checkForUsers(io, user) {
|
|||
|
||||
// Checks if any sockets are getting updates for this user
|
||||
//TODO: Use Object.values() after upgrading to node v7
|
||||
if (Object.keys(io.sockets.connected).map( (id)=>{
|
||||
return io.sockets.connected[id];
|
||||
/* if (Object.values(io.sockets.connected).some( (socket)=>{
|
||||
* return socket.gets==user;
|
||||
* })) {
|
||||
*/
|
||||
if (Object.keys(io.sockets.connected).map( (key)=>{
|
||||
return io.sockets.connected[key];
|
||||
}).some( (socket)=>{
|
||||
return socket.gets==user;
|
||||
return socket.gets===user;
|
||||
})) {
|
||||
//console.log(`Activating updates for ${user}.`);
|
||||
io.to(user).emit('activate','true');
|
||||
|
@ -32,8 +35,8 @@ module.exports = {
|
|||
//console.log(`${socket.id} connected.`);
|
||||
|
||||
// Set a few variables
|
||||
socket.ip = socket.client.request.headers['x-real-ip'];
|
||||
socket.ua = socket.client.request.headers['user-agent'];
|
||||
//socket.ip = socket.client.request.headers['x-real-ip'];
|
||||
//socket.ua = socket.client.request.headers['user-agent'];
|
||||
|
||||
/* Log */
|
||||
//socket.on('log', (text)=>{
|
||||
|
|
|
@ -79,8 +79,8 @@ const
|
|||
// Path for redirects
|
||||
let nextPath = ( req.path.substring(0, req.path.indexOf('#')) || req.path );
|
||||
if ( nextPath.substring(0,6)!=='/login' && nextPath.substring(0,7)!=='/logout' ){
|
||||
//console.log(`Setting redirect path to ${nextPath}#`);
|
||||
req.session.next = nextPath+'#';
|
||||
//console.log(`Set redirect path to ${nextPath}#`);
|
||||
}
|
||||
|
||||
// User account
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
|
||||
/* Submit buttons */
|
||||
#submit-group {
|
||||
padding: 0 0 60px;
|
||||
justify-content: space-around;
|
||||
}
|
||||
#submit-group .main {
|
||||
|
|
|
@ -8,7 +8,7 @@ function validateEmail(email) {
|
|||
}
|
||||
|
||||
// Replace inputed value with response
|
||||
function validateFromEndpoint(type, selector, cb) {
|
||||
function replaceFromEndpoint(type, selector, cb) {
|
||||
$.get('/validate?'+type+'='+$(selector).val())
|
||||
.done(function(data){
|
||||
$(selector).val(data);
|
||||
|
@ -18,95 +18,17 @@ function validateFromEndpoint(type, selector, cb) {
|
|||
|
||||
// On page load
|
||||
$(function(){
|
||||
|
||||
function validateForm(input) {
|
||||
|
||||
// Everything passed - make sure no help texts are visible
|
||||
function recheckInputs() {
|
||||
if ($('#email-help').is(":visible")) {
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to supply a different email address. ");
|
||||
}
|
||||
else if ($('#slug-help').is(":visible")) {
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to supply a different slug. ");
|
||||
}
|
||||
else {
|
||||
$('#submit-group .main').prop('disabled',false).prop('title',"Click here to save your changes. ");
|
||||
}
|
||||
}
|
||||
|
||||
// Empty fields
|
||||
if ($('#slug-input').val()===''){
|
||||
$('#slug-help').show().text("A slug is required. ");
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to enter a slug. ");
|
||||
}
|
||||
else if ($('#email-input').val()===''){
|
||||
$('#email-help').show().text("An email is required. ");
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to enter an email address. ");
|
||||
}
|
||||
|
||||
// Is email
|
||||
else if (!validateEmail($('#email-input').val())) {
|
||||
$('#email-help').show().text("You must enter a valid email address. ");
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to enter a valid email address. ");
|
||||
}
|
||||
|
||||
// Validate unique fields with server
|
||||
else if (input) {
|
||||
|
||||
// Make AJAX request
|
||||
$.get('/validate?'+input+'='+$('#'+input+'-input').val())
|
||||
.fail(function(data,status){
|
||||
|
||||
// Input is not unique
|
||||
if (status===400) {
|
||||
$('#'+input+'-help').show().text("That "+input+" is already in use by another user. ");
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to supply a different "+input+". ");
|
||||
}
|
||||
|
||||
// Server error
|
||||
else {
|
||||
$('#'+input+'-help').show().text("Unable to confirm unique "+input+" with the server. This might not work... ");
|
||||
recheckInputs();
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
// Input is unique
|
||||
.done(function(){
|
||||
$('#'+input+'-help').hide();
|
||||
recheckInputs();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// All passed
|
||||
else { recheckInputs(); }
|
||||
|
||||
}
|
||||
|
||||
// Validate slug
|
||||
$('#slug-input').change(function(){
|
||||
validateFromEndpoint('slugify','#slug-input',function(){
|
||||
validateForm(slug);
|
||||
});
|
||||
});
|
||||
|
||||
// Validate email
|
||||
$('#email-input').change(function(){
|
||||
validateForm('email');
|
||||
});
|
||||
|
||||
// Validate name
|
||||
$('#name-input').change(function(){
|
||||
validateFromEndpoint('xss','#name-input',validateForm);
|
||||
});
|
||||
var slugNotUnique, emailNotUnique;
|
||||
|
||||
// Set timezone in password change link
|
||||
$('#password').attr('href',"/settings/password?tz="+new Date().getTimezoneOffset());
|
||||
|
||||
// Delete account
|
||||
$('#delete').click(function(){
|
||||
if (confirm("Are you sure you want to delete your account? This CANNOT be undone! ")) {
|
||||
$.ajax({
|
||||
url: "/settings",
|
||||
type: "DELETE",
|
||||
url: '/settings',
|
||||
type: 'DELETE',
|
||||
success: function(){
|
||||
location.reload();
|
||||
},
|
||||
|
@ -117,4 +39,126 @@ $(function(){
|
|||
}
|
||||
});
|
||||
|
||||
function validateForm(input) {
|
||||
|
||||
// Perform basic check, then validate uniqueness
|
||||
basicCheck(function(){ validateUniqueness(input); });
|
||||
|
||||
function basicCheck(cb){
|
||||
var checkedCount = 0;
|
||||
|
||||
// Check slug
|
||||
if (!$('#slug-input').val()){
|
||||
$('#slug-help').show().text("A slug is required. ");
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to enter a slug. ");
|
||||
if (checkedCount>0) {cb();} else {checkedCount++;}
|
||||
}
|
||||
else {
|
||||
if (!slugNotUnique){ $('#slug-help').hide(); }
|
||||
if (checkedCount>0) {cb();} else {checkedCount++;}
|
||||
}
|
||||
|
||||
// Check email
|
||||
if (!$('#email-input').val()){
|
||||
$('#email-help').show().text("An email is required. ");
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to enter an email address. ");
|
||||
if (checkedCount>0) {cb();} else {checkedCount++;}
|
||||
}
|
||||
else if (!validateEmail($('#email-input').val())) {
|
||||
$('#email-help').show().text("You must enter a valid email address. ");
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to enter a valid email address. ");
|
||||
if (checkedCount>0) {cb();} else {checkedCount++;}
|
||||
}
|
||||
else {
|
||||
if (!emailNotUnique){ $('#email-help').hide(); }
|
||||
if (checkedCount>0) {cb();} else {checkedCount++;}
|
||||
}
|
||||
}
|
||||
|
||||
function validateUniqueness(input){
|
||||
|
||||
function recheckBasic(){
|
||||
if ($('#email-help').is(":visible") && $('#email-help').text().substring(0,25)!=="Unable to confirm unique ") {
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to supply a different email address. ");
|
||||
}
|
||||
else if ($('#slug-help').is(":visible") && $('#slug-help').text().substring(0,25)!=="Unable to confirm unique ") {
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to supply a different slug. ");
|
||||
}
|
||||
else if ( $('#slug-help').text().substring(0,25)==="Unable to confirm unique " ) {
|
||||
$('#submit-group .main').prop('title',"Unable to confirm unique slug with the server. This might not work... ");
|
||||
}
|
||||
else if ( $('#email-help').text().substring(0,25)==="Unable to confirm unique " ) {
|
||||
$('#submit-group .main').prop('title',"Unable to confirm unique email with the server. This might not work... ");
|
||||
}
|
||||
else {
|
||||
$('#submit-group .main').prop('disabled',false).prop('title',"Click here to save your changes. ");
|
||||
}
|
||||
}
|
||||
|
||||
// Should server be queried for unique values?
|
||||
if (input && $('#'+input+'-input').val()) {
|
||||
if (input==='email' && !validateEmail($('#email-input').val())) {}
|
||||
|
||||
// Query server for unique values
|
||||
else {
|
||||
$.ajax({
|
||||
url: '/validate?'+input+'='+$('#'+input+'-input').val(),
|
||||
type: 'GET',
|
||||
statusCode: {
|
||||
|
||||
// Is unique
|
||||
200: function(){
|
||||
$('#'+input+'-help').hide();
|
||||
if (input==='slug'){ slugNotUnique=false; }
|
||||
else if (input==='email'){ emailNotUnique=false; }
|
||||
recheckBasic();
|
||||
},
|
||||
|
||||
// Isn't unique
|
||||
400: function(){
|
||||
if (input==='slug'){ slugNotUnique=true; }
|
||||
else if (input==='email'){ emailNotUnique=true; }
|
||||
$('#'+input+'-help').show().text("That "+input+" is already in use by another user. ");
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to supply a different "+input+". ");
|
||||
}
|
||||
|
||||
} })
|
||||
|
||||
// Server error
|
||||
.error( function(){
|
||||
if (input==='slug'){ slugNotUnique=undefined; }
|
||||
else if (input==='email'){ emailNotUnique=undefined; }
|
||||
$('#'+input+'-help').show().text("Unable to confirm unique "+input+". This might not work... ");
|
||||
recheckBasic();
|
||||
});
|
||||
|
||||
} }
|
||||
|
||||
// Nothing changed. Recheck basic validations
|
||||
else { recheckBasic(); }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Input change listeners
|
||||
$('#slug-input').change(function(){
|
||||
if (!$('#slug-input').val()){
|
||||
$('#slug-help').show().text("A slug is required. ");
|
||||
$('#submit-group .main').prop('disabled',true).prop('title',"You need to enter a slug. ");
|
||||
}
|
||||
else {
|
||||
$('#slug-help').hide();
|
||||
replaceFromEndpoint('slugify','#slug-input',function(){
|
||||
validateForm('slug');
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#email-input').change(function(){
|
||||
validateForm('email');
|
||||
});
|
||||
$('#name-input').change(function(){
|
||||
replaceFromEndpoint('xss','#name-input',validateForm);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue