-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #102 from PermanentOrg/feature/PER-8805-allow-remo…
…ve-self-from-archive PER-8805 Allow remove self from archive
- Loading branch information
Showing
15 changed files
with
635 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"editor.tabSize": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import request from "supertest"; | ||
import type { Request, NextFunction } from "express"; | ||
|
||
import { db } from "../database"; | ||
import { EVENT_ACTION, EVENT_ACTOR, EVENT_ENTITY } from "../constants"; | ||
import { verifyUserAuthentication, extractIp } from "../middleware"; | ||
import { app } from "../app"; | ||
|
||
jest.mock("../database"); | ||
jest.mock("@stela/logger"); | ||
jest.mock("../middleware"); | ||
|
||
const loadFixtures = async (): Promise<void> => { | ||
await db.sql("fixtures.create_test_accounts"); | ||
await db.sql("fixtures.create_test_archives"); | ||
await db.sql("fixtures.create_test_account_archives"); | ||
}; | ||
|
||
const clearDatabase = async (): Promise<void> => { | ||
await db.query("TRUNCATE event, account_archive, account, archive CASCADE"); | ||
}; | ||
|
||
describe("leaveArchive", () => { | ||
const agent = request(app); | ||
|
||
const ip = "127.0.0.1"; | ||
const selectEventRow = ` | ||
SELECT * FROM event e | ||
WHERE e.entity = '${EVENT_ENTITY.AccountArchive}' | ||
AND e.version = 1 | ||
AND e.entity_id = '5' | ||
AND e.action = '${EVENT_ACTION.Delete}' | ||
AND e.ip = '${ip}' | ||
AND e.actor_type = '${EVENT_ACTOR.User}' | ||
AND e.actor_id = 'b5461dc2-1eb0-450e-b710-fef7b2cafe1e'`; | ||
|
||
const selectAccountArchiveRow = `SELECT * FROM account_archive WHERE | ||
accountid = 3 AND archiveid = 1`; | ||
|
||
beforeEach(async () => { | ||
(verifyUserAuthentication as jest.Mock).mockImplementation( | ||
async ( | ||
req: Request< | ||
unknown, | ||
unknown, | ||
{ userSubjectFromAuthToken?: string; emailFromAuthToken?: string } | ||
>, | ||
__, | ||
next: NextFunction | ||
) => { | ||
req.body.emailFromAuthToken = "[email protected]"; | ||
req.body.userSubjectFromAuthToken = | ||
"b5461dc2-1eb0-450e-b710-fef7b2cafe1e"; | ||
|
||
next(); | ||
} | ||
); | ||
|
||
(extractIp as jest.Mock).mockImplementation( | ||
async ( | ||
req: Request<unknown, unknown, { ip?: string }>, | ||
__, | ||
next: NextFunction | ||
) => { | ||
req.body.ip = ip; | ||
|
||
next(); | ||
} | ||
); | ||
|
||
await loadFixtures(); | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
afterEach(async () => { | ||
await clearDatabase(); | ||
}); | ||
|
||
test("should successfully leave an archive", async () => { | ||
const accountArchiveBeforeLeaveResult = await db.query( | ||
selectAccountArchiveRow | ||
); | ||
|
||
expect(accountArchiveBeforeLeaveResult.rows.length).toBe(1); | ||
|
||
await agent.delete("/api/v2/account/archive/1").expect(204); | ||
|
||
const accountArchiveAfterLeaveResult = await db.query( | ||
selectAccountArchiveRow | ||
); | ||
|
||
expect(accountArchiveAfterLeaveResult.rows.length).toBe(0); | ||
}); | ||
|
||
test("should throw 404 error if account archive relationship is not found", async () => { | ||
await agent.delete("/api/v2/account/archive/2022").expect(404); | ||
}); | ||
|
||
test("should throw 400 error if the account owns the archive", async () => { | ||
await agent.delete("/api/v2/account/archive/2").expect(400); | ||
}); | ||
|
||
test("should log an action in the database events table", async () => { | ||
const eventsBeforeLeave = await db.query(selectEventRow); | ||
expect(eventsBeforeLeave.rows.length).toBe(0); | ||
|
||
await agent.delete("/api/v2/account/archive/1").expect(204); | ||
|
||
const eventsAfterLeave = await db.query(selectEventRow); | ||
expect(eventsAfterLeave.rows.length).toBe(1); | ||
}); | ||
|
||
test("logged event contains expected body values", async () => { | ||
await agent.delete("/api/v2/account/archive/1").expect(204); | ||
|
||
const eventResult = await db.query<{ body: object }>(selectEventRow); | ||
expect(eventResult.rows.length).toBe(1); | ||
|
||
const eventBody = eventResult.rows[0]?.body; | ||
expect(eventBody).toEqual({ | ||
archiveId: "1", | ||
accountId: "3", | ||
accountPrimaryEmail: "[email protected]", | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
DELETE FROM account_archive | ||
WHERE | ||
archiveid = :archiveId | ||
AND accessrole != 'access.role.owner' | ||
AND accountid IN (SELECT accountid FROM account WHERE primaryemail = :email) | ||
RETURNING | ||
account_archiveid AS "accountArchiveId"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
SELECT | ||
account_archive.account_archiveid AS "accountArchiveId", | ||
account_archive.accountid AS "accountId", | ||
account_archive.accessrole AS "accessRole", | ||
account_archive.type, | ||
account_archive.status | ||
FROM | ||
account_archive | ||
INNER JOIN | ||
account | ||
ON account_archive.accountid = account.accountid | ||
WHERE | ||
account_archive.archiveid = :archiveId | ||
AND account.primaryemail = :email | ||
AND account_archive.status = 'status.generic.ok'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.