Skip to content

Commit b2a6d86

Browse files
committed
msw: Implement DELETE /api/v1/crates/:name/owners request handler
1 parent 0d002b5 commit b2a6d86

File tree

3 files changed

+127
-0
lines changed

3 files changed

+127
-0
lines changed

packages/crates-io-msw/handlers/crates.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import followCrate from './crates/follow.js';
55
import following from './crates/following.js';
66
import getCrate from './crates/get.js';
77
import listCrates from './crates/list.js';
8+
import removeOwners from './crates/remove-owners.js';
89
import reverseDependencies from './crates/reverse-dependencies.js';
910
import teamOwners from './crates/team-owners.js';
1011
import unfollowCrate from './crates/unfollow.js';
@@ -18,6 +19,7 @@ export default [
1819
followCrate,
1920
unfollowCrate,
2021
addOwners,
22+
removeOwners,
2123
userOwners,
2224
teamOwners,
2325
reverseDependencies,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { http, HttpResponse } from 'msw';
2+
3+
import { db } from '../../index.js';
4+
import { notFound } from '../../utils/handlers.js';
5+
import { getSession } from '../../utils/session.js';
6+
7+
export default http.delete('/api/v1/crates/:name/owners', async ({ request, params }) => {
8+
let { user } = getSession();
9+
if (!user) {
10+
return HttpResponse.json({ errors: [{ detail: 'must be logged in to perform that action' }] }, { status: 403 });
11+
}
12+
13+
let crate = db.crate.findFirst({ where: { name: { equals: params.name } } });
14+
if (!crate) {
15+
return notFound();
16+
}
17+
18+
let body = await request.json();
19+
20+
for (let owner of body.owners) {
21+
let ownership = db.crateOwnership.findFirst({
22+
where: owner.includes(':') ? { team: { login: { equals: owner } } } : { user: { login: { equals: owner } } },
23+
});
24+
if (!ownership) return notFound();
25+
db.crateOwnership.delete({ where: { id: { equals: ownership.id } } });
26+
}
27+
28+
return HttpResponse.json({ ok: true, msg: 'owners successfully removed' });
29+
});
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { assert, test } from 'vitest';
2+
3+
import { db } from '../../index.js';
4+
5+
const REMOVE_USER_BODY = JSON.stringify({ owners: ['john-doe'] });
6+
7+
test('returns 403 if unauthenticated', async function () {
8+
let response = await fetch('/api/v1/crates/foo/owners', { method: 'DELETE', body: REMOVE_USER_BODY });
9+
assert.strictEqual(response.status, 403);
10+
assert.deepEqual(await response.json(), {
11+
errors: [{ detail: 'must be logged in to perform that action' }],
12+
});
13+
});
14+
15+
test('returns 404 for unknown crates', async function () {
16+
let user = db.user.create();
17+
db.mswSession.create({ user });
18+
19+
let response = await fetch('/api/v1/crates/foo/owners', { method: 'DELETE', body: REMOVE_USER_BODY });
20+
assert.strictEqual(response.status, 404);
21+
assert.deepEqual(await response.json(), { errors: [{ detail: 'Not Found' }] });
22+
});
23+
24+
test('can remove a user owner', async function () {
25+
let user = db.user.create();
26+
db.mswSession.create({ user });
27+
28+
let crate = db.crate.create({ name: 'foo' });
29+
db.crateOwnership.create({ crate, user });
30+
31+
let user2 = db.user.create();
32+
db.crateOwnership.create({ crate, user: user2 });
33+
34+
let body = JSON.stringify({ owners: [user2.login] });
35+
let response = await fetch('/api/v1/crates/foo/owners', { method: 'DELETE', body });
36+
assert.strictEqual(response.status, 200);
37+
assert.deepEqual(await response.json(), { ok: true, msg: 'owners successfully removed' });
38+
39+
let owners = db.crateOwnership.findMany({ where: { crate: { id: { equals: crate.id } } } });
40+
assert.strictEqual(owners.length, 1);
41+
assert.strictEqual(owners[0].user.id, user.id);
42+
43+
let invites = db.crateOwnerInvitation.findMany({ where: { crate: { id: { equals: crate.id } } } });
44+
assert.strictEqual(invites.length, 0);
45+
});
46+
47+
test('can remove a team owner', async function () {
48+
let user = db.user.create();
49+
db.mswSession.create({ user });
50+
51+
let crate = db.crate.create({ name: 'foo' });
52+
db.crateOwnership.create({ crate, user });
53+
54+
let team = db.team.create();
55+
db.crateOwnership.create({ crate, team });
56+
57+
let body = JSON.stringify({ owners: [team.login] });
58+
let response = await fetch('/api/v1/crates/foo/owners', { method: 'DELETE', body });
59+
assert.strictEqual(response.status, 200);
60+
assert.deepEqual(await response.json(), { ok: true, msg: 'owners successfully removed' });
61+
62+
let owners = db.crateOwnership.findMany({ where: { crate: { id: { equals: crate.id } } } });
63+
assert.strictEqual(owners.length, 1);
64+
assert.strictEqual(owners[0].user.id, user.id);
65+
assert.strictEqual(owners[0].team, null);
66+
67+
let invites = db.crateOwnerInvitation.findMany({ where: { crate: { id: { equals: crate.id } } } });
68+
assert.strictEqual(invites.length, 0);
69+
});
70+
71+
test('can remove multiple owners', async function () {
72+
let user = db.user.create();
73+
db.mswSession.create({ user });
74+
75+
let crate = db.crate.create({ name: 'foo' });
76+
db.crateOwnership.create({ crate, user });
77+
78+
let team = db.team.create();
79+
db.crateOwnership.create({ crate, team });
80+
81+
let user2 = db.user.create();
82+
db.crateOwnership.create({ crate, user: user2 });
83+
84+
let body = JSON.stringify({ owners: [user2.login, team.login] });
85+
let response = await fetch('/api/v1/crates/foo/owners', { method: 'DELETE', body });
86+
assert.strictEqual(response.status, 200);
87+
assert.deepEqual(await response.json(), { ok: true, msg: 'owners successfully removed' });
88+
89+
let owners = db.crateOwnership.findMany({ where: { crate: { id: { equals: crate.id } } } });
90+
assert.strictEqual(owners.length, 1);
91+
assert.strictEqual(owners[0].user.id, user.id);
92+
assert.strictEqual(owners[0].team, null);
93+
94+
let invites = db.crateOwnerInvitation.findMany({ where: { crate: { id: { equals: crate.id } } } });
95+
assert.strictEqual(invites.length, 0);
96+
});

0 commit comments

Comments
 (0)