206 lines
7.4 KiB
TypeScript
206 lines
7.4 KiB
TypeScript
import cryptoRandomString from 'crypto-random-string'
|
|
import {
|
|
createStreamFactory,
|
|
getStreamFactory
|
|
} from '@/modules/core/repositories/streams'
|
|
import { db } from '@/db/knex'
|
|
import {
|
|
createStreamReturnRecordFactory,
|
|
legacyCreateStreamFactory
|
|
} from '@/modules/core/services/streams/management'
|
|
import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement'
|
|
import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation'
|
|
import {
|
|
deleteServerOnlyInvitesFactory,
|
|
findUserByTargetFactory,
|
|
insertInviteAndDeleteOldFactory,
|
|
updateAllInviteTargetsFactory
|
|
} from '@/modules/serverinvites/repositories/serverInvites'
|
|
import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection'
|
|
import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents'
|
|
import { getEventBus } from '@/modules/shared/services/eventBus'
|
|
import {
|
|
createBranchFactory,
|
|
getStreamBranchByNameFactory
|
|
} from '@/modules/core/repositories/branches'
|
|
import {
|
|
countAdminUsersFactory,
|
|
getUserFactory,
|
|
getUsersFactory,
|
|
storeUserAclFactory,
|
|
storeUserFactory
|
|
} from '@/modules/core/repositories/users'
|
|
import {
|
|
createUserEmailFactory,
|
|
ensureNoPrimaryEmailForUserFactory,
|
|
findEmailFactory
|
|
} from '@/modules/core/repositories/userEmails'
|
|
import { requestNewEmailVerificationFactory } from '@/modules/emails/services/verification/request'
|
|
import { deleteOldAndInsertNewVerificationFactory } from '@/modules/emails/repositories'
|
|
import { renderEmail } from '@/modules/emails/services/emailRendering'
|
|
import { createUserFactory } from '@/modules/core/services/users/management'
|
|
import { validateAndCreateUserEmailFactory } from '@/modules/core/services/userEmails'
|
|
import { finalizeInvitedServerRegistrationFactory } from '@/modules/serverinvites/services/processing'
|
|
import { sendEmail } from '@/modules/emails/services/sending'
|
|
import { getServerInfoFactory } from '@/modules/core/repositories/server'
|
|
import { manageFileImportExpiryFactory } from '@/modules/fileuploads/services/tasks'
|
|
import {
|
|
expireOldPendingUploadsFactory,
|
|
getFileInfoFactory,
|
|
saveUploadFileFactory
|
|
} from '@/modules/fileuploads/repositories/fileUploads'
|
|
import {
|
|
insertNewUploadAndNotifyFactory,
|
|
notifyChangeInFileStatus
|
|
} from '@/modules/fileuploads/services/management'
|
|
import { publish } from '@/modules/shared/utils/subscriptions'
|
|
import { testLogger as logger } from '@/observability/logging'
|
|
import { sleep } from '@/test/helpers'
|
|
import { expect } from 'chai'
|
|
import { FileUploadConvertedStatus } from '@/modules/fileuploads/helpers/types'
|
|
import { TIME } from '@speckle/shared'
|
|
|
|
const getServerInfo = getServerInfoFactory({ db })
|
|
const getUser = getUserFactory({ db })
|
|
const getUsers = getUsersFactory({ db })
|
|
const getStream = getStreamFactory({ db })
|
|
const createStream = legacyCreateStreamFactory({
|
|
createStreamReturnRecord: createStreamReturnRecordFactory({
|
|
inviteUsersToProject: inviteUsersToProjectFactory({
|
|
createAndSendInvite: createAndSendInviteFactory({
|
|
findUserByTarget: findUserByTargetFactory({ db }),
|
|
insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }),
|
|
collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({
|
|
getStream
|
|
}),
|
|
buildInviteEmailContents: buildCoreInviteEmailContentsFactory({
|
|
getStream
|
|
}),
|
|
emitEvent: ({ eventName, payload }) =>
|
|
getEventBus().emit({
|
|
eventName,
|
|
payload
|
|
}),
|
|
getUser,
|
|
getServerInfo
|
|
}),
|
|
getUsers
|
|
}),
|
|
createStream: createStreamFactory({ db }),
|
|
createBranch: createBranchFactory({ db }),
|
|
emitEvent: getEventBus().emit
|
|
})
|
|
})
|
|
|
|
const findEmail = findEmailFactory({ db })
|
|
const requestNewEmailVerification = requestNewEmailVerificationFactory({
|
|
findEmail,
|
|
getUser: getUserFactory({ db }),
|
|
getServerInfo,
|
|
deleteOldAndInsertNewVerification: deleteOldAndInsertNewVerificationFactory({ db }),
|
|
renderEmail,
|
|
sendEmail
|
|
})
|
|
const createUser = createUserFactory({
|
|
getServerInfo,
|
|
findEmail,
|
|
storeUser: storeUserFactory({ db }),
|
|
countAdminUsers: countAdminUsersFactory({ db }),
|
|
storeUserAcl: storeUserAclFactory({ db }),
|
|
validateAndCreateUserEmail: validateAndCreateUserEmailFactory({
|
|
createUserEmail: createUserEmailFactory({ db }),
|
|
ensureNoPrimaryEmailForUser: ensureNoPrimaryEmailForUserFactory({ db }),
|
|
findEmail,
|
|
updateEmailInvites: finalizeInvitedServerRegistrationFactory({
|
|
deleteServerOnlyInvites: deleteServerOnlyInvitesFactory({ db }),
|
|
updateAllInviteTargets: updateAllInviteTargetsFactory({ db })
|
|
}),
|
|
requestNewEmailVerification
|
|
}),
|
|
emitEvent: getEventBus().emit
|
|
})
|
|
|
|
const garbageCollector = manageFileImportExpiryFactory({
|
|
garbageCollectExpiredPendingUploads: expireOldPendingUploadsFactory({
|
|
db
|
|
}),
|
|
notifyUploadStatus: notifyChangeInFileStatus({
|
|
getStreamBranchByName: getStreamBranchByNameFactory({ db }),
|
|
publish
|
|
})
|
|
})
|
|
|
|
describe('FileUploads @fileuploads', () => {
|
|
const userOne = {
|
|
name: cryptoRandomString({ length: 10 }),
|
|
email: `${cryptoRandomString({ length: 10 })}@example.org`,
|
|
password: cryptoRandomString({ length: 10 })
|
|
}
|
|
|
|
let userOneId: string
|
|
let createdStreamId: string
|
|
|
|
before(async () => {
|
|
userOneId = await createUser(userOne)
|
|
})
|
|
|
|
beforeEach(async () => {
|
|
createdStreamId = await createStream({ ownerId: userOneId })
|
|
})
|
|
afterEach(async () => {
|
|
createdStreamId = ''
|
|
})
|
|
describe('Convert files', () => {
|
|
it('Should garbage collect expired files', async () => {
|
|
const insertNewUploadAndNotify = insertNewUploadAndNotifyFactory({
|
|
getStreamBranchByName: getStreamBranchByNameFactory({ db }),
|
|
saveUploadFile: saveUploadFileFactory({ db }),
|
|
publish
|
|
})
|
|
const fileId = cryptoRandomString({ length: 10 })
|
|
await insertNewUploadAndNotify({
|
|
streamId: createdStreamId,
|
|
branchName: 'main',
|
|
userId: userOneId,
|
|
fileId,
|
|
fileName: 'testfile.txt',
|
|
fileSize: 100,
|
|
fileType: 'text/plain'
|
|
})
|
|
await sleep(2000)
|
|
await garbageCollector({ logger, timeoutThresholdSeconds: 1 })
|
|
const results = await getFileInfoFactory({ db })({ fileId })
|
|
if (!results) {
|
|
expect(results).to.not.be.undefined
|
|
return //HACK to appease typescript
|
|
}
|
|
expect(results.convertedStatus).to.be.equal(FileUploadConvertedStatus.Error)
|
|
})
|
|
it('Should not garbage collect files that are not expired', async () => {
|
|
const insertNewUploadAndNotify = insertNewUploadAndNotifyFactory({
|
|
getStreamBranchByName: getStreamBranchByNameFactory({ db }),
|
|
saveUploadFile: saveUploadFileFactory({ db }),
|
|
publish
|
|
})
|
|
const fileId = cryptoRandomString({ length: 10 })
|
|
await insertNewUploadAndNotify({
|
|
streamId: createdStreamId,
|
|
branchName: 'main',
|
|
userId: userOneId,
|
|
fileId,
|
|
fileName: 'testfile.txt',
|
|
fileSize: 100,
|
|
fileType: 'text/plain'
|
|
})
|
|
// timeout far in the future, so it won't be garbage collected
|
|
await garbageCollector({ logger, timeoutThresholdSeconds: 1 * TIME.hour })
|
|
const results = await getFileInfoFactory({ db })({ fileId })
|
|
if (!results) {
|
|
expect(results).to.not.be.undefined
|
|
return //HACK to appease typescript
|
|
}
|
|
expect(results.convertedStatus).to.be.equal(FileUploadConvertedStatus.Queued)
|
|
})
|
|
})
|
|
})
|