-
Signup
+
Signup
+ );
+};
+
+const handleSubmit = async (password) => {
+ //generate a new formdata payload
+ let formData = new FormData();
+
+ formData.append('password', password);
+
+ const result = await fetch('/api/accounts/deletion', { method: 'POST', body: formData });
+
+ if (!result.ok) {
+ alert(await result.text());
+ } else {
+ //force logout
+ fetch('/api/accounts/logout', { method: 'POST' })
+ .then(alert(await result.text()))
+ .then(() => window.location.reload(true)) //BUFGIX: force reload of the header element
+ .catch(e => console.error(e))
+ ;
+ }
+};
+
+export default DeleteAccount;
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 56844cf..1dd6260 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"express-formidable": "^1.2.0",
"express-session": "^1.17.1",
"mariadb": "^2.5.2",
+ "node-cron": "^2.0.3",
"nodemailer": "^6.4.17",
"react-cookie": "^4.0.3",
"regenerator-runtime": "^0.13.7",
@@ -5722,6 +5723,19 @@
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
"dev": true
},
+ "node_modules/node-cron": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-2.0.3.tgz",
+ "integrity": "sha512-eJI+QitXlwcgiZwNNSRbqsjeZMp5shyajMR81RZCqeW0ZDEj4zU9tpd4nTh/1JsBiKbF8d08FCewiipDmVIYjg==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "opencollective-postinstall": "^2.0.0",
+ "tz-offset": "0.0.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
@@ -5986,6 +6000,14 @@
"node": ">=6"
}
},
+ "node_modules/opencollective-postinstall": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
+ "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
+ "bin": {
+ "opencollective-postinstall": "index.js"
+ }
+ },
"node_modules/opener": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
@@ -8061,6 +8083,11 @@
"is-typedarray": "^1.0.0"
}
},
+ "node_modules/tz-offset": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/tz-offset/-/tz-offset-0.0.1.tgz",
+ "integrity": "sha512-kMBmblijHJXyOpKzgDhKx9INYU4u4E1RPMB0HqmKSgWG8vEcf3exEfLh4FFfzd3xdQOw9EuIy/cP0akY6rHopQ=="
+ },
"node_modules/uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
@@ -14298,6 +14325,15 @@
}
}
},
+ "node-cron": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-2.0.3.tgz",
+ "integrity": "sha512-eJI+QitXlwcgiZwNNSRbqsjeZMp5shyajMR81RZCqeW0ZDEj4zU9tpd4nTh/1JsBiKbF8d08FCewiipDmVIYjg==",
+ "requires": {
+ "opencollective-postinstall": "^2.0.0",
+ "tz-offset": "0.0.1"
+ }
+ },
"node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
@@ -14503,6 +14539,11 @@
"mimic-fn": "^2.1.0"
}
},
+ "opencollective-postinstall": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
+ "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q=="
+ },
"opener": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
@@ -16219,6 +16260,11 @@
"is-typedarray": "^1.0.0"
}
},
+ "tz-offset": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/tz-offset/-/tz-offset-0.0.1.tgz",
+ "integrity": "sha512-kMBmblijHJXyOpKzgDhKx9INYU4u4E1RPMB0HqmKSgWG8vEcf3exEfLh4FFfzd3xdQOw9EuIy/cP0akY6rHopQ=="
+ },
"uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
diff --git a/package.json b/package.json
index cc11ec9..2572df2 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
"express-formidable": "^1.2.0",
"express-session": "^1.17.1",
"mariadb": "^2.5.2",
+ "node-cron": "^2.0.3",
"nodemailer": "^6.4.17",
"react-cookie": "^4.0.3",
"regenerator-runtime": "^0.13.7",
diff --git a/server/accounts/deletion.js b/server/accounts/deletion.js
new file mode 100644
index 0000000..8896db5
--- /dev/null
+++ b/server/accounts/deletion.js
@@ -0,0 +1,52 @@
+//libraries
+const utils = require('util');
+const bcrypt = require('bcryptjs');
+var cron = require('node-cron');
+
+const Sequelize = require('sequelize');
+const Op = Sequelize.Op;
+const { accounts } = require('../database/models');
+
+//api/accounts/deletion
+const route = async (req, res) => {
+ //make sure the account is logged in
+ if (req.cookies['loggedin'] !== process.env.WEB_ADDRESS) {
+ return res.status(401).send('invalid session status');
+ }
+
+ //compare the user's password
+ const compare = utils.promisify(bcrypt.compare);
+ const match = await compare(req.fields.password, req.session.account.hash);
+
+ if (!match) {
+ return res.status(401).send('incorrect password');
+ }
+
+ //set the deletion time (2 days from now)
+ const interval = new Date(new Date().setDate(new Date().getDate() + 2)); //wow
+ await accounts.update({
+ deletion: interval
+ },
+ {
+ where: {
+ id: req.session.account.id
+ }
+ });
+
+ //finally
+ return res.status(200).send('account will be deleted in two days - log in to cancel');
+};
+
+//actually delete the accounts
+cron.schedule('0 * * * *', () => {
+ console.log('wiping accounts');
+ accounts.destroy({
+ where: {
+ deletion: {
+ [Op.lt]: Sequelize.fn('NOW')
+ }
+ }
+ });
+});
+
+module.exports = route;
\ No newline at end of file
diff --git a/server/accounts/index.js b/server/accounts/index.js
index ac5021d..dda4dd2 100644
--- a/server/accounts/index.js
+++ b/server/accounts/index.js
@@ -6,5 +6,6 @@ router.post('/signup', require('./signup'));
router.get('/validation', require('./validation'));
router.post('/login', require('./login'));
router.post('/logout', require('./logout'));
+router.post('/deletion', require('./deletion'));
module.exports = router;
diff --git a/server/accounts/login.js b/server/accounts/login.js
index ae09a63..07a2095 100644
--- a/server/accounts/login.js
+++ b/server/accounts/login.js
@@ -40,6 +40,13 @@ const route = async (req, res) => {
req.session.account = account;
res.cookie('loggedin', process.env.WEB_ADDRESS);
+ //cancel deletion if any
+ await accounts.update({ deletion: null }, {
+ where: {
+ id: account.id
+ }
+ });
+
//finally
res.status(200).send('login succeeded');
};
diff --git a/server/database/index.js b/server/database/index.js
index fadb96a..bde6631 100644
--- a/server/database/index.js
+++ b/server/database/index.js
@@ -3,6 +3,7 @@ const Sequelize = require('sequelize');
const sequelize = new Sequelize(process.env.DB_DATABASE, process.env.DB_USERNAME, process.env.DB_PASSWORD, {
host: process.env.DB_HOSTADDR,
dialect: 'mariadb',
+ timezone: process.env.DB_TIMEZONE,
logging: false
});