diff --git a/migrations/20190703031708-apps-remove-ownerId.js b/migrations/20190703031708-apps-remove-ownerId.js new file mode 100644 index 000000000..95f3ded83 --- /dev/null +++ b/migrations/20190703031708-apps-remove-ownerId.js @@ -0,0 +1,14 @@ +'use strict'; + +var async = require('async'); + +exports.up = function(db, callback) { + async.series([ + db.runSql.bind(db, 'ALTER TABLE apps DROP FOREIGN KEY apps_owner_constraint'), + db.runSql.bind(db, 'ALTER TABLE apps DROP COLUMN ownerId') + ], callback); +}; + +exports.down = function(db, callback) { + callback(); +}; diff --git a/migrations/schema.sql b/migrations/schema.sql index f42931593..72ebc9f10 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -93,9 +93,6 @@ CREATE TABLE IF NOT EXISTS apps( oldConfigJson TEXT, // used to pass old config to apptask (configure, restore) updateConfigJson TEXT, // used to pass new config to apptask (update) - ownerId VARCHAR(128), - - FOREIGN KEY(ownerId) REFERENCES users(id), PRIMARY KEY(id)); CREATE TABLE IF NOT EXISTS appPortBindings( diff --git a/src/appdb.js b/src/appdb.js index 7d0d057bd..b14b28dae 100644 --- a/src/appdb.js +++ b/src/appdb.js @@ -25,9 +25,6 @@ exports = module.exports = { setRunCommand: setRunCommand, getAppStoreIds: getAppStoreIds, - setOwner: setOwner, - transferOwnership: transferOwnership, - // installation codes (keep in sync in UI) ISTATE_PENDING_INSTALL: 'pending_install', // installs and fresh reinstalls ISTATE_PENDING_CLONE: 'pending_clone', // clone @@ -70,7 +67,7 @@ var APPS_FIELDS_PREFIXED = [ 'apps.id', 'apps.appStoreId', 'apps.installationSta 'apps.accessRestrictionJson', 'apps.restoreConfigJson', 'apps.oldConfigJson', 'apps.updateConfigJson', 'apps.memoryLimit', 'apps.label', 'apps.tagsJson', 'apps.sso', 'apps.debugModeJson', 'apps.robotsTxt', 'apps.enableBackup', - 'apps.creationTime', 'apps.updateTime', 'apps.ownerId', 'apps.mailboxName', 'apps.enableAutomaticUpdate', + 'apps.creationTime', 'apps.updateTime', 'apps.mailboxName', 'apps.enableAutomaticUpdate', 'apps.dataDir', 'apps.ts', 'apps.healthTime' ].join(','); var PORT_BINDINGS_FIELDS = [ 'hostPort', 'type', 'environmentVariable', 'appId' ].join(','); @@ -257,14 +254,13 @@ function getAll(callback) { }); } -function add(id, appStoreId, manifest, location, domain, ownerId, portBindings, data, callback) { +function add(id, appStoreId, manifest, location, domain, portBindings, data, callback) { assert.strictEqual(typeof id, 'string'); assert.strictEqual(typeof appStoreId, 'string'); assert(manifest && typeof manifest === 'object'); assert.strictEqual(typeof manifest.version, 'string'); assert.strictEqual(typeof location, 'string'); assert.strictEqual(typeof domain, 'string'); - assert.strictEqual(typeof ownerId, 'string'); assert.strictEqual(typeof portBindings, 'object'); assert(data && typeof data === 'object'); assert.strictEqual(typeof callback, 'function'); @@ -290,10 +286,10 @@ function add(id, appStoreId, manifest, location, domain, ownerId, portBindings, queries.push({ query: 'INSERT INTO apps (id, appStoreId, manifestJson, installationState, accessRestrictionJson, memoryLimit, ' - + 'restoreConfigJson, sso, debugModeJson, robotsTxt, ownerId, mailboxName, label, tagsJson) ' - + ' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + + 'restoreConfigJson, sso, debugModeJson, robotsTxt, mailboxName, label, tagsJson) ' + + ' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', args: [ id, appStoreId, manifestJson, installationState, accessRestrictionJson, memoryLimit, restoreConfigJson, - sso, debugModeJson, robotsTxt, ownerId, mailboxName, label, tagsJson ] + sso, debugModeJson, robotsTxt, mailboxName, label, tagsJson ] }); queries.push({ @@ -648,31 +644,3 @@ function getAddonConfigByName(appId, addonId, namePattern, callback) { callback(null, results[0].value); }); } - -function setOwner(appId, ownerId, callback) { - assert.strictEqual(typeof appId, 'string'); - assert.strictEqual(typeof ownerId, 'string'); - assert.strictEqual(typeof callback, 'function'); - - database.query('UPDATE apps SET ownerId=? WHERE appId=?', [ ownerId, appId ], function (error, results) { - if (error && error.code === 'ER_NO_REFERENCED_ROW_2') return callback(new DatabaseError(DatabaseError.NOT_FOUND, 'No such user')); - if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); - - if (results.length === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND, 'No such app')); - - callback(null); - }); -} - -function transferOwnership(oldOwnerId, newOwnerId, callback) { - assert.strictEqual(typeof oldOwnerId, 'string'); - assert.strictEqual(typeof newOwnerId, 'string'); - assert.strictEqual(typeof callback, 'function'); - - database.query('UPDATE apps SET ownerId=? WHERE ownerId=?', [ newOwnerId, oldOwnerId ], function (error) { - if (error && error.code === 'ER_NO_REFERENCED_ROW_2') return callback(new DatabaseError(DatabaseError.NOT_FOUND, 'No such user')); - if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); - - callback(null); - }); -} diff --git a/src/apps.js b/src/apps.js index da3dd5fe6..ca8b2472b 100644 --- a/src/apps.js +++ b/src/apps.js @@ -46,9 +46,6 @@ exports = module.exports = { downloadFile: downloadFile, uploadFile: uploadFile, - setOwner: setOwner, - transferOwnership: transferOwnership, - PORT_TYPE_TCP: 'tcp', PORT_TYPE_UDP: 'udp', @@ -384,13 +381,13 @@ function removeInternalFields(app) { 'location', 'domain', 'fqdn', 'mailboxName', 'accessRestriction', 'manifest', 'portBindings', 'iconUrl', 'memoryLimit', 'sso', 'debugMode', 'robotsTxt', 'enableBackup', 'creationTime', 'updateTime', 'ts', 'tags', - 'label', 'alternateDomains', 'ownerId', 'env', 'enableAutomaticUpdate', 'dataDir'); + 'label', 'alternateDomains', 'env', 'enableAutomaticUpdate', 'dataDir'); } // non-admins can only see these function removeRestrictedFields(app) { return _.pick(app, - 'id', 'appStoreId', 'installationState', 'installationProgress', 'runState', 'health', 'ownerId', + 'id', 'appStoreId', 'installationState', 'installationProgress', 'runState', 'health', 'location', 'domain', 'fqdn', 'manifest', 'portBindings', 'iconUrl', 'creationTime', 'ts', 'tags', 'label'); } @@ -593,7 +590,6 @@ function install(data, user, auditSource, callback) { enableAutomaticUpdate = 'enableAutomaticUpdate' in data ? data.enableAutomaticUpdate : true, backupId = data.backupId || null, backupFormat = data.backupFormat || 'tgz', - ownerId = data.ownerId, alternateDomains = data.alternateDomains || [], env = data.env || {}, mailboxName = data.mailboxName || '', @@ -687,7 +683,7 @@ function install(data, user, auditSource, callback) { env: env }; - appdb.add(appId, appStoreId, manifest, location, domain, ownerId, translatePortBindings(portBindings, manifest), data, function (error) { + appdb.add(appId, appStoreId, manifest, location, domain, translatePortBindings(portBindings, manifest), data, function (error) { if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(getDuplicateErrorDetails(error, location, domainObject, portBindings, data.alternateDomains)); if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, error.message)); if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); @@ -1080,14 +1076,12 @@ function clone(appId, data, user, auditSource, callback) { domain = data.domain.toLowerCase(), portBindings = data.portBindings || null, backupId = data.backupId, - ownerId = data.ownerId, mailboxName = data.mailboxName || ''; assert.strictEqual(typeof backupId, 'string'); assert.strictEqual(typeof location, 'string'); assert.strictEqual(typeof domain, 'string'); assert.strictEqual(typeof portBindings, 'object'); - assert(ownerId === null || typeof ownerId === 'string'); get(appId, function (error, app) { if (error) return callback(error); @@ -1136,7 +1130,7 @@ function clone(appId, data, user, auditSource, callback) { env: app.env }; - appdb.add(newAppId, app.appStoreId, manifest, location, domain, ownerId, translatePortBindings(portBindings, manifest), data, function (error) { + appdb.add(newAppId, app.appStoreId, manifest, location, domain, translatePortBindings(portBindings, manifest), data, function (error) { if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(getDuplicateErrorDetails(error, location, domainObject, portBindings, [])); if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); @@ -1527,28 +1521,3 @@ function uploadFile(appId, sourceFilePath, destFilePath, callback) { readFile.pipe(stream); }); } - -function setOwner(appId, ownerId, callback) { - assert.strictEqual(typeof appId, 'string'); - assert.strictEqual(typeof callback, 'function'); - - appdb.setOwner(appId, ownerId, function (error) { - if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, error.message)); - if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); - - callback(); - }); -} - -function transferOwnership(oldOwnerId, newOwnerId, callback) { - assert.strictEqual(typeof oldOwnerId, 'string'); - assert.strictEqual(typeof newOwnerId, 'string'); - assert.strictEqual(typeof callback, 'function'); - - appdb.transferOwnership(oldOwnerId, newOwnerId, function (error) { - if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new AppsError(AppsError.NOT_FOUND, error.message)); - if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); - - callback(); - }); -} diff --git a/src/ldap.js b/src/ldap.js index 3d9ea4374..027f52cbd 100644 --- a/src/ldap.js +++ b/src/ldap.js @@ -135,7 +135,7 @@ function userSearch(req, res, next) { var dn = ldap.parseDN('cn=' + entry.id + ',ou=users,dc=cloudron'); var groups = [ GROUP_USERS_DN ]; - if (entry.admin || req.app.ownerId === entry.id) groups.push(GROUP_ADMINS_DN); + if (entry.admin) groups.push(GROUP_ADMINS_DN); var displayName = entry.displayName || entry.username || ''; // displayName can be empty and username can be null var nameParts = displayName.split(' '); @@ -155,7 +155,7 @@ function userSearch(req, res, next) { givenName: firstName, username: entry.username, samaccountname: entry.username, // to support ActiveDirectory clients - isadmin: (entry.admin || req.app.ownerId === entry.id) ? 1 : 0, + isadmin: entry.admin, memberof: groups } }; @@ -195,7 +195,7 @@ function groupSearch(req, res, next) { groups.forEach(function (group) { var dn = ldap.parseDN('cn=' + group.name + ',ou=groups,dc=cloudron'); - var members = group.admin ? result.filter(function (entry) { return entry.admin || req.app.ownerId === entry.id; }) : result; + var members = group.admin ? result.filter(function (entry) { return entry.admin; }) : result; var obj = { dn: dn.toString(), @@ -244,7 +244,7 @@ function groupAdminsCompare(req, res, next) { // we only support memberuid here, if we add new group attributes later add them here if (req.attribute === 'memberuid') { var found = result.find(function (u) { return u.id === req.value; }); - if (found && (found.admin || req.app.ownerId == found.id)) return res.end(true); + if (found && found.admin) return res.end(true); } res.end(false); diff --git a/src/routes/apps.js b/src/routes/apps.js index 30dec3088..f86aaa36b 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -21,8 +21,6 @@ exports = module.exports = { cloneApp: cloneApp, - setOwner: setOwner, - uploadFile: uploadFile, downloadFile: downloadFile }; @@ -80,7 +78,6 @@ function installApp(req, res, next) { assert.strictEqual(typeof req.body, 'object'); var data = req.body; - data.ownerId = req.user.id; // atleast one if ('manifest' in data && typeof data.manifest !== 'object') return next(new HttpError(400, 'manifest must be an object')); @@ -233,7 +230,6 @@ function cloneApp(req, res, next) { assert.strictEqual(typeof req.params.id, 'string'); var data = req.body; - data.ownerId = req.user.id; debug('Clone app id:%s', req.params.id); @@ -584,17 +580,3 @@ function downloadFile(req, res, next) { stream.pipe(res); }); } - -function setOwner(req, res, next) { - assert.strictEqual(typeof req.params.id, 'string'); - assert.strictEqual(typeof req.body, 'object'); - - if (typeof req.body.ownerId !== 'string') return next(new HttpError(400, 'ownerId must be a string')); - - apps.setOwner(req.params.id, req.body.ownerId, function (error) { - if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, error.message)); - if (error) return next(new HttpError(500, error)); - - next(new HttpSuccess(200, { })); - }); -} diff --git a/src/routes/test/backups-test.js b/src/routes/test/backups-test.js index 030cf6959..e29a0d7d7 100644 --- a/src/routes/test/backups-test.js +++ b/src/routes/test/backups-test.js @@ -31,7 +31,7 @@ const DOMAIN_0 = { let AUDIT_SOURCE = { ip: '1.2.3.4' }; -var token = null, ownerId = null; +var token = null; function setup(done) { nock.cleanAll(); @@ -51,7 +51,6 @@ function setup(done) { expect(result.statusCode).to.eql(201); // stash token for further use - ownerId = result.body.userId; token = result.body.token; callback(); @@ -60,7 +59,7 @@ function setup(done) { function addApp(callback) { var manifest = { version: '0.0.1', manifestVersion: 1, dockerImage: 'foo', healthCheckPath: '/', httpPort: 3, title: 'ok', addons: { } }; - appdb.add('appid', 'appStoreId', manifest, 'location', DOMAIN_0.domain, ownerId, [ ] /* portBindings */, { }, callback); + appdb.add('appid', 'appStoreId', manifest, 'location', DOMAIN_0.domain, [ ] /* portBindings */, { }, callback); }, function createSettings(callback) { diff --git a/src/routes/test/oauth2-test.js b/src/routes/test/oauth2-test.js index 68526932d..92a867cc4 100644 --- a/src/routes/test/oauth2-test.js +++ b/src/routes/test/oauth2-test.js @@ -64,8 +64,7 @@ describe('OAuth2', function () { domain: DOMAIN_0.domain, portBindings: {}, accessRestriction: null, - memoryLimit: 0, - ownerId: USER_0.id + memoryLimit: 0 }; var APP_1 = { @@ -76,8 +75,7 @@ describe('OAuth2', function () { domain: DOMAIN_0.domain, portBindings: {}, accessRestriction: { users: [ 'foobar' ] }, - memoryLimit: 0, - ownerId: USER_0.id + memoryLimit: 0 }; var APP_2 = { @@ -88,8 +86,7 @@ describe('OAuth2', function () { domain: DOMAIN_0.domain, portBindings: {}, accessRestriction: { users: [ USER_0.id ] }, - memoryLimit: 0, - ownerId: USER_0.id + memoryLimit: 0 }; var APP_3 = { @@ -100,8 +97,7 @@ describe('OAuth2', function () { domain: DOMAIN_0.domain, portBindings: {}, accessRestriction: { groups: [ 'someothergroup', 'admin', 'anothergroup' ] }, - memoryLimit: 0, - ownerId: USER_0.id + memoryLimit: 0 }; // unknown app @@ -225,14 +221,13 @@ describe('OAuth2', function () { expect(error).to.not.be.ok(); // update the global objects to reflect the new user id - USER_0.id = APP_0.ownerId = APP_1.ownerId = APP_2.ownerId = APP_3.ownerId = userObject.id; APP_2.accessRestriction = { users: [ 'foobar', userObject.id ] }; async.series([ - appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.ownerId, APP_0.portBindings, APP_0), - appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.domain, APP_1.ownerId, APP_1.portBindings, APP_1), - appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.domain, APP_2.ownerId, APP_2.portBindings, APP_2), - appdb.add.bind(null, APP_3.id, APP_3.appStoreId, APP_3.manifest, APP_3.location, APP_3.domain, APP_3.ownerId, APP_3.portBindings, APP_3), + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.portBindings, APP_0), + appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.domain, APP_1.portBindings, APP_1), + appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.domain, APP_2.portBindings, APP_2), + appdb.add.bind(null, APP_3.id, APP_3.appStoreId, APP_3.manifest, APP_3.location, APP_3.domain, APP_3.portBindings, APP_3), appdb.update.bind(null, APP_2.id, APP_2) ], callback); diff --git a/src/routes/users.js b/src/routes/users.js index 621644aec..4a7eeb3e6 100644 --- a/src/routes/users.js +++ b/src/routes/users.js @@ -10,8 +10,7 @@ exports = module.exports = { verifyPassword: verifyPassword, createInvite: createInvite, sendInvite: sendInvite, - setGroups: setGroups, - transferOwnership: transferOwnership + setGroups: setGroups }; var assert = require('assert'), @@ -179,20 +178,6 @@ function setGroups(req, res, next) { }); } -function transferOwnership(req, res, next) { - assert.strictEqual(typeof req.body, 'object'); - assert.strictEqual(typeof req.params.userId, 'string'); - - if (typeof req.body.ownerId !== 'string') return next(new HttpError(400, 'ownerId must be a string')); - - users.transferOwnership(req.params.userId, req.body.ownerId, auditSource.fromRequest(req), function (error) { - if (error && error.reason === UsersError.NOT_FOUND) return next(new HttpError(404, 'No such user')); - if (error) return next(new HttpError(500, error)); - - next(new HttpSuccess(200, {})); - }); -} - function changePassword(req, res, next) { assert.strictEqual(typeof req.body, 'object'); assert.strictEqual(typeof req.params.userId, 'string'); diff --git a/src/server.js b/src/server.js index befb951d0..5d3f368b0 100644 --- a/src/server.js +++ b/src/server.js @@ -173,7 +173,6 @@ function initializeExpressSync() { router.put ('/api/v1/users/:userId/groups', usersManageScope, routes.users.setGroups); router.post('/api/v1/users/:userId/send_invite', usersManageScope, routes.users.sendInvite); router.post('/api/v1/users/:userId/create_invite', usersManageScope, routes.users.createInvite); - router.post('/api/v1/users/:userId/transfer', usersManageScope, routes.users.transferOwnership); // Group management router.get ('/api/v1/groups', usersReadScope, routes.groups.list); @@ -240,7 +239,6 @@ function initializeExpressSync() { 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); - router.post('/api/v1/apps/:id/owner', appsManageScope, routes.apps.setOwner); // settings routes (these are for the settings tab - avatar & name have public routes for normal users. see above) router.get ('/api/v1/settings/:setting', settingsScope, routes.settings.get); diff --git a/src/test/apps-test.js b/src/test/apps-test.js index f6a4fed73..2bae21247 100644 --- a/src/test/apps-test.js +++ b/src/test/apps-test.js @@ -115,7 +115,6 @@ describe('Apps', function () { memoryLimit: 0, robotsTxt: null, sso: false, - ownerId: USER_0.id, env: { 'CUSTOM_KEY': 'CUSTOM_VALUE' }, @@ -135,7 +134,6 @@ describe('Apps', function () { portBindings: {}, accessRestriction: { users: [ 'someuser' ], groups: [ GROUP_0.id ] }, memoryLimit: 0, - ownerId: USER_0.id, env: {}, dataDir: '' }; @@ -155,7 +153,6 @@ describe('Apps', function () { memoryLimit: 0, robotsTxt: null, sso: false, - ownerId: USER_0.id, env: {}, dataDir: '' }; @@ -177,9 +174,9 @@ describe('Apps', function () { groupdb.add.bind(null, GROUP_0.id, GROUP_0.name), groupdb.add.bind(null, GROUP_1.id, GROUP_1.name), groups.addMember.bind(null, GROUP_0.id, USER_1.id), - appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.ownerId, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0), - appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.domain, APP_1.ownerId, apps._translatePortBindings(APP_1.portBindings, APP_1.manifest), APP_1), - appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.domain, APP_2.ownerId, apps._translatePortBindings(APP_2.portBindings, APP_2.manifest), APP_2), + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0), + appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.domain, apps._translatePortBindings(APP_1.portBindings, APP_1.manifest), APP_1), + appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.domain, apps._translatePortBindings(APP_2.portBindings, APP_2.manifest), APP_2), ], done); }); diff --git a/src/test/apptask-test.js b/src/test/apptask-test.js index 12bdf4237..e0660f82f 100644 --- a/src/test/apptask-test.js +++ b/src/test/apptask-test.js @@ -91,8 +91,7 @@ var APP = { httpPort: 4567, portBindings: null, accessRestriction: null, - memoryLimit: 0, - ownerId: ADMIN.id + memoryLimit: 0 }; var awsHostedZones; @@ -123,7 +122,7 @@ describe('apptask', function () { database._clear, domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE), userdb.add.bind(null, ADMIN.id, ADMIN), - appdb.add.bind(null, APP.id, APP.appStoreId, APP.manifest, APP.location, APP.domain, APP.ownerId, APP.portBindings, APP) + appdb.add.bind(null, APP.id, APP.appStoreId, APP.manifest, APP.location, APP.domain, APP.portBindings, APP) ], done); }); diff --git a/src/test/database-test.js b/src/test/database-test.js index a8356ef5d..3f701a85e 100644 --- a/src/test/database-test.js +++ b/src/test/database-test.js @@ -416,7 +416,6 @@ describe('database', function () { debugMode: null, robotsTxt: null, enableBackup: true, - ownerId: USER_0.id, env: {}, mailboxName: 'talktome', enableAutomaticUpdate: true, @@ -426,7 +425,7 @@ describe('database', function () { }; it('cannot delete referenced domain', function (done) { - appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.ownerId, APP_0.portBindings, APP_0, function (error) { + appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.portBindings, APP_0, function (error) { expect(error).to.be(null); domaindb.del(DOMAIN_0.domain, function (error) { @@ -996,7 +995,6 @@ describe('database', function () { debugMode: null, robotsTxt: null, enableBackup: true, - ownerId: USER_0.id, alternateDomains: [], env: { 'CUSTOM_KEY': 'CUSTOM_VALUE' @@ -1030,7 +1028,6 @@ describe('database', function () { debugMode: null, robotsTxt: null, enableBackup: true, - ownerId: USER_0.id, alternateDomains: [], env: {}, mailboxName: 'callme', @@ -1065,7 +1062,7 @@ describe('database', function () { }); it('add succeeds', function (done) { - appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.ownerId, APP_0.portBindings, APP_0, function (error) { + appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.portBindings, APP_0, function (error) { expect(error).to.be(null); done(); }); @@ -1089,7 +1086,7 @@ describe('database', function () { }); it('add of same app fails', function (done) { - appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.ownerId, [], APP_0, function (error) { + appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, [], APP_0, function (error) { expect(error).to.be.a(DatabaseError); expect(error.reason).to.be(DatabaseError.ALREADY_EXISTS); done(); @@ -1162,7 +1159,7 @@ describe('database', function () { }); it('add second app succeeds', function (done) { - appdb.add(APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.domain, APP_0.ownerId, [], APP_1, function (error) { + appdb.add(APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.domain, [], APP_1, function (error) { expect(error).to.be(null); done(); }); diff --git a/src/test/ldap-test.js b/src/test/ldap-test.js index 5fabf1781..7e11f71b8 100644 --- a/src/test/ldap-test.js +++ b/src/test/ldap-test.js @@ -79,7 +79,6 @@ var APP_0 = { restoreConfig: null, oldConfig: null, memoryLimit: 4294967296, - ownerId: null, mailboxName: 'some-location-0.app' }; @@ -105,11 +104,12 @@ function setup(done) { users.createOwner(USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE, function (error, result) { if (error) return callback(error); - USER_0.id = APP_0.ownerId = result.id; + USER_0.id = result.id; - appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.ownerId, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0, callback); + callback(); }); }, + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0), (done) => mailboxdb.addMailbox(USER_0.username.toLowerCase(), DOMAIN_0.domain, USER_0.id, done), (done) => mailboxdb.setAliasesForName(USER_0.username.toLowerCase(), DOMAIN_0.domain, [ USER_0_ALIAS.toLocaleLowerCase() ], done), appdb.update.bind(null, APP_0.id, { containerId: APP_0.containerId }), @@ -185,6 +185,15 @@ function setup(done) { } }; status = 200; + } else if (req.method === 'GET' && req.url === '/containers/someContainerId/json') { + answer = { + Config: { + Labels: { + appId: APP_0.id + } + } + }; + status = 200; } res.writeHead(status); @@ -554,42 +563,6 @@ describe('Ldap', function () { }); }); }); - - it ('lists the owner as admin', function (done) { - // make a normal user the owner - appdb.update(APP_0.id, { ownerId: USER_1.id, accessRestriction: { users: [], groups: [ GROUP_ID ] } }, function (error) { - expect(error).to.be(null); - - var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') }); - - var opts = { - filter: 'objectcategory=person' - }; - - client.search('ou=users,dc=cloudron', opts, function (error, result) { - expect(error).to.be(null); - expect(result).to.be.an(EventEmitter); - - var entries = []; - - result.on('searchEntry', function (entry) { entries.push(entry.object); }); - result.on('error', done); - result.on('end', function (result) { - expect(result.status).to.equal(0); - expect(entries.length).to.equal(2); - entries.sort(function (a, b) { return a.username > b.username; }); - - expect(entries[0].username).to.equal(USER_0.username.toLowerCase()); - expect(entries[1].username).to.equal(USER_1.username.toLowerCase()); - expect(entries[1].isadmin).to.equal('1'); - - client.unbind(); - - appdb.update(APP_0.id, { ownerId: USER_0.id, accessRestriction: null }, done); - }); - }); - }); - }); }); describe('search groups', function () { @@ -760,45 +733,6 @@ describe('Ldap', function () { }); }); }); - - it ('shows owner as admin', function (done) { - appdb.update(APP_0.id, { ownerId: USER_1.id, accessRestriction: { users: [], groups: [ GROUP_ID ] } }, function (error) { - expect(error).to.be(null); - - var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') }); - - var opts = { - filter: '&(objectclass=group)(cn=*)' - }; - - client.search('ou=groups,dc=cloudron', opts, function (error, result) { - expect(error).to.be(null); - expect(result).to.be.an(EventEmitter); - - var entries = []; - - result.on('searchEntry', function (entry) { entries.push(entry.object); }); - result.on('error', done); - result.on('end', function (result) { - expect(result.status).to.equal(0); - expect(entries.length).to.equal(2); - expect(entries[0].cn).to.equal('users'); - expect(entries[0].memberuid.length).to.equal(2); - expect(entries[0].memberuid[0]).to.equal(USER_0.id); - expect(entries[0].memberuid[1]).to.equal(USER_1.id); - expect(entries[1].cn).to.equal('admins'); - - expect(entries[1].memberuid.length).to.equal(2); - expect(entries[1].memberuid[0]).to.equal(USER_0.id); - expect(entries[1].memberuid[1]).to.equal(USER_1.id); - - client.unbind(); - - appdb.update(APP_0.id, { ownerId: USER_0.id, accessRestriction: null }, done); - }); - }); - }); - }); }); // ldapsearch -LLL -E pr=10/noprompt -x -h localhost -p 3002 -b cn=userName0@example.com,ou=mailboxes,dc=cloudron objectclass=mailbox diff --git a/src/test/updatechecker-test.js b/src/test/updatechecker-test.js index d3d090f14..b786f6dbd 100644 --- a/src/test/updatechecker-test.js +++ b/src/test/updatechecker-test.js @@ -245,8 +245,7 @@ describe('updatechecker - app - manual (email)', function () { portBindings: { PORT: 5678 }, healthy: null, accessRestriction: null, - memoryLimit: 0, - ownerId: null + memoryLimit: 0 }; before(function (done) { @@ -263,14 +262,8 @@ describe('updatechecker - app - manual (email)', function () { cron.startJobs, domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE), mail.addDomain.bind(null, DOMAIN_0.domain), - function (next) { - users.createOwner(USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE, function (error, userObject) { - if (error) return next(error); - - APP_0.ownerId = userObject.id; - appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.ownerId, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0, next); - }); - }, + users.createOwner.bind(null, USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE), + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0), settings.setAppAutoupdatePattern.bind(null, constants.AUTOUPDATE_PATTERN_NEVER), settingsdb.set.bind(null, settings.CLOUDRON_TOKEN_KEY, 'atoken'), ], done); @@ -363,8 +356,7 @@ describe('updatechecker - app - automatic (no email)', function () { portBindings: { PORT: 5678 }, healthy: null, accessRestriction: null, - memoryLimit: 0, - ownerId: null + memoryLimit: 0 }; before(function (done) { @@ -381,14 +373,8 @@ describe('updatechecker - app - automatic (no email)', function () { cron.startJobs, domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE), mail.addDomain.bind(null, DOMAIN_0.domain), - function (next) { - users.createOwner(USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE, function (error, userObject) { - if (error) return next(error); - - APP_0.ownerId = userObject.id; - appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.ownerId, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0, next); - }); - }, + users.createOwner.bind(null, USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE), + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0), settings.setAppAutoupdatePattern.bind(null, '00 00 1,3,5,23 * * *'), settingsdb.set.bind(null, settings.CLOUDRON_TOKEN_KEY, 'atoken'), ], done); @@ -437,8 +423,7 @@ describe('updatechecker - app - automatic free (email)', function () { portBindings: { PORT: 5678 }, healthy: null, accessRestriction: null, - memoryLimit: 0, - ownerId: null + memoryLimit: 0 }; before(function (done) { @@ -455,14 +440,8 @@ describe('updatechecker - app - automatic free (email)', function () { cron.startJobs, domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE), mail.addDomain.bind(null, DOMAIN_0.domain), - function (next) { - users.createOwner(USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE, function (error, userObject) { - if (error) return next(error); - - APP_0.ownerId = userObject.id; - appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, APP_0.ownerId, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0, next); - }); - }, + users.createOwner.bind(null, USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE), + appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.domain, apps._translatePortBindings(APP_0.portBindings, APP_0.manifest), APP_0), settings.setAppAutoupdatePattern.bind(null, '00 00 1,3,5,23 * * *'), settingsdb.set.bind(null, settings.CLOUDRON_TOKEN_KEY, 'atoken'), ], done); diff --git a/src/users.js b/src/users.js index 10390ec1e..4424957f3 100644 --- a/src/users.js +++ b/src/users.js @@ -29,12 +29,11 @@ exports = module.exports = { setTwoFactorAuthenticationSecret: setTwoFactorAuthenticationSecret, enableTwoFactorAuthentication: enableTwoFactorAuthentication, disableTwoFactorAuthentication: disableTwoFactorAuthentication, - transferOwnership: transferOwnership + + count: count }; -var apps = require('./apps.js'), - AppsError = apps.AppsError, - assert = require('assert'), +let assert = require('assert'), crypto = require('crypto'), config = require('./config.js'), constants = require('./constants.js'), @@ -542,7 +541,7 @@ function createOwner(username, password, email, displayName, auditSource, callba // This is only not allowed for the owner if (username === '') return callback(new UsersError(UsersError.BAD_FIELD, 'Username cannot be empty')); - userdb.count(function (error, count) { + count(function (error, count) { if (error) return callback(new UsersError(UsersError.INTERNAL_ERROR, error)); if (count !== 0) return callback(new UsersError(UsersError.ALREADY_EXISTS, 'Owner already exists')); @@ -655,19 +654,3 @@ function disableTwoFactorAuthentication(userId, callback) { callback(null); }); } - -function transferOwnership(oldOwnerId, newOwnerId, auditSource, callback) { - assert.strictEqual(typeof oldOwnerId, 'string'); - assert.strictEqual(typeof newOwnerId, 'string'); - assert(auditSource && typeof auditSource === 'object'); - assert.strictEqual(typeof callback, 'function'); - - apps.transferOwnership(oldOwnerId, newOwnerId, function (error) { - if (error && error.reason === AppsError.NOT_FOUND) return callback(new UsersError(UsersError.NOT_FOUND, error.message)); - if (error) return callback(new UsersError(UsersError.INTERNAL_ERROR, error)); - - eventlog.add(eventlog.ACTION_USER_TRANSFER, auditSource, { oldOwnerId: oldOwnerId, newOwnerId: newOwnerId }); - - callback(null); - }); -}