Merge branch 'master' into patch-1

pull/107/head
Suresh Alse 5 years ago committed by GitHub
commit 29e98b3e3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,2 +1,5 @@
.git
*.swp
node_modules node_modules
.git crontabs/*.db
crontabs/logs/*.log

@ -1,7 +1,9 @@
# docker run -d -p 8000:8000 alseambusher/crontab-ui # docker run -d -p 8000:8000 alseambusher/crontab-ui
FROM alpine:3.10 FROM alpine:3.10
RUN mkdir /crontab-ui; touch /etc/crontabs/root; chmod +x /etc/crontabs/root ENV CRON_PATH /etc/crontabs
RUN mkdir /crontab-ui; touch $CRON_PATH/root; chmod +x $CRON_PATH/root
WORKDIR /crontab-ui WORKDIR /crontab-ui
@ -24,7 +26,6 @@ ENV HOST 0.0.0.0
ENV PORT 8000 ENV PORT 8000
ENV CRON_PATH /etc/crontabs
ENV CRON_IN_DOCKER true ENV CRON_IN_DOCKER true
EXPOSE $PORT EXPOSE $PORT

@ -1,4 +1,4 @@
VER=0.3.8 VER=0.3.12
release: release:
sed -i '' "s/version\": \".*/version\": \"$(VER)\",/" package.json sed -i '' "s/version\": \".*/version\": \"$(VER)\",/" package.json

@ -42,14 +42,30 @@ If you need to autosave your changes to crontab directly:
crontab-ui --autosave crontab-ui --autosave
Setting up with docker. You can use the prebuilt images in the [dockerhub](https://hub.docker.com/r/alseambusher/crontab-ui/tags) or build it yourself like this: ## Docker
You can use crontab-ui with docker. You can use the prebuilt images in the [dockerhub](https://hub.docker.com/r/alseambusher/crontab-ui/tags)
```bash
docker run -d -p 8000:8000 alseambusher/crontab-ui
```
You can also build it yourself if you want to customize, like this:
```bash ```bash
git clone https://github.com/alseambusher/crontab-ui.git git clone https://github.com/alseambusher/crontab-ui.git
cd crontab-ui cd crontab-ui
docker build -t alseambusher/crontab-ui . docker build -t alseambusher/crontab-ui .
docker run -d -p 8000:8000 alseambusher/crontab-ui docker run -d -p 8000:8000 alseambusher/crontab-ui
``` ```
If you want to use it with authentication, You can pass `BASIC_AUTH_USER` and `BASIC_AUTH_PWD` as env variables
```bash
docker run -e BASIC_AUTH_USER=user -e BASIC_AUTH_PWD=SecretPassword -d -p 8000:8000 alseambusher/crontab-ui
```
You can also mount a folder to store the db and logs.
```bash
mkdir -p crontabs/logs
docker run --mount type=bind,source="$(pwd)"/crontabs/,target=/crontab-ui/crontabs/ -d -p 8000:8000 alseambusher/crontab-ui
```
## Resources ## Resources

@ -30,6 +30,7 @@ if (BASIC_AUTH_USER && BASIC_AUTH_PWD) {
// include the routes // include the routes
var routes = require("./routes").routes; var routes = require("./routes").routes;
var routes_relative = require("./routes").relative
// set the view engine to ejs // set the view engine to ejs
app.set('view engine', 'ejs'); app.set('view engine', 'ejs');
@ -61,7 +62,7 @@ app.get(routes.root, function(req, res) {
// send all the required parameters // send all the required parameters
crontab.crontabs( function(docs){ crontab.crontabs( function(docs){
res.render('index', { res.render('index', {
routes : JSON.stringify(routes), routes : JSON.stringify(routes_relative),
crontabs : JSON.stringify(docs), crontabs : JSON.stringify(docs),
backups : crontab.get_backup_names(), backups : crontab.get_backup_names(),
env : crontab.get_env(), env : crontab.get_env(),
@ -130,7 +131,7 @@ app.get(routes.restore, function(req, res) {
// get all the crontabs // get all the crontabs
restore.crontabs(req.query.db, function(docs){ restore.crontabs(req.query.db, function(docs){
res.render('restore', { res.render('restore', {
routes : JSON.stringify(routes), routes : JSON.stringify(routes_relative),
crontabs : JSON.stringify(docs), crontabs : JSON.stringify(docs),
backups : crontab.get_backup_names(), backups : crontab.get_backup_names(),
db: req.query.db db: req.query.db
@ -152,7 +153,7 @@ app.get(routes.restore_backup, function(req, res) {
// export current crontab db so that user can download it // export current crontab db so that user can download it
app.get(routes.export, function(req, res) { app.get(routes.export, function(req, res) {
var file = __dirname + '/crontabs/crontab.db'; var file = crontab.crontab_db_file;
var filename = path.basename(file); var filename = path.basename(file);
var mimetype = mime.lookup(file); var mimetype = mime.lookup(file);
@ -169,7 +170,7 @@ app.post(routes.import, function(req, res) {
var fstream; var fstream;
req.pipe(req.busboy); req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) { req.busboy.on('file', function (fieldname, file, filename) {
fstream = fs.createWriteStream(__dirname + '/crontabs/crontab.db'); fstream = fs.createWriteStream(crontab.crontab_db_file);
file.pipe(fstream); file.pipe(fstream);
fstream.on('close', function () { fstream.on('close', function () {
crontab.reload_db(); crontab.reload_db();
@ -184,13 +185,23 @@ app.get(routes.import_crontab, function(req, res) {
res.end(); res.end();
}); });
// get the log file a given job. id passed as query param function sendLog(path, req, res) {
app.get(routes.logger, function(req, res) { if (fs.existsSync(path))
_file = crontab.log_folder +"/"+req.query.id+".log"; res.sendFile(path);
if (fs.existsSync(_file))
res.sendFile(_file);
else else
res.end("No errors logged yet"); res.end("No errors logged yet");
}
// get the log file a given job. id passed as query param
app.get(routes.logger, function(req, res) {
let _file = crontab.log_folder + "/" + req.query.id + ".log";
sendLog(_file, req, res);
});
// get the log file a given job. id passed as query param
app.get(routes.stdout, function(req, res) {
let _file = crontab.log_folder + "/" + req.query.id + ".stdout.log";
sendLog(_file, req, res);
}); });
// error handler // error handler
@ -204,7 +215,7 @@ app.use(function(err, req, res, next) {
data.stack = err.stack; data.stack = err.stack;
} }
if (parseInt(data.statusCode) >= 500) { if (statusCode >= 500) {
console.error(err); console.error(err);
} }
@ -233,7 +244,7 @@ app.listen(app.get('port'), app.get('host'), function() {
// we do this by watching log file and setting a on change hook to it // we do this by watching log file and setting a on change hook to it
if (process.argv.includes("--autosave")){ if (process.argv.includes("--autosave")){
crontab.autosave_crontab(()=>{}); crontab.autosave_crontab(()=>{});
fs.watchFile(__dirname + '/crontabs/crontab.db', () => { fs.watchFile(crontab.crontab_db_file, () => {
crontab.autosave_crontab(()=>{ crontab.autosave_crontab(()=>{
console.log("Attempted to autosave crontab"); console.log("Attempted to autosave crontab");
}); });
@ -241,8 +252,8 @@ app.listen(app.get('port'), app.get('host'), function() {
} }
if (process.argv.includes("--reset")){ if (process.argv.includes("--reset")){
console.log("Resetting crontab-ui"); console.log("Resetting crontab-ui");
var crontabdb = __dirname + "/crontabs/crontab.db"; var crontabdb = crontab.crontab_db_file;
var envdb = __dirname + "/crontabs/env.db"; var envdb = crontab.env_file;
console.log("Deleting " + crontabdb); console.log("Deleting " + crontabdb);
try{ try{

@ -2,7 +2,14 @@
//load database //load database
var Datastore = require('nedb'); var Datastore = require('nedb');
var path = require("path"); var path = require("path");
var db = new Datastore({ filename: __dirname + '/crontabs/crontab.db' });
exports.db_folder = process.env.CRON_DB_PATH === undefined ? path.join(__dirname, "crontabs") : process.env.CRON_DB_PATH;
console.log("Cron db path: " + exports.db_folder);
exports.log_folder = path.join(exports.db_folder, 'logs');
exports.env_file = path.join(exports.db_folder, 'env.db');
exports.crontab_db_file = path.join(exports.db_folder, 'crontab.db');
var db = new Datastore({ filename: exports.crontab_db_file});
var cronPath = "/tmp"; var cronPath = "/tmp";
if(process.env.CRON_PATH !== undefined) { if(process.env.CRON_PATH !== undefined) {
@ -18,8 +25,6 @@ var exec = require('child_process').exec;
var fs = require('fs'); var fs = require('fs');
var cron_parser = require("cron-parser"); var cron_parser = require("cron-parser");
exports.log_folder = __dirname + '/crontabs/logs';
exports.env_file = __dirname + '/crontabs/env.db';
crontab = function(name, command, schedule, stopped, logging, mailing){ crontab = function(name, command, schedule, stopped, logging, mailing){
var data = {}; var data = {};
@ -62,7 +67,12 @@ exports.crontabs = function(callback){
if(docs[i].schedule == "@reboot") if(docs[i].schedule == "@reboot")
docs[i].next = "Next Reboot"; docs[i].next = "Next Reboot";
else else
docs[i].next = cron_parser.parseExpression(docs[i].schedule).next().toString(); try {
docs[i].next = cron_parser.parseExpression(docs[i].schedule).next().toString();
} catch(err) {
console.error(err);
docs[i].next = "invalid";
}
} }
callback(docs); callback(docs);
}); });
@ -95,6 +105,7 @@ exports.set_crontab = function(env_vars, callback){
let stderr = path.join(cronPath, tab._id + ".stderr"); let stderr = path.join(cronPath, tab._id + ".stderr");
let stdout = path.join(cronPath, tab._id + ".stdout"); let stdout = path.join(cronPath, tab._id + ".stdout");
let log_file = path.join(exports.log_folder, tab._id + ".log"); let log_file = path.join(exports.log_folder, tab._id + ".log");
let log_file_stdout = path.join(exports.log_folder, tab._id + ".stdout.log");
if(tab.command[tab.command.length-1] != ";") // add semicolon if(tab.command[tab.command.length-1] != ";") // add semicolon
tab.command +=";"; tab.command +=";";
@ -103,8 +114,13 @@ exports.set_crontab = function(env_vars, callback){
if (tab.logging && tab.logging == "true") { if (tab.logging && tab.logging == "true") {
crontab_string += "; if test -f " + stderr + crontab_string += "; if test -f " + stderr +
"; then date >> " + log_file + "; then date >> \"" + log_file + "\"" +
"; cat " + stderr + " >> " + log_file + "; cat " + stderr + " >> \"" + log_file + "\"" +
"; fi";
crontab_string += "; if test -f " + stdout +
"; then date >> \"" + log_file_stdout + "\"" +
"; cat " + stdout + " >> \"" + log_file_stdout + "\"" +
"; fi"; "; fi";
} }
@ -123,24 +139,25 @@ exports.set_crontab = function(env_vars, callback){
}); });
fs.writeFile(exports.env_file, env_vars, function(err) { fs.writeFile(exports.env_file, env_vars, function(err) {
if (err) callback(err); if (err) {
// In docker we're running as the root user, so we need to write the file as root and not crontab console.error(err);
var fileName = "crontab" callback(err);
if(process.env.CRON_IN_DOCKER !== undefined) {
fileName = "root"
} }
// In docker we're running as the root user, so we need to write the file as root and not crontab
var fileName = process.env.CRON_IN_DOCKER !== undefined ? "root" : "crontab";
fs.writeFile(path.join(cronPath, fileName), crontab_string, function(err) { fs.writeFile(path.join(cronPath, fileName), crontab_string, function(err) {
if (err) return callback(err); if (err) {
/// In docker we're running crond using busybox implementation of crond console.error(err);
/// It is launched as part of the container startup process, so no need to run it again return callback(err);
if(process.env.CRON_IN_DOCKER === undefined) {
exec("crontab " + path.join(cronPath, "crontab"), function(err) {
if (err) return callback(err);
else callback();
});
} else {
callback();
} }
exec("crontab " + path.join(cronPath, fileName), function(err) {
if (err) {
console.error(err);
return callback(err);
}
else callback();
});
}); });
}); });
}); });
@ -148,7 +165,7 @@ exports.set_crontab = function(env_vars, callback){
exports.get_backup_names = function(){ exports.get_backup_names = function(){
var backups = []; var backups = [];
fs.readdirSync(__dirname + '/crontabs').forEach(function(file){ fs.readdirSync(exports.db_folder).forEach(function(file){
// file name begins with backup // file name begins with backup
if(file.indexOf("backup") === 0){ if(file.indexOf("backup") === 0){
backups.push(file); backups.push(file);
@ -175,11 +192,11 @@ exports.get_backup_names = function(){
exports.backup = function(){ exports.backup = function(){
//TODO check if it failed //TODO check if it failed
fs.createReadStream( __dirname + '/crontabs/crontab.db').pipe(fs.createWriteStream( __dirname + '/crontabs/backup ' + (new Date()).toString().replace("+", " ") + '.db')); fs.createReadStream(exports.crontab_db_file).pipe(fs.createWriteStream( path.join(exports.db_folder, 'backup ' + (new Date()).toString().replace("+", " ") + '.db')));
}; };
exports.restore = function(db_name){ exports.restore = function(db_name){
fs.createReadStream( __dirname + '/crontabs/' + db_name).pipe(fs.createWriteStream( __dirname + '/crontabs/crontab.db')); fs.createReadStream(path.join(exports.db_folder, db_name)).pipe(fs.createWriteStream(exports.crontab_db_file));
db.loadDatabase(); // reload the database db.loadDatabase(); // reload the database
}; };

414
package-lock.json generated

@ -1,16 +1,24 @@
{ {
"name": "crontab-ui", "name": "crontab-ui",
"version": "0.3.5", "version": "0.3.9",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"accepts": { "accepts": {
"version": "1.3.5", "version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"requires": { "requires": {
"mime-types": "~2.1.18", "mime-types": "~2.1.24",
"negotiator": "0.6.1" "negotiator": "0.6.2"
}
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
} }
}, },
"array-flatten": { "array-flatten": {
@ -19,9 +27,14 @@
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
}, },
"async": { "async": {
"version": "0.2.10", "version": "0.9.2",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
}, },
"basic-auth": { "basic-auth": {
"version": "2.0.1", "version": "2.0.1",
@ -40,20 +53,29 @@
} }
}, },
"body-parser": { "body-parser": {
"version": "1.18.3", "version": "1.19.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
"requires": { "requires": {
"bytes": "3.0.0", "bytes": "3.1.0",
"content-type": "~1.0.4", "content-type": "~1.0.4",
"debug": "2.6.9", "debug": "2.6.9",
"depd": "~1.1.2", "depd": "~1.1.2",
"http-errors": "~1.6.3", "http-errors": "1.7.2",
"iconv-lite": "0.4.23", "iconv-lite": "0.4.24",
"on-finished": "~2.3.0", "on-finished": "~2.3.0",
"qs": "6.5.2", "qs": "6.7.0",
"raw-body": "2.3.3", "raw-body": "2.4.0",
"type-is": "~1.6.16" "type-is": "~1.6.17"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
} }
}, },
"busboy": { "busboy": {
@ -65,9 +87,37 @@
} }
}, },
"bytes": { "bytes": {
"version": "3.0.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
}, },
"connect-busboy": { "connect-busboy": {
"version": "0.0.2", "version": "0.0.2",
@ -78,9 +128,12 @@
} }
}, },
"content-disposition": { "content-disposition": {
"version": "0.5.2", "version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
"integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
"requires": {
"safe-buffer": "5.1.2"
}
}, },
"content-type": { "content-type": {
"version": "1.0.4", "version": "1.0.4",
@ -88,9 +141,9 @@
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
}, },
"cookie": { "cookie": {
"version": "0.3.1", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
}, },
"cookie-signature": { "cookie-signature": {
"version": "1.0.6", "version": "1.0.6",
@ -98,12 +151,12 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
}, },
"cron-parser": { "cron-parser": {
"version": "2.11.0", "version": "2.15.0",
"resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.11.0.tgz", "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.15.0.tgz",
"integrity": "sha512-L5LAGlvq2xmCLErhjQRX8IL5v72y8jhGOaxrarYOhse0kJjJGb/vY/0sV/c7F/SylJGkUIY2iZPPJXZD3glZqA==", "integrity": "sha512-rMFkrQw8+oG5OuwjiXesup4KeIlEG/IU82YtG4xyAHbO5jhKmYaHPp/ZNhq9+7TjSJ65E3zV3kQPUbmXSff2/g==",
"requires": { "requires": {
"is-nan": "^1.2.1", "is-nan": "^1.3.0",
"moment-timezone": "^0.5.23" "moment-timezone": "^0.5.31"
} }
}, },
"debug": { "debug": {
@ -146,9 +199,12 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
}, },
"ejs": { "ejs": {
"version": "2.6.1", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.3.tgz",
"integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" "integrity": "sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg==",
"requires": {
"jake": "^10.6.1"
}
}, },
"encodeurl": { "encodeurl": {
"version": "1.0.2", "version": "1.0.2",
@ -160,53 +216,51 @@
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
}, },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"etag": { "etag": {
"version": "1.8.1", "version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
}, },
"express": { "express": {
"version": "4.16.4", "version": "4.17.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
"integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
"requires": { "requires": {
"accepts": "~1.3.5", "accepts": "~1.3.7",
"array-flatten": "1.1.1", "array-flatten": "1.1.1",
"body-parser": "1.18.3", "body-parser": "1.19.0",
"content-disposition": "0.5.2", "content-disposition": "0.5.3",
"content-type": "~1.0.4", "content-type": "~1.0.4",
"cookie": "0.3.1", "cookie": "0.4.0",
"cookie-signature": "1.0.6", "cookie-signature": "1.0.6",
"debug": "2.6.9", "debug": "2.6.9",
"depd": "~1.1.2", "depd": "~1.1.2",
"encodeurl": "~1.0.2", "encodeurl": "~1.0.2",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"etag": "~1.8.1", "etag": "~1.8.1",
"finalhandler": "1.1.1", "finalhandler": "~1.1.2",
"fresh": "0.5.2", "fresh": "0.5.2",
"merge-descriptors": "1.0.1", "merge-descriptors": "1.0.1",
"methods": "~1.1.2", "methods": "~1.1.2",
"on-finished": "~2.3.0", "on-finished": "~2.3.0",
"parseurl": "~1.3.2", "parseurl": "~1.3.3",
"path-to-regexp": "0.1.7", "path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.4", "proxy-addr": "~2.0.5",
"qs": "6.5.2", "qs": "6.7.0",
"range-parser": "~1.2.0", "range-parser": "~1.2.1",
"safe-buffer": "5.1.2", "safe-buffer": "5.1.2",
"send": "0.16.2", "send": "0.17.1",
"serve-static": "1.13.2", "serve-static": "1.14.1",
"setprototypeof": "1.1.0", "setprototypeof": "1.1.1",
"statuses": "~1.4.0", "statuses": "~1.5.0",
"type-is": "~1.6.16", "type-is": "~1.6.18",
"utils-merge": "1.0.1", "utils-merge": "1.0.1",
"vary": "~1.1.2" "vary": "~1.1.2"
},
"dependencies": {
"statuses": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
}
} }
}, },
"express-basic-auth": { "express-basic-auth": {
@ -217,25 +271,26 @@
"basic-auth": "^2.0.1" "basic-auth": "^2.0.1"
} }
}, },
"filelist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz",
"integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==",
"requires": {
"minimatch": "^3.0.4"
}
},
"finalhandler": { "finalhandler": {
"version": "1.1.1", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
"requires": { "requires": {
"debug": "2.6.9", "debug": "2.6.9",
"encodeurl": "~1.0.2", "encodeurl": "~1.0.2",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"on-finished": "~2.3.0", "on-finished": "~2.3.0",
"parseurl": "~1.3.2", "parseurl": "~1.3.3",
"statuses": "~1.4.0", "statuses": "~1.5.0",
"unpipe": "~1.0.0" "unpipe": "~1.0.0"
},
"dependencies": {
"statuses": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
}
} }
}, },
"forwarded": { "forwarded": {
@ -248,21 +303,27 @@
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
}, },
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"http-errors": { "http-errors": {
"version": "1.6.3", "version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
"requires": { "requires": {
"depd": "~1.1.2", "depd": "~1.1.2",
"inherits": "2.0.3", "inherits": "2.0.3",
"setprototypeof": "1.1.0", "setprototypeof": "1.1.1",
"statuses": ">= 1.4.0 < 2" "statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
} }
}, },
"iconv-lite": { "iconv-lite": {
"version": "0.4.23", "version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": { "requires": {
"safer-buffer": ">= 2.1.2 < 3" "safer-buffer": ">= 2.1.2 < 3"
} }
@ -278,16 +339,27 @@
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}, },
"ipaddr.js": { "ipaddr.js": {
"version": "1.9.0", "version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
}, },
"is-nan": { "is-nan": {
"version": "1.2.1", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.2.1.tgz", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz",
"integrity": "sha1-n69ltvttskt/XAYoR16nH5iEAeI=", "integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==",
"requires": {
"define-properties": "^1.1.3"
}
},
"jake": {
"version": "10.8.1",
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.1.tgz",
"integrity": "sha512-eSp5h9S7UFzKdQERTyF+KuPLjDZa1Tbw8gCVUn98n4PbIkLEDGe4zl7vF4Qge9kQj06HcymnksPk8jznPZeKsA==",
"requires": { "requires": {
"define-properties": "^1.1.1" "async": "0.9.x",
"chalk": "^2.4.2",
"filelist": "^1.0.1",
"minimatch": "^3.0.4"
} }
}, },
"lie": { "lie": {
@ -299,9 +371,9 @@
} }
}, },
"localforage": { "localforage": {
"version": "1.7.3", "version": "1.7.4",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.7.3.tgz", "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.7.4.tgz",
"integrity": "sha512-1TulyYfc4udS7ECSBT2vwJksWbkwwTX8BzeUIiq8Y07Riy7bDAAnxDaPU/tWyOVmQAcWJIEIFP9lPfBGqVoPgQ==", "integrity": "sha512-3EmVZatmNVeCo/t6Te7P06h2alGwbq8wXlSkcSXMvDE2/edPmsVqTPlzGnZaqwZZDBs6v+kxWpqjVsqsNJT8jA==",
"requires": { "requires": {
"lie": "3.1.1" "lie": "3.1.1"
} }
@ -322,45 +394,53 @@
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
}, },
"mime": { "mime": {
"version": "1.4.1", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
}, },
"mime-db": { "mime-db": {
"version": "1.40.0", "version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
}, },
"mime-types": { "mime-types": {
"version": "2.1.24", "version": "2.1.27",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
"requires": { "requires": {
"mime-db": "1.40.0" "mime-db": "1.44.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
} }
}, },
"minimist": { "minimist": {
"version": "0.0.8", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "^1.2.5"
} }
}, },
"moment": { "moment": {
"version": "2.24.0", "version": "2.26.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
}, },
"moment-timezone": { "moment-timezone": {
"version": "0.5.25", "version": "0.5.31",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.25.tgz", "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz",
"integrity": "sha512-DgEaTyN/z0HFaVcVbSyVCUU6HeFdnNC3vE4c9cgu2dgMTvjBUBdBzWfasTBmAW45u5OIMeCJtU8yNjM22DHucw==", "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==",
"requires": { "requires": {
"moment": ">= 2.9.0" "moment": ">= 2.9.0"
} }
@ -380,17 +460,24 @@
"localforage": "^1.3.0", "localforage": "^1.3.0",
"mkdirp": "~0.5.1", "mkdirp": "~0.5.1",
"underscore": "~1.4.4" "underscore": "~1.4.4"
},
"dependencies": {
"async": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
}
} }
}, },
"negotiator": { "negotiator": {
"version": "0.6.1", "version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
}, },
"nodemailer": { "nodemailer": {
"version": "6.1.1", "version": "6.4.8",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.1.1.tgz", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.8.tgz",
"integrity": "sha512-/x5MRIh56VyuuhLfcz+DL2SlBARpZpgQIf2A4Ao4hMb69MHSgDIMPwYmFwesGT1lkRDZ0eBSoym5+JoIZ3N+cQ==" "integrity": "sha512-UbJD0+g5e2H20bWv7Rpj3B+N3TMMJ0MLoLwaGVJ0k3Vo8upq0UltwHJ5BJfrpST1vFa91JQ8cf7cICK5DSIo1Q=="
}, },
"object-keys": { "object-keys": {
"version": "1.1.1", "version": "1.1.1",
@ -416,32 +503,32 @@
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
}, },
"proxy-addr": { "proxy-addr": {
"version": "2.0.5", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
"integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
"requires": { "requires": {
"forwarded": "~0.1.2", "forwarded": "~0.1.2",
"ipaddr.js": "1.9.0" "ipaddr.js": "1.9.1"
} }
}, },
"qs": { "qs": {
"version": "6.5.2", "version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
}, },
"range-parser": { "range-parser": {
"version": "1.2.0", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
}, },
"raw-body": { "raw-body": {
"version": "2.3.3", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
"integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
"requires": { "requires": {
"bytes": "3.0.0", "bytes": "3.1.0",
"http-errors": "1.6.3", "http-errors": "1.7.2",
"iconv-lite": "0.4.23", "iconv-lite": "0.4.24",
"unpipe": "1.0.0" "unpipe": "1.0.0"
} }
}, },
@ -456,9 +543,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"send": { "send": {
"version": "0.16.2", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
"requires": { "requires": {
"debug": "2.6.9", "debug": "2.6.9",
"depd": "~1.1.2", "depd": "~1.1.2",
@ -467,36 +554,36 @@
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"etag": "~1.8.1", "etag": "~1.8.1",
"fresh": "0.5.2", "fresh": "0.5.2",
"http-errors": "~1.6.2", "http-errors": "~1.7.2",
"mime": "1.4.1", "mime": "1.6.0",
"ms": "2.0.0", "ms": "2.1.1",
"on-finished": "~2.3.0", "on-finished": "~2.3.0",
"range-parser": "~1.2.0", "range-parser": "~1.2.1",
"statuses": "~1.4.0" "statuses": "~1.5.0"
}, },
"dependencies": { "dependencies": {
"statuses": { "ms": {
"version": "1.4.0", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
} }
} }
}, },
"serve-static": { "serve-static": {
"version": "1.13.2", "version": "1.14.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
"requires": { "requires": {
"encodeurl": "~1.0.2", "encodeurl": "~1.0.2",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"parseurl": "~1.3.2", "parseurl": "~1.3.3",
"send": "0.16.2" "send": "0.17.1"
} }
}, },
"setprototypeof": { "setprototypeof": {
"version": "1.1.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
}, },
"statuses": { "statuses": {
"version": "1.5.0", "version": "1.5.0",
@ -508,10 +595,23 @@
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
}, },
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"requires": {
"has-flag": "^3.0.0"
}
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"type-is": { "type-is": {
"version": "1.6.17", "version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.17.tgz", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-jYZzkOoAPVyQ9vlZ4xEJ4BBbHC4a7hbY1xqyCPe6AiQVVqfbZEulJm0VpqK4B+096O1VQi0l6OBGH210ejx/bA==", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"requires": { "requires": {
"media-typer": "0.3.0", "media-typer": "0.3.0",
"mime-types": "~2.1.24" "mime-types": "~2.1.24"

@ -1,6 +1,6 @@
{ {
"name": "crontab-ui", "name": "crontab-ui",
"version": "0.3.8", "version": "0.3.12",
"description": "Easy and safe way to manage your crontab file", "description": "Easy and safe way to manage your crontab file",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

@ -14,5 +14,12 @@ exports.crontabs = function(db_name, callback){
}; };
exports.delete = function(db_name){ exports.delete = function(db_name){
fs.unlink(__dirname + '/crontabs/' + db_name); fs.unlink(__dirname + '/crontabs/' + db_name, function(err){
if(err) {
return console.log("Delete error: " + err);
}
else{
console.log("Backup deleted");
}
});
}; };

@ -14,4 +14,8 @@ exports.routes = {
"import": "/import", // this is import from database "import": "/import", // this is import from database
"import_crontab": "/import_crontab", // this is from existing crontab "import_crontab": "/import_crontab", // this is from existing crontab
"logger": "/logger", "logger": "/logger",
"stdout": "/stdout",
}; };
exports.relative = Object.keys(exports.routes).reduce((p, c) => ({...p, [c]: exports.routes[c].replace(/^\//, '')}), {});
exports.relative["root"] = ".";

@ -21,7 +21,7 @@
</script> </script>
</head> </head>
<body> <body>
<% include navbar %> <%- include('navbar.ejs') -%>
<div class="container-fluid"> <div class="container-fluid">
<h2>Cronjobs</h2> <h2>Cronjobs</h2>
<div class="form-group"> <div class="form-group">
@ -82,7 +82,8 @@
<!-- controls based on crontab state --> <!-- controls based on crontab state -->
<% if (!crontab.stopped) { %> <% if (!crontab.stopped) { %>
<% if (crontab.logging && crontab.logging != "false") {%> <% if (crontab.logging && crontab.logging != "false") {%>
<a class="btn btn-primary" data-toggle="tooltip" data-placement="left" title="See Log" href="<%= JSON.parse(routes).logger + '?id=' + crontab._id %>" target="_blank"><span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span></a> <a class="btn btn-primary btn-danger" data-toggle="tooltip" data-placement="left" title="stderr" href="<%= JSON.parse(routes).logger + '?id=' + crontab._id %>" target="_blank"><span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span></a>
<a class="btn btn-primary" data-toggle="tooltip" data-placement="left" title="stdout" href="<%= JSON.parse(routes).stdout + '?id=' + crontab._id %>" target="_blank"><span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span></a>
<% } %> <% } %>
<a class="btn btn-info" onclick="runJob('<%= crontab._id %>')"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Run</a> <a class="btn btn-info" onclick="runJob('<%= crontab._id %>')"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Run</a>
<a class="btn btn-primary" onclick="editJob('<%= crontab._id %>')"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Edit</a> <a class="btn btn-primary" onclick="editJob('<%= crontab._id %>')"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Edit</a>
@ -99,7 +100,7 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<% include popup.ejs %> <%- include('popup.ejs') -%>
<script> <script>
jQuery(function($) { jQuery(function($) {
$('#main_table').DataTable({ $('#main_table').DataTable({

@ -17,7 +17,7 @@
</script> </script>
</head> </head>
<body> <body>
<% include navbar %> <%- include('navbar.ejs') -%>
<div class="container"> <div class="container">
<h2><%= db %></h2> <h2><%= db %></h2>
<table class="table"> <table class="table">
@ -60,6 +60,6 @@
<a class="btn btn-primary" onclick="restore_backup('<%= db %>')"><span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span> Restore</a> <a class="btn btn-primary" onclick="restore_backup('<%= db %>')"><span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span> Restore</a>
<a class="btn btn-danger" onclick="delete_backup('<%= db %>')"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete</a> <a class="btn btn-danger" onclick="delete_backup('<%= db %>')"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete</a>
</div> </div>
<% include popup.ejs %> <%- include('popup.ejs') -%>
</body> </body>
</html> </html>

Loading…
Cancel
Save