Skip to content

Commit 0d002b5

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

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import addOwners from './crates/add-owners.js';
12
import deleteCrate from './crates/delete.js';
23
import downloads from './crates/downloads.js';
34
import followCrate from './crates/follow.js';
@@ -16,6 +17,7 @@ export default [
1617
following,
1718
followCrate,
1819
unfollowCrate,
20+
addOwners,
1921
userOwners,
2022
teamOwners,
2123
reverseDependencies,
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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.put('/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+
let users = [];
21+
let teams = [];
22+
let msgs = [];
23+
for (let login of body.owners) {
24+
if (login.includes(':')) {
25+
let team = db.team.findFirst({ where: { login: { equals: login } } });
26+
if (!team) {
27+
let errorMessage = `could not find team with login \`${login}\``;
28+
return HttpResponse.json({ errors: [{ detail: errorMessage }] }, { status: 404 });
29+
}
30+
31+
teams.push(team);
32+
msgs.push(`team ${login} has been added as an owner of crate ${crate.name}`);
33+
} else {
34+
let user = db.user.findFirst({ where: { login: { equals: login } } });
35+
if (!user) {
36+
let errorMessage = `could not find user with login \`${login}\``;
37+
return HttpResponse.json({ errors: [{ detail: errorMessage }] }, { status: 404 });
38+
}
39+
40+
users.push(user);
41+
msgs.push(`user ${login} has been invited to be an owner of crate ${crate.name}`);
42+
}
43+
}
44+
45+
for (let team of teams) {
46+
db.crateOwnership.create({ crate, team });
47+
}
48+
49+
for (let invitee of users) {
50+
db.crateOwnerInvitation.create({ crate, inviter: user, invitee });
51+
}
52+
53+
return HttpResponse.json({ ok: true, msg: msgs.join(',') });
54+
});
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { assert, test } from 'vitest';
2+
3+
import { db } from '../../index.js';
4+
5+
const ADD_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: 'PUT', body: ADD_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: 'PUT', body: ADD_USER_BODY });
20+
assert.strictEqual(response.status, 404);
21+
assert.deepEqual(await response.json(), { errors: [{ detail: 'Not Found' }] });
22+
});
23+
24+
test('can add new 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+
33+
let body = JSON.stringify({ owners: [user2.login] });
34+
let response = await fetch('/api/v1/crates/foo/owners', { method: 'PUT', body });
35+
assert.strictEqual(response.status, 200);
36+
assert.deepEqual(await response.json(), {
37+
ok: true,
38+
msg: 'user user-2 has been invited to be an owner of crate foo',
39+
});
40+
41+
let owners = db.crateOwnership.findMany({ where: { crate: { id: { equals: crate.id } } } });
42+
assert.strictEqual(owners.length, 1);
43+
assert.strictEqual(owners[0].user.id, user.id);
44+
45+
let invites = db.crateOwnerInvitation.findMany({ where: { crate: { id: { equals: crate.id } } } });
46+
assert.strictEqual(invites.length, 1);
47+
assert.strictEqual(invites[0].inviter.id, user.id);
48+
assert.strictEqual(invites[0].invitee.id, user2.id);
49+
});
50+
51+
test('can add team owner', async function () {
52+
let user = db.user.create();
53+
db.mswSession.create({ user });
54+
55+
let crate = db.crate.create({ name: 'foo' });
56+
db.crateOwnership.create({ crate, user });
57+
58+
let team = db.team.create();
59+
60+
let body = JSON.stringify({ owners: [team.login] });
61+
let response = await fetch('/api/v1/crates/foo/owners', { method: 'PUT', body });
62+
assert.strictEqual(response.status, 200);
63+
assert.deepEqual(await response.json(), {
64+
ok: true,
65+
msg: 'team github:rust-lang:team-1 has been added as an owner of crate foo',
66+
});
67+
68+
let owners = db.crateOwnership.findMany({ where: { crate: { id: { equals: crate.id } } } });
69+
assert.strictEqual(owners.length, 2);
70+
assert.strictEqual(owners[0].user.id, user.id);
71+
assert.strictEqual(owners[0].team, null);
72+
assert.strictEqual(owners[1].user, null);
73+
assert.strictEqual(owners[1].team.id, user.id);
74+
75+
let invites = db.crateOwnerInvitation.findMany({ where: { crate: { id: { equals: crate.id } } } });
76+
assert.strictEqual(invites.length, 0);
77+
});
78+
79+
test('can add multiple owners', async function () {
80+
let user = db.user.create();
81+
db.mswSession.create({ user });
82+
83+
let crate = db.crate.create({ name: 'foo' });
84+
db.crateOwnership.create({ crate, user });
85+
86+
let team = db.team.create();
87+
let user2 = db.user.create();
88+
let user3 = db.user.create();
89+
90+
let body = JSON.stringify({ owners: [user2.login, team.login, user3.login] });
91+
let response = await fetch('/api/v1/crates/foo/owners', { method: 'PUT', body });
92+
assert.strictEqual(response.status, 200);
93+
assert.deepEqual(await response.json(), {
94+
ok: true,
95+
msg: 'user user-2 has been invited to be an owner of crate foo,team github:rust-lang:team-1 has been added as an owner of crate foo,user user-3 has been invited to be an owner of crate foo',
96+
});
97+
98+
let owners = db.crateOwnership.findMany({ where: { crate: { id: { equals: crate.id } } } });
99+
assert.strictEqual(owners.length, 2);
100+
assert.strictEqual(owners[0].user.id, user.id);
101+
assert.strictEqual(owners[0].team, null);
102+
assert.strictEqual(owners[1].user, null);
103+
assert.strictEqual(owners[1].team.id, user.id);
104+
105+
let invites = db.crateOwnerInvitation.findMany({ where: { crate: { id: { equals: crate.id } } } });
106+
assert.strictEqual(invites.length, 2);
107+
assert.strictEqual(invites[0].inviter.id, user.id);
108+
assert.strictEqual(invites[0].invitee.id, user2.id);
109+
assert.strictEqual(invites[1].inviter.id, user.id);
110+
assert.strictEqual(invites[1].invitee.id, user3.id);
111+
});

0 commit comments

Comments
 (0)