9f9575f46a
restart service does not rebuild automatically, we should add a route for that. we need to figure where to scale services etc if we randomly create containers like that.
394 lines
29 KiB
JavaScript
394 lines
29 KiB
JavaScript
'use strict';
|
|
|
|
exports = module.exports = {
|
|
start: start,
|
|
stop: stop
|
|
};
|
|
|
|
let assert = require('assert'),
|
|
async = require('async'),
|
|
cloudron = require('./cloudron.js'),
|
|
constants = require('./constants.js'),
|
|
database = require('./database.js'),
|
|
debug = require('debug')('box:server'),
|
|
eventlog = require('./eventlog.js'),
|
|
express = require('express'),
|
|
http = require('http'),
|
|
middleware = require('./middleware'),
|
|
routes = require('./routes/index.js'),
|
|
settings = require('./settings.js'),
|
|
users = require('./users.js'),
|
|
ws = require('ws');
|
|
|
|
let gHttpServer = null;
|
|
|
|
function initializeExpressSync() {
|
|
var app = express();
|
|
var httpServer = http.createServer(app);
|
|
|
|
const wsServer = new ws.Server({ noServer: true }); // in noServer mode, we have to handle 'upgrade' and call handleUpgrade
|
|
|
|
var QUERY_LIMIT = '1mb', // max size for json and urlencoded queries (see also client_max_body_size in nginx)
|
|
FIELD_LIMIT = 2 * 1024 * 1024; // max fields that can appear in multipart
|
|
|
|
var REQUEST_TIMEOUT = 20000; // timeout for all requests (see also setTimeout on the httpServer)
|
|
|
|
var json = middleware.json({ strict: true, limit: QUERY_LIMIT }), // application/json
|
|
urlencoded = middleware.urlencoded({ extended: false, limit: QUERY_LIMIT }); // application/x-www-form-urlencoded
|
|
|
|
app.set('json spaces', 2); // pretty json
|
|
|
|
// for rate limiting
|
|
app.enable('trust proxy');
|
|
|
|
if (process.env.BOX_ENV !== 'test') {
|
|
app.use(middleware.morgan(function (tokens, req, res) {
|
|
return [
|
|
'Box',
|
|
tokens.method(req, res),
|
|
tokens.url(req, res).replace(/(access_token=)[^&]+/, '$1' + '<redacted>'),
|
|
tokens.status(req, res),
|
|
res.errorBody ? res.errorBody.status : '', // attached by connect-lastmile. can be missing when router errors like 404
|
|
res.errorBody ? res.errorBody.message : '', // attached by connect-lastmile. can be missing when router errors like 404
|
|
tokens['response-time'](req, res), 'ms', '-',
|
|
tokens.res(req, res, 'content-length')
|
|
].join(' ');
|
|
}, {
|
|
immediate: false,
|
|
// only log failed requests by default
|
|
skip: function (req, res) { return res.statusCode < 400; }
|
|
}));
|
|
}
|
|
|
|
var router = new express.Router();
|
|
router.del = router.delete; // amend router.del for readability further on
|
|
|
|
app
|
|
// the timeout middleware will respond with a 503. the request itself cannot be 'aborted' and will continue
|
|
// search for req.clearTimeout in route handlers to see places where this timeout is reset
|
|
.use(middleware.timeout(REQUEST_TIMEOUT, { respond: true }))
|
|
.use(urlencoded)
|
|
.use(middleware.cors({ origins: [ '*' ], allowCredentials: false }))
|
|
.use(router)
|
|
.use(middleware.lastMile());
|
|
|
|
// NOTE: routes that use multi-part have to be whitelisted in the reverse proxy
|
|
var FILE_SIZE_LIMIT = '256mb', // max file size that can be uploaded (see also client_max_body_size in nginx)
|
|
FILE_TIMEOUT = 60 * 1000; // increased timeout for file uploads (1 min)
|
|
|
|
var multipart = middleware.multipart({ maxFieldsSize: FIELD_LIMIT, limit: FILE_SIZE_LIMIT, timeout: FILE_TIMEOUT });
|
|
|
|
// to keep routes code short
|
|
const password = routes.accesscontrol.passwordAuth;
|
|
const token = routes.accesscontrol.tokenAuth;
|
|
const authorizeOwner = routes.accesscontrol.authorize(users.ROLE_OWNER);
|
|
const authorizeAdmin = routes.accesscontrol.authorize(users.ROLE_ADMIN);
|
|
const authorizeUserManager = routes.accesscontrol.authorize(users.ROLE_USER_MANAGER);
|
|
|
|
// public routes
|
|
router.post('/api/v1/cloudron/setup', json, routes.provision.setupTokenAuth, routes.provision.providerTokenAuth, routes.provision.setup); // only available until no-domain
|
|
router.post('/api/v1/cloudron/restore', json, routes.provision.setupTokenAuth, routes.provision.restore); // only available until activated
|
|
router.post('/api/v1/cloudron/activate', json, routes.provision.setupTokenAuth, routes.provision.activate);
|
|
router.get ('/api/v1/cloudron/status', routes.provision.getStatus);
|
|
router.get ('/api/v1/cloudron/languages', routes.cloudron.getLanguages);
|
|
router.get ('/api/v1/cloudron/avatar', routes.branding.getCloudronAvatar); // this is a public alias for /api/v1/branding/cloudron_avatar
|
|
|
|
// login/logout routes
|
|
router.post('/api/v1/cloudron/login', json, password, routes.cloudron.login);
|
|
router.get ('/api/v1/cloudron/logout', token, routes.cloudron.logout); // this will invalidate the token if any and redirect to /login.html always
|
|
router.post('/api/v1/cloudron/password_reset_request', json, routes.cloudron.passwordResetRequest);
|
|
router.post('/api/v1/cloudron/password_reset', json, routes.cloudron.passwordReset);
|
|
router.post('/api/v1/cloudron/setup_account', json, routes.cloudron.setupAccount);
|
|
|
|
// developer routes
|
|
router.post('/api/v1/developer/login', json, password, routes.cloudron.login); // DEPRECATED we should use the regular /api/v1/cloudron/login
|
|
|
|
// cloudron routes
|
|
router.get ('/api/v1/cloudron/update', token, authorizeAdmin, routes.cloudron.getUpdateInfo);
|
|
router.post('/api/v1/cloudron/update', json, token, authorizeAdmin, routes.cloudron.update);
|
|
router.post('/api/v1/cloudron/prepare_dashboard_domain', json, token, authorizeAdmin, routes.cloudron.prepareDashboardDomain);
|
|
router.post('/api/v1/cloudron/set_dashboard_domain', json, token, authorizeAdmin, routes.cloudron.updateDashboardDomain);
|
|
router.post('/api/v1/cloudron/renew_certs', json, token, authorizeAdmin, routes.cloudron.renewCerts);
|
|
router.post('/api/v1/cloudron/check_for_updates', json, token, authorizeAdmin, routes.cloudron.checkForUpdates);
|
|
router.get ('/api/v1/cloudron/reboot', token, authorizeAdmin, routes.cloudron.isRebootRequired);
|
|
router.post('/api/v1/cloudron/reboot', json, token, authorizeAdmin, routes.cloudron.reboot);
|
|
router.get ('/api/v1/cloudron/graphs', token, authorizeAdmin, routes.graphs.getGraphs);
|
|
router.get ('/api/v1/cloudron/disks', token, authorizeAdmin, routes.cloudron.getDisks);
|
|
router.get ('/api/v1/cloudron/memory', token, authorizeAdmin, routes.cloudron.getMemory);
|
|
router.get ('/api/v1/cloudron/logs/:unit', token, authorizeAdmin, routes.cloudron.getLogs);
|
|
router.get ('/api/v1/cloudron/logstream/:unit', token, authorizeAdmin, routes.cloudron.getLogStream);
|
|
router.get ('/api/v1/cloudron/eventlog', token, authorizeAdmin, routes.eventlog.list);
|
|
router.get ('/api/v1/cloudron/eventlog/:eventId', token, authorizeAdmin, routes.eventlog.get);
|
|
router.post('/api/v1/cloudron/sync_external_ldap', json, token, authorizeAdmin, routes.cloudron.syncExternalLdap);
|
|
router.get ('/api/v1/cloudron/server_ip', token, authorizeAdmin, routes.cloudron.getServerIp);
|
|
|
|
// task routes
|
|
router.get ('/api/v1/tasks', token, authorizeAdmin, routes.tasks.list);
|
|
router.get ('/api/v1/tasks/:taskId', token, authorizeAdmin, routes.tasks.get);
|
|
router.get ('/api/v1/tasks/:taskId/logs', token, authorizeAdmin, routes.tasks.getLogs);
|
|
router.get ('/api/v1/tasks/:taskId/logstream', token, authorizeAdmin, routes.tasks.getLogStream);
|
|
router.post('/api/v1/tasks/:taskId/stop', json, token, authorizeAdmin, routes.tasks.stopTask);
|
|
|
|
// notification routes
|
|
router.get ('/api/v1/notifications', token, routes.notifications.verifyOwnership, routes.notifications.list);
|
|
router.get ('/api/v1/notifications/:notificationId', token, routes.notifications.verifyOwnership, routes.notifications.get);
|
|
router.post('/api/v1/notifications/:notificationId', json, token, routes.notifications.verifyOwnership, routes.notifications.ack);
|
|
|
|
// backup routes
|
|
router.get ('/api/v1/backups', token, authorizeAdmin, routes.backups.list);
|
|
router.post('/api/v1/backups/create', token, authorizeAdmin, routes.backups.startBackup);
|
|
router.post('/api/v1/backups/cleanup', json, token, authorizeAdmin, routes.backups.cleanup);
|
|
router.get ('/api/v1/backups/check', token, authorizeAdmin, routes.backups.check);
|
|
|
|
// config route (for dashboard). can return some private configuration unlike status
|
|
router.get ('/api/v1/config', token, routes.cloudron.getConfig);
|
|
|
|
// working off the user behind the provided token
|
|
router.get ('/api/v1/profile', token, routes.profile.get);
|
|
router.post('/api/v1/profile', json, token, routes.profile.authorize, routes.profile.update);
|
|
router.get ('/api/v1/profile/avatar/:identifier', routes.profile.getAvatar); // this is not scoped so it can used directly in img tag
|
|
router.post('/api/v1/profile/avatar', json, token, multipart, routes.profile.setAvatar); // avatar is not exposed in LDAP. so it's personal and not locked
|
|
router.del ('/api/v1/profile/avatar', token, routes.profile.clearAvatar);
|
|
router.post('/api/v1/profile/password', json, token, routes.users.verifyPassword, routes.profile.changePassword);
|
|
router.post('/api/v1/profile/twofactorauthentication', json, token, routes.profile.setTwoFactorAuthenticationSecret);
|
|
router.post('/api/v1/profile/twofactorauthentication/enable', json, token, routes.profile.enableTwoFactorAuthentication);
|
|
router.post('/api/v1/profile/twofactorauthentication/disable', json, token, routes.users.verifyPassword, routes.profile.disableTwoFactorAuthentication);
|
|
|
|
// app password routes
|
|
router.get ('/api/v1/app_passwords', token, routes.appPasswords.list);
|
|
router.post('/api/v1/app_passwords', json, token, routes.appPasswords.add);
|
|
router.get ('/api/v1/app_passwords/:id', token, routes.appPasswords.get);
|
|
router.del ('/api/v1/app_passwords/:id', token, routes.appPasswords.del);
|
|
|
|
// access tokens
|
|
router.get ('/api/v1/tokens', token, routes.tokens.getAll);
|
|
router.post('/api/v1/tokens', json, token, routes.tokens.add);
|
|
router.get ('/api/v1/tokens/:id', token, routes.tokens.verifyOwnership, routes.tokens.get);
|
|
router.del ('/api/v1/tokens/:id', token, routes.tokens.verifyOwnership, routes.tokens.del);
|
|
|
|
// user routes
|
|
router.get ('/api/v1/users', token, authorizeUserManager, routes.users.list);
|
|
router.post('/api/v1/users', json, token, authorizeUserManager, routes.users.create);
|
|
router.get ('/api/v1/users/:userId', token, authorizeUserManager, routes.users.load, routes.users.get); // this is manage scope because it returns non-restricted fields
|
|
router.del ('/api/v1/users/:userId', token, authorizeUserManager, routes.users.load, routes.users.remove);
|
|
router.post('/api/v1/users/:userId', json, token, authorizeUserManager, routes.users.load, routes.users.update);
|
|
router.post('/api/v1/users/:userId/password', json, token, authorizeUserManager, routes.users.load, routes.users.changePassword);
|
|
router.put ('/api/v1/users/:userId/groups', json, token, authorizeUserManager, routes.users.load, routes.users.setGroups);
|
|
router.post('/api/v1/users/:userId/make_owner', json, token, authorizeOwner, routes.users.load, routes.users.makeOwner);
|
|
router.post('/api/v1/users/:userId/send_invite', json, token, authorizeUserManager, routes.users.load, routes.users.sendInvite);
|
|
router.post('/api/v1/users/:userId/create_invite', json, token, authorizeUserManager, routes.users.load, routes.users.createInvite);
|
|
router.post('/api/v1/users/:userId/avatar', json, token, authorizeUserManager, routes.users.load, multipart, routes.users.setAvatar);
|
|
router.del ('/api/v1/users/:userId/avatar', token, authorizeUserManager, routes.users.load, routes.users.clearAvatar);
|
|
|
|
// Group management
|
|
router.get ('/api/v1/groups', token, authorizeUserManager, routes.groups.list);
|
|
router.post('/api/v1/groups', json, token, authorizeUserManager, routes.groups.create);
|
|
router.get ('/api/v1/groups/:groupId', token, authorizeUserManager, routes.groups.get);
|
|
router.put ('/api/v1/groups/:groupId/members', json, token, authorizeUserManager, routes.groups.updateMembers);
|
|
router.post('/api/v1/groups/:groupId', json, token, authorizeUserManager, routes.groups.update);
|
|
router.del ('/api/v1/groups/:groupId', token, authorizeUserManager, routes.groups.remove);
|
|
|
|
// appstore and subscription routes
|
|
router.post('/api/v1/appstore/register_cloudron', json, token, authorizeAdmin, routes.appstore.registerCloudron);
|
|
router.post('/api/v1/appstore/user_token', json, token, authorizeAdmin, routes.appstore.createUserToken);
|
|
router.get ('/api/v1/appstore/subscription', token, authorizeAdmin, routes.appstore.getSubscription);
|
|
router.get ('/api/v1/appstore/apps', token, authorizeAdmin, routes.appstore.getApps);
|
|
router.get ('/api/v1/appstore/apps/:appstoreId', token, authorizeAdmin, routes.appstore.getApp);
|
|
router.get ('/api/v1/appstore/apps/:appstoreId/versions/:versionId', token, authorizeAdmin, routes.appstore.getAppVersion);
|
|
|
|
// app routes
|
|
router.post('/api/v1/apps/install', json, token, authorizeAdmin, routes.apps.install);
|
|
router.get ('/api/v1/apps', token, routes.apps.getApps);
|
|
router.get ('/api/v1/apps/:id', token, authorizeAdmin, routes.apps.load, routes.apps.getApp);
|
|
router.get ('/api/v1/apps/:id/icon', token, routes.apps.load, routes.apps.getAppIcon);
|
|
router.post('/api/v1/apps/:id/uninstall', json, token, authorizeAdmin, routes.apps.load, routes.apps.uninstall);
|
|
router.post('/api/v1/apps/:id/configure/access_restriction', json, token, authorizeAdmin, routes.apps.load, routes.apps.setAccessRestriction);
|
|
router.post('/api/v1/apps/:id/configure/label', json, token, authorizeAdmin, routes.apps.load, routes.apps.setLabel);
|
|
router.post('/api/v1/apps/:id/configure/tags', json, token, authorizeAdmin, routes.apps.load, routes.apps.setTags);
|
|
router.post('/api/v1/apps/:id/configure/icon', json, token, authorizeAdmin, routes.apps.load, routes.apps.setIcon);
|
|
router.post('/api/v1/apps/:id/configure/memory_limit', json, token, authorizeAdmin, routes.apps.load, routes.apps.setMemoryLimit);
|
|
router.post('/api/v1/apps/:id/configure/cpu_shares', json, token, authorizeAdmin, routes.apps.load, routes.apps.setCpuShares);
|
|
router.post('/api/v1/apps/:id/configure/automatic_backup', json, token, authorizeAdmin, routes.apps.load, routes.apps.setAutomaticBackup);
|
|
router.post('/api/v1/apps/:id/configure/automatic_update', json, token, authorizeAdmin, routes.apps.load, routes.apps.setAutomaticUpdate);
|
|
router.post('/api/v1/apps/:id/configure/reverse_proxy', json, token, authorizeAdmin, routes.apps.load, routes.apps.setReverseProxyConfig);
|
|
router.post('/api/v1/apps/:id/configure/cert', json, token, authorizeAdmin, routes.apps.load, routes.apps.setCertificate);
|
|
router.post('/api/v1/apps/:id/configure/debug_mode', json, token, authorizeAdmin, routes.apps.load, routes.apps.setDebugMode);
|
|
router.post('/api/v1/apps/:id/configure/mailbox', json, token, authorizeAdmin, routes.apps.load, routes.apps.setMailbox);
|
|
router.post('/api/v1/apps/:id/configure/env', json, token, authorizeAdmin, routes.apps.load, routes.apps.setEnvironment);
|
|
router.post('/api/v1/apps/:id/configure/data_dir', json, token, authorizeAdmin, routes.apps.load, routes.apps.setDataDir);
|
|
router.post('/api/v1/apps/:id/configure/location', json, token, authorizeAdmin, routes.apps.load, routes.apps.setLocation);
|
|
router.post('/api/v1/apps/:id/configure/mounts', json, token, authorizeAdmin, routes.apps.load, routes.apps.setMounts);
|
|
router.post('/api/v1/apps/:id/repair', json, token, authorizeAdmin, routes.apps.load, routes.apps.repair);
|
|
router.post('/api/v1/apps/:id/update', json, token, authorizeAdmin, routes.apps.load, routes.apps.update);
|
|
router.post('/api/v1/apps/:id/restore', json, token, authorizeAdmin, routes.apps.load, routes.apps.restore);
|
|
router.post('/api/v1/apps/:id/import', json, token, authorizeAdmin, routes.apps.load, routes.apps.importApp);
|
|
router.post('/api/v1/apps/:id/export', json, token, authorizeAdmin, routes.apps.load, routes.apps.exportApp);
|
|
router.post('/api/v1/apps/:id/backup', json, token, authorizeAdmin, routes.apps.load, routes.apps.backup);
|
|
router.get ('/api/v1/apps/:id/backups', token, authorizeAdmin, routes.apps.load, routes.apps.listBackups);
|
|
router.post('/api/v1/apps/:id/start', json, token, authorizeAdmin, routes.apps.load, routes.apps.start);
|
|
router.post('/api/v1/apps/:id/stop', json, token, authorizeAdmin, routes.apps.load, routes.apps.stop);
|
|
router.post('/api/v1/apps/:id/restart', json, token, authorizeAdmin, routes.apps.load, routes.apps.restart);
|
|
router.get ('/api/v1/apps/:id/logstream', token, authorizeAdmin, routes.apps.load, routes.apps.getLogStream);
|
|
router.get ('/api/v1/apps/:id/logs', token, authorizeAdmin, routes.apps.load, routes.apps.getLogs);
|
|
router.post('/api/v1/apps/:id/clone', json, token, authorizeAdmin, routes.apps.load, routes.apps.clone);
|
|
router.get ('/api/v1/apps/:id/download', token, authorizeAdmin, routes.apps.load, routes.apps.downloadFile);
|
|
router.post('/api/v1/apps/:id/upload', json, token, authorizeAdmin, multipart, routes.apps.load, routes.apps.uploadFile);
|
|
router.use ('/api/v1/apps/:id/files/*', token, authorizeAdmin, routes.filemanager.proxy);
|
|
router.get ('/api/v1/apps/:id/exec', token, authorizeAdmin, routes.apps.load, routes.apps.exec);
|
|
|
|
// websocket cannot do bearer authentication
|
|
router.get ('/api/v1/apps/:id/execws', routes.accesscontrol.websocketAuth.bind(null, users.ROLE_ADMIN), routes.apps.load, routes.apps.execWebSocket);
|
|
|
|
// branding routes
|
|
router.get ('/api/v1/branding/:setting', token, authorizeOwner, routes.branding.get);
|
|
router.post('/api/v1/branding/:setting', json, token, authorizeOwner, (req, res, next) => {
|
|
return req.params.setting === 'cloudron_avatar' ? multipart(req, res, next) : next();
|
|
}, routes.branding.set);
|
|
|
|
// network routes
|
|
router.get ('/api/v1/network/blocklist', token, authorizeOwner, routes.network.getBlocklist);
|
|
router.post('/api/v1/network/blocklist', json, token, authorizeOwner, routes.network.setBlocklist);
|
|
|
|
// settings routes (these are for the settings tab - avatar & name have public routes for normal users. see above)
|
|
router.get ('/api/v1/settings/:setting', token, authorizeAdmin, routes.settings.get);
|
|
router.post('/api/v1/settings/backup_config', json, token, authorizeOwner, routes.settings.setBackupConfig);
|
|
router.post('/api/v1/settings/:setting', json, token, authorizeAdmin, routes.settings.set);
|
|
|
|
// email routes
|
|
router.get ('/api/v1/mailserver/eventlog', token, authorizeOwner, routes.mailserver.proxy);
|
|
router.get ('/api/v1/mailserver/usage', token, authorizeAdmin, routes.mailserver.proxy);
|
|
router.post('/api/v1/mailserver/clear_eventlog', token, authorizeOwner, routes.mailserver.proxy);
|
|
router.get ('/api/v1/mailserver/location', token, authorizeAdmin, routes.mailserver.getLocation);
|
|
router.post('/api/v1/mailserver/location', json, token, authorizeAdmin, routes.mailserver.setLocation);
|
|
router.get ('/api/v1/mailserver/max_email_size', token, authorizeAdmin, routes.mailserver.proxy);
|
|
router.post('/api/v1/mailserver/max_email_size', token, authorizeAdmin, routes.mailserver.proxy);
|
|
router.get ('/api/v1/mailserver/spam_acl', token, authorizeAdmin, routes.mailserver.proxy);
|
|
router.post('/api/v1/mailserver/spam_acl', token, authorizeAdmin, routes.mailserver.proxy);
|
|
router.get ('/api/v1/mailserver/spam_custom_config', token, authorizeAdmin, routes.mailserver.proxy);
|
|
router.post('/api/v1/mailserver/spam_custom_config', token, authorizeAdmin, routes.mailserver.proxy);
|
|
router.get ('/api/v1/mailserver/solr_config', token, authorizeAdmin, routes.mailserver.proxy);
|
|
router.post('/api/v1/mailserver/solr_config', token, authorizeAdmin, routes.mailserver.proxy, routes.mailserver.restart);
|
|
|
|
router.get ('/api/v1/mail/:domain', token, authorizeAdmin, routes.mail.getDomain);
|
|
router.get ('/api/v1/mail/:domain/status', token, authorizeAdmin, routes.mail.getStatus);
|
|
router.post('/api/v1/mail/:domain/mail_from_validation', json, token, authorizeAdmin, routes.mail.setMailFromValidation);
|
|
router.post('/api/v1/mail/:domain/catch_all', json, token, authorizeAdmin, routes.mail.setCatchAllAddress);
|
|
router.post('/api/v1/mail/:domain/relay', json, token, authorizeAdmin, routes.mail.setMailRelay);
|
|
router.post('/api/v1/mail/:domain/enable', json, token, authorizeAdmin, routes.mail.setMailEnabled);
|
|
router.post('/api/v1/mail/:domain/dns', json, token, authorizeAdmin, routes.mail.setDnsRecords);
|
|
router.post('/api/v1/mail/:domain/banner', json, token, authorizeAdmin, routes.mail.setBanner);
|
|
router.post('/api/v1/mail/:domain/send_test_mail', json, token, authorizeAdmin, routes.mail.sendTestMail);
|
|
router.get ('/api/v1/mail/:domain/mailbox_count', token, authorizeAdmin, routes.mail.getMailboxCount);
|
|
router.get ('/api/v1/mail/:domain/mailboxes', token, authorizeAdmin, routes.mail.listMailboxes);
|
|
router.get ('/api/v1/mail/:domain/mailboxes/:name', token, authorizeAdmin, routes.mail.getMailbox);
|
|
router.post('/api/v1/mail/:domain/mailboxes', json, token, authorizeAdmin, routes.mail.addMailbox);
|
|
router.post('/api/v1/mail/:domain/mailboxes/:name', json, token, authorizeAdmin, routes.mail.updateMailbox);
|
|
router.del ('/api/v1/mail/:domain/mailboxes/:name', json, token, authorizeAdmin, routes.mail.removeMailbox);
|
|
router.get ('/api/v1/mail/:domain/mailboxes/:name/aliases', token, authorizeAdmin, routes.mail.getAliases);
|
|
router.put ('/api/v1/mail/:domain/mailboxes/:name/aliases', json, token, authorizeAdmin, routes.mail.setAliases);
|
|
router.get ('/api/v1/mail/:domain/lists', token, authorizeAdmin, routes.mail.getLists);
|
|
router.post('/api/v1/mail/:domain/lists', json, token, authorizeAdmin, routes.mail.addList);
|
|
router.get ('/api/v1/mail/:domain/lists/:name', token, authorizeAdmin, routes.mail.getList);
|
|
router.post('/api/v1/mail/:domain/lists/:name', json, token, authorizeAdmin, routes.mail.updateList);
|
|
router.del ('/api/v1/mail/:domain/lists/:name', token, authorizeAdmin, routes.mail.removeList);
|
|
|
|
// support routes
|
|
router.post('/api/v1/support/ticket', json, token, authorizeAdmin, routes.support.canCreateTicket, routes.support.createTicket);
|
|
router.get ('/api/v1/support/remote_support', token, authorizeAdmin, routes.support.getRemoteSupport);
|
|
router.post('/api/v1/support/remote_support', json, token, authorizeAdmin, routes.support.canEnableRemoteSupport, routes.support.enableRemoteSupport);
|
|
|
|
// domain routes
|
|
router.post('/api/v1/domains', json, token, authorizeAdmin, routes.domains.add);
|
|
router.get ('/api/v1/domains', token, routes.domains.getAll);
|
|
router.get ('/api/v1/domains/:domain', token, authorizeAdmin, routes.domains.get); // this is manage scope because it returns non-restricted fields
|
|
router.put ('/api/v1/domains/:domain', json, token, authorizeAdmin, routes.domains.update);
|
|
router.del ('/api/v1/domains/:domain', token, authorizeAdmin, routes.domains.del);
|
|
router.get ('/api/v1/domains/:domain/dns_check', token, authorizeAdmin, routes.domains.checkDnsRecords);
|
|
|
|
// volume routes
|
|
router.post('/api/v1/volumes', json, token, authorizeAdmin, routes.volumes.add);
|
|
router.get ('/api/v1/volumes', token, authorizeAdmin, routes.volumes.list);
|
|
router.get ('/api/v1/volumes/:id', token, authorizeAdmin, routes.volumes.load, routes.volumes.get);
|
|
router.del ('/api/v1/volumes/:id', token, authorizeAdmin, routes.volumes.load, routes.volumes.del);
|
|
router.use ('/api/v1/volumes/:id/files/*', token, authorizeAdmin, routes.filemanager.proxy);
|
|
|
|
// service routes
|
|
router.get ('/api/v1/services', token, authorizeAdmin, routes.services.getAll);
|
|
router.get ('/api/v1/services/:service', token, authorizeAdmin, routes.services.get);
|
|
router.post('/api/v1/services/:service', json, token, authorizeAdmin, routes.services.configure);
|
|
router.get ('/api/v1/services/:service/logs', token, authorizeAdmin, routes.services.getLogs);
|
|
router.get ('/api/v1/services/:service/logstream', token, authorizeAdmin, routes.services.getLogStream);
|
|
router.post('/api/v1/services/:service/restart', json, token, authorizeAdmin, routes.services.restart);
|
|
router.post('/api/v1/services/:service/rebuild', json, token, authorizeAdmin, routes.services.rebuild);
|
|
|
|
// well known
|
|
router.get ('/well-known-handler/*', routes.wellknown.get);
|
|
|
|
// disable server socket "idle" timeout. we use the timeout middleware to handle timeouts on a route level
|
|
// we rely on nginx for timeouts on the TCP level (see client_header_timeout)
|
|
httpServer.setTimeout(0);
|
|
|
|
// upgrade handler
|
|
httpServer.on('upgrade', function (req, socket, head) {
|
|
// create a node response object for express
|
|
var res = new http.ServerResponse({});
|
|
res.assignSocket(socket);
|
|
|
|
if (req.headers.upgrade === 'websocket') {
|
|
res.handleUpgrade = function (callback) {
|
|
wsServer.handleUpgrade(req, socket, head, callback);
|
|
};
|
|
} else {
|
|
res.sendUpgradeHandshake = function () { // could extend express.response as well
|
|
socket.write('HTTP/1.1 101 TCP Handshake\r\n' +
|
|
'Upgrade: tcp\r\n' +
|
|
'Connection: Upgrade\r\n' +
|
|
'\r\n');
|
|
};
|
|
}
|
|
|
|
// route through express middleware. if we provide no callback, express will provide a 'finalhandler'
|
|
// TODO: it's not clear if socket needs to be destroyed
|
|
app(req, res);
|
|
});
|
|
|
|
return httpServer;
|
|
}
|
|
|
|
function start(callback) {
|
|
assert.strictEqual(typeof callback, 'function');
|
|
assert.strictEqual(gHttpServer, null, 'Server is already up and running.');
|
|
|
|
debug('==========================================');
|
|
debug(` Cloudron ${constants.VERSION} `);
|
|
debug('==========================================');
|
|
|
|
gHttpServer = initializeExpressSync();
|
|
|
|
async.series([
|
|
database.initialize,
|
|
settings.initCache, // pre-load very often used settings
|
|
cloudron.initialize,
|
|
gHttpServer.listen.bind(gHttpServer, constants.PORT, '127.0.0.1'),
|
|
eventlog.add.bind(null, eventlog.ACTION_START, { userId: null, username: 'boot' }, { version: constants.VERSION })
|
|
], callback);
|
|
}
|
|
|
|
function stop(callback) {
|
|
assert.strictEqual(typeof callback, 'function');
|
|
|
|
if (!gHttpServer) return callback(null);
|
|
|
|
async.series([
|
|
cloudron.uninitialize,
|
|
database.uninitialize,
|
|
gHttpServer.close.bind(gHttpServer)
|
|
], function (error) {
|
|
if (error) return callback(error);
|
|
|
|
gHttpServer = null;
|
|
|
|
callback(null);
|
|
});
|
|
}
|