2015-07-20 00:09:47 -07:00
'use strict' ;
exports = module . exports = {
start : start ,
stop : stop
} ;
2018-04-26 15:54:53 -07:00
var accesscontrol = require ( './accesscontrol.js' ) ,
assert = require ( 'assert' ) ,
2015-07-20 00:09:47 -07:00
async = require ( 'async' ) ,
cloudron = require ( './cloudron.js' ) ,
config = require ( './config.js' ) ,
database = require ( './database.js' ) ,
2016-05-02 09:39:38 -07:00
eventlog = require ( './eventlog.js' ) ,
2015-07-20 00:09:47 -07:00
express = require ( 'express' ) ,
2018-06-11 12:38:15 -07:00
hat = require ( './hat.js' ) ,
2015-07-20 00:09:47 -07:00
http = require ( 'http' ) ,
middleware = require ( './middleware' ) ,
passport = require ( 'passport' ) ,
path = require ( 'path' ) ,
2017-08-18 17:56:01 -07:00
routes = require ( './routes/index.js' ) ,
ws = require ( 'ws' ) ;
2015-07-20 00:09:47 -07:00
var gHttpServer = null ;
2016-04-15 12:33:54 -07:00
var gSysadminHttpServer = null ;
2015-07-20 00:09:47 -07:00
function initializeExpressSync ( ) {
var app = express ( ) ;
var httpServer = http . createServer ( app ) ;
2017-08-18 17:56:01 -07:00
const wsServer = new ws . Server ( { noServer : true } ) ; // in noServer mode, we have to handle 'upgrade' and call handleUpgrade
2017-08-15 20:00:52 +02:00
2016-06-01 18:09:23 -07:00
var QUERY _LIMIT = '1mb' , // max size for json and urlencoded queries (see also client_max_body_size in nginx)
2015-07-20 00:09:47 -07:00
FIELD _LIMIT = 2 * 1024 * 1024 ; // max fields that can appear in multipart
2016-01-18 12:20:09 -08:00
var REQUEST _TIMEOUT = 10000 ; // timeout for all requests (see also setTimeout on the httpServer)
2015-07-20 00:09:47 -07:00
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 ( 'views' , path . join ( _ _dirname , 'oauth2views' ) ) ;
2016-02-18 18:00:23 +01:00
app . set ( 'view options' , { layout : true , debug : false } ) ;
2015-07-20 00:09:47 -07:00
app . set ( 'view engine' , 'ejs' ) ;
2016-05-31 11:14:59 -07:00
app . set ( 'json spaces' , 2 ) ; // pretty json
2015-07-20 00:09:47 -07:00
2017-01-16 16:49:01 +01:00
// for rate limiting
app . enable ( 'trust proxy' ) ;
2017-04-10 14:17:26 +02:00
if ( process . env . BOX _ENV !== 'test' ) {
app . use ( middleware . morgan ( 'Box :method :url :status :response-time ms - :res[content-length]' , {
immediate : false ,
// only log failed requests by default
skip : function ( req , res ) { return res . statusCode < 400 ; }
} ) ) ;
}
2015-07-20 00:09:47 -07:00
var router = new express . Router ( ) ;
router . del = router . delete ; // amend router.del for readability further on
app
2018-03-08 09:27:56 -08:00
// 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 } ) )
2017-10-31 12:04:26 -07:00
. use ( json )
. use ( urlencoded )
. use ( middleware . cookieParser ( ) )
. use ( middleware . cors ( { origins : [ '*' ] , allowCredentials : false } ) )
. use ( middleware . session ( {
secret : hat ( 128 ) , // we only use the session during oauth, and already have an in-memory session store, so we can safely change that during restarts
resave : true ,
saveUninitialized : true ,
cookie : {
path : '/' ,
httpOnly : true ,
secure : process . env . BOX _ENV !== 'test' ,
maxAge : 600000
}
} ) )
. use ( passport . initialize ( ) )
. use ( passport . session ( ) )
. use ( router )
. use ( middleware . lastMile ( ) ) ;
2015-07-20 00:09:47 -07:00
// NOTE: these limits have to be in sync with nginx limits
2017-08-20 19:00:00 -07:00
var FILE _SIZE _LIMIT = '256mb' , // max file size that can be uploaded (see also client_max_body_size in nginx)
2015-07-20 00:09:47 -07:00
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 } ) ;
// scope middleware implicitly also adds bearer token verification
2018-04-26 15:54:53 -07:00
var cloudronScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _CLOUDRON ) ;
2019-05-03 16:27:47 -07:00
var subscriptionScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _SUBSCRIPTION ) ;
2019-05-04 11:45:03 -07:00
var appstoreScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _APPSTORE ) ;
2018-04-26 15:54:53 -07:00
var profileScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _PROFILE ) ;
2018-06-25 15:54:24 -07:00
var usersReadScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _USERS _READ ) ;
var usersManageScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _USERS _MANAGE ) ;
2018-06-25 16:45:15 -07:00
var appsReadScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _APPS _READ ) ;
2018-09-05 23:02:06 -07:00
var appsManageScope = [ routes . accesscontrol . scope ( accesscontrol . SCOPE _APPS _MANAGE ) , routes . apps . verifyOwnership ] ;
2018-04-26 15:54:53 -07:00
var settingsScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _SETTINGS ) ;
var mailScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _MAIL ) ;
2018-12-17 16:37:19 +01:00
var notificationsScope = [ routes . accesscontrol . scope ( accesscontrol . SCOPE _PROFILE ) , routes . notifications . verifyOwnership ] ;
2018-04-26 15:54:53 -07:00
var clientsScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _CLIENTS ) ;
2018-06-25 15:12:20 -07:00
var domainsReadScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _DOMAINS _READ ) ;
var domainsManageScope = routes . accesscontrol . scope ( accesscontrol . SCOPE _DOMAINS _MANAGE ) ;
2015-07-20 00:09:47 -07:00
2018-10-30 20:56:43 -07:00
const isUnmanaged = routes . accesscontrol . isUnmanaged ;
2018-09-05 22:58:43 -07:00
const verifyDomainLock = routes . domains . verifyDomainLock ;
2019-01-25 14:57:07 -08:00
const verifySettingsLock = routes . settings . verifySettingsLock ;
2018-09-05 13:18:06 -07:00
2015-07-20 00:09:47 -07:00
// csrf protection
2018-04-29 20:11:45 -07:00
var csrf = routes . oauth2 . csrf ( ) ;
2015-07-20 00:09:47 -07:00
// public routes
2018-12-11 15:29:47 -08:00
router . post ( '/api/v1/cloudron/setup' , routes . provision . providerTokenAuth , routes . provision . setup ) ; // only available until no-domain
router . post ( '/api/v1/cloudron/restore' , routes . provision . restore ) ; // only available until activated
router . post ( '/api/v1/cloudron/activate' , routes . provision . setupTokenAuth , routes . provision . activate ) ;
2018-12-15 15:27:16 -08:00
router . get ( '/api/v1/cloudron/status' , routes . provision . getStatus ) ;
2017-11-22 11:16:44 -08:00
2015-07-20 00:09:47 -07:00
router . get ( '/api/v1/cloudron/avatar' , routes . settings . getCloudronAvatar ) ; // this is a public alias for /api/v1/settings/cloudron_avatar
// developer routes
2017-11-23 23:41:01 +01:00
router . post ( '/api/v1/developer/login' , routes . developer . login ) ;
2015-07-20 00:09:47 -07:00
2016-06-02 15:58:58 -07:00
// cloudron routes
2018-06-28 17:43:20 -07:00
router . get ( '/api/v1/cloudron/update' , cloudronScope , routes . cloudron . getUpdateInfo ) ;
2018-04-27 21:47:11 -07:00
router . post ( '/api/v1/cloudron/update' , cloudronScope , routes . cloudron . update ) ;
2018-12-18 15:05:36 -08:00
router . post ( '/api/v1/cloudron/prepare_dashboard_domain' , cloudronScope , routes . cloudron . prepareDashboardDomain ) ;
2019-02-26 19:43:18 -08:00
router . post ( '/api/v1/cloudron/set_dashboard_domain' , cloudronScope , routes . cloudron . setDashboardAndMailDomain ) ;
2018-12-10 20:20:53 -08:00
router . post ( '/api/v1/cloudron/renew_certs' , cloudronScope , routes . cloudron . renewCerts ) ;
2018-04-27 21:47:11 -07:00
router . post ( '/api/v1/cloudron/check_for_updates' , cloudronScope , routes . cloudron . checkForUpdates ) ;
2018-11-25 17:02:01 +01:00
router . get ( '/api/v1/cloudron/reboot' , cloudronScope , routes . cloudron . isRebootRequired ) ;
2018-04-27 21:47:11 -07:00
router . post ( '/api/v1/cloudron/reboot' , cloudronScope , routes . cloudron . reboot ) ;
router . get ( '/api/v1/cloudron/graphs' , cloudronScope , routes . graphs . getGraphs ) ;
router . get ( '/api/v1/cloudron/disks' , cloudronScope , routes . cloudron . getDisks ) ;
2018-06-11 20:09:38 +02:00
router . get ( '/api/v1/cloudron/logs/:unit' , cloudronScope , routes . cloudron . getLogs ) ;
router . get ( '/api/v1/cloudron/logstream/:unit' , cloudronScope , routes . cloudron . getLogStream ) ;
2019-01-23 16:44:45 +01:00
router . get ( '/api/v1/cloudron/eventlog' , cloudronScope , routes . eventlog . list ) ;
router . get ( '/api/v1/cloudron/eventlog/:eventId' , cloudronScope , routes . eventlog . get ) ;
2015-07-20 00:09:47 -07:00
2019-05-03 16:27:47 -07:00
// subscription routes
router . post ( '/api/v1/subscription' , subscriptionScope , routes . subscription . subscribeCloudron ) ;
2019-05-03 20:17:40 -07:00
router . get ( '/api/v1/subscription' , subscriptionScope , routes . subscription . getSubscription ) ;
2019-05-03 16:27:47 -07:00
2018-11-16 11:13:03 -08:00
// tasks
2018-12-08 20:12:23 -08:00
router . get ( '/api/v1/tasks' , settingsScope , routes . tasks . list ) ;
2018-11-30 14:16:00 -08:00
router . get ( '/api/v1/tasks/:taskId' , settingsScope , routes . tasks . get ) ;
2018-12-08 21:31:55 -08:00
router . get ( '/api/v1/tasks/:taskId/logs' , cloudronScope , routes . tasks . getLogs ) ;
router . get ( '/api/v1/tasks/:taskId/logstream' , cloudronScope , routes . tasks . getLogStream ) ;
2018-11-16 11:13:03 -08:00
router . post ( '/api/v1/tasks/:taskId/stop' , settingsScope , routes . tasks . stopTask ) ;
2018-11-17 19:53:15 -08:00
2018-12-17 16:37:19 +01:00
// notifications
router . get ( '/api/v1/notifications' , notificationsScope , routes . notifications . list ) ;
router . get ( '/api/v1/notifications/:notificationId' , notificationsScope , routes . notifications . get ) ;
router . post ( '/api/v1/notifications/:notificationId' , notificationsScope , routes . notifications . ack ) ;
2018-11-19 14:40:32 -08:00
// backups
router . get ( '/api/v1/backups' , settingsScope , routes . backups . list ) ;
2019-04-13 18:09:04 -07:00
router . post ( '/api/v1/backups/create' , settingsScope , routes . backups . startBackup ) ;
router . post ( '/api/v1/backups/cleanup' , settingsScope , routes . backups . cleanup ) ;
2018-11-19 14:40:32 -08:00
2018-06-28 17:40:57 -07:00
// config route (for dashboard)
router . get ( '/api/v1/config' , profileScope , routes . cloudron . getConfig ) ;
2018-04-26 19:57:44 -07:00
// working off the user behind the provided token
2018-05-13 21:52:48 -07:00
router . get ( '/api/v1/profile' , profileScope , routes . profile . get ) ;
router . post ( '/api/v1/profile' , profileScope , routes . profile . update ) ;
router . post ( '/api/v1/profile/password' , profileScope , routes . users . verifyPassword , routes . profile . changePassword ) ;
router . post ( '/api/v1/profile/twofactorauthentication' , profileScope , routes . profile . setTwoFactorAuthenticationSecret ) ;
router . post ( '/api/v1/profile/twofactorauthentication/enable' , profileScope , routes . profile . enableTwoFactorAuthentication ) ;
router . post ( '/api/v1/profile/twofactorauthentication/disable' , profileScope , routes . users . verifyPassword , routes . profile . disableTwoFactorAuthentication ) ;
2018-04-25 19:08:15 +02:00
2016-06-02 00:20:33 -07:00
// user routes
2018-06-25 15:54:24 -07:00
router . get ( '/api/v1/users' , usersReadScope , routes . users . list ) ;
router . post ( '/api/v1/users' , usersManageScope , routes . users . create ) ;
2018-08-03 21:52:31 -07:00
router . get ( '/api/v1/users/:userId' , usersManageScope , routes . users . get ) ; // this is manage scope because it returns non-restricted fields
2018-06-25 15:54:24 -07:00
router . del ( '/api/v1/users/:userId' , usersManageScope , routes . users . verifyPassword , routes . users . remove ) ;
router . post ( '/api/v1/users/:userId' , usersManageScope , routes . users . update ) ;
2018-08-31 14:30:00 -07:00
router . post ( '/api/v1/users/:userId/password' , usersManageScope , routes . users . changePassword ) ;
2018-06-25 15:54:24 -07:00
router . put ( '/api/v1/users/:userId/groups' , usersManageScope , routes . users . setGroups ) ;
2018-08-17 09:49:58 -07:00
router . post ( '/api/v1/users/:userId/send_invite' , usersManageScope , routes . users . sendInvite ) ;
router . post ( '/api/v1/users/:userId/create_invite' , usersManageScope , routes . users . createInvite ) ;
2018-06-28 16:48:04 -07:00
router . post ( '/api/v1/users/:userId/transfer' , usersManageScope , routes . users . transferOwnership ) ;
2015-07-20 00:09:47 -07:00
2016-02-09 13:34:01 -08:00
// Group management
2018-06-25 15:54:24 -07:00
router . get ( '/api/v1/groups' , usersReadScope , routes . groups . list ) ;
router . post ( '/api/v1/groups' , usersManageScope , routes . groups . create ) ;
router . get ( '/api/v1/groups/:groupId' , usersManageScope , routes . groups . get ) ;
router . put ( '/api/v1/groups/:groupId/members' , usersManageScope , routes . groups . updateMembers ) ;
router . post ( '/api/v1/groups/:groupId' , usersManageScope , routes . groups . update ) ;
router . del ( '/api/v1/groups/:groupId' , usersManageScope , routes . users . verifyPassword , routes . groups . remove ) ;
2016-02-09 13:34:01 -08:00
2015-07-20 00:09:47 -07:00
// form based login routes used by oauth2 frame
router . get ( '/api/v1/session/login' , csrf , routes . oauth2 . loginForm ) ;
router . post ( '/api/v1/session/login' , csrf , routes . oauth2 . login ) ;
router . get ( '/api/v1/session/logout' , routes . oauth2 . logout ) ;
2018-04-29 20:11:45 -07:00
router . get ( '/api/v1/session/callback' , routes . oauth2 . sessionCallback ( ) ) ;
2015-07-20 00:09:47 -07:00
router . get ( '/api/v1/session/password/resetRequest.html' , csrf , routes . oauth2 . passwordResetRequestSite ) ;
router . post ( '/api/v1/session/password/resetRequest' , csrf , routes . oauth2 . passwordResetRequest ) ;
router . get ( '/api/v1/session/password/sent.html' , routes . oauth2 . passwordSentSite ) ;
router . get ( '/api/v1/session/password/reset.html' , csrf , routes . oauth2 . passwordResetSite ) ;
router . post ( '/api/v1/session/password/reset' , csrf , routes . oauth2 . passwordReset ) ;
2016-04-01 16:32:22 +02:00
router . get ( '/api/v1/session/account/setup.html' , csrf , routes . oauth2 . accountSetupSite ) ;
2016-04-01 16:35:22 +02:00
router . post ( '/api/v1/session/account/setup' , csrf , routes . oauth2 . accountSetup ) ;
2015-07-20 00:09:47 -07:00
// oauth2 routes
2018-04-29 20:11:45 -07:00
router . get ( '/api/v1/oauth/dialog/authorize' , routes . oauth2 . authorization ( ) ) ;
router . post ( '/api/v1/oauth/token' , routes . oauth2 . token ( ) ) ;
2018-04-27 23:52:35 -07:00
2018-05-01 11:30:44 -07:00
// client/token routes
router . get ( '/api/v1/clients' , clientsScope , routes . clients . getAll ) ;
router . post ( '/api/v1/clients' , clientsScope , routes . clients . add ) ;
router . get ( '/api/v1/clients/:clientId' , clientsScope , routes . clients . get ) ;
router . post ( '/api/v1/clients/:clientId' , clientsScope , routes . clients . add ) ;
router . del ( '/api/v1/clients/:clientId' , clientsScope , routes . clients . del ) ;
router . get ( '/api/v1/clients/:clientId/tokens' , clientsScope , routes . clients . getTokens ) ;
router . post ( '/api/v1/clients/:clientId/tokens' , clientsScope , routes . clients . addToken ) ;
router . del ( '/api/v1/clients/:clientId/tokens' , clientsScope , routes . clients . delTokens ) ;
router . del ( '/api/v1/clients/:clientId/tokens/:tokenId' , clientsScope , routes . clients . delToken ) ;
2015-07-20 00:09:47 -07:00
2019-05-04 11:45:03 -07:00
// appstore routes
router . get ( '/api/v1/appstore/apps' , appstoreScope , routes . appstore . getApps ) ;
router . get ( '/api/v1/appstore/apps/:appstoreId' , appstoreScope , routes . appstore . getApp ) ;
router . get ( '/api/v1/appstore/apps/:appstoreId/versions/:versionId' , appstoreScope , routes . appstore . getAppVersion ) ;
2015-07-20 00:09:47 -07:00
// app routes
2018-06-25 16:45:15 -07:00
router . get ( '/api/v1/apps' , appsReadScope , routes . apps . getApps ) ;
router . get ( '/api/v1/apps/:id' , appsManageScope , routes . apps . getApp ) ;
2015-10-12 16:49:55 +02:00
router . get ( '/api/v1/apps/:id/icon' , routes . apps . getAppIcon ) ;
2015-07-20 00:09:47 -07:00
2018-06-25 16:45:15 -07:00
router . post ( '/api/v1/apps/install' , appsManageScope , routes . apps . installApp ) ;
router . post ( '/api/v1/apps/:id/uninstall' , appsManageScope , routes . users . verifyPassword , routes . apps . uninstallApp ) ;
router . post ( '/api/v1/apps/:id/configure' , appsManageScope , routes . apps . configureApp ) ;
router . post ( '/api/v1/apps/:id/update' , appsManageScope , routes . apps . updateApp ) ;
router . post ( '/api/v1/apps/:id/restore' , appsManageScope , routes . users . verifyPassword , routes . apps . restoreApp ) ;
router . post ( '/api/v1/apps/:id/backup' , appsManageScope , routes . apps . backupApp ) ;
router . get ( '/api/v1/apps/:id/backups' , appsManageScope , routes . apps . listBackups ) ;
router . post ( '/api/v1/apps/:id/stop' , appsManageScope , routes . apps . stopApp ) ;
router . post ( '/api/v1/apps/:id/start' , appsManageScope , routes . apps . startApp ) ;
router . get ( '/api/v1/apps/:id/logstream' , appsManageScope , routes . apps . getLogStream ) ;
router . get ( '/api/v1/apps/:id/logs' , appsManageScope , routes . apps . getLogs ) ;
router . get ( '/api/v1/apps/:id/exec' , appsManageScope , routes . apps . exec ) ;
2017-08-18 17:56:01 -07:00
// websocket cannot do bearer authentication
2018-09-05 23:02:06 -07:00
router . get ( '/api/v1/apps/:id/execws' , routes . accesscontrol . websocketAuth . bind ( null , [ accesscontrol . SCOPE _APPS _MANAGE ] ) , routes . apps . verifyOwnership , routes . apps . execWebSocket ) ;
2018-06-25 16:45:15 -07:00
router . post ( '/api/v1/apps/:id/clone' , appsManageScope , routes . apps . cloneApp ) ;
router . get ( '/api/v1/apps/:id/download' , appsManageScope , routes . apps . downloadFile ) ;
router . post ( '/api/v1/apps/:id/upload' , appsManageScope , multipart , routes . apps . uploadFile ) ;
2018-06-28 16:48:04 -07:00
router . post ( '/api/v1/apps/:id/owner' , appsManageScope , routes . apps . setOwner ) ;
2015-07-20 00:09:47 -07:00
2016-05-06 08:42:27 -07:00
// settings routes (these are for the settings tab - avatar & name have public routes for normal users. see above)
2019-01-25 14:57:07 -08:00
router . get ( '/api/v1/settings/:setting' , settingsScope , verifySettingsLock , routes . settings . get ) ;
router . post ( '/api/v1/settings/:setting' , settingsScope , verifySettingsLock , ( req , res , next ) => {
return req . params . setting === 'cloudron_avatar' ? multipart ( req , res , next ) : next ( ) ;
} , routes . settings . set ) ;
2018-10-12 17:04:04 -07:00
2017-06-28 17:06:12 -05:00
// email routes
2018-04-27 21:47:11 -07:00
router . get ( '/api/v1/mail/:domain' , mailScope , routes . mail . getDomain ) ;
router . post ( '/api/v1/mail' , mailScope , routes . mail . addDomain ) ;
router . get ( '/api/v1/mail/:domain/stats' , mailScope , routes . users . verifyPassword , routes . mail . getDomainStats ) ;
router . del ( '/api/v1/mail/:domain' , mailScope , routes . users . verifyPassword , routes . mail . removeDomain ) ;
router . get ( '/api/v1/mail/:domain/status' , mailScope , routes . mail . getStatus ) ;
router . post ( '/api/v1/mail/:domain/mail_from_validation' , mailScope , routes . mail . setMailFromValidation ) ;
router . post ( '/api/v1/mail/:domain/catch_all' , mailScope , routes . mail . setCatchAllAddress ) ;
router . post ( '/api/v1/mail/:domain/relay' , mailScope , routes . mail . setMailRelay ) ;
router . post ( '/api/v1/mail/:domain/enable' , mailScope , routes . mail . setMailEnabled ) ;
2018-07-25 10:29:26 -07:00
router . post ( '/api/v1/mail/:domain/dns' , mailScope , routes . mail . setDnsRecords ) ;
2018-04-27 21:47:11 -07:00
router . post ( '/api/v1/mail/:domain/send_test_mail' , mailScope , routes . mail . sendTestMail ) ;
2018-12-06 10:23:10 -08:00
router . get ( '/api/v1/mail/:domain/mailboxes' , mailScope , routes . mail . listMailboxes ) ;
2018-04-27 21:47:11 -07:00
router . get ( '/api/v1/mail/:domain/mailboxes/:name' , mailScope , routes . mail . getMailbox ) ;
router . post ( '/api/v1/mail/:domain/mailboxes' , mailScope , routes . mail . addMailbox ) ;
router . post ( '/api/v1/mail/:domain/mailboxes/:name' , mailScope , routes . mail . updateMailbox ) ;
router . del ( '/api/v1/mail/:domain/mailboxes/:name' , mailScope , routes . mail . removeMailbox ) ;
router . get ( '/api/v1/mail/:domain/aliases' , mailScope , routes . mail . listAliases ) ;
router . get ( '/api/v1/mail/:domain/aliases/:name' , mailScope , routes . mail . getAliases ) ;
router . put ( '/api/v1/mail/:domain/aliases/:name' , mailScope , routes . mail . setAliases ) ;
router . get ( '/api/v1/mail/:domain/lists' , mailScope , routes . mail . getLists ) ;
router . post ( '/api/v1/mail/:domain/lists' , mailScope , routes . mail . addList ) ;
router . get ( '/api/v1/mail/:domain/lists/:name' , mailScope , routes . mail . getList ) ;
router . post ( '/api/v1/mail/:domain/lists/:name' , mailScope , routes . mail . updateList ) ;
router . del ( '/api/v1/mail/:domain/lists/:name' , mailScope , routes . mail . removeList ) ;
2015-07-20 00:09:47 -07:00
2017-04-18 14:49:28 -07:00
// feedback
2018-12-19 10:54:33 -08:00
router . post ( '/api/v1/support/feedback' , cloudronScope , isUnmanaged , routes . support . feedback ) ;
2018-12-19 11:47:15 -08:00
router . get ( '/api/v1/support/remote_support' , cloudronScope , isUnmanaged , routes . support . getRemoteSupport ) ;
router . post ( '/api/v1/support/remote_support' , cloudronScope , isUnmanaged , routes . support . enableRemoteSupport ) ;
2017-04-18 14:49:28 -07:00
2017-10-28 22:18:07 +02:00
// domain routes
2018-06-25 15:12:20 -07:00
router . post ( '/api/v1/domains' , domainsManageScope , routes . domains . add ) ;
router . get ( '/api/v1/domains' , domainsReadScope , routes . domains . getAll ) ;
2018-09-05 22:58:43 -07:00
router . get ( '/api/v1/domains/:domain' , domainsManageScope , verifyDomainLock , routes . domains . get ) ; // this is manage scope because it returns non-restricted fields
router . put ( '/api/v1/domains/:domain' , domainsManageScope , verifyDomainLock , routes . domains . update ) ;
router . del ( '/api/v1/domains/:domain' , domainsManageScope , verifyDomainLock , routes . users . verifyPassword , routes . domains . del ) ;
2017-10-28 22:18:07 +02:00
2018-11-15 19:59:08 +01:00
// addon routes
2018-12-02 18:46:34 -08:00
router . get ( '/api/v1/services' , cloudronScope , routes . services . getAll ) ;
router . get ( '/api/v1/services/:service' , cloudronScope , routes . services . get ) ;
router . post ( '/api/v1/services/:service' , cloudronScope , routes . services . configure ) ;
router . get ( '/api/v1/services/:service/logs' , cloudronScope , routes . services . getLogs ) ;
router . get ( '/api/v1/services/:service/logstream' , cloudronScope , routes . services . getLogStream ) ;
router . post ( '/api/v1/services/:service/restart' , cloudronScope , routes . services . restart ) ;
2018-11-15 19:59:08 +01:00
2016-06-01 16:31:47 -07:00
// disable server socket "idle" timeout. we use the timeout middleware to handle timeouts on a route level
2016-06-01 17:33:04 -07:00
// we rely on nginx for timeouts on the TCP level (see client_header_timeout)
2016-01-18 12:20:09 -08:00
httpServer . setTimeout ( 0 ) ;
2015-07-20 00:09:47 -07:00
// upgrade handler
2017-08-17 09:32:38 +02:00
httpServer . on ( 'upgrade' , function ( req , socket , head ) {
2017-08-18 17:56:01 -07:00
// create a node response object for express
var res = new http . ServerResponse ( { } ) ;
res . assignSocket ( socket ) ;
2017-08-17 11:56:51 +02:00
if ( req . headers . upgrade === 'websocket' ) {
2017-08-18 17:56:01 -07:00
res . handleUpgrade = function ( callback ) {
wsServer . handleUpgrade ( req , socket , head , callback ) ;
} ;
2017-08-17 11:56:51 +02:00
} 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' ) ;
} ;
}
2017-08-18 17:56:01 -07:00
// 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 ) ;
2017-08-17 09:32:38 +02:00
} ) ;
2015-07-20 00:09:47 -07:00
return httpServer ;
}
2016-10-31 15:23:53 +01:00
// provides local webhooks for sysadmins
2016-04-15 12:33:54 -07:00
function initializeSysadminExpressSync ( ) {
2015-07-20 00:09:47 -07:00
var app = express ( ) ;
var httpServer = http . createServer ( app ) ;
2016-06-01 18:09:23 -07:00
var QUERY _LIMIT = '1mb' ; // max size for json and urlencoded queries
2016-06-30 15:01:42 +02:00
var REQUEST _TIMEOUT = 10000 ; // timeout for all requests
2015-07-20 00:09:47 -07:00
var json = middleware . json ( { strict : true , limit : QUERY _LIMIT } ) , // application/json
urlencoded = middleware . urlencoded ( { extended : false , limit : QUERY _LIMIT } ) ; // application/x-www-form-urlencoded
2016-04-15 12:33:54 -07:00
if ( process . env . BOX _ENV !== 'test' ) app . use ( middleware . morgan ( 'Box Sysadmin :method :url :status :response-time ms - :res[content-length]' , { immediate : false } ) ) ;
2015-07-20 00:09:47 -07:00
var router = new express . Router ( ) ;
router . del = router . delete ; // amend router.del for readability further on
app
2017-10-31 12:04:26 -07:00
. use ( middleware . timeout ( REQUEST _TIMEOUT ) )
. use ( json )
. use ( urlencoded )
. use ( router )
. use ( middleware . lastMile ( ) ) ;
2015-07-20 00:09:47 -07:00
2016-04-15 12:33:54 -07:00
// Sysadmin routes
router . post ( '/api/v1/backup' , routes . sysadmin . backup ) ;
router . post ( '/api/v1/update' , routes . sysadmin . update ) ;
router . post ( '/api/v1/retire' , routes . sysadmin . retire ) ;
2018-11-11 21:58:02 -08:00
router . post ( '/api/v1/apps/:id/import' , routes . sysadmin . importAppDatabase ) ;
2015-07-20 00:09:47 -07:00
2019-02-27 12:05:45 +01:00
// routes to test features otherwise hard to test
router . post ( '/api/v1/test/digest' , routes . sysadmin . testDigest ) ;
2015-07-20 00:09:47 -07:00
return httpServer ;
}
function start ( callback ) {
assert . strictEqual ( typeof callback , 'function' ) ;
assert . strictEqual ( gHttpServer , null , 'Server is already up and running.' ) ;
2018-05-01 13:34:46 -07:00
routes . oauth2 . initialize ( ) ; // init's the oauth server
2018-04-29 20:11:45 -07:00
2015-07-20 00:09:47 -07:00
gHttpServer = initializeExpressSync ( ) ;
2016-04-15 12:33:54 -07:00
gSysadminHttpServer = initializeSysadminExpressSync ( ) ;
2015-07-20 00:09:47 -07:00
async . series ( [
2018-06-15 17:31:28 -07:00
routes . accesscontrol . initialize , // hooks up authentication strategies into passport
2015-07-20 00:09:47 -07:00
database . initialize ,
2017-01-09 12:35:39 -08:00
cloudron . initialize ,
2015-07-20 00:09:47 -07:00
gHttpServer . listen . bind ( gHttpServer , config . get ( 'port' ) , '127.0.0.1' ) ,
2016-05-02 09:39:38 -07:00
gSysadminHttpServer . listen . bind ( gSysadminHttpServer , config . get ( 'sysadminPort' ) , '127.0.0.1' ) ,
eventlog . add . bind ( null , eventlog . ACTION _START , { userId : null , username : 'boot' } , { version : config . version ( ) } )
2015-07-20 00:09:47 -07:00
] , callback ) ;
}
function stop ( callback ) {
assert . strictEqual ( typeof callback , 'function' ) ;
if ( ! gHttpServer ) return callback ( null ) ;
async . series ( [
cloudron . uninitialize ,
database . uninitialize ,
2018-06-15 17:31:28 -07:00
routes . accesscontrol . uninitialize ,
2015-07-20 00:09:47 -07:00
gHttpServer . close . bind ( gHttpServer ) ,
2016-04-15 12:33:54 -07:00
gSysadminHttpServer . close . bind ( gSysadminHttpServer )
2015-07-20 00:09:47 -07:00
] , function ( error ) {
2018-11-10 13:58:18 -08:00
if ( error ) return callback ( error ) ;
2015-07-20 00:09:47 -07:00
2018-04-29 20:11:45 -07:00
routes . oauth2 . uninitialize ( ) ;
2015-07-20 00:09:47 -07:00
gHttpServer = null ;
2016-04-15 12:33:54 -07:00
gSysadminHttpServer = null ;
2015-07-20 00:09:47 -07:00
callback ( null ) ;
} ) ;
}