Skip to content

Commit 9565dc7

Browse files
committed
trustpub: Add trustpub-github-config Ember Data model, adapter and serializer
1 parent 3b7b699 commit 9565dc7

File tree

4 files changed

+258
-0
lines changed

4 files changed

+258
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import ApplicationAdapter from './application';
2+
3+
export default class TrustpubGitHubConfigAdapter extends ApplicationAdapter {
4+
pathForType() {
5+
return 'trusted_publishing/github_configs';
6+
}
7+
}

app/models/trustpub-github-config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Model, { attr, belongsTo } from '@ember-data/model';
2+
3+
export default class TrustpubGitHubConfig extends Model {
4+
@belongsTo('crate', { async: true, inverse: null }) crate;
5+
@attr repository_owner;
6+
@attr repository_name;
7+
@attr workflow_filename;
8+
@attr environment;
9+
@attr('date') created_at;
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import ApplicationSerializer from './application';
2+
3+
export default class TrustpubGitHubConfigSerializer extends ApplicationSerializer {
4+
modelNameFromPayloadKey() {
5+
return 'trustpub-github-config';
6+
}
7+
8+
payloadKeyFromModelName() {
9+
return 'github_config';
10+
}
11+
}
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
import { module, test } from 'qunit';
2+
3+
import { db } from '@crates-io/msw';
4+
5+
import { setupTest } from 'crates-io/tests/helpers';
6+
import setupMsw from 'crates-io/tests/helpers/setup-msw';
7+
8+
module('Model | TrustpubGitHubConfig', function (hooks) {
9+
setupTest(hooks);
10+
setupMsw(hooks);
11+
12+
hooks.beforeEach(function () {
13+
this.store = this.owner.lookup('service:store');
14+
});
15+
16+
module('query()', function () {
17+
test('fetches GitHub configs for a crate', async function (assert) {
18+
let user = this.db.user.create();
19+
this.authenticateAs(user);
20+
21+
let crate = this.db.crate.create();
22+
this.db.version.create({ crate });
23+
this.db.crateOwnership.create({ crate, user });
24+
25+
let config = this.db.trustpubGithubConfig.create({
26+
crate,
27+
repository_owner: 'rust-lang',
28+
repository_name: 'crates.io',
29+
workflow_filename: 'ci.yml',
30+
});
31+
32+
let configs = await this.store.query('trustpub-github-config', { crate: crate.name });
33+
assert.strictEqual(configs.length, 1);
34+
assert.strictEqual(parseInt(configs[0].id, 10), config.id);
35+
assert.strictEqual(configs[0].repository_owner, 'rust-lang');
36+
assert.strictEqual(configs[0].repository_name, 'crates.io');
37+
assert.strictEqual(configs[0].workflow_filename, 'ci.yml');
38+
assert.true(configs[0].created_at instanceof Date);
39+
});
40+
41+
test('returns an error if the user is not authenticated', async function (assert) {
42+
let crate = this.db.crate.create();
43+
this.db.version.create({ crate });
44+
45+
await assert.rejects(this.store.query('trustpub-github-config', { crate: crate.name }), function (error) {
46+
assert.deepEqual(error.errors, [{ detail: 'must be logged in to perform that action' }]);
47+
return true;
48+
});
49+
});
50+
51+
test('returns an error if the user is not an owner of the crate', async function (assert) {
52+
let user = this.db.user.create();
53+
this.authenticateAs(user);
54+
55+
let crate = this.db.crate.create();
56+
this.db.version.create({ crate });
57+
58+
await assert.rejects(this.store.query('trustpub-github-config', { crate: crate.name }), function (error) {
59+
assert.deepEqual(error.errors, [{ detail: 'You are not an owner of this crate' }]);
60+
return true;
61+
});
62+
});
63+
});
64+
65+
module('createRecord()', function () {
66+
test('creates a new GitHub config', async function (assert) {
67+
let user = this.db.user.create({ emailVerified: true });
68+
this.authenticateAs(user);
69+
70+
let crate = this.db.crate.create();
71+
this.db.version.create({ crate });
72+
this.db.crateOwnership.create({ crate, user });
73+
74+
let config = this.store.createRecord('trustpub-github-config', {
75+
crate: await this.store.findRecord('crate', crate.name),
76+
repository_owner: 'rust-lang',
77+
repository_name: 'crates.io',
78+
workflow_filename: 'ci.yml',
79+
});
80+
81+
await config.save();
82+
assert.strictEqual(config.id, '1');
83+
assert.strictEqual(config.repository_owner, 'rust-lang');
84+
assert.strictEqual(config.repository_name, 'crates.io');
85+
assert.strictEqual(config.workflow_filename, 'ci.yml');
86+
});
87+
88+
test('returns an error if the user is not authenticated', async function (assert) {
89+
let crate = this.db.crate.create();
90+
this.db.version.create({ crate });
91+
92+
let config = this.store.createRecord('trustpub-github-config', {
93+
crate: await this.store.findRecord('crate', crate.name),
94+
repository_owner: 'rust-lang',
95+
repository_name: 'crates.io',
96+
workflow_filename: 'ci.yml',
97+
});
98+
99+
await assert.rejects(config.save(), function (error) {
100+
assert.deepEqual(error.errors, [{ detail: 'must be logged in to perform that action' }]);
101+
return true;
102+
});
103+
});
104+
105+
test('returns an error if the user is not an owner of the crate', async function (assert) {
106+
let user = this.db.user.create({ emailVerified: true });
107+
this.authenticateAs(user);
108+
109+
let crate = this.db.crate.create();
110+
this.db.version.create({ crate });
111+
112+
let config = this.store.createRecord('trustpub-github-config', {
113+
crate: await this.store.findRecord('crate', crate.name),
114+
repository_owner: 'rust-lang',
115+
repository_name: 'crates.io',
116+
workflow_filename: 'ci.yml',
117+
});
118+
119+
await assert.rejects(config.save(), function (error) {
120+
assert.deepEqual(error.errors, [{ detail: 'You are not an owner of this crate' }]);
121+
return true;
122+
});
123+
});
124+
125+
test('returns an error if the user does not have a verified email', async function (assert) {
126+
let user = this.db.user.create({ emailVerified: false });
127+
this.authenticateAs(user);
128+
129+
let crate = this.db.crate.create();
130+
this.db.version.create({ crate });
131+
this.db.crateOwnership.create({ crate, user });
132+
133+
let config = this.store.createRecord('trustpub-github-config', {
134+
crate: await this.store.findRecord('crate', crate.name),
135+
repository_owner: 'rust-lang',
136+
repository_name: 'crates.io',
137+
workflow_filename: 'ci.yml',
138+
});
139+
140+
await assert.rejects(config.save(), function (error) {
141+
let detail = 'You must verify your email address to create a Trusted Publishing config';
142+
assert.deepEqual(error.errors, [{ detail }]);
143+
return true;
144+
});
145+
});
146+
});
147+
148+
module('deleteRecord()', function () {
149+
test('deletes a GitHub config', async function (assert) {
150+
let user = this.db.user.create();
151+
this.authenticateAs(user);
152+
153+
let crate = this.db.crate.create();
154+
this.db.version.create({ crate });
155+
this.db.crateOwnership.create({ crate, user });
156+
157+
// Create a config in the database that will be queried later
158+
this.db.trustpubGithubConfig.create({
159+
crate,
160+
repository_owner: 'rust-lang',
161+
repository_name: 'crates.io',
162+
workflow_filename: 'ci.yml',
163+
});
164+
165+
let configs = await this.store.query('trustpub-github-config', { crate: crate.name });
166+
assert.strictEqual(configs.length, 1);
167+
168+
await configs[0].destroyRecord();
169+
170+
configs = await this.store.query('trustpub-github-config', { crate: crate.name });
171+
assert.strictEqual(configs.length, 0);
172+
});
173+
174+
test('returns an error if the user is not authenticated', async function (assert) {
175+
let user = this.db.user.create();
176+
177+
let crate = this.db.crate.create();
178+
this.db.version.create({ crate });
179+
this.db.crateOwnership.create({ crate, user });
180+
181+
// Create a config in the database that will be queried later
182+
this.db.trustpubGithubConfig.create({
183+
crate,
184+
repository_owner: 'rust-lang',
185+
repository_name: 'crates.io',
186+
workflow_filename: 'ci.yml',
187+
});
188+
189+
this.authenticateAs(user);
190+
let configs = await this.store.query('trustpub-github-config', { crate: crate.name });
191+
assert.strictEqual(configs.length, 1);
192+
193+
db.mswSession.deleteMany({});
194+
195+
await assert.rejects(configs[0].destroyRecord(), function (error) {
196+
assert.deepEqual(error.errors, [{ detail: 'must be logged in to perform that action' }]);
197+
return true;
198+
});
199+
});
200+
201+
test('returns an error if the user is not an owner of the crate', async function (assert) {
202+
let user1 = this.db.user.create();
203+
let user2 = this.db.user.create();
204+
205+
let crate = this.db.crate.create();
206+
this.db.version.create({ crate });
207+
this.db.crateOwnership.create({ crate, user: user1 });
208+
209+
// Create a config in the database that will be queried later
210+
this.db.trustpubGithubConfig.create({
211+
crate,
212+
repository_owner: 'rust-lang',
213+
repository_name: 'crates.io',
214+
workflow_filename: 'ci.yml',
215+
});
216+
217+
this.authenticateAs(user1);
218+
let configs = await this.store.query('trustpub-github-config', { crate: crate.name });
219+
assert.strictEqual(configs.length, 1);
220+
221+
db.mswSession.deleteMany({});
222+
this.authenticateAs(user2);
223+
224+
await assert.rejects(configs[0].destroyRecord(), function (error) {
225+
assert.deepEqual(error.errors, [{ detail: 'You are not an owner of this crate' }]);
226+
return true;
227+
});
228+
});
229+
});
230+
});

0 commit comments

Comments
 (0)