Compare commits
482 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53fed09a5d | |||
| 4e2d1bd26e | |||
| 477128c586 | |||
| 4dec09f639 | |||
| eda3d5c143 | |||
| b450efe5c2 | |||
| ca76626d55 | |||
| ed887953b6 | |||
| 04debe3ea3 | |||
| 4312096dd2 | |||
| 94b079fa7b | |||
| 0373d86349 | |||
| 0f5c290785 | |||
| c79f43bb27 | |||
| 184ad3bc4e | |||
| aa0a4ae3e9 | |||
| ff9c4b407f | |||
| c3b01d477e | |||
| 3c0641745b | |||
| 7186a0c41b | |||
| 4c3bc7450e | |||
| 02f04e2d33 | |||
| 97b6e4c672 | |||
| 2fd1caa2aa | |||
| cb25217c48 | |||
| ab70bc663d | |||
| 0cfe931cd1 | |||
| 29bddb5fcb | |||
| cb7d160346 | |||
| 507c8b8786 | |||
| 60107147c2 | |||
| be2afec86b | |||
| d316d216db | |||
| dd53d0d575 | |||
| 0f6c0a2ccd | |||
| 937a165711 | |||
| 22c402ca3d | |||
| eddbd4fddc | |||
| 0e43ca31a3 | |||
| 9c90a20b4d | |||
| 764e7e7d1f | |||
| 0e8cb00233 | |||
| 0a1a011338 | |||
| 3dfcd9324d | |||
| 3e4ac4a0ca | |||
| be1795d50d | |||
| 0b0b06baa9 | |||
| b789cd2af0 | |||
| 0871403c0a | |||
| 53a34d9352 | |||
| fe23551b04 | |||
| 484b6477d3 | |||
| 8ebe04c2ff | |||
| 672d6b0856 | |||
| 0c066fafa2 | |||
| 6c574ead94 | |||
| 31a62313bb | |||
| 4dacf7064f | |||
| e900e4de77 | |||
| 4ce6939b79 | |||
| 8430fd1473 | |||
| ac7c54e273 | |||
| 6c9a3b530d | |||
| 2f2c70d1df | |||
| a78c991330 | |||
| 8f9349ec53 | |||
| bc6be6a9ad | |||
| a9b7c2795a | |||
| cd81cc8cb8 | |||
| 473b35d807 | |||
| 0c04d5bfc8 | |||
| eed460f435 | |||
| d742982973 | |||
| c8263077a2 | |||
| eae01bdbd9 | |||
| 1ebafbbc20 | |||
| a525bb0257 | |||
| cf5cf9e42f | |||
| 7969dff043 | |||
| d73f7304b3 | |||
| 4400b0117a | |||
| 739c91b1c6 | |||
| 510115ade9 | |||
| 8c2d79b75e | |||
| 1a31fb78e5 | |||
| 97f4d5e3ac | |||
| d0b17f7e7b | |||
| eb74aaff3b | |||
| 9108b665a8 | |||
| e449147ed4 | |||
| 53e82876dd | |||
| dd4a4518b3 | |||
| a9e46c64b1 | |||
| fb85770fd3 | |||
| 9e9e651714 | |||
| 314da7ace8 | |||
| 54103ca120 | |||
| be86a3022f | |||
| 91ecab08da | |||
| cae445556e | |||
| 8c2af87857 | |||
| 2d44e356d3 | |||
| dec1931f07 | |||
| 46473c3756 | |||
| cd893edfcf | |||
| 84302c1739 | |||
| d6f6b4bfe5 | |||
| 8c6531b6fb | |||
| f4993a7e58 | |||
| cc812c2177 | |||
| e11dc028d1 | |||
| e314910a76 | |||
| ee9140c365 | |||
| ce4ccc21dd | |||
| 6108fcf17b | |||
| cd3fb77033 | |||
| 0697274311 | |||
| 11f5aaaf3b | |||
| 8f0b66bd98 | |||
| 3be660dcd9 | |||
| 3bb82d5e68 | |||
| 3f9f1480d3 | |||
| 948c446362 | |||
| 25f888e0d8 | |||
| 98661de24e | |||
| a833ceb737 | |||
| b41d0379f0 | |||
| df6da7dd1c | |||
| 24ca5bc990 | |||
| e3e62b8407 | |||
| 0c98e6f4ca | |||
| 6034121695 | |||
| afe837e30a | |||
| f3cf640e21 | |||
| 8d98cefcca | |||
| bdf57a5c0a | |||
| 37f108d9f7 | |||
| 091663afe0 | |||
| a77918bef9 | |||
| f167714ea1 | |||
| 1cab172169 | |||
| 35c3df5a18 | |||
| b9a6f46543 | |||
| 12b1909c7a | |||
| 5bd57b6dbd | |||
| 961220be3f | |||
| 4db703aeb1 | |||
| cec1cc7086 | |||
| 2bacbe6701 | |||
| 3c65d88c65 | |||
| 726a1c37cc | |||
| 63f2bbb253 | |||
| 7f11cc0daf | |||
| f32884b3b2 | |||
| 97465c1bd8 | |||
| ce0a1ce38a | |||
| f5060a0d4f | |||
| bb34c8a242 | |||
| 34fd733bb7 | |||
| 19b65460ff | |||
| edf277fcaf | |||
| 9db334c2a4 | |||
| 1039d9c95e | |||
| 37c8b2b57f | |||
| 461fb0144e | |||
| 60a9c60f40 | |||
| 869a6b5a51 | |||
| 133e101f83 | |||
| 6ecadb2308 | |||
| 0d3ff81d6c | |||
| e938886629 | |||
| aa32055aa8 | |||
| 59481c37bc | |||
| 0b868dad2d | |||
| 3c063a2263 | |||
| 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,182 @@
|
||||
<!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">
|
||||
<link rel="apple-touch-icon" href="/api/v1/cloudron/avatar">
|
||||
<link 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">
|
||||
<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 || config.features.spaces">
|
||||
<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 && config.features.operatorActions" class="divider"></li>
|
||||
<li ng-show="user.admin && config.features.operatorActions"><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));
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
/* global angular */
|
||||
/* global EventSource */
|
||||
/* global asyncForEach */
|
||||
|
||||
angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'Notification', function ($http, $interval, md5, Notification) {
|
||||
var client = null;
|
||||
@@ -105,13 +106,12 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
function Client() {
|
||||
this._ready = false;
|
||||
this._configListener = [];
|
||||
this._appsListener = [];
|
||||
this._readyListener = [];
|
||||
this._userInfo = {
|
||||
id: null,
|
||||
username: null,
|
||||
email: null,
|
||||
admin: false
|
||||
twoFactorAuthenticationEnabled: false
|
||||
};
|
||||
this._config = {
|
||||
apiServerOrigin: null,
|
||||
@@ -123,17 +123,17 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
progress: {},
|
||||
region: null,
|
||||
size: null,
|
||||
memory: 0
|
||||
memory: 0,
|
||||
edition: null
|
||||
};
|
||||
this._installedApps = [];
|
||||
this._installedAppsById = {};
|
||||
this._clientId = '<%= oauth.clientId %>';
|
||||
this._clientSecret = '<%= oauth.clientSecret %>';
|
||||
// window.location fallback for websocket connections which do not have relative uris
|
||||
this.apiOrigin = '<%= oauth.apiOrigin %>' || window.location.origin;
|
||||
this.avatar = '';
|
||||
|
||||
this._refreshConfigTimer = null;
|
||||
|
||||
this.resetAvatar();
|
||||
|
||||
this.setToken(localStorage.token);
|
||||
@@ -151,6 +151,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 +165,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');
|
||||
@@ -200,11 +204,6 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
if (this._config && this._config.apiServerOrigin) callback(this._config);
|
||||
};
|
||||
|
||||
Client.prototype.onApps = function (callback) {
|
||||
this._appsListener.push(callback);
|
||||
callback(this._installedApps);
|
||||
};
|
||||
|
||||
Client.prototype.resetAvatar = function () {
|
||||
this.avatar = this.apiOrigin + '/api/v1/cloudron/avatar?' + String(Math.random()).slice(2);
|
||||
|
||||
@@ -219,7 +218,8 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
this._userInfo.email = userInfo.email;
|
||||
this._userInfo.fallbackEmail = userInfo.fallbackEmail;
|
||||
this._userInfo.displayName = userInfo.displayName;
|
||||
this._userInfo.admin = !!userInfo.admin;
|
||||
this._userInfo.twoFactorAuthenticationEnabled = userInfo.twoFactorAuthenticationEnabled;
|
||||
this._userInfo.admin = userInfo.admin;
|
||||
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';
|
||||
};
|
||||
@@ -230,6 +230,13 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
// provide fallback to caas
|
||||
if (!config.provider) config.provider = 'caas';
|
||||
|
||||
// derive feature flags from edition
|
||||
config.features = {
|
||||
spaces: config.edition === 'education',
|
||||
hyphenatedSubdomains: config.edition === 'hostingprovider',
|
||||
operatorActions: config.edition !== 'hostingprovider'
|
||||
};
|
||||
|
||||
angular.copy(config, this._config);
|
||||
|
||||
this._configListener.forEach(function (callback) {
|
||||
@@ -265,7 +272,7 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
* Rest API wrappers
|
||||
*/
|
||||
Client.prototype.config = function (callback) {
|
||||
get('/api/v1/cloudron/config').success(function(data, status) {
|
||||
get('/api/v1/config').success(function(data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
@@ -329,6 +336,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, data);
|
||||
}).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 +359,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) {
|
||||
@@ -347,7 +377,6 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
|
||||
Client.prototype.configureApp = function (id, config, callback) {
|
||||
var data = {
|
||||
appId: id,
|
||||
location: config.location,
|
||||
domain: config.domain,
|
||||
portBindings: config.portBindings,
|
||||
@@ -355,12 +384,14 @@ 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
|
||||
enableBackup: config.enableBackup,
|
||||
};
|
||||
|
||||
if ('mailboxName' in config) data.mailboxName = config.mailboxName;
|
||||
if ('alternateDomains' in config) data.alternateDomains = config.alternateDomains;
|
||||
|
||||
post('/api/v1/apps/' + id + '/configure', data).success(function (data, status) {
|
||||
if (status !== 202) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
@@ -453,30 +484,45 @@ 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) {
|
||||
Client.prototype.getUpdateInfo = function (callback) {
|
||||
get('/api/v1/cloudron/update').success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
callback(null, data);
|
||||
}).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));
|
||||
@@ -498,6 +544,13 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getCaasConfig = function (callback) {
|
||||
get('/api/v1/caas/config').success(function(data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.addAuthorizedKey = function (key, callback) {
|
||||
put('/api/v1/cloudron/ssh/authorized_keys', { key: key }).success(function (data, status) {
|
||||
if (status !== 201) return callback(new ClientError(status, data));
|
||||
@@ -546,10 +599,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 +616,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));
|
||||
@@ -608,6 +661,13 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getUser = function (userId, callback) {
|
||||
get('/api/v1/users/' + userId).success(function (data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getGroups = function (callback) {
|
||||
get('/api/v1/groups').success(function (data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
@@ -640,6 +700,29 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.updateGroup = function (id, name, callback) {
|
||||
var data = {
|
||||
name: name
|
||||
};
|
||||
|
||||
post('/api/v1/groups/' + id, data).success(function(data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.setGroupMembers = function (id, userIds, callback) {
|
||||
var data = {
|
||||
userIds: userIds
|
||||
|
||||
};
|
||||
|
||||
put('/api/v1/groups/' + id + '/members', data).success(function(data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.removeGroup = function (groupId, password, callback) {
|
||||
var config = {
|
||||
data: {
|
||||
@@ -657,6 +740,13 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
};
|
||||
|
||||
Client.prototype.getApp = function (appId, callback) {
|
||||
get('/api/v1/apps/' + appId).success(function (data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
callback(null, data);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getCachedApp = function (appId, callback) {
|
||||
var appFound = null;
|
||||
this._installedApps.some(function (app) {
|
||||
if (app.id === appId) {
|
||||
@@ -678,17 +768,24 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
};
|
||||
};
|
||||
|
||||
Client.prototype.sendInvite = function (user, callback) {
|
||||
post('/api/v1/users/' + user.id + '/invite').success(function (data, status) {
|
||||
Client.prototype.createInvite = function (userId, callback) {
|
||||
post('/api/v1/users/' + userId + '/create_invite').success(function (data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null, data.resetToken);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.sendInvite = function (userId, callback) {
|
||||
post('/api/v1/users/' + userId + '/send_invite').success(function (data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.setupDnsConfig = function (domain, zoneName, provider, dnsConfig, tlsConfig, callback) {
|
||||
var data = {
|
||||
domain: domain,
|
||||
adminFqdn: 'my.' + domain,
|
||||
adminFqdn: 'my' + (dnsConfig.hyphenatedSubdomains ? '-' : '.' ) + domain,
|
||||
zoneName: zoneName,
|
||||
provider: provider,
|
||||
config: dnsConfig,
|
||||
@@ -718,14 +815,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 +835,47 @@ 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, name, callback) {
|
||||
var data = {
|
||||
scope: scope,
|
||||
expiresAt: expiresAt,
|
||||
name: name || ''
|
||||
};
|
||||
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 +948,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) {
|
||||
@@ -859,14 +962,14 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.createUser = function (username, email, displayName, sendInvite, callback) {
|
||||
Client.prototype.createUser = function (user, callback) {
|
||||
var data = {
|
||||
email: email,
|
||||
displayName: displayName,
|
||||
invite: !!sendInvite
|
||||
email: user.email,
|
||||
displayName: user.displayName,
|
||||
admin: user.admin
|
||||
};
|
||||
|
||||
if (username !== null) data.username = username;
|
||||
if (user.username !== null) data.username = user.username;
|
||||
|
||||
post('/api/v1/users', data).success(function(data, status) {
|
||||
if (status !== 201 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
@@ -878,7 +981,8 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
var data = {
|
||||
email: user.email,
|
||||
displayName: user.displayName,
|
||||
fallbackEmail: user.fallbackEmail
|
||||
fallbackEmail: user.fallbackEmail,
|
||||
admin: user.admin
|
||||
};
|
||||
|
||||
post('/api/v1/users/' + user.id, data).success(function(data, status) {
|
||||
@@ -887,6 +991,17 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.transferOwnership = function (oldOwnerId, newOwnerId, callback) {
|
||||
var data = {
|
||||
ownerId: newOwnerId
|
||||
};
|
||||
|
||||
post('/api/v1/users/' + oldOwnerId + '/transfer', data).success(function (data, status) {
|
||||
if (status !== 200) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.removeUser = function (userId, password, callback) {
|
||||
var config = {
|
||||
data: {
|
||||
@@ -922,6 +1037,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;
|
||||
|
||||
@@ -943,13 +1089,16 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
this.config(function (error, result) {
|
||||
if (error) return callback(error);
|
||||
|
||||
that.setConfig(result);
|
||||
that.getUpdateInfo(function (error, info) { // note: non-admin users may get access denied for this
|
||||
if (!error) result.update = info.update; // attach update information to config object
|
||||
|
||||
callback(null);
|
||||
that.setConfig(result);
|
||||
callback(null);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Client.prototype.appPostProcess = function (app) {
|
||||
Client.prototype._appPostProcess = function (app) {
|
||||
// calculate the icon paths
|
||||
var icons = this.getAppIconUrls(app);
|
||||
app.iconUrl = icons.cloudron;
|
||||
@@ -968,9 +1117,69 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
app.message = installationProgress.replace(/.*, /,'');
|
||||
}
|
||||
|
||||
// amend the post install confirm state
|
||||
app.pendingPostInstallConfirmation = !!localStorage['confirmPostInstall_' + app.id];
|
||||
|
||||
return app;
|
||||
};
|
||||
|
||||
function binarySearch(array, pred) {
|
||||
var lo = -1, hi = array.length;
|
||||
while (1 + lo !== hi) {
|
||||
var mi = lo + ((hi - lo) >> 1);
|
||||
if (pred(array[mi])) {
|
||||
hi = mi;
|
||||
} else {
|
||||
lo = mi;
|
||||
}
|
||||
}
|
||||
return hi;
|
||||
}
|
||||
|
||||
Client.prototype._updateAppCache = function (app) {
|
||||
var found = -1;
|
||||
|
||||
// find by id and not by loc because the app's fqdn might have changed between invokations
|
||||
for (var i = 0; i < this._installedApps.length; ++i) {
|
||||
if (this._installedApps[i].id === app.id) {
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var tmp = {};
|
||||
angular.copy(app, tmp);
|
||||
|
||||
this._appPostProcess(tmp);
|
||||
|
||||
// only replace if the app is already known
|
||||
if (found !== -1 && this._installedApps[found].fqdn === tmp.fqdn) { // app location has not changed
|
||||
angular.copy(tmp, this._installedApps[found]);
|
||||
} else {
|
||||
if (found !== -1) this._installedApps.splice(found, 1); // remove it
|
||||
|
||||
var loc = binarySearch(this._installedApps, function (item) { return item.fqdn.localeCompare(app.fqdn) <= 0; });
|
||||
this._installedApps.splice(loc, 0, tmp); // insert into sorted fqdn array
|
||||
}
|
||||
|
||||
this._installedAppsById[app.id] = this._installedApps[found];
|
||||
};
|
||||
|
||||
// this requires app:manage permissions
|
||||
Client.prototype.refreshAppCache = function (id, callback) {
|
||||
var that = this;
|
||||
|
||||
callback = typeof callback === 'function' ? callback : function () {};
|
||||
|
||||
this.getApp(id, function (error, app) {
|
||||
if (error) return callback(error);
|
||||
|
||||
that._updateAppCache(app);
|
||||
|
||||
callback(null, app);
|
||||
});
|
||||
};
|
||||
|
||||
Client.prototype.refreshInstalledApps = function (callback) {
|
||||
var that = this;
|
||||
|
||||
@@ -979,44 +1188,30 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
this.getApps(function (error, apps) {
|
||||
if (error) return callback(error);
|
||||
|
||||
// insert or update new apps
|
||||
apps.forEach(function (app) {
|
||||
var found = false;
|
||||
asyncForEach(apps, function (app, iteratorCallback) {
|
||||
var canManageApp = that._userInfo.admin || that._userInfo.id === app.ownerId;
|
||||
|
||||
for (var i = 0; i < that._installedApps.length; ++i) {
|
||||
if (that._installedApps[i].id === app.id) {
|
||||
found = i;
|
||||
break;
|
||||
if (!canManageApp) {
|
||||
that._updateAppCache(app);
|
||||
return iteratorCallback();
|
||||
}
|
||||
|
||||
if (that._installedAppsById[app.id] && that._installedAppsById[app.id].ts === app.ts) return iteratorCallback(); // app has not changed
|
||||
|
||||
that.refreshAppCache(app.id, iteratorCallback);
|
||||
}, function iteratorDone(error) {
|
||||
if (error) return callback(error);
|
||||
|
||||
// filter out old apps, going backwards to allow splicing
|
||||
for (var i = that._installedApps.length - 1; i >= 0; --i) {
|
||||
if (!apps.some(function (elem) { return (elem.id === that._installedApps[i].id); })) {
|
||||
var removed = that._installedApps.splice(i, 1);
|
||||
delete that._installedAppsById[removed[0].id];
|
||||
}
|
||||
}
|
||||
|
||||
var tmp = {};
|
||||
angular.copy(app, tmp);
|
||||
|
||||
that.appPostProcess(tmp);
|
||||
|
||||
// only replace if the app is already known
|
||||
if (found !== false) {
|
||||
angular.copy(tmp, that._installedApps[found]);
|
||||
} else {
|
||||
that._installedApps.push(tmp);
|
||||
}
|
||||
callback(null);
|
||||
});
|
||||
|
||||
// filter out old entries, going backwards to allow splicing
|
||||
for(var i = that._installedApps.length - 1; i >= 0; --i) {
|
||||
if (!apps.some(function (elem) { return (elem.id === that._installedApps[i].id); })) {
|
||||
that._installedApps.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
that._installedApps = that._installedApps.sort(function (app1, app2) { return app1.fqdn.localeCompare(app2.fqdn); });
|
||||
|
||||
that._appsListener.forEach(function (callback) {
|
||||
callback(that._installedApps);
|
||||
});
|
||||
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1046,6 +1241,7 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
window.location.href = this.apiOrigin + '/api/v1/session/logout?redirect=' + origin;
|
||||
};
|
||||
|
||||
// this is ununsed because webadmin uses implicit grant flow
|
||||
Client.prototype.exchangeCodeForToken = function (code, callback) {
|
||||
var data = {
|
||||
grant_type: 'authorization_code',
|
||||
@@ -1066,7 +1262,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 +1326,14 @@ 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.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 +1346,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.setDnsRecords(domain, callback); // this is done so that an out-of-sync dkim key can be synced
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
@@ -1214,6 +1414,13 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.setDnsRecords = function (domain, callback) {
|
||||
post('/api/v1/mail/' + domain + '/dns', { }).success(function (data, status) {
|
||||
if (status !== 201) return callback(new ClientError(status, data));
|
||||
callback(null);
|
||||
}).error(defaultErrorHandler(callback));
|
||||
};
|
||||
|
||||
Client.prototype.getMailStatusForDomain = function (domain, callback) {
|
||||
get('/api/v1/mail/' + domain + '/status').success(function (data, status) {
|
||||
if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data));
|
||||
@@ -1229,7 +1436,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 +1453,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 +1549,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));
|
||||