Compare commits
307 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f9750e237a | |||
| 908bb75fdc | |||
| a273827166 | |||
| 0cb96f4b03 | |||
| af7764253d | |||
| af9652f7c8 | |||
| e741ca9216 | |||
| e3950c2fb0 | |||
| 3eae49139c | |||
| 97f17916f9 | |||
| ee0a25962b | |||
| 55fb3b3b55 | |||
| a58d9d1497 | |||
| 801dbc9705 | |||
| e3897c4c34 | |||
| 04dd8914cd | |||
| c2651fd8f8 | |||
| 27f760fdbf | |||
| a74cf0b064 | |||
| e09d2db7e6 | |||
| 28f183f450 | |||
| 5126b605f2 | |||
| aaebdda9d6 | |||
| af29a3f498 | |||
| 55b6773d88 | |||
| 239ec86c4a | |||
| 13adca00d6 | |||
| a76631ee3d | |||
| 7ac99f16cd | |||
| 3b6ca1c59d | |||
| 3f55064c47 | |||
| 917bc2a88c | |||
| 85dfa1ccad | |||
| 606828da1d | |||
| a182d78566 | |||
| 0f294531d3 | |||
| 9189532b83 | |||
| c031253bd4 | |||
| 11ae5d4832 | |||
| 3251dc3d73 | |||
| a671e6acf7 | |||
| 5ce658125c | |||
| 1d88a935a5 | |||
| 8da07a16b9 | |||
| 7ce045ae51 | |||
| a3e253436e | |||
| 08955ce5a4 | |||
| 57a4fa2d38 | |||
| 548e652ba2 | |||
| e92cfae4d9 | |||
| ed1320c937 | |||
| abccffd05f | |||
| c1106aa32e | |||
| a94f5daac9 | |||
| 9d9f16e948 | |||
| 0b5bd0b4cd | |||
| caa59dd9a9 | |||
| 423958dd0e | |||
| 6a90cf5102 | |||
| 2d820a3005 | |||
| 7fff55a1ed | |||
| 52d1d47030 | |||
| 7df1d388f0 | |||
| a34f5f13da | |||
| bcc1e5f79c | |||
| 44d32ea281 | |||
| 63e16c9bb8 | |||
| 528be0e4c0 | |||
| 0660a924b7 | |||
| 6f29d5f3f6 | |||
| 9903004af5 | |||
| 0c2b250901 | |||
| 00f8e96dd2 | |||
| 267fa79164 | |||
| 1528aa9d0c | |||
| 0cd6f7f2e7 | |||
| f05967d871 | |||
| 26087e1580 | |||
| 9275c4fbfd | |||
| a2e03ccf7a | |||
| 6605a38eab | |||
| 0a09d89684 | |||
| c0d4100dd1 | |||
| 791f5af3e0 | |||
| ed57e701bc | |||
| c678a9b6d7 | |||
| 07b428f051 | |||
| a1ab8b6aa8 | |||
| a07848164c | |||
| 1b1d4ee431 | |||
| f8e5668c5c | |||
| d8719626d9 | |||
| 3a06797de0 | |||
| b9d7149dbb | |||
| 72bbb4ec68 | |||
| d9ec1be9b6 | |||
| ecddb6977a | |||
| 77220038a1 | |||
| 016f194271 | |||
| e34fecee5e | |||
| 7448dc5ec5 | |||
| bfd25a08c2 | |||
| 8861e61bdf | |||
| 049c2fca8a | |||
| 63df9df913 | |||
| 05b6740e07 | |||
| 46aac0288c | |||
| 4ec0fbd33c | |||
| 7a24d5fdfa | |||
| 3f082ccace | |||
| a37fc3093a | |||
| 4541940a76 | |||
| 3017fe0c95 | |||
| d3bf9a2478 | |||
| 7107672358 | |||
| 8519d6665e | |||
| 774c9e435e | |||
| e1f35a8d9f | |||
| 67136e418c | |||
| 924cc997aa | |||
| 12eda5f507 | |||
| 96bb979abf | |||
| f74ad0323c | |||
| 62fd73f1b1 | |||
| 44f027eb04 | |||
| c9cf6d610b | |||
| 16d4d28046 | |||
| 2280008029 | |||
| a36439314d | |||
| 290b44fbb7 | |||
| 404c280595 | |||
| b0f8370a31 | |||
| 6abcf4ec3c | |||
| db6d7bcefb | |||
| 0e1913b0b4 | |||
| cc6b097dc5 | |||
| c4f7a0c857 | |||
| 34187d76b6 | |||
| 87e7e9fa07 | |||
| 8643fbb65c | |||
| 6a2846afeb | |||
| 7bfa23e2b1 | |||
| bcd55972cd | |||
| d75e1d04b3 | |||
| 02ef77398a | |||
| b0b19053a7 | |||
| 5cc298555a | |||
| f2a0dcca31 | |||
| c274e60868 | |||
| bde6ef8797 | |||
| df15f63424 | |||
| 1bd4a0aa8e | |||
| f068ce4e85 | |||
| 20093c581c | |||
| 814d7bafa8 | |||
| e07fac0335 | |||
| 39730c71ce | |||
| 8565130166 | |||
| 9acde7fe86 | |||
| 63e43e8d20 | |||
| 10a3af8e5e | |||
| 14536febaf | |||
| 75b597418c | |||
| 435730470b | |||
| 689ddf6875 | |||
| fa550f57b3 | |||
| b9b84b661a | |||
| b7573f449f | |||
| 69f6895bd6 | |||
| 72a1e0d5ca | |||
| 4eb80eedc0 | |||
| 32e6931b46 | |||
| f60258ed71 | |||
| 32454ba64a | |||
| de212f49c2 | |||
| c308bd90cb | |||
| 593bde9d92 | |||
| a16bd7030a | |||
| 4d248bce39 | |||
| e236264848 | |||
| 20e9877fe9 | |||
| b0c4021d17 | |||
| 01bfd84853 | |||
| a0dbcc9bb3 | |||
| bbe351161f | |||
| 968f515679 | |||
| cbb5cb3702 | |||
| 82ed1881ea | |||
| 4d13d309d3 | |||
| 75eae0d8ec | |||
| c329541708 | |||
| 10b8e93713 | |||
| 963b1d60b5 | |||
| 158271de14 | |||
| baba63889d | |||
| d52273a516 | |||
| 1b7556443f | |||
| 9575a1158a | |||
| 8ebcc2f8af | |||
| 8d6de76fa0 | |||
| 0ad813cc8d | |||
| 63ae9a90cf | |||
| 551912145e | |||
| 611f54c237 | |||
| 60c9f49b44 | |||
| 9f66003755 | |||
| 862e1d94be | |||
| 8196f76847 | |||
| 09f1bb4653 | |||
| f626a1f0b7 | |||
| fd609d3e19 | |||
| 977e83cc22 | |||
| 59b3cabf7e | |||
| 4d85c36c16 | |||
| b762f80812 | |||
| 4e0791eb22 | |||
| 392e6d1c98 | |||
| 5a49a555ad | |||
| d59cb63188 | |||
| 1d0f87f408 | |||
| a26264e8ce | |||
| ed716d7569 | |||
| f85fca1720 | |||
| ed2539cbfc | |||
| 5405338d20 | |||
| f8ad2fdc11 | |||
| a618f2b523 | |||
| 8b5a88ba5e | |||
| db9e3b44a1 | |||
| 634408d3a3 | |||
| 529a668db3 | |||
| c0f01da1cd | |||
| 4cbab59fdb | |||
| ec9c9fb0f5 | |||
| 286d634756 | |||
| ca2457bfcb | |||
| 459cafdf56 | |||
| b9d6c8f8bb | |||
| 2da019556b | |||
| cbd28bc12f | |||
| 4332f60cc4 | |||
| 950179ee1c | |||
| 803eb4760e | |||
| 32a41e6c1c | |||
| de195c461b | |||
| 5003a8ea4d | |||
| caa41b0022 | |||
| c7151d2b8d | |||
| 0929ae1a4c | |||
| 0c79c42c10 | |||
| 028b24db03 | |||
| bce3d3f664 | |||
| 828d6f6cc8 | |||
| 0a026cc143 | |||
| 3bc9a87933 | |||
| 769f9adc9d | |||
| b5f53d921e | |||
| 105e9e7825 | |||
| c8cf050156 | |||
| b7baafbbe6 | |||
| 85dde71ec3 | |||
| 2970b086a3 | |||
| 5910709008 | |||
| 2b6ce4f813 | |||
| 451c697fb7 | |||
| 09149318b1 | |||
| d2d8eb9485 | |||
| 91265613a9 | |||
| 31c414bbe1 | |||
| e2a3654ed7 | |||
| 96d7283534 | |||
| 256a7e322b | |||
| e5b78337ac | |||
| 67ba5aa1c5 | |||
| 848a617f98 | |||
| 1fc7efef0d | |||
| 576f6eafbb | |||
| 2caf73b5e3 | |||
| 56abb68e0c | |||
| 7aaac5a48a | |||
| 8326587886 | |||
| 466b3f4784 | |||
| bccdf548a8 | |||
| fa4b1b3d5b | |||
| 9d47fd198f | |||
| 5966ee6800 | |||
| 2d20e3c13d | |||
| 2172f8532d | |||
| 9dc4318152 | |||
| e1a92e7127 | |||
| 767b31caa2 | |||
| c2232936e0 | |||
| 4f1bbfd9e3 | |||
| caf57e37dc | |||
| 64b8e4ad6c | |||
| c9d3907124 | |||
| bf6bea800b | |||
| 26f1673d47 | |||
| 08153454a2 | |||
| efc26ab587 | |||
| e24e0a7e87 | |||
| 23bc267c46 | |||
| 35cc592d61 | |||
| 512f6a1166 | |||
| 3160ffec3f | |||
| c543d4517f | |||
| d7334b991b |
@@ -1,9 +1,6 @@
|
||||
dist/
|
||||
node_modules/
|
||||
coverage/
|
||||
webadmin/dist/
|
||||
installer/src/certs/server.key
|
||||
|
||||
# vim swap files
|
||||
*.swp
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Cloudron
|
||||
# Cloudron Dashboard
|
||||
|
||||
[Cloudron](https://cloudron.io) is the best way to run apps on your server.
|
||||
|
||||
@@ -29,7 +29,7 @@ anyone to effortlessly host web applications on their server on their own terms.
|
||||
* Trivially migrate to another server keeping your apps and data (for example, switch your
|
||||
infrastructure provider or move to a bigger server).
|
||||
|
||||
* Comprehensive [REST API](https://cloudron.io/documentation/developer/api/).
|
||||
* Comprehensive [REST API](https://cloudron.io/developer/api/).
|
||||
|
||||
* [CLI](https://cloudron.io/documentation/cli/) to configure apps.
|
||||
|
||||
@@ -59,6 +59,6 @@ the containers in the Cloudron.
|
||||
|
||||
## Community
|
||||
|
||||
* [Chat](https://chat.cloudron.io/)
|
||||
* [Forum](https://forum.cloudron.io/)
|
||||
* [Support](mailto:support@cloudron.io)
|
||||
|
||||
|
||||
@@ -12,26 +12,25 @@ var argv = require('yargs').argv,
|
||||
sass = require('gulp-sass'),
|
||||
serve = require('gulp-serve'),
|
||||
sourcemaps = require('gulp-sourcemaps'),
|
||||
uglify = require('gulp-uglify'),
|
||||
url = require('url');
|
||||
uglify = require('gulp-uglify');
|
||||
|
||||
gulp.task('3rdparty', function () {
|
||||
gulp.src([
|
||||
'webadmin/src/3rdparty/**/*.js',
|
||||
'webadmin/src/3rdparty/**/*.map',
|
||||
'webadmin/src/3rdparty/**/*.css',
|
||||
'webadmin/src/3rdparty/**/*.otf',
|
||||
'webadmin/src/3rdparty/**/*.eot',
|
||||
'webadmin/src/3rdparty/**/*.svg',
|
||||
'webadmin/src/3rdparty/**/*.gif',
|
||||
'webadmin/src/3rdparty/**/*.ttf',
|
||||
'webadmin/src/3rdparty/**/*.woff',
|
||||
'webadmin/src/3rdparty/**/*.woff2'
|
||||
'src/3rdparty/**/*.js',
|
||||
'src/3rdparty/**/*.map',
|
||||
'src/3rdparty/**/*.css',
|
||||
'src/3rdparty/**/*.otf',
|
||||
'src/3rdparty/**/*.eot',
|
||||
'src/3rdparty/**/*.svg',
|
||||
'src/3rdparty/**/*.gif',
|
||||
'src/3rdparty/**/*.ttf',
|
||||
'src/3rdparty/**/*.woff',
|
||||
'src/3rdparty/**/*.woff2'
|
||||
])
|
||||
.pipe(gulp.dest('webadmin/dist/3rdparty/'));
|
||||
.pipe(gulp.dest('dist/3rdparty/'));
|
||||
|
||||
gulp.src('node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js')
|
||||
.pipe(gulp.dest('webadmin/dist/3rdparty/js'));
|
||||
.pipe(gulp.dest('dist/3rdparty/js'));
|
||||
});
|
||||
|
||||
|
||||
@@ -44,6 +43,7 @@ if (argv.help || argv.h) {
|
||||
console.log(' --client-id <clientId>');
|
||||
console.log(' --client-secret <clientSecret>');
|
||||
console.log(' --api-origin <cloudron api uri>');
|
||||
console.log(' --revision <revision>');
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -54,15 +54,17 @@ var oauth = {
|
||||
clientId: argv.clientId || 'cid-webadmin',
|
||||
clientSecret: argv.clientSecret || 'unused',
|
||||
apiOrigin: argv.apiOrigin || '',
|
||||
apiOriginHostname: argv.apiOrigin ? url.parse(argv.apiOrigin).hostname : ''
|
||||
};
|
||||
|
||||
var revision = argv.revision || '';
|
||||
|
||||
console.log();
|
||||
console.log('Using OAuth credentials:');
|
||||
console.log(' ClientId: %s', oauth.clientId);
|
||||
console.log(' ClientSecret: %s', oauth.clientSecret);
|
||||
console.log(' Cloudron API: %s', oauth.apiOrigin || 'default');
|
||||
console.log(' Cloudron Host: %s', oauth.apiOriginHostname);
|
||||
console.log();
|
||||
console.log('Building for revision: %s', revision);
|
||||
console.log();
|
||||
|
||||
|
||||
@@ -74,18 +76,18 @@ gulp.task('js-index', function () {
|
||||
});
|
||||
|
||||
gulp.src([
|
||||
'webadmin/src/js/index.js',
|
||||
'webadmin/src/js/client.js',
|
||||
'webadmin/src/js/appstore.js',
|
||||
'webadmin/src/js/main.js',
|
||||
'webadmin/src/views/*.js'
|
||||
'src/js/index.js',
|
||||
'src/js/client.js',
|
||||
'src/js/appstore.js',
|
||||
'src/js/main.js',
|
||||
'src/views/*.js'
|
||||
])
|
||||
.pipe(ejs({ oauth: oauth }, {}, { ext: '.js' }))
|
||||
.pipe(ejs({ oauth: oauth, revision: revision }, {}, { ext: '.js' }))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(concat('index.js', { newLine: ';' }))
|
||||
.pipe(uglifyer)
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('webadmin/dist/js'));
|
||||
.pipe(gulp.dest('dist/js'));
|
||||
});
|
||||
|
||||
gulp.task('js-logs', function () {
|
||||
@@ -95,13 +97,13 @@ gulp.task('js-logs', function () {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
gulp.src(['webadmin/src/js/logs.js', 'webadmin/src/js/client.js'])
|
||||
gulp.src(['src/js/logs.js', 'src/js/client.js'])
|
||||
.pipe(ejs({ oauth: oauth }, {}, { ext: '.js' }))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(concat('logs.js', { newLine: ';' }))
|
||||
.pipe(uglifyer)
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('webadmin/dist/js'));
|
||||
.pipe(gulp.dest('dist/js'));
|
||||
});
|
||||
|
||||
gulp.task('js-terminal', function () {
|
||||
@@ -111,13 +113,13 @@ gulp.task('js-terminal', function () {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
gulp.src(['webadmin/src/js/terminal.js', 'webadmin/src/js/client.js'])
|
||||
gulp.src(['src/js/terminal.js', 'src/js/client.js'])
|
||||
.pipe(ejs({ oauth: oauth }, {}, { ext: '.js' }))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(concat('terminal.js', { newLine: ';' }))
|
||||
.pipe(uglifyer)
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('webadmin/dist/js'));
|
||||
.pipe(gulp.dest('dist/js'));
|
||||
});
|
||||
|
||||
gulp.task('js-setup', function () {
|
||||
@@ -127,13 +129,13 @@ gulp.task('js-setup', function () {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
gulp.src(['webadmin/src/js/setup.js', 'webadmin/src/js/client.js'])
|
||||
gulp.src(['src/js/setup.js', 'src/js/client.js'])
|
||||
.pipe(ejs({ oauth: oauth }, {}, { ext: '.js' }))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(concat('setup.js', { newLine: ';' }))
|
||||
.pipe(uglifyer)
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('webadmin/dist/js'));
|
||||
.pipe(gulp.dest('dist/js'));
|
||||
});
|
||||
|
||||
gulp.task('js-setupdns', function () {
|
||||
@@ -143,13 +145,13 @@ gulp.task('js-setupdns', function () {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
gulp.src(['webadmin/src/js/setupdns.js', 'webadmin/src/js/client.js'])
|
||||
gulp.src(['src/js/setupdns.js', 'src/js/client.js'])
|
||||
.pipe(ejs({ oauth: oauth }, {}, { ext: '.js' }))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(concat('setupdns.js', { newLine: ';' }))
|
||||
.pipe(uglifyer)
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('webadmin/dist/js'));
|
||||
.pipe(gulp.dest('dist/js'));
|
||||
});
|
||||
|
||||
gulp.task('js-restore', function () {
|
||||
@@ -159,13 +161,13 @@ gulp.task('js-restore', function () {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
gulp.src(['webadmin/src/js/restore.js', 'webadmin/src/js/client.js'])
|
||||
gulp.src(['src/js/restore.js', 'src/js/client.js'])
|
||||
.pipe(ejs({ oauth: oauth }, {}, { ext: '.js' }))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(concat('restore.js', { newLine: ';' }))
|
||||
.pipe(uglifyer)
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('webadmin/dist/js'));
|
||||
.pipe(gulp.dest('dist/js'));
|
||||
});
|
||||
|
||||
|
||||
@@ -176,11 +178,11 @@ gulp.task('js-update', function () {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
gulp.src(['webadmin/src/js/update.js'])
|
||||
gulp.src(['src/js/update.js'])
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(uglifyer)
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('webadmin/dist/js'));
|
||||
.pipe(gulp.dest('dist/js'));
|
||||
});
|
||||
|
||||
|
||||
@@ -189,15 +191,15 @@ gulp.task('js-update', function () {
|
||||
// --------------
|
||||
|
||||
gulp.task('html', ['html-views', 'html-templates'], function () {
|
||||
return gulp.src('webadmin/src/*.html').pipe(ejs({ apiOriginHostname: oauth.apiOriginHostname }, {}, { ext: '.html' })).pipe(gulp.dest('webadmin/dist'));
|
||||
return gulp.src('src/*.html').pipe(ejs({ revision: revision }, {}, { ext: '.html' })).pipe(gulp.dest('dist'));
|
||||
});
|
||||
|
||||
gulp.task('html-views', function () {
|
||||
return gulp.src('webadmin/src/views/**/*.html').pipe(gulp.dest('webadmin/dist/views'));
|
||||
return gulp.src('src/views/**/*.html').pipe(gulp.dest('dist/views'));
|
||||
});
|
||||
|
||||
gulp.task('html-templates', function () {
|
||||
return gulp.src('webadmin/src/templates/**/*.html').pipe(gulp.dest('webadmin/dist/templates'));
|
||||
return gulp.src('src/templates/**/*.html').pipe(gulp.dest('dist/templates'));
|
||||
});
|
||||
|
||||
// --------------
|
||||
@@ -205,18 +207,18 @@ gulp.task('html-templates', function () {
|
||||
// --------------
|
||||
|
||||
gulp.task('css', function () {
|
||||
return gulp.src('webadmin/src/*.scss')
|
||||
return gulp.src('src/*.scss')
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(sass({ includePaths: ['node_modules/bootstrap-sass/assets/stylesheets/'] }).on('error', sass.logError))
|
||||
.pipe(autoprefixer())
|
||||
.pipe(cssnano())
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest('webadmin/dist'));
|
||||
.pipe(gulp.dest('dist'));
|
||||
});
|
||||
|
||||
gulp.task('images', function () {
|
||||
return gulp.src('webadmin/src/img/**')
|
||||
.pipe(gulp.dest('webadmin/dist/img'));
|
||||
return gulp.src('src/img/**')
|
||||
.pipe(gulp.dest('dist/img'));
|
||||
});
|
||||
|
||||
// --------------
|
||||
@@ -224,25 +226,25 @@ gulp.task('images', function () {
|
||||
// --------------
|
||||
|
||||
gulp.task('watch', ['default'], function () {
|
||||
gulp.watch(['webadmin/src/*.scss'], ['css']);
|
||||
gulp.watch(['webadmin/src/img/*'], ['images']);
|
||||
gulp.watch(['webadmin/src/**/*.html'], ['html']);
|
||||
gulp.watch(['webadmin/src/views/*.html'], ['html-views']);
|
||||
gulp.watch(['webadmin/src/templates/*.html'], ['html-templates']);
|
||||
gulp.watch(['webadmin/src/js/update.js'], ['js-update']);
|
||||
gulp.watch(['webadmin/src/js/setup.js', 'webadmin/src/js/client.js'], ['js-setup']);
|
||||
gulp.watch(['webadmin/src/js/setupdns.js', 'webadmin/src/js/client.js'], ['js-setupdns']);
|
||||
gulp.watch(['webadmin/src/js/restore.js', 'webadmin/src/js/client.js'], ['js-restore']);
|
||||
gulp.watch(['webadmin/src/js/logs.js', 'webadmin/src/js/client.js'], ['js-logs']);
|
||||
gulp.watch(['webadmin/src/js/terminal.js', 'webadmin/src/js/client.js'], ['js-terminal']);
|
||||
gulp.watch(['webadmin/src/js/index.js', 'webadmin/src/js/client.js', 'webadmin/src/js/appstore.js', 'webadmin/src/js/main.js', 'webadmin/src/views/*.js'], ['js-index']);
|
||||
gulp.watch(['webadmin/src/3rdparty/**/*'], ['3rdparty']);
|
||||
gulp.watch(['src/*.scss'], ['css']);
|
||||
gulp.watch(['src/img/*'], ['images']);
|
||||
gulp.watch(['src/**/*.html'], ['html']);
|
||||
gulp.watch(['src/views/*.html'], ['html-views']);
|
||||
gulp.watch(['src/templates/*.html'], ['html-templates']);
|
||||
gulp.watch(['src/js/update.js'], ['js-update']);
|
||||
gulp.watch(['src/js/setup.js', 'src/js/client.js'], ['js-setup']);
|
||||
gulp.watch(['src/js/setupdns.js', 'src/js/client.js'], ['js-setupdns']);
|
||||
gulp.watch(['src/js/restore.js', 'src/js/client.js'], ['js-restore']);
|
||||
gulp.watch(['src/js/logs.js', 'src/js/client.js'], ['js-logs']);
|
||||
gulp.watch(['src/js/terminal.js', 'src/js/client.js'], ['js-terminal']);
|
||||
gulp.watch(['src/js/index.js', 'src/js/client.js', 'src/js/appstore.js', 'src/js/main.js', 'src/views/*.js'], ['js-index']);
|
||||
gulp.watch(['src/3rdparty/**/*'], ['3rdparty']);
|
||||
});
|
||||
|
||||
gulp.task('clean', function () {
|
||||
rimraf.sync('webadmin/dist');
|
||||
rimraf.sync('dist');
|
||||
});
|
||||
|
||||
gulp.task('default', ['clean', 'html', 'js', '3rdparty', 'images', 'css'], function () {});
|
||||
|
||||
gulp.task('develop', ['watch'], serve({ root: 'webadmin/dist', port: 4000 }));
|
||||
gulp.task('develop', ['watch'], serve({ root: 'dist', port: 4000 }));
|
||||
|
||||
@@ -1,111 +1,28 @@
|
||||
{
|
||||
"name": "cloudron",
|
||||
"description": "Main code for a cloudron",
|
||||
"name": "dashboard",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"author": {
|
||||
"name": "Cloudron authors"
|
||||
"description": "[Cloudron](https://cloudron.io) is the best way to run apps on your server.",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.cloudron.io/cloudron/box.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0 <=4.1.1"
|
||||
"url": "ssh://git@git.cloudron.io:6000/cloudron/dashboard.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"dependencies": {
|
||||
"@google-cloud/dns": "^0.7.0",
|
||||
"@google-cloud/storage": "^1.2.1",
|
||||
"@sindresorhus/df": "^2.1.0",
|
||||
"async": "^2.6.0",
|
||||
"aws-sdk": "^2.151.0",
|
||||
"body-parser": "^1.18.2",
|
||||
"cloudron-manifestformat": "^2.10.0",
|
||||
"connect-ensure-login": "^0.1.1",
|
||||
"connect-lastmile": "^1.0.2",
|
||||
"connect-timeout": "^1.9.0",
|
||||
"cookie-parser": "^1.3.5",
|
||||
"cookie-session": "^1.3.2",
|
||||
"cron": "^1.3.0",
|
||||
"csurf": "^1.6.6",
|
||||
"db-migrate": "^0.10.0-beta.24",
|
||||
"db-migrate-mysql": "^1.1.10",
|
||||
"debug": "^3.1.0",
|
||||
"dockerode": "^2.5.3",
|
||||
"ejs": "^2.5.7",
|
||||
"ejs-cli": "^2.0.0",
|
||||
"express": "^4.16.2",
|
||||
"express-session": "^1.15.6",
|
||||
"hat": "0.0.3",
|
||||
"json": "^9.0.3",
|
||||
"ldapjs": "^1.0.0",
|
||||
"lodash.chunk": "^4.2.0",
|
||||
"mime": "^2.0.3",
|
||||
"moment-timezone": "^0.5.14",
|
||||
"morgan": "^1.9.0",
|
||||
"multiparty": "^4.1.2",
|
||||
"mysql": "^2.15.0",
|
||||
"nodemailer": "^4.4.0",
|
||||
"nodemailer-smtp-transport": "^2.7.4",
|
||||
"oauth2orize": "^1.11.0",
|
||||
"once": "^1.3.2",
|
||||
"parse-links": "^0.1.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-http": "^0.3.0",
|
||||
"passport-http-bearer": "^1.0.1",
|
||||
"passport-local": "^1.0.0",
|
||||
"passport-oauth2-client-password": "^0.1.2",
|
||||
"password-generator": "^2.2.0",
|
||||
"progress-stream": "^2.0.0",
|
||||
"proxy-middleware": "^0.15.0",
|
||||
"recursive-readdir": "^2.2.1",
|
||||
"request": "^2.83.0",
|
||||
"s3-block-read-stream": "^0.2.0",
|
||||
"safetydance": "^0.7.1",
|
||||
"semver": "^5.4.1",
|
||||
"showdown": "^1.8.2",
|
||||
"split": "^1.0.0",
|
||||
"superagent": "^3.8.1",
|
||||
"supererror": "^0.7.1",
|
||||
"tar-fs": "^1.16.0",
|
||||
"tar-stream": "^1.5.5",
|
||||
"tldjs": "^2.2.0",
|
||||
"underscore": "^1.7.0",
|
||||
"uuid": "^3.1.0",
|
||||
"valid-url": "^1.0.9",
|
||||
"validator": "^9.1.1",
|
||||
"ws": "^3.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bootstrap-sass": "^3.3.3",
|
||||
"expect.js": "*",
|
||||
"bootstrap-sass": "^3.3.7",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-autoprefixer": "^4.0.0",
|
||||
"gulp-concat": "^2.4.3",
|
||||
"gulp-cssnano": "^2.1.0",
|
||||
"gulp-ejs": "^3.1.0",
|
||||
"gulp-sass": "^3.1.0",
|
||||
"gulp-serve": "^1.0.0",
|
||||
"gulp-sourcemaps": "^2.6.1",
|
||||
"gulp-autoprefixer": "^5.0.0",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-cssnano": "^2.1.3",
|
||||
"gulp-ejs": "^3.1.2",
|
||||
"gulp-sass": "^4.0.1",
|
||||
"gulp-serve": "^1.4.0",
|
||||
"gulp-sourcemaps": "^2.6.4",
|
||||
"gulp-uglify": "^3.0.0",
|
||||
"hock": "^1.3.2",
|
||||
"istanbul": "*",
|
||||
"js2xmlparser": "^3.0.0",
|
||||
"mocha": "*",
|
||||
"mock-aws-s3": "git+https://github.com/cloudron-io/mock-aws-s3.git",
|
||||
"nock": "^9.0.14",
|
||||
"node-sass": "^4.6.1",
|
||||
"readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"scripts": {
|
||||
"migrate_local": "DATABASE_URL=mysql://root:@localhost/box node_modules/.bin/db-migrate up",
|
||||
"migrate_test": "BOX_ENV=test DATABASE_URL=mysql://root:@localhost/boxtest node_modules/.bin/db-migrate up",
|
||||
"test": "npm run migrate_test && src/test/setupTest && BOX_ENV=test ./node_modules/istanbul/lib/cli.js test $1 ./node_modules/mocha/bin/_mocha -- --exit -R spec ./src/test ./src/routes/test/[^a]*",
|
||||
"test_all": "npm run migrate_test && src/test/setupTest && BOX_ENV=test ./node_modules/istanbul/lib/cli.js test $1 ./node_modules/mocha/bin/_mocha -- --exit -R spec ./src/test ./src/routes/test",
|
||||
"postmerge": "/bin/true",
|
||||
"precommit": "/bin/true",
|
||||
"prepush": "npm test",
|
||||
"webadmin": "node_modules/.bin/gulp"
|
||||
"rimraf": "^2.6.2",
|
||||
"yargs": "^11.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 434 KiB |
@@ -68,7 +68,7 @@
|
||||
<footer class="text-center">
|
||||
<span class="text-muted"><a href="https://cloudron.io" target="_blank">Cloudron</a></span>
|
||||
<span class="text-muted"><a href="https://twitter.com/cloudron_io" target="_blank">Twitter</a></span>
|
||||
<span class="text-muted"><a href="https://chat.cloudron.io" target="_blank">Chat <i class="fa fa-comments"></i></a></span>
|
||||
<span class="text-muted"><a href="https://forum.cloudron.io" target="_blank">Forum <i class="fa fa-comments"></i></a></span>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
@@ -3,27 +3,26 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'unsafe-inline' 'unsafe-eval' 'self' <%= apiOriginHostname %>; img-src 'self' <%= apiOriginHostname %>;" />
|
||||
|
||||
<title> Cloudron Error </title>
|
||||
|
||||
<link id="favicon" href="/api/v1/cloudron/avatar" rel="icon" type="image/png">
|
||||
<link id="favicon" type="image/png" rel="icon" href="/api/v1/cloudron/avatar">
|
||||
|
||||
<!-- Theme CSS -->
|
||||
<link href="theme.css" rel="stylesheet" type="text/css">
|
||||
<link type="text/css" rel="stylesheet" href="/theme.css">
|
||||
|
||||
<!-- external fonts and CSS -->
|
||||
<link href="3rdparty/css/font-awesome.min.css" rel="stylesheet" rel="stylesheet" type="text/css">
|
||||
<link type="text/css" rel="stylesheet" href="/3rdparty/css/font-awesome.min.css">
|
||||
|
||||
<!-- jQuery-->
|
||||
<script src="3rdparty/js/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/jquery.min.js"></script>
|
||||
|
||||
<!-- Bootstrap Core JavaScript -->
|
||||
<script src="3rdparty/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/bootstrap.min.js"></script>
|
||||
|
||||
<!-- Angularjs scripts -->
|
||||
<script src="3rdparty/js/angular.min.js"></script>
|
||||
<script src="3rdparty/js/angular-loader.min.js"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular.min.js"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-loader.min.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -92,7 +91,7 @@
|
||||
<footer class="text-center">
|
||||
<span class="text-muted">©2018 <a href="https://cloudron.io" target="_blank">Cloudron</a></span>
|
||||
<span class="text-muted"><a href="https://twitter.com/cloudron_io" target="_blank">Twitter <i class="fa fa-twitter"></i></a></span>
|
||||
<span class="text-muted"><a href="https://chat.cloudron.io" target="_blank">Chat <i class="fa fa-comments"></i></a></span>
|
||||
<span class="text-muted"><a href="https://forum.cloudron.io" target="_blank">Forum <i class="fa fa-comments"></i></a></span>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,187 @@
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="Application" ng-controller="MainController">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
|
||||
|
||||
<!-- this gets changed once we get the config (because angular has not loaded yet, we see template string for a flash) -->
|
||||
<title> Cloudron </title>
|
||||
|
||||
<link id="favicon" type="image/png" rel="icon" href="/api/v1/cloudron/avatar">
|
||||
|
||||
<!-- CSS -->
|
||||
<link type="text/css" rel="stylesheet" href="/3rdparty/slick.css?<%= revision %>"/>
|
||||
<link type="text/css" rel="stylesheet" href="/3rdparty/angular-ui-notification.min.css?<%= revision %>"/>
|
||||
<link type="text/css" rel="stylesheet" href="/3rdparty/bootstrap-slider/bootstrap-slider.min.css?<%= revision %>"/>
|
||||
<link type="text/css" rel="stylesheet" href="/theme.css?<%= revision %>">
|
||||
|
||||
<!-- Custom Fonts -->
|
||||
<link type="text/css" rel="stylesheet" href="/3rdparty/css/font-awesome.min.css?<%= revision %>">
|
||||
|
||||
<!-- jQuery-->
|
||||
<script type="text/javascript" src="/3rdparty/js/jquery.min.js?<%= revision %>"></script>
|
||||
|
||||
<!-- toBlob() polyfill-->
|
||||
<script type="text/javascript" src="/3rdparty/js/canvas-to-blob.min.js?<%= revision %>"></script>
|
||||
|
||||
<!-- Bootstrap Core JavaScript -->
|
||||
<script type="text/javascript" src="/3rdparty/js/bootstrap.min.js?<%= revision %>"></script>
|
||||
|
||||
<!-- Slick carousel -->
|
||||
<script type="text/javascript" src="/3rdparty/js/slick.js?<%= revision %>"></script>
|
||||
|
||||
<!-- Angularjs scripts -->
|
||||
<script type="text/javascript" src="/3rdparty/js/angular.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-loader.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-route.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-animate.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-base64.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-md5.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-sanitize.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-slick.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-ui-notification.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-fittext.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/autofill-event.js?<%= revision %>"></script>
|
||||
|
||||
<!-- Angular directives for tldjs -->
|
||||
<script type="text/javascript" src="/3rdparty/js/tld.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-tld.js?<%= revision %>"></script>
|
||||
|
||||
<!-- Angular directives for bootstrap https://angular-ui.github.io/bootstrap/ -->
|
||||
<script type="text/javascript" src="/3rdparty/js/ui-bootstrap-tpls-1.3.3.min.js?<%= revision %>"></script>
|
||||
|
||||
<script type="text/javascript" src="/3rdparty/js/Chart.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/ansi_up.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/clipboard.min.js?<%= revision %>"></script>
|
||||
|
||||
<!-- Showdown (markdown converter) -->
|
||||
<script type="text/javascript" src="/3rdparty/js/showdown-1.6.4.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/js/showdown-target-blank.min.js?<%= revision %>"></script>
|
||||
|
||||
<!-- Bootstrap slider -->
|
||||
<script type="text/javascript" src="/3rdparty/bootstrap-slider/bootstrap-slider.min.js?<%= revision %>"></script>
|
||||
<script type="text/javascript" src="/3rdparty/bootstrap-slider/slider.js?<%= revision %>"></script>
|
||||
|
||||
<!-- Anugular Multiselect https://github.com/sebastianha/angular-bootstrap-multiselect -->
|
||||
<script type="text/javascript" src="/3rdparty/js/angular-bootstrap-multiselect.js?<%= revision %>"></script>
|
||||
|
||||
<!-- colors -->
|
||||
<script type="text/javascript" src="/3rdparty/js/colors.js?<%= revision %>"></script>
|
||||
|
||||
<!-- moment -->
|
||||
<script type="text/javascript" src="/3rdparty/js/moment.min.js?<%= revision %>"></script>
|
||||
|
||||
<!-- Main Application -->
|
||||
<script type="text/javascript" src="/js/index.js?<%= revision %>"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/ng-template" id="notification.html">
|
||||
<div class="ui-notification">
|
||||
<h3 ng-show="title" ng-bind-html="title"></h3>
|
||||
<div class="message">
|
||||
<a href="{{action}}" ng-show="action" ng-bind-html="message"></a>
|
||||
<span ng-hide="action" ng-bind-html="message"></span>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Modal setup subscription -->
|
||||
<div class="modal fade" id="setupSubscriptionModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Setup Subscription</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p ng-show="config.update.box">
|
||||
You can update to the next version once you have <a ng-href="{{ config.webServerOrigin + '/console.html#/userprofile?view=subscriptions&email=' + appstoreConfig.profile.emailEncoded + '&cloudronId=' + appstoreConfig.cloudronId }}" target="_blank">setup billing</a>.
|
||||
</p>
|
||||
<p>
|
||||
Our paid plans allow you to install more apps and create more users.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn btn-success" ng-click="waitForPlanSelection()" ng-href="{{ config.webServerOrigin + '/console.html#/userprofile?view=subscriptions&email=' + appstoreConfig.profile.emailEncoded + '&cloudronId=' + appstoreConfig.cloudronId }}" target="_blank" ng-disabled="waitingForPlanSelection"><i class="fa fa-circle-o-notch fa-spin" ng-show="waitingForPlanSelection"></i> Setup Subscription</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="animateMe ng-hide layout-root" ng-show="initialized">
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav class="navbar navbar-default navbar-static-top shadow" role="navigation" style="margin-bottom: 0">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand navbar-brand-icon" href="#/"><img ng-src="{{ client.avatar }}" width="40" height="40"/></a>
|
||||
<a class="navbar-brand" href="#/">{{ config.cloudronName || 'Cloudron' }}</a>
|
||||
</div>
|
||||
<!-- /.navbar-header -->
|
||||
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav navbar-right" ng-hide="hideNavBarActions">
|
||||
<li ng-show="ready && subscription.plan.id === 'free'">
|
||||
<a ng-href="" ng-click="showSubscriptionModal()" style="cursor: pointer">
|
||||
<!-- trial expired -->
|
||||
<span class="badge badge-success">Setup Subscription</span>
|
||||
</a>
|
||||
</li>
|
||||
<li ng-show="ready && subscription && subscription.status === 'trialing' && !appstoreConfig.profile.billing">
|
||||
<a ng-href="{{ config.webServerOrigin + '/console.html#/userprofile?view=credit_card&email=' + appstoreConfig.profile.emailEncoded }}" target="_blank">
|
||||
<!-- in trial -->
|
||||
<span class="badge badge-success">Setup Subscription</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a ng-class="{ active: isActive('/apps')}" href="#/apps"><i class="fa fa-cloud-download fa-fw"></i> My Apps</a>
|
||||
</li>
|
||||
<li ng-show="user.admin">
|
||||
<a ng-class="{ active: isActive('/appstore')}" href="#/appstore"><i class="fa fa-th-large fa-fw"></i> App Store</a>
|
||||
</li>
|
||||
<li ng-show="user.admin">
|
||||
<a ng-class="{ active: isActive('/users')}" href="#/users"><i class="fa fa-users fa-fw"></i> Users</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><img ng-src="{{user.gravatar}}" style="margin-top: -4px;"/> {{user.username}} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="#/account"><i class="fa fa-user fa-fw"></i> Account</a></li>
|
||||
<li ng-show="user.admin"><a href="#/activity"><i class="fa fa-list-alt fa-fw"></i> Activity</a></li>
|
||||
<li ng-show="user.admin"><a href="#/tokens"><i class="fa fa-key fa-fw"></i> API Access</a></li>
|
||||
<li ng-show="user.admin"><a href="#/backups"><i class="fa fa-archive fa-fw"></i> Backups</a></li>
|
||||
<li ng-show="user.admin"><a href="#/domains"><i class="fa fa-globe fa-fw"></i> Domains</a></li>
|
||||
<li ng-show="user.admin"><a href="#/email"><i class="fa fa-envelope fa-fw"></i> Email</a></li>
|
||||
<li ng-show="user.admin"><a href="#/graphs"><i class="fa fa-bar-chart fa-fw"></i> Graphs</a></li>
|
||||
<li ng-show="user.admin"><a href="#/settings"><i class="fa fa-wrench fa-fw"></i> Settings</a></li>
|
||||
<li ng-show="user.admin" class="divider"></li>
|
||||
<li ng-show="user.admin"><a href="#/support"><i class="fa fa-comment fa-fw"></i> Support</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="" ng-click="logout($event)"><i class="fa fa-sign-out fa-fw"></i> Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div ng-view id="ng-view" class="layout-content"></div>
|
||||
|
||||
<footer class="text-center ng-cloak">
|
||||
<span class="text-muted">© 2018 <a href="https://cloudron.io" target="_blank">Cloudron</a></span>
|
||||
<span class="text-muted"> v{{config.version}}</span>
|
||||
<span class="text-muted"><a href="https://twitter.com/cloudron_io" target="_blank">Twitter <i class="fa fa-twitter"></i></a></span>
|
||||
<span class="text-muted"><a href="https://forum.cloudron.io" target="_blank">Forum <i class="fa fa-comments"></i></a></span>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -143,13 +143,14 @@ angular.module('Application').service('AppStore', ['$http', '$base64', 'Client',
|
||||
});
|
||||
};
|
||||
|
||||
AppStore.prototype.login = function (email, password, callback) {
|
||||
AppStore.prototype.login = function (email, password, totpToken, callback) {
|
||||
if (Client.getConfig().apiServerOrigin === null) return callback(new AppStoreError(420, 'Enhance Your Calm'));
|
||||
|
||||
var data = {
|
||||
email: email,
|
||||
password: password,
|
||||
persistent: true
|
||||
persistent: true,
|
||||
totpToken: totpToken
|
||||
};
|
||||
|
||||
$http.post(Client.getConfig().apiServerOrigin + '/api/v1/login', data).success(function (data, status) {
|
||||
@@ -176,6 +177,10 @@ angular.module('Application').service('AppStore', ['$http', '$base64', 'Client',
|
||||
|
||||
$http.get(Client.getConfig().apiServerOrigin + '/api/v1/profile', { params: { accessToken: token }}).success(function (data, status) {
|
||||
if (status !== 200) return callback(new AppStoreError(status, data));
|
||||
|
||||
// just some helper property, since angular bindings cannot dot his easily
|
||||
data.profile.emailEncoded = encodeURIComponent(data.profile.email);
|
||||
|
||||
return callback(null, data.profile);
|
||||
}).error(function (data, status) {
|
||||
return callback(new AppStoreError(status, data));
|
||||
@@ -111,7 +111,8 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
id: null,
|
||||
username: null,
|
||||
email: null,
|
||||
admin: false
|
||||
admin: false,
|
||||
twoFactorAuthenticationEnabled: false
|
||||
};
|
||||
this._config = {
|
||||
apiServerOrigin: null,
|
||||
@@ -151,6 +152,10 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
Notification.error({ title: 'Cloudron Error', message: message });
|
||||
};
|
||||
|
||||
Client.prototype.clearNotifications = function () {
|
||||
Notification.clearAll();
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Example usage with an action:
|
||||
@@ -161,10 +166,10 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
Client.notify('title', 'message', true, actionScope);
|
||||
|
||||
*/
|
||||
Client.prototype.notify = function (title, message, persitent, type, actionScope) {
|
||||
Client.prototype.notify = function (title, message, persistent, type, actionScope) {
|
||||
var options = { title: title, message: message};
|
||||
|
||||
if (persitent) options.delay = 'never'; // any non Number means never timeout
|
||||
if (persistent) options.delay = 'never'; // any non Number means never timeout
|
||||
|
||||
if (actionScope) {
|
||||
if (typeof actionScope.action !== 'string') throw('an actionScope has to have an action url');
|
||||
@@ -220,6 +225,8 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
this._userInfo.fallbackEmail = userInfo.fallbackEmail;
|
||||
this._userInfo.displayName = userInfo.displayName;
|
||||
this._userInfo.admin = !!userInfo.admin;
|
||||
this._userInfo.twoFactorAuthenticationEnabled = userInfo.twoFactorAuthenticationEnabled;
|
||||
this._userInfo.scope = userInfo.scope;
|
||||
this._userInfo.gravatar = 'https://www.gravatar.com/avatar/' + md5.createHash(userInfo.email) + '.jpg?s=24&d=mm';
|
||||
this._userInfo.gravatarHuge = 'https://www.gravatar.com/avatar/' + md5.createHash(userInfo.email) + '.jpg?s=128&d=mm';
|
||||
};
|
||||
@@ -261,11 +268,17 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
return token;
|
||||
};
|
||||
|
||||
Client.prototype.hasScope = function (scope) {
|
||||
return this.getUserInfo().scope.split(',').indexOf(scope) !== -1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Rest API wrappers
|
||||
*/
|
||||
Client.prototype.config = function (callback) {
|
||||
get('/api/v1/cloudron/config').success(function(data, status) {
|
||||
var configRoute = this.hasScope('cloudron') ? '/api/v1/cloudron/config' : '/api/v1/user/cloudron_config';
|
||||
|
||||
get(configRoute).success(function(data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
@@ -329,6 +342,21 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.cloneApp = function (appId, config, callback) {
|
||||
var data = {
|
||||
location: config.location,
|
||||
domain: config.domain,
|
||||
portBindings: config.portBindings,
|
||||
backupId: config.backupId
|
||||
};
|
||||
|
||||
post('/api/v1/apps/' + appId + '/clone', data).success(function (data, status) {
|
||||
if (status !== 201 || typeof data !== 'object') return defaultErrorHandler(callback);
|
||||
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.restoreApp = function (appId, backupId, password, callback) {
|
||||
var data = { password: password, backupId: backupId };
|
||||
post('/api/v1/apps/' + appId + '/restore', data).success(function (data, status) {
|
||||
@@ -337,6 +365,14 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.backupApp = function (appId, callback) {
|
||||
var data = { };
|
||||
post('/api/v1/apps/' + appId + '/backup', data).success(function (data, status) {
|
||||
if (status !== 202) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.uninstallApp = function (appId, password, callback) {
|
||||
var data = { password: password };
|
||||
post('/api/v1/apps/' + appId + '/uninstall', data).success(function (data, status) {
|
||||
@@ -355,12 +391,13 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
cert: config.cert,
|
||||
key: config.key,
|
||||
memoryLimit: config.memoryLimit,
|
||||
altDomain: config.altDomain || null,
|
||||
xFrameOptions: config.xFrameOptions,
|
||||
robotsTxt: config.robotsTxt || null,
|
||||
enableBackup: config.enableBackup
|
||||
};
|
||||
|
||||
if ('mailboxName' in config) data.mailboxName = config.mailboxName;
|
||||
|
||||
post('/api/v1/apps/' + id + '/configure', data).success(function (data, status) {
|
||||
if (status !== 202) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
@@ -453,30 +490,38 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.setAutoupdatePattern = function (pattern, callback) {
|
||||
post('/api/v1/settings/autoupdate_pattern', { pattern: pattern }).success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.checkForUpdates = function (callback) {
|
||||
var that = this;
|
||||
|
||||
if (that._refreshConfigTimer) $interval.cancel(that._refreshConfigTimer);
|
||||
that._refreshConfigTimer = null;
|
||||
|
||||
post('/api/v1/cloudron/check_for_updates', { }).success(function(data, status) {
|
||||
post('/api/v1/cloudron/check_for_updates', {}).success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
that.refreshConfig(callback);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
that._refreshConfigTimer = $interval(that.refreshConfig.bind(that), 5000, 20 /* 20 times */);
|
||||
|
||||
Client.prototype.setAppAutoupdatePattern = function (pattern, callback) {
|
||||
post('/api/v1/settings/app_autoupdate_pattern', { pattern: pattern }).success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getAutoupdatePattern = function (callback) {
|
||||
get('/api/v1/settings/autoupdate_pattern').success(function(data, status) {
|
||||
Client.prototype.getAppAutoupdatePattern = function (callback) {
|
||||
get('/api/v1/settings/app_autoupdate_pattern').success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.setBoxAutoupdatePattern = function (pattern, callback) {
|
||||
post('/api/v1/settings/box_autoupdate_pattern', { pattern: pattern }).success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getBoxAutoupdatePattern = function (callback) {
|
||||
get('/api/v1/settings/box_autoupdate_pattern').success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
@@ -546,10 +591,10 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getEventLogs = function (action, search, page, perPage, callback) {
|
||||
Client.prototype.getEventLogs = function (actions, search, page, perPage, callback) {
|
||||
var config = {
|
||||
params: {
|
||||
action: action,
|
||||
actions: actions,
|
||||
search: search,
|
||||
page: page,
|
||||
per_page: perPage
|
||||
@@ -563,12 +608,12 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getPlatformLogs = function (units, follow, lines, callback) {
|
||||
Client.prototype.getPlatformLogs = function (unit, follow, lines, callback) {
|
||||
if (follow) {
|
||||
var eventSource = new EventSource(client.apiOrigin + '/api/v1/cloudron/logstream?lines=' + lines + '&access_token=' + token + '&units=' + units);
|
||||
var eventSource = new EventSource(client.apiOrigin + '/api/v1/cloudron/logstream/' + unit + '?lines=' + lines + '&access_token=' + token);
|
||||
callback(null, eventSource);
|
||||
} else {
|
||||
get('/api/v1/cloudron/logs?lines=100&units=' + units).success(function (data, status) {
|
||||
get('/api/v1/cloudron/logs/' + unit + '?lines=100').success(function (data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
@@ -582,6 +627,13 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getAppsByUser = function (callback) {
|
||||
get('/api/v1/user/apps').success(function (data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data.apps);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getAppLogs = function (appId, follow, lines, callback) {
|
||||
if (follow) {
|
||||
var eventSource = new EventSource(client.apiOrigin + '/api/v1/apps/' + appId + '/logstream?lines=' + lines + '&access_token=' + token);
|
||||
@@ -718,14 +770,14 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
if (status !== 201 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
|
||||
that.setToken(data.token);
|
||||
that.setUserInfo({ username: username, email: email, admin: true });
|
||||
that.setUserInfo({ username: username, email: email, admin: true, twoFactorAuthenticationEnabled: false });
|
||||
|
||||
callback(null, data.activated);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getOAuthClients = function (callback) {
|
||||
get('/api/v1/oauth/clients').success(function(data, status) {
|
||||
get('/api/v1/clients').success(function(data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data.clients);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
@@ -738,42 +790,46 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
redirectURI: redirectURI
|
||||
};
|
||||
|
||||
post('/api/v1/oauth/clients', data).success(function(data, status) {
|
||||
post('/api/v1/clients', data).success(function(data, status) {
|
||||
if (status !== 201 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data.clients);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.delOAuthClient = function (id, callback) {
|
||||
del('/api/v1/oauth/clients/' + id).success(function(data, status) {
|
||||
del('/api/v1/clients/' + id).success(function(data, status) {
|
||||
if (status !== 204) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.createTokenByClientId = function (id, expiresAt, callback) {
|
||||
post('/api/v1/oauth/clients/' + id + '/tokens?expiresAt=' + expiresAt).success(function(data, status) {
|
||||
Client.prototype.createTokenByClientId = function (id, scope, expiresAt, callback) {
|
||||
var data = {
|
||||
scope: scope,
|
||||
expiresAt: expiresAt
|
||||
};
|
||||
post('/api/v1/clients/' + id + '/tokens', data).success(function(data, status) {
|
||||
if (status !== 201) return callback(new ClientError(status, data));
|
||||
callback(null, data.token);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getTokensByClientId = function (id, callback) {
|
||||
get('/api/v1/oauth/clients/' + id + '/tokens').success(function(data, status) {
|
||||
get('/api/v1/clients/' + id + '/tokens').success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data.tokens);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.delTokensByClientId = function (id, callback) {
|
||||
del('/api/v1/oauth/clients/' + id + '/tokens').success(function(data, status) {
|
||||
del('/api/v1/clients/' + id + '/tokens').success(function(data, status) {
|
||||
if (status !== 204) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.delToken = function (clientId, tokenId, callback) {
|
||||
del('/api/v1/oauth/clients/' + clientId + '/tokens/' + tokenId).success(function(data, status) {
|
||||
del('/api/v1/clients/' + clientId + '/tokens/' + tokenId).success(function(data, status) {
|
||||
if (status !== 204) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
@@ -846,11 +902,12 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.feedback = function (type, subject, description, callback) {
|
||||
Client.prototype.feedback = function (type, subject, description, appId /* optional */, callback) {
|
||||
var data = {
|
||||
type: type,
|
||||
subject: subject,
|
||||
description: description
|
||||
description: description,
|
||||
appId: appId || undefined
|
||||
};
|
||||
|
||||
post('/api/v1/feedback', data).success(function (data, status) {
|
||||
@@ -922,6 +979,37 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.setTwoFactorAuthenticationSecret = function (callback) {
|
||||
var data = {};
|
||||
|
||||
post('/api/v1/profile/twofactorauthentication', data).success(function(data, status) {
|
||||
if (status !== 201) return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.enableTwoFactorAuthentication = function (totpToken, callback) {
|
||||
var data = {
|
||||
totpToken: totpToken
|
||||
};
|
||||
|
||||
post('/api/v1/profile/twofactorauthentication/enable', data).success(function(data, status) {
|
||||
if (status !== 202) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.disableTwoFactorAuthentication = function (password, callback) {
|
||||
var data = {
|
||||
password: password
|
||||
};
|
||||
|
||||
post('/api/v1/profile/twofactorauthentication/disable', data).success(function(data, status) {
|
||||
if (status !== 202) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.refreshUserInfo = function (callback) {
|
||||
var that = this;
|
||||
|
||||
@@ -976,7 +1064,9 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
|
||||
callback = typeof callback === 'function' ? callback : function () {};
|
||||
|
||||
this.getApps(function (error, apps) {
|
||||
var getAppsFunc = this.hasScope('apps') ? this.getApps : this.getAppsByUser;
|
||||
|
||||
getAppsFunc(function (error, apps) {
|
||||
if (error) return callback(error);
|
||||
|
||||
// insert or update new apps
|
||||
@@ -1066,7 +1156,7 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
var needed = app.manifest.memoryLimit || DEFAULT_MEMORY_LIMIT; // RAM+Swap
|
||||
var used = this.getInstalledApps().reduce(function (prev, cur) { return prev + (cur.memoryLimit || cur.manifest.memoryLimit || DEFAULT_MEMORY_LIMIT); }, 0);
|
||||
var roundedMemory = Math.round(this.getConfig().memory / (1024 * 1024 * 1024)) * 1024 * 1024 * 1024; // round to nearest GB
|
||||
var totalMemory = roundedMemory * 1.2; // cloudron-system-setup.sh creates equal amount of swap. 1.2 factor is arbitrary
|
||||
var totalMemory = roundedMemory * 1.5; // cloudron-system-setup.sh creates equal amount of swap. 1.5 factor is arbitrary
|
||||
var available = (totalMemory || 0) - used;
|
||||
|
||||
return (available - needed) >= 0;
|
||||
@@ -1130,13 +1220,21 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback)); // this doesn't call defaultErrorHandler till we fix domains code to use this directly
|
||||
};
|
||||
|
||||
Client.prototype.addDomain = function (domain, provider, config, fallbackCertificate, tlsConfig, callback) {
|
||||
Client.prototype.updateMailDomain = function (domain, callback) {
|
||||
post('/api/v1/mail/' + domain, { }).success(function (data, status) {
|
||||
if (status !== 202) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback)); // this doesn't call defaultErrorHandler till we fix domains code to use this directly
|
||||
};
|
||||
|
||||
Client.prototype.addDomain = function (domain, zoneName, provider, config, fallbackCertificate, tlsConfig, callback) {
|
||||
var data = {
|
||||
domain: domain,
|
||||
provider: provider,
|
||||
config: config,
|
||||
tlsConfig: tlsConfig
|
||||
};
|
||||
if (zoneName) data.zoneName = zoneName;
|
||||
var that = this;
|
||||
|
||||
if (fallbackCertificate) data.fallbackCertificate = fallbackCertificate;
|
||||
@@ -1149,18 +1247,21 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.updateDomain = function (domain, provider, config, fallbackCertificate, tlsConfig, callback) {
|
||||
Client.prototype.updateDomain = function (domain, zoneName, provider, config, fallbackCertificate, tlsConfig, callback) {
|
||||
var data = {
|
||||
provider: provider,
|
||||
config: config,
|
||||
tlsConfig: tlsConfig
|
||||
};
|
||||
if (zoneName) data.zoneName = zoneName;
|
||||
var that = this;
|
||||
|
||||
if (fallbackCertificate) data.fallbackCertificate = fallbackCertificate;
|
||||
|
||||
put('/api/v1/domains/' + domain, data).success(function (data, status) {
|
||||
if (status !== 204) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
|
||||
that.updateMailDomain(domain, callback); // this is done so that an out-of-sync dkim key can be synced
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
@@ -1229,7 +1330,14 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
};
|
||||
|
||||
Client.prototype.setCatchallAddresses = function (domain, addresses, callback) {
|
||||
post('/api/v1/mail/' + domain + '/catch_all', { address: addresses }).success(function(data, status) {
|
||||
post('/api/v1/mail/' + domain + '/catch_all', { addresses: addresses }).success(function(data, status) {
|
||||
if (status !== 202) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.setMailFromValidation = function (domain, enabled, callback) {
|
||||
post('/api/v1/mail/' + domain + '/mail_from_validation', { enabled: enabled }).success(function(data, status) {
|
||||
if (status !== 202) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
@@ -1239,59 +1347,94 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
Client.prototype.getMailboxes = function (domain, callback) {
|
||||
get('/api/v1/mail/' + domain + '/mailboxes').success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
|
||||
// filter out app mailboxes
|
||||
data.mailboxes = data.mailboxes.filter(function (m) { return m.ownerType !== 'app'; });
|
||||
|
||||
callback(null, data.mailboxes);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getUserMailbox = function (domain, userId, callback) {
|
||||
get('/api/v1/mail/' + domain + '/mailboxes/' + userId).success(function(data, status) {
|
||||
Client.prototype.getMailbox = function (domain, name, callback) {
|
||||
get('/api/v1/mail/' + domain + '/mailboxes/' + name).success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data.mailbox);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.enableUserMailbox = function (domain, userId, callback) {
|
||||
post('/api/v1/mail/' + domain + '/mailboxes/' + userId, {}).success(function(data, status) {
|
||||
Client.prototype.addMailbox = function (domain, name, userId, callback) {
|
||||
var data = {
|
||||
name: name,
|
||||
userId: userId
|
||||
};
|
||||
|
||||
post('/api/v1/mail/' + domain + '/mailboxes', data).success(function(data, status) {
|
||||
if (status !== 201) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.disableUserMailbox = function (domain, userId, callback) {
|
||||
del('/api/v1/mail/' + domain + '/mailboxes/' + userId).success(function(data, status) {
|
||||
Client.prototype.updateMailbox = function (domain, name, userId, callback) {
|
||||
var data = {
|
||||
userId: userId
|
||||
};
|
||||
|
||||
post('/api/v1/mail/' + domain + '/mailboxes/' + name, data).success(function(data, status) {
|
||||
if (status !== 204) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.removeMailbox = function (domain, name, callback) {
|
||||
del('/api/v1/mail/' + domain + '/mailboxes/' + name).success(function(data, status) {
|
||||
if (status !== 201) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getAliases = function (domain, userId, callback) {
|
||||
get('/api/v1/mail/' + domain + '/aliases/' + userId).success(function(data, status) {
|
||||
Client.prototype.listAliases = function (domain, callback) {
|
||||
get('/api/v1/mail/' + domain + '/aliases').success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data.aliases);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.setAliases = function (domain, userId, aliases, callback) {
|
||||
Client.prototype.getAliases = function (domain, name, callback) {
|
||||
get('/api/v1/mail/' + domain + '/aliases/' + name).success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data.aliases);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.setAliases = function (domain, name, aliases, callback) {
|
||||
var data = {
|
||||
aliases: aliases
|
||||
};
|
||||
|
||||
put('/api/v1/mail/' + domain + '/aliases/' + userId, data).success(function(data, status) {
|
||||
put('/api/v1/mail/' + domain + '/aliases/' + name, data).success(function(data, status) {
|
||||
if (status !== 202) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getMailingList = function (domain, groupId, callback) {
|
||||
get('/api/v1/mail/' + domain + '/lists/' + groupId).success(function(data, status) {
|
||||
Client.prototype.listMailingLists = function (domain, callback) {
|
||||
get('/api/v1/mail/' + domain + '/lists').success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data.lists);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getMailingList = function (domain, name, callback) {
|
||||
get('/api/v1/mail/' + domain + '/lists/' + name).success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data.list);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.addMailingList = function (domain, groupId, callback) {
|
||||
Client.prototype.addMailingList = function (domain, name, members, callback) {
|
||||
var data = {
|
||||
groupId: groupId
|
||||
name: name,
|
||||
members: members
|
||||
};
|
||||
|
||||
post('/api/v1/mail/' + domain + '/lists', data).success(function(data, status) {
|
||||
@@ -1300,8 +1443,19 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.removeMailingList = function (domain, groupId, callback) {
|
||||
del('/api/v1/mail/' + domain + '/lists/' + groupId).success(function(data, status) {
|
||||
Client.prototype.updateMailingList = function (domain, name, members, callback) {
|
||||
var data = {
|
||||
members: members
|
||||
};
|
||||
|
||||
post('/api/v1/mail/' + domain + '/lists/' + name, data).success(function(data, status) {
|
||||
if (status !== 204) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.removeMailingList = function (domain, name, callback) {
|
||||
del('/api/v1/mail/' + domain + '/lists/' + name).success(function(data, status) {
|
||||
if (status !== 204) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||