mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 17:33:51 +02:00
Defer async tenant import validation
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
1c5cfa5ba8
commit
d1c5bf1d0f
2 files changed
+30
-4
No files matched your search
@@ -538,6 +538,28 @@ describe.sequential("company portability routes", () => {
|
||||
expect(mockLogActivity).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.sequential("accepts trusted Cloud async import jobs before validating the full import payload", async () => {
|
||||
const app = await createApp(cloudTenantActor());
|
||||
|
||||
const accepted = await request(app)
|
||||
.post("/api/companies/import")
|
||||
.set("x-paperclip-cloud-async-import", "1")
|
||||
.set(cloudHeaders)
|
||||
.send({ target: { mode: "existing_company", companyId } });
|
||||
|
||||
expect(accepted.status).toBe(202);
|
||||
expect(accepted.body.job.status).toBe("running");
|
||||
expect(mockCompanyPortabilityService.importBundle).not.toHaveBeenCalled();
|
||||
|
||||
const failed = await waitForImportJobStatus(app, accepted.body.statusUrl, "failed");
|
||||
|
||||
expect(failed.status).toBe(200);
|
||||
expect(failed.body.job.status).toBe("failed");
|
||||
expect(failed.body.job.error.message).toEqual(expect.any(String));
|
||||
expect(mockCompanyPortabilityService.importBundle).not.toHaveBeenCalled();
|
||||
expect(mockLogActivity).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.sequential("keeps global import apply synchronous when Cloud async opt-in is absent", async () => {
|
||||
mockCompanyPortabilityService.importBundle.mockResolvedValueOnce(createImportResult("created"));
|
||||
const app = await createApp(cloudTenantActor());
|
||||
|
||||
@@ -188,18 +188,19 @@ export function companyRoutes(db: Db, storage?: StorageService) {
|
||||
res.json(importJobResponse(job));
|
||||
});
|
||||
|
||||
router.post("/import", validate(companyPortabilityImportSchema), async (req, res) => {
|
||||
router.post("/import", async (req, res) => {
|
||||
assertBoard(req);
|
||||
assertImportTargetAccess(req, req.body.target);
|
||||
const rawImportBody: unknown = req.body;
|
||||
const actor = getActorInfo(req);
|
||||
const importBody = req.body;
|
||||
const boardUserId = req.actor.type === "board" ? req.actor.userId : null;
|
||||
const activity = importedCompanyActivityContext(actor, importBody.include ?? null);
|
||||
if (req.header("x-paperclip-cloud-async-import") === "1") {
|
||||
assertCloudTenantCaller(req);
|
||||
const job = createImportJob(cloudTenantRequestKey(req));
|
||||
importJobs.set(job.id, job);
|
||||
const operation = async () => {
|
||||
const importBody = companyPortabilityImportSchema.parse(rawImportBody);
|
||||
assertImportTargetAccess(req, importBody.target);
|
||||
const activity = importedCompanyActivityContext(actor, importBody.include ?? null);
|
||||
const result = await portability.importBundle(importBody, boardUserId);
|
||||
await logImportedCompanyActivity(db, activity, result);
|
||||
return result;
|
||||
@@ -211,6 +212,9 @@ export function companyRoutes(db: Db, storage?: StorageService) {
|
||||
return;
|
||||
}
|
||||
|
||||
const importBody = companyPortabilityImportSchema.parse(rawImportBody);
|
||||
assertImportTargetAccess(req, importBody.target);
|
||||
const activity = importedCompanyActivityContext(actor, importBody.include ?? null);
|
||||
const result = await portability.importBundle(importBody, boardUserId);
|
||||
await logImportedCompanyActivity(db, activity, result);
|
||||
res.json(result);
|
||||
|
||||
Reference in new issue
Block a user