mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-02 05:41:33 +02:00
Merge pull request #27476 from overleaf/jpa-transfer-all
[web] add script for transferring all of a users projects in Server Pro GitOrigin-RevId: 3aad2b624e1da2af83fec0715c2e5e08eff43695
This commit is contained in:
+167
-144
@@ -1,4 +1,4 @@
|
||||
import { execSync } from 'node:child_process'
|
||||
import { exec } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import Settings from '@overleaf/settings'
|
||||
import { expect } from 'chai'
|
||||
@@ -9,31 +9,43 @@ const { promises: User } = UserHelper
|
||||
|
||||
/**
|
||||
* @param {string} cmd
|
||||
* @return {string}
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
function run(cmd) {
|
||||
async function run(cmd) {
|
||||
// https://nodejs.org/docs/latest-v12.x/api/child_process.html#child_process_child_process_execsync_command_options
|
||||
// > stderr by default will be output to the parent process' stderr
|
||||
// > unless stdio is specified.
|
||||
// https://nodejs.org/docs/latest-v12.x/api/child_process.html#child_process_options_stdio
|
||||
// Pipe stdin from /dev/null, store stdout, pipe stderr to /dev/null.
|
||||
return execSync(cmd, {
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
env: {
|
||||
...process.env,
|
||||
LOG_LEVEL: 'warn',
|
||||
},
|
||||
}).toString()
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(
|
||||
cmd,
|
||||
{
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
env: {
|
||||
...process.env,
|
||||
LOG_LEVEL: 'warn',
|
||||
},
|
||||
},
|
||||
(error, stdout) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(stdout)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function runAndExpectError(cmd, errorMessages) {
|
||||
async function runAndExpectError(cmd, errorMessages, exitCode = 1) {
|
||||
try {
|
||||
run(cmd)
|
||||
await run(cmd)
|
||||
} catch (error) {
|
||||
expect(error.status).to.equal(1)
|
||||
expect(error.code).to.equal(exitCode)
|
||||
if (errorMessages) {
|
||||
errorMessages.forEach(errorMessage =>
|
||||
expect(error.stderr.toString()).to.include(errorMessage)
|
||||
expect(error.message).to.include(errorMessage)
|
||||
)
|
||||
}
|
||||
return
|
||||
@@ -47,60 +59,48 @@ async function getUser(email) {
|
||||
|
||||
describe('ServerCEScripts', function () {
|
||||
describe('check-mongodb', function () {
|
||||
it('should exit with code 0 on success', function () {
|
||||
run('node modules/server-ce-scripts/scripts/check-mongodb.mjs')
|
||||
it('should exit with code 0 on success', async function () {
|
||||
await run('node modules/server-ce-scripts/scripts/check-mongodb.mjs')
|
||||
})
|
||||
|
||||
it('should exit with code 1 on error', function () {
|
||||
try {
|
||||
run(
|
||||
'MONGO_SERVER_SELECTION_TIMEOUT=1' +
|
||||
'MONGO_CONNECTION_STRING=mongodb://127.0.0.1:4242 ' +
|
||||
'node modules/server-ce-scripts/scripts/check-mongodb.mjs'
|
||||
)
|
||||
} catch (e) {
|
||||
expect(e.status).to.equal(1)
|
||||
return
|
||||
}
|
||||
expect.fail('command should have failed')
|
||||
it('should exit with code 1 on error', async function () {
|
||||
await runAndExpectError(
|
||||
'MONGO_SERVER_SELECTION_TIMEOUT=1 ' +
|
||||
'MONGO_CONNECTION_STRING=mongodb://127.0.0.1:4242 ' +
|
||||
'node modules/server-ce-scripts/scripts/check-mongodb.mjs'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('check-redis', function () {
|
||||
it('should exit with code 0 on success', function () {
|
||||
run('node modules/server-ce-scripts/scripts/check-redis.mjs')
|
||||
it('should exit with code 0 on success', async function () {
|
||||
await run('node modules/server-ce-scripts/scripts/check-redis.mjs')
|
||||
})
|
||||
|
||||
it('should exit with code 1 on error', function () {
|
||||
try {
|
||||
run(
|
||||
'REDIS_PORT=42 node modules/server-ce-scripts/scripts/check-redis.mjs'
|
||||
)
|
||||
} catch (e) {
|
||||
expect(e.status).to.equal(1)
|
||||
return
|
||||
}
|
||||
expect.fail('command should have failed')
|
||||
it('should exit with code 1 on error', async function () {
|
||||
await runAndExpectError(
|
||||
'REDIS_PORT=42 node modules/server-ce-scripts/scripts/check-redis.mjs'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('create-user', function () {
|
||||
it('should exit with code 0 on success', function () {
|
||||
const out = run(
|
||||
it('should exit with code 0 on success', async function () {
|
||||
const out = await run(
|
||||
'node modules/server-ce-scripts/scripts/create-user.js --email=foo@bar.com'
|
||||
)
|
||||
expect(out).to.include('/user/activate?token=')
|
||||
})
|
||||
|
||||
it('should create a regular user by default', async function () {
|
||||
run(
|
||||
await run(
|
||||
'node modules/server-ce-scripts/scripts/create-user.js --email=foo@bar.com'
|
||||
)
|
||||
expect(await getUser('foo@bar.com')).to.deep.equal({ isAdmin: false })
|
||||
})
|
||||
|
||||
it('should also work with mjs version', async function () {
|
||||
const out = run(
|
||||
const out = await run(
|
||||
'node modules/server-ce-scripts/scripts/create-user.mjs --email=foo@bar.com'
|
||||
)
|
||||
expect(out).to.include('/user/activate?token=')
|
||||
@@ -108,20 +108,16 @@ describe('ServerCEScripts', function () {
|
||||
})
|
||||
|
||||
it('should create an admin user with --admin flag', async function () {
|
||||
run(
|
||||
await run(
|
||||
'node modules/server-ce-scripts/scripts/create-user.js --admin --email=foo@bar.com'
|
||||
)
|
||||
expect(await getUser('foo@bar.com')).to.deep.equal({ isAdmin: true })
|
||||
})
|
||||
|
||||
it('should exit with code 1 on missing email', function () {
|
||||
try {
|
||||
run('node modules/server-ce-scripts/scripts/create-user.js')
|
||||
} catch (e) {
|
||||
expect(e.status).to.equal(1)
|
||||
return
|
||||
}
|
||||
expect.fail('command should have failed')
|
||||
it('should exit with code 1 on missing email', async function () {
|
||||
await runAndExpectError(
|
||||
'node modules/server-ce-scripts/scripts/create-user.js'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -132,18 +128,18 @@ describe('ServerCEScripts', function () {
|
||||
await user.login()
|
||||
})
|
||||
|
||||
it('should log missing user', function () {
|
||||
it('should log missing user', async function () {
|
||||
const email = 'does-not-exist@example.com'
|
||||
const out = run(
|
||||
const out = await run(
|
||||
'node modules/server-ce-scripts/scripts/delete-user.mjs --email=' +
|
||||
email
|
||||
)
|
||||
expect(out).to.include('not in database, potentially already deleted')
|
||||
})
|
||||
|
||||
it('should exit with code 0 on success', function () {
|
||||
it('should exit with code 0 on success', async function () {
|
||||
const email = user.email
|
||||
run(
|
||||
await run(
|
||||
'node modules/server-ce-scripts/scripts/delete-user.mjs --email=' +
|
||||
email
|
||||
)
|
||||
@@ -151,7 +147,7 @@ describe('ServerCEScripts', function () {
|
||||
|
||||
it('should have deleted the user on success', async function () {
|
||||
const email = user.email
|
||||
run(
|
||||
await run(
|
||||
'node modules/server-ce-scripts/scripts/delete-user.mjs --email=' +
|
||||
email
|
||||
)
|
||||
@@ -164,14 +160,10 @@ describe('ServerCEScripts', function () {
|
||||
expect(softDeletedEntry.deleterData.deleterIpAddress).to.equal('0.0.0.0')
|
||||
})
|
||||
|
||||
it('should exit with code 1 on missing email', function () {
|
||||
try {
|
||||
run('node modules/server-ce-scripts/scripts/delete-user.mjs')
|
||||
} catch (e) {
|
||||
expect(e.status).to.equal(1)
|
||||
return
|
||||
}
|
||||
expect.fail('command should have failed')
|
||||
it('should exit with code 1 on missing email', async function () {
|
||||
await runAndExpectError(
|
||||
'node modules/server-ce-scripts/scripts/delete-user.mjs'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -221,7 +213,7 @@ describe('ServerCEScripts', function () {
|
||||
})
|
||||
|
||||
it('should do a dry run by default', async function () {
|
||||
run(
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs ${csv}`
|
||||
)
|
||||
for (const user of usersToMigrate) {
|
||||
@@ -234,14 +226,14 @@ describe('ServerCEScripts', function () {
|
||||
}
|
||||
})
|
||||
|
||||
it('should exit with code 0 when successfully migrating user emails', function () {
|
||||
run(
|
||||
it('should exit with code 0 when successfully migrating user emails', async function () {
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs --commit ${csv}`
|
||||
)
|
||||
})
|
||||
|
||||
it('should migrate the user emails with the --commit option', async function () {
|
||||
run(
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs --commit ${csv}`
|
||||
)
|
||||
for (const user of usersToMigrate) {
|
||||
@@ -255,7 +247,7 @@ describe('ServerCEScripts', function () {
|
||||
})
|
||||
|
||||
it('should leave other user emails unchanged', async function () {
|
||||
run(
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs --commit ${csv}`
|
||||
)
|
||||
for (const user of otherUsers) {
|
||||
@@ -264,39 +256,27 @@ describe('ServerCEScripts', function () {
|
||||
}
|
||||
})
|
||||
|
||||
it('should exit with code 1 when there are failures migrating user emails', function () {
|
||||
try {
|
||||
run(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs --commit ${csvfail}`
|
||||
)
|
||||
} catch (e) {
|
||||
expect(e.status).to.equal(1)
|
||||
return
|
||||
}
|
||||
expect.fail('command should have failed')
|
||||
it('should exit with code 1 when there are failures migrating user emails', async function () {
|
||||
await runAndExpectError(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs --commit ${csvfail}`
|
||||
)
|
||||
})
|
||||
|
||||
it('should migrate other users when there are failures with the --continue option', async function () {
|
||||
try {
|
||||
run(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs --commit ${csvfail}`
|
||||
)
|
||||
} catch (e) {
|
||||
expect(e.status).to.equal(1)
|
||||
run(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs --commit --continue ${csvfail}`
|
||||
)
|
||||
for (const user of usersToMigrate) {
|
||||
const dbEntry = await user.get()
|
||||
expect(dbEntry.email).to.equal(`new-${user.email}`)
|
||||
expect(dbEntry.emails).to.have.lengthOf(1)
|
||||
expect(dbEntry.emails[0].email).to.equal(`new-${user.email}`)
|
||||
expect(dbEntry.emails[0].reversedHostname).to.equal('moc.elpmaxe')
|
||||
expect(dbEntry.emails[0].createdAt).to.eql(user.emails[0].createdAt)
|
||||
}
|
||||
return
|
||||
await runAndExpectError(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs --commit ${csvfail}`
|
||||
)
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/migrate-user-emails.mjs --commit --continue ${csvfail}`
|
||||
)
|
||||
for (const user of usersToMigrate) {
|
||||
const dbEntry = await user.get()
|
||||
expect(dbEntry.email).to.equal(`new-${user.email}`)
|
||||
expect(dbEntry.emails).to.have.lengthOf(1)
|
||||
expect(dbEntry.emails[0].email).to.equal(`new-${user.email}`)
|
||||
expect(dbEntry.emails[0].reversedHostname).to.equal('moc.elpmaxe')
|
||||
expect(dbEntry.emails[0].createdAt).to.eql(user.emails[0].createdAt)
|
||||
}
|
||||
expect.fail('command should have failed')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -323,7 +303,7 @@ describe('ServerCEScripts', function () {
|
||||
|
||||
expect(await getTagNames()).to.deep.equal([oldName])
|
||||
|
||||
run(
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/rename-tag.mjs --user-id=${user.id} --old-name=${oldName} --new-name=${newName}`
|
||||
)
|
||||
|
||||
@@ -354,9 +334,9 @@ describe('ServerCEScripts', function () {
|
||||
|
||||
describe('happy path', function () {
|
||||
let newUserATimeout
|
||||
beforeEach('run script on user a', function () {
|
||||
beforeEach('run script on user a', async function () {
|
||||
newUserATimeout = userATimeout - 1
|
||||
run(
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/change-compile-timeout.mjs --user-id=${userA.id} --compile-timeout=${newUserATimeout}`
|
||||
)
|
||||
})
|
||||
@@ -374,27 +354,21 @@ describe('ServerCEScripts', function () {
|
||||
|
||||
describe('bad options', function () {
|
||||
it('should reject zero timeout', async function () {
|
||||
try {
|
||||
run(
|
||||
`node modules/server-ce-scripts/scripts/change-compile-timeout.mjs --user-id=${userA.id} --compile-timeout=0`
|
||||
)
|
||||
expect.fail('should error out')
|
||||
} catch (err) {
|
||||
expect(err.stderr.toString()).to.include('positive number of seconds')
|
||||
}
|
||||
await runAndExpectError(
|
||||
`node modules/server-ce-scripts/scripts/change-compile-timeout.mjs --user-id=${userA.id} --compile-timeout=0`,
|
||||
['positive number of seconds'],
|
||||
101
|
||||
)
|
||||
expect(await getCompileTimeout(userA)).to.equal(userATimeout)
|
||||
expect(await getCompileTimeout(userB)).to.equal(userBTimeout)
|
||||
})
|
||||
|
||||
it('should reject a 20min timeout', async function () {
|
||||
try {
|
||||
run(
|
||||
`node modules/server-ce-scripts/scripts/change-compile-timeout.mjs --user-id=${userA.id} --compile-timeout=1200`
|
||||
)
|
||||
expect.fail('should error out')
|
||||
} catch (err) {
|
||||
expect(err.stderr.toString()).to.include('below 10 minutes')
|
||||
}
|
||||
await runAndExpectError(
|
||||
`node modules/server-ce-scripts/scripts/change-compile-timeout.mjs --user-id=${userA.id} --compile-timeout=1200`,
|
||||
['below 10 minutes'],
|
||||
101
|
||||
)
|
||||
expect(await getCompileTimeout(userA)).to.equal(userATimeout)
|
||||
expect(await getCompileTimeout(userB)).to.equal(userBTimeout)
|
||||
})
|
||||
@@ -432,13 +406,13 @@ describe('ServerCEScripts', function () {
|
||||
})
|
||||
|
||||
beforeEach('downgrade userCustomTimeoutLower', async function () {
|
||||
run(
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/change-compile-timeout.mjs --user-id=${userCustomTimeoutLower.id} --compile-timeout=42`
|
||||
)
|
||||
})
|
||||
|
||||
beforeEach('upgrade userCustomTimeoutHigher', async function () {
|
||||
run(
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/change-compile-timeout.mjs --user-id=${userCustomTimeoutHigher.id} --compile-timeout=360`
|
||||
)
|
||||
})
|
||||
@@ -472,8 +446,8 @@ describe('ServerCEScripts', function () {
|
||||
|
||||
describe('dry-run', function () {
|
||||
let output
|
||||
beforeEach('run script', function () {
|
||||
output = run(
|
||||
beforeEach('run script', async function () {
|
||||
output = await run(
|
||||
`node modules/server-ce-scripts/scripts/upgrade-user-features.mjs`
|
||||
)
|
||||
})
|
||||
@@ -501,8 +475,8 @@ describe('ServerCEScripts', function () {
|
||||
|
||||
describe('live run', function () {
|
||||
let output
|
||||
beforeEach('run script', function () {
|
||||
output = run(
|
||||
beforeEach('run script', async function () {
|
||||
output = await run(
|
||||
`node modules/server-ce-scripts/scripts/upgrade-user-features.mjs --dry-run=false`
|
||||
)
|
||||
})
|
||||
@@ -572,8 +546,10 @@ describe('ServerCEScripts', function () {
|
||||
})
|
||||
|
||||
describe('when running in CE', function () {
|
||||
beforeEach('run script', function () {
|
||||
output = run(buildCheckTexLiveCmd({ OVERLEAF_IS_SERVER_PRO: false }))
|
||||
beforeEach('run script', async function () {
|
||||
output = await run(
|
||||
buildCheckTexLiveCmd({ OVERLEAF_IS_SERVER_PRO: false })
|
||||
)
|
||||
})
|
||||
|
||||
it('should skip checks', function () {
|
||||
@@ -584,8 +560,8 @@ describe('ServerCEScripts', function () {
|
||||
})
|
||||
|
||||
describe('when sandboxed compiles are disabled', function () {
|
||||
beforeEach('run script', function () {
|
||||
output = run(buildCheckTexLiveCmd({ SANDBOXED_COMPILES: false }))
|
||||
beforeEach('run script', async function () {
|
||||
output = await run(buildCheckTexLiveCmd({ SANDBOXED_COMPILES: false }))
|
||||
})
|
||||
|
||||
it('should skip checks', function () {
|
||||
@@ -596,8 +572,8 @@ describe('ServerCEScripts', function () {
|
||||
})
|
||||
|
||||
describe('when texlive configuration is incorrect', function () {
|
||||
it('should fail when TEX_LIVE_DOCKER_IMAGE is not set', function () {
|
||||
runAndExpectError(
|
||||
it('should fail when TEX_LIVE_DOCKER_IMAGE is not set', async function () {
|
||||
await runAndExpectError(
|
||||
buildCheckTexLiveCmd({
|
||||
SANDBOXED_COMPILES: true,
|
||||
ALL_TEX_LIVE_DOCKER_IMAGES: TEST_TL_IMAGE_LIST,
|
||||
@@ -608,8 +584,8 @@ describe('ServerCEScripts', function () {
|
||||
)
|
||||
})
|
||||
|
||||
it('should fail when ALL_TEX_LIVE_DOCKER_IMAGES is not set', function () {
|
||||
runAndExpectError(
|
||||
it('should fail when ALL_TEX_LIVE_DOCKER_IMAGES is not set', async function () {
|
||||
await runAndExpectError(
|
||||
buildCheckTexLiveCmd({
|
||||
SANDBOXED_COMPILES: true,
|
||||
TEX_LIVE_DOCKER_IMAGE: TEST_TL_IMAGE,
|
||||
@@ -620,8 +596,8 @@ describe('ServerCEScripts', function () {
|
||||
)
|
||||
})
|
||||
|
||||
it('should fail when TEX_LIVE_DOCKER_IMAGE is not defined in ALL_TEX_LIVE_DOCKER_IMAGES', function () {
|
||||
runAndExpectError(
|
||||
it('should fail when TEX_LIVE_DOCKER_IMAGE is not defined in ALL_TEX_LIVE_DOCKER_IMAGES', async function () {
|
||||
await runAndExpectError(
|
||||
buildCheckTexLiveCmd({
|
||||
SANDBOXED_COMPILES: true,
|
||||
TEX_LIVE_DOCKER_IMAGE: 'tl-1',
|
||||
@@ -639,8 +615,8 @@ describe('ServerCEScripts', function () {
|
||||
await db.projects.updateMany({}, { $unset: { imageName: 1 } })
|
||||
})
|
||||
|
||||
it('should fail and suggest running backfilling scripts', function () {
|
||||
runAndExpectError(
|
||||
it('should fail and suggest running backfilling scripts', async function () {
|
||||
await runAndExpectError(
|
||||
buildCheckTexLiveCmd({
|
||||
SANDBOXED_COMPILES: true,
|
||||
TEX_LIVE_DOCKER_IMAGE: TEST_TL_IMAGE,
|
||||
@@ -659,8 +635,8 @@ describe('ServerCEScripts', function () {
|
||||
await db.projects.updateMany({}, { $set: { imageName: null } })
|
||||
})
|
||||
|
||||
it('should fail and suggest running backfilling scripts', function () {
|
||||
runAndExpectError(
|
||||
it('should fail and suggest running backfilling scripts', async function () {
|
||||
await runAndExpectError(
|
||||
buildCheckTexLiveCmd({
|
||||
SANDBOXED_COMPILES: true,
|
||||
TEX_LIVE_DOCKER_IMAGE: TEST_TL_IMAGE,
|
||||
@@ -677,7 +653,7 @@ describe('ServerCEScripts', function () {
|
||||
describe('when TexLive ALL_TEX_LIVE_DOCKER_IMAGES are upgraded and used images are no longer available', function () {
|
||||
it('should suggest running a fixing script', async function () {
|
||||
await db.projects.updateMany({}, { $set: { imageName: TEST_TL_IMAGE } })
|
||||
runAndExpectError(
|
||||
await runAndExpectError(
|
||||
buildCheckTexLiveCmd({
|
||||
SANDBOXED_COMPILES: true,
|
||||
TEX_LIVE_DOCKER_IMAGE: 'tl-1',
|
||||
@@ -695,8 +671,8 @@ describe('ServerCEScripts', function () {
|
||||
await db.projects.updateMany({}, { $set: { imageName: TEST_TL_IMAGE } })
|
||||
})
|
||||
|
||||
it('should succeed when there are no changes to the TexLive images', function () {
|
||||
const output = run(
|
||||
it('should succeed when there are no changes to the TexLive images', async function () {
|
||||
const output = await run(
|
||||
buildCheckTexLiveCmd({
|
||||
SANDBOXED_COMPILES: true,
|
||||
TEX_LIVE_DOCKER_IMAGE: TEST_TL_IMAGE,
|
||||
@@ -706,8 +682,8 @@ describe('ServerCEScripts', function () {
|
||||
expect(output).to.include('Done.')
|
||||
})
|
||||
|
||||
it('should succeed when there are valid changes to the TexLive images', function () {
|
||||
const output = run(
|
||||
it('should succeed when there are valid changes to the TexLive images', async function () {
|
||||
const output = await run(
|
||||
buildCheckTexLiveCmd({
|
||||
SANDBOXED_COMPILES: true,
|
||||
TEX_LIVE_DOCKER_IMAGE: 'new-image',
|
||||
@@ -718,4 +694,51 @@ describe('ServerCEScripts', function () {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('transfer-all-projects-to-user', function () {
|
||||
let fromUser, projects
|
||||
beforeEach(async function () {
|
||||
fromUser = new User()
|
||||
await fromUser.login()
|
||||
projects = await Promise.all([
|
||||
fromUser.createProject('a'),
|
||||
fromUser.createProject('b'),
|
||||
fromUser.createProject('c'),
|
||||
])
|
||||
})
|
||||
let toUser
|
||||
beforeEach(async function () {
|
||||
toUser = new User()
|
||||
await toUser.login()
|
||||
})
|
||||
|
||||
it('should log missing user', async function () {
|
||||
const email = 'does-not-exist@example.com'
|
||||
await runAndExpectError(
|
||||
`node modules/server-ce-scripts/scripts/transfer-all-projects-to-user.mjs --from-user=${email}`,
|
||||
[`user with email --from-user=${email} does not exist`]
|
||||
)
|
||||
})
|
||||
|
||||
it('should transfer projects by email', async function () {
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/transfer-all-projects-to-user.mjs --from-user=${fromUser.email} --to-user=${toUser.email}`
|
||||
)
|
||||
for (const projectId of projects) {
|
||||
expect(
|
||||
(await toUser.getProject(projectId)).owner_ref.toString()
|
||||
).to.equal(toUser._id.toString())
|
||||
}
|
||||
})
|
||||
it('should transfer projects by id', async function () {
|
||||
await run(
|
||||
`node modules/server-ce-scripts/scripts/transfer-all-projects-to-user.mjs --from-user=${fromUser._id} --to-user=${toUser._id}`
|
||||
)
|
||||
for (const projectId of projects) {
|
||||
expect(
|
||||
(await toUser.getProject(projectId)).owner_ref.toString()
|
||||
).to.equal(toUser._id.toString())
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user