Many fixes, added emailing capability
parent
4abf003a11
commit
016c6a6cdd
|
@ -55,11 +55,11 @@ module.exports = function(app, passport) {
|
|||
newUser.createToken(function(err,token){
|
||||
if (err){ next(err); }
|
||||
mail({
|
||||
from: '"Trackmap" <accounts@trackmap.tech>',
|
||||
from: '"Tracman" <NoReply@tracman.org>',
|
||||
to: req.body.email,
|
||||
subject: 'Complete your Trackmap registration',
|
||||
text: `Welcome to trackmap! \n\nTo complete your registration, follow this link and set your password:\n${env.url}/account/password/${token}`, // plaintext body
|
||||
html: `<p>Welcome to trackmap! </p><p>To complete your registration, follow this link and set your password:<br><a href="${env.url}/account/password/${token}">${env.url}/account/password/${token}</a></p>` // html body
|
||||
subject: 'Complete your Tracman registration',
|
||||
text: `Welcome to Tracman! \n\nTo complete your registration, follow this link and set your password:\n${env.url}/settings/password/${token}`,
|
||||
html: `<p>Welcome to Tracman! </p><p>To complete your registration, follow this link and set your password:<br><a href="${env.url}/settings/password/${token}">${env.url}/settings/password/${token}</a></p>`
|
||||
}).then(function(){
|
||||
req.flash('success',`An email has been sent to <u>${req.body.email}</u>. Check your inbox to complete your registration.`);
|
||||
res.redirect('/');
|
||||
|
@ -100,11 +100,11 @@ module.exports = function(app, passport) {
|
|||
|
||||
// Email reset link
|
||||
mail({
|
||||
from: '"Trackmap" <accounts@trackmap.tech>',
|
||||
to: user.email,
|
||||
subject: 'Reset your Trackmap password',
|
||||
text: `Hi, \n\nDid you request to reset your trackmap password? If so, follow this link to do so:\n${env.url}/account/password/${token}\n\nIf you didn't initiate this request, just ignore this email. `,
|
||||
html: `<p>Hi, </p><p>Did you request to reset your trackmap password? If so, follow this link to do so:<br><a href="${env.url}/account/password/${token}">${env.url}/account/password/${token}</a></p><p>If you didn't initiate this request, just ignore this email. </p>`
|
||||
from: '"Tracman" <NoReply@tracman.org>',
|
||||
to: `"${user.name}"" <${user.email}>`,
|
||||
subject: 'Reset your Tracman password',
|
||||
text: `Hi, \n\nDid you request to reset your Tracman password? If so, follow this link to do so:\n${env.url}/account/password/${token}\n\nIf you didn't initiate this request, just ignore this email. `,
|
||||
html: `<p>Hi, </p><p>Did you request to reset your Tracman password? If so, follow this link to do so:<br><a href="${env.url}/account/password/${token}">${env.url}/account/password/${token}</a></p><p>If you didn't initiate this request, just ignore this email. </p>`
|
||||
}).then(function(){
|
||||
req.flash('success', `An email has been sent to <u>${req.body.email}</u>. Check your email for instructions to reset your password. `);
|
||||
res.redirect('/');
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = require('nodemailer').createTransport({
|
||||
const nodemailer = require('nodemailer');
|
||||
|
||||
let transporter = nodemailer.createTransport({
|
||||
host: 'keithirwin.us',
|
||||
port: 587,
|
||||
secure: false,
|
||||
|
@ -9,8 +11,30 @@ module.exports = require('nodemailer').createTransport({
|
|||
user: 'NoReply@tracman.org',
|
||||
pass: 'Ei0UwfrZuE'
|
||||
},
|
||||
// logger: true,
|
||||
// debug: true
|
||||
logger: true,
|
||||
debug: true
|
||||
});
|
||||
|
||||
// require('./mail.js').(mailData, context).then(...).catch(...);
|
||||
/* Confirm login */
|
||||
// transporter.verify(function(err, success) {
|
||||
// if (err){ console.error(`SMTP Error: ${err}`); }
|
||||
// if (success){
|
||||
// console.log("SMTP ready...");
|
||||
// } else {
|
||||
// console.error("SMTP not ready!");
|
||||
// }
|
||||
// });
|
||||
|
||||
/* Send test email */
|
||||
transporter.sendMail({
|
||||
to: `"Keith Irwin" <mail@keithirwin.us>`,
|
||||
from: '"Tracman" <NoReply@tracman.org>',
|
||||
subject: 'Test email',
|
||||
text: "Looks like everything's working",
|
||||
}).then(function(){
|
||||
console.log("Email should have sent...");
|
||||
}).catch(function(err){
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
module.exports = transporter.sendMail.bind(transporter);
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
const mongoose = require('mongoose'),
|
||||
unique = require('mongoose-unique-validator'),
|
||||
bcrypt = require('bcrypt-nodejs');
|
||||
bcrypt = require('bcrypt-nodejs'),
|
||||
crypto = require('crypto');
|
||||
|
||||
const userSchema = new mongoose.Schema({
|
||||
name: {type:String, required:true},
|
||||
|
@ -52,8 +53,9 @@ const userSchema = new mongoose.Schema({
|
|||
|
||||
// Create password reset token
|
||||
userSchema.methods.createToken = function(next){
|
||||
//TODO: Use the same token if there already is one that's not yet expired.
|
||||
var user = this;
|
||||
require('crypto').randomBytes(16, function(err,buf){
|
||||
crypto.randomBytes(16, function(err,buf){
|
||||
if (err){ next(err,null); }
|
||||
else {
|
||||
user.auth.passToken = buf.toString('hex');
|
||||
|
|
|
@ -1,91 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
const slug = require('slug'),
|
||||
xss = require('xss'),
|
||||
mw = require('../middleware.js'),
|
||||
User = require('../models.js').user,
|
||||
router = require('express').Router();
|
||||
const mw = require('../middleware.js'),
|
||||
router = require('express').Router(),
|
||||
slug = require('slug'),
|
||||
User = require('../models.js').user;
|
||||
|
||||
// Index
|
||||
router.get('/', function(req,res,next) {
|
||||
res.render('index');
|
||||
});
|
||||
|
||||
// Settings
|
||||
router.route('/settings').all(mw.ensureAuth, function(req,res,next){
|
||||
next();
|
||||
})
|
||||
|
||||
// Get settings form
|
||||
.get(function(req,res,next){
|
||||
User.findById(req.session.passport.user, function(err,user){
|
||||
if (err){ console.log('Error finding settings for user:',err); mw.throwErr(req,err); }
|
||||
res.render('settings');
|
||||
});
|
||||
})
|
||||
|
||||
// Set new settings
|
||||
.post(function(req,res,next){
|
||||
User.findByIdAndUpdate(req.session.passport.user, {$set:{
|
||||
name: xss(req.body.name),
|
||||
slug: slug(xss(req.body.slug)),
|
||||
email: req.body.email,
|
||||
settings: {
|
||||
units: req.body.units,
|
||||
defaultMap: req.body.map,
|
||||
defaultZoom: req.body.zoom,
|
||||
showSpeed: (req.body.showSpeed)?true:false,
|
||||
showAlt: (req.body.showAlt)?true:false,
|
||||
showStreetview: (req.body.showStreet)?true:false
|
||||
}
|
||||
}}, function(err, user){
|
||||
if (err) { console.log('Error updating user settings:',err); mw.throwErr(req,err); }
|
||||
else { req.flash('success', 'Settings updated. '); }
|
||||
res.redirect('/settings');
|
||||
});
|
||||
})
|
||||
|
||||
// Delete user account
|
||||
.delete(function(req,res,next){
|
||||
User.findByIdAndRemove( req.session.passport.user,
|
||||
function(err) {
|
||||
if (err) {
|
||||
console.log('Error deleting user:',err);
|
||||
mw.throwErr(req,err);
|
||||
} else {
|
||||
req.flash('success', 'Your account has been deleted. ');
|
||||
res.redirect('/');
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Tracman pro
|
||||
router.route('/pro').all(mw.ensureAuth, function(req,res,next){
|
||||
next();
|
||||
})
|
||||
|
||||
// Get info about pro
|
||||
.get(function(req,res,next){
|
||||
User.findById(req.session.passport.user, function(err, user){
|
||||
if (err){ mw.throwErr(req,err); }
|
||||
if (!user){ next(); }
|
||||
else { res.render('pro'); }
|
||||
});
|
||||
})
|
||||
|
||||
// Join Tracman pro
|
||||
.post(function(req,res){
|
||||
User.findByIdAndUpdate(req.session.passport.user,
|
||||
{$set:{ isPro:true }},
|
||||
function(err, user){
|
||||
if (err){ mw.throwErr(req,err); }
|
||||
else { req.flash('success','You have been signed up for pro. '); }
|
||||
res.redirect('/map');
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Help
|
||||
router.get('/help', mw.ensureAuth, function(req,res){
|
||||
res.render('help');
|
||||
|
@ -98,4 +22,39 @@ router.get('/terms', function(req,res){
|
|||
res.render('privacy');
|
||||
});
|
||||
|
||||
// robots.txt
|
||||
router.get('/robots.txt', function(req,res){
|
||||
res.type('text/plain');
|
||||
res.send("User-agent: *\n"+
|
||||
"Disallow: /map/*\n"
|
||||
);
|
||||
});
|
||||
|
||||
// favicon.ico
|
||||
router.get('/favicon.ico', function(req,res){
|
||||
res.redirect('/static/img/icon/by/16-32-48.ico');
|
||||
});
|
||||
|
||||
// Endpoint to validate forms
|
||||
router.get('/validate', function(req,res){
|
||||
if (req.query.slug) { // validate unique slug
|
||||
User.findOne({slug:slug(req.query.slug)}, function(err, existingUser){
|
||||
if (err) { console.log('/validate error:',err); }
|
||||
if (existingUser && existingUser.id!==req.session.passport.user) { res.sendStatus(400); }
|
||||
else { res.sendStatus(200); }
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Link to androidapp in play store
|
||||
router.get('/android', function(req,res){
|
||||
res.redirect('https://play.google.com/store/apps/details?id=us.keithirwin.tracman');
|
||||
});
|
||||
|
||||
// Link to iphone app in the apple store
|
||||
router.get('/ios', function(req,res){
|
||||
res.sendStatus(404);
|
||||
//TODO: Add link to info about why there's no ios app
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -1,36 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const router = require('express').Router(),
|
||||
slug = require('slug'),
|
||||
User = require('../models.js').user;
|
||||
|
||||
// robots.txt
|
||||
router.get('/robots.txt', function(req,res){
|
||||
res.type('text/plain');
|
||||
res.send("User-agent: *\n"+
|
||||
"Disallow: /map/*\n"
|
||||
);
|
||||
});
|
||||
|
||||
// favicon.ico
|
||||
router.get('/favicon.ico', function(req,res){
|
||||
res.redirect('/static/img/icon/by/16-32-48.ico');
|
||||
});
|
||||
|
||||
// Endpoint to validate forms
|
||||
router.get('/validate', function(req,res){
|
||||
if (req.query.slug) { // validate unique slug
|
||||
User.findOne({slug:slug(req.query.slug)}, function(err, existingUser){
|
||||
if (err) { console.log('/validate error:',err); }
|
||||
if (existingUser && existingUser.id!==req.session.passport.user) { res.sendStatus(400); }
|
||||
else { res.sendStatus(200); }
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Link to android app in play store
|
||||
router.get('/android', function(req,res){
|
||||
res.redirect('https://play.google.com/store/apps/details?id=us.keithirwin.tracman');
|
||||
});
|
||||
|
||||
module.exports = router;
|
20
server.js
20
server.js
|
@ -92,16 +92,16 @@ const
|
|||
});
|
||||
|
||||
// Main routes
|
||||
app.use('/',
|
||||
require('./config/routes/index.js'),
|
||||
require('./config/routes/misc.js')
|
||||
);
|
||||
app.use( '/', require('./config/routes/index.js') );
|
||||
|
||||
// Settings
|
||||
app.use( '/settings', require('./config/routes/settings.js') );
|
||||
|
||||
// Map
|
||||
app.use(['/map','/trac'], require('./config/routes/map.js'));
|
||||
app.use( ['/map','/trac'], require('./config/routes/map.js') );
|
||||
|
||||
// Admin
|
||||
app.use('/admin', require('./config/routes/admin.js'));
|
||||
// Site administration
|
||||
app.use( '/admin', require('./config/routes/admin.js') );
|
||||
|
||||
}
|
||||
|
||||
|
@ -147,12 +147,6 @@ const
|
|||
|
||||
/* RUNTIME */ {
|
||||
|
||||
// Check mail transporter
|
||||
require('./config/mail.js').verify(function(err, success) {
|
||||
if (err){ console.error(`SMTP Error: ${err}`); }
|
||||
console.log(success?'SMTP ready...':'SMTP not ready!');
|
||||
});
|
||||
|
||||
// Listen
|
||||
http.listen(env.port, function(){
|
||||
console.log(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
form {
|
||||
margin: auto;
|
||||
max-width: 600px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
|
@ -27,6 +27,10 @@ form input, form textarea, form select {
|
|||
border: 1px solid #666;
|
||||
border-radius: .3vw;
|
||||
}
|
||||
form input:not(.input-addon):not(.input-with-addon):not([type="radio"]):not([type="checkbox"]),
|
||||
form .input-with-addon-group {
|
||||
min-width: 50%;
|
||||
}
|
||||
form input:active:not(.input-addon), form textarea:active, form select:active,
|
||||
form input:focus:not(.input-addon), form textarea:focus, form select:focus {
|
||||
outline: none;
|
||||
|
|
122
test.js
122
test.js
|
@ -1,11 +1,10 @@
|
|||
var chai = require('chai'),
|
||||
const chai = require('chai'),
|
||||
chaiHttp = require('chai-http'),
|
||||
request = require('supertest'),
|
||||
server = require('./server'),
|
||||
should = chai.should(),
|
||||
expect = chai.expect();
|
||||
server = require('./server');
|
||||
chai.use(chaiHttp);
|
||||
|
||||
|
||||
describe('Index', function() {
|
||||
// I think this restarts the server after each try?
|
||||
// var server;
|
||||
|
@ -37,54 +36,54 @@ describe('Index', function() {
|
|||
|
||||
});
|
||||
|
||||
describe('Auth', function() {
|
||||
// describe('Auth', function() {
|
||||
|
||||
it('Creates an account', function(done){
|
||||
request(server).get('/login')
|
||||
.expect(200)
|
||||
.end(function(err,res){
|
||||
//TODO: google authentication
|
||||
it('Logs out', function(done){
|
||||
request(server).get('/logout')
|
||||
.expect(200)
|
||||
.end(function(err,res){
|
||||
it('Logs in', function(done){
|
||||
request(server).get('/logout')
|
||||
.expect(200)
|
||||
.end(function(err,res){
|
||||
cbc=2;
|
||||
var deletesAccount = function(done){
|
||||
it('Deletes own account', function(){
|
||||
//TODO: Delete account via GUI
|
||||
});
|
||||
}
|
||||
it('Shows own map', function(done){
|
||||
request(server).get('/map')
|
||||
.expect(200)
|
||||
//TODO: Expect no js errors
|
||||
.end(function(err,res){
|
||||
if (cbc<2){ deletesAccount(); }
|
||||
else { cbc--; }
|
||||
done();
|
||||
});
|
||||
});
|
||||
// it('Creates an account', function(done){
|
||||
// request(server).get('/login')
|
||||
// .expect(200)
|
||||
// .end(function(err,res){
|
||||
// //TODO: google authentication
|
||||
// it('Logs out', function(done){
|
||||
// request(server).get('/logout')
|
||||
// .expect(200)
|
||||
// .end(function(err,res){
|
||||
// it('Logs in', function(done){
|
||||
// request(server).get('/logout')
|
||||
// .expect(200)
|
||||
// .end(function(err,res){
|
||||
// cbc=2;
|
||||
// var deletesAccount = function(done){
|
||||
// it('Deletes own account', function(){
|
||||
// //TODO: Delete account via GUI
|
||||
// });
|
||||
// }
|
||||
// it('Shows own map', function(done){
|
||||
// request(server).get('/map')
|
||||
// .expect(200)
|
||||
// //TODO: Expect no js errors
|
||||
// .end(function(err,res){
|
||||
// if (cbc<2){ deletesAccount(); }
|
||||
// else { cbc--; }
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
|
||||
it('Has the correct account info', function(done){
|
||||
//TODO: Check account info
|
||||
if (cbc<2){ deletesAccount(); }
|
||||
else { cbc--; }
|
||||
done();
|
||||
});
|
||||
// it('Has the correct account info', function(done){
|
||||
// //TODO: Check account info
|
||||
// if (cbc<2){ deletesAccount(); }
|
||||
// else { cbc--; }
|
||||
// done();
|
||||
// });
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
|
||||
//TODO: it('Has the correct account info', function(done){
|
||||
|
||||
|
@ -106,9 +105,9 @@ describe('Auth', function() {
|
|||
|
||||
// });
|
||||
|
||||
});
|
||||
// });
|
||||
|
||||
describe('Map controls', function() {
|
||||
// describe('Map controls', function() {
|
||||
|
||||
//TODO: it('Sets location', function(done){
|
||||
|
||||
|
@ -126,24 +125,5 @@ describe('Map controls', function() {
|
|||
|
||||
// });
|
||||
|
||||
});
|
||||
// });
|
||||
|
||||
describe('Map popups', function() {
|
||||
|
||||
//TODO: it('Opens Share popup', function(done){
|
||||
|
||||
// });
|
||||
|
||||
//TODO: it('Closes Share popup', function(done){
|
||||
|
||||
// });
|
||||
|
||||
//TODO: it('Opens Settings popup', function(done){
|
||||
|
||||
// });
|
||||
|
||||
//TODO: it('Closes Settings popup', function(done){
|
||||
|
||||
// });
|
||||
|
||||
});
|
||||
|
|
|
@ -341,19 +341,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Delete account
|
||||
function deleteAccount() {
|
||||
if (confirm("Are you sure you want to delete your account? This CANNOT be undone! ")) {
|
||||
$.ajax({
|
||||
url: "/map",
|
||||
type: "DELETE",
|
||||
success: function(){
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
|
||||
// Check altitude
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
{% extends 'templates/base.html' %}
|
||||
{% block title %}{{super()}} | Settings{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
{{super()}}
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/form.css">
|
||||
<style>
|
||||
/*#slug-input {*/
|
||||
/* padding-left: calc(146px + 1.6%);*/
|
||||
/*}*/
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
@ -30,12 +26,80 @@
|
|||
<input class='form-control' name="email" type="email" value="{{user.email}}" maxlength="160">
|
||||
</div>
|
||||
|
||||
<!--TODO: add password field-->
|
||||
<div id='social-connect' class='form-group'>
|
||||
<style>
|
||||
|
||||
#social-connect {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
#social-connect > .btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
margin-left: 1vw;
|
||||
margin-right: 1vw;
|
||||
flex-grow: 1;
|
||||
flex-basis: 0;
|
||||
font-size: .9em;
|
||||
}
|
||||
#social-connect > .btn:hover {
|
||||
color: #fff;
|
||||
}
|
||||
#social-connect > .btn .fa {
|
||||
font-size: 1.1em;
|
||||
margin-left: 0;
|
||||
margin-right: 5%;
|
||||
}
|
||||
|
||||
/* Connected social button styles */
|
||||
#social-connect > .btn.gp.connected {
|
||||
border: 2px solid rgb(206,77,57);
|
||||
}
|
||||
#social-connect > .btn.fb.connected {
|
||||
border: 2px solid rgb(48,88,145);
|
||||
}
|
||||
#social-connect > .btn.tw.connected {
|
||||
border: 2px solid rgb(44,168,210);
|
||||
}
|
||||
|
||||
/* Unconnected social button styles */
|
||||
#social-connect > .btn.gp:not(.connected) {
|
||||
background: rgb(206,77,57);
|
||||
}
|
||||
#social-connect > .btn.gp:not(.connected):hover {
|
||||
background: rgb(251,122,102);
|
||||
}
|
||||
#social-connect > .btn.fb:not(.connected) {
|
||||
background: rgb(48,88,145);
|
||||
}
|
||||
#social-connect > .btn.fb:not(.connected):hover {
|
||||
background: rgb(93,133,190);
|
||||
}
|
||||
#social-connect > .btn.tw:not(.connected) {
|
||||
background: rgb(44,168,210);
|
||||
}
|
||||
#social-connect > .btn.tw:not(.connected):hover {
|
||||
background: rgb(89,213,255);
|
||||
}
|
||||
|
||||
</style>
|
||||
<a href="/login/google" class='btn gp{% if user.auth.google %} connected{% endif %}'>
|
||||
<i class="fa fa-google-plus"></i>
|
||||
{% if user.auth.google %}Disconnect{% else %}Connect{% endif %} Google
|
||||
</a>
|
||||
<a href="/login/facebook" class='btn fb{% if user.auth.facebook %} connected{% endif %}'>
|
||||
<i class="fa fa-facebook"></i>
|
||||
{% if user.auth.facebook %}Disconnect{% else %}Connect{% endif %} Facebook
|
||||
</a>
|
||||
<a href="/login/twitter" class='btn tw{% if user.auth.twitter %} connected{% endif %}'>
|
||||
<i class="fa fa-twitter"></i>
|
||||
{% if user.auth.twitter %}Disconnect{% else %}Connect{% endif %} Twitter
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!--TODO: add social login buttons-->
|
||||
|
||||
<div id='delete' class='form-group' title="Permently delete your Tracman account. ">
|
||||
<a class='red' style='width:100%; text-align:right' href="" onclick="deleteAccount()">Delete account</a>
|
||||
<div id='password-delete' class='form-group'>
|
||||
<a href="/settings/password?next=/settings" title="Click here to {% if user.auth.password %}change{% else %}set{% endif %} your password. ">{% if user.auth.password %}Change{% else %}Set{% endif %} password</a>
|
||||
<a class='red' style="text-align:right" href="#" onclick="deleteAccount()" title="Permently delete your Tracman account. ">Delete account</a>
|
||||
</div>
|
||||
|
||||
<h2>Map settings</h2>
|
||||
|
@ -124,9 +188,32 @@
|
|||
|
||||
</form>
|
||||
|
||||
{% if not user.isPro %}<p style="clear:both">Want to try <a href="/pro">Tracman Pro</a>? It's free during beta testing. </p>{% endif %}
|
||||
{% if not user.isPro %}<p style="clear:both">Want to try <a href="/settings/pro">Tracman Pro</a>? It's free during beta testing. </p>{% endif %}
|
||||
<p style="clear:both">Would you like to <a href="https://github.com/Tracman-org/Server/issues/new">submit a suggestion or bug report</a>? </p>
|
||||
|
||||
</section>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
{{super()}}
|
||||
<script>
|
||||
|
||||
// Delete account
|
||||
function deleteAccount() {
|
||||
if (confirm("Are you sure you want to delete your account? This CANNOT be undone! ")) {
|
||||
$.ajax({
|
||||
url: "/settings",
|
||||
type: "DELETE",
|
||||
success: function(){
|
||||
location.reload();
|
||||
},
|
||||
fail: function(){
|
||||
alert("Failed to delete account!");
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue