Skip to content

Commit fc2ad36

Browse files
committed
frontend work
1 parent de80090 commit fc2ad36

File tree

7 files changed

+205
-0
lines changed

7 files changed

+205
-0
lines changed

app/models/user.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default class User extends Model {
1414
@attr avatar;
1515
@attr url;
1616
@attr kind;
17+
@attr admin;
1718

1819
async stats() {
1920
return await customAction(this, { method: 'GET', path: 'stats' });

app/router.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ Router.map(function () {
3030
this.route('following');
3131
this.route('pending-invites');
3232
});
33+
this.route('admin', function () {
34+
this.route('rate-limits');
35+
});
3336
this.route('settings', function () {
3437
this.route('appearance');
3538
this.route('email-notifications');

app/routes/admin/index.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { A } from '@ember/array';
2+
import { inject as service } from '@ember/service';
3+
import RSVP from 'rsvp';
4+
5+
import AuthenticatedRoute from './../-authenticated-route';
6+
7+
export default class AdminRoute extends AuthenticatedRoute {
8+
@service router;
9+
@service session;
10+
11+
async beforeModel(transition) {
12+
// wait for the `loadUserTask.perform()` of either the `application` route,
13+
// or the `session.login()` call
14+
let result = await this.session.loadUserTask.last;
15+
16+
if (!result.currentUser) {
17+
this.session.savedTransition = transition;
18+
this.router.replaceWith('catch-all', {
19+
transition,
20+
loginNeeded: true,
21+
title: 'This page requires admin authentication',
22+
});
23+
} else if (!result.currentUser.admin) {
24+
this.session.savedTransition = transition;
25+
this.router.replaceWith('catch-all', {
26+
transition,
27+
loginNeeded: false,
28+
title: 'This page requires admin authentication',
29+
});
30+
}
31+
}
32+
33+
redirect() {
34+
this.router.replaceWith('admin.rate-limits');
35+
}
36+
}

app/routes/admin/rate-limits.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { A } from '@ember/array';
2+
import { inject as service } from '@ember/service';
3+
import RSVP from 'rsvp';
4+
5+
import AuthenticatedRoute from './../-authenticated-route';
6+
7+
export default class RateLimitsAdminRoute extends AuthenticatedRoute {
8+
@service router;
9+
@service session;
10+
11+
async beforeModel(transition) {
12+
// wait for the `loadUserTask.perform()` of either the `application` route,
13+
// or the `session.login()` call
14+
let result = await this.session.loadUserTask.last;
15+
16+
if (!result.currentUser) {
17+
this.session.savedTransition = transition;
18+
this.router.replaceWith('catch-all', {
19+
transition,
20+
loginNeeded: true,
21+
title: 'This page requires admin authentication',
22+
});
23+
} else if (!result.currentUser.admin) {
24+
this.session.savedTransition = transition;
25+
this.router.replaceWith('catch-all', {
26+
transition,
27+
loginNeeded: false,
28+
title: 'This page requires admin authentication',
29+
});
30+
}
31+
}
32+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.rate-limit {}
2+
3+
.page {
4+
display: grid;
5+
gap: 16px;
6+
7+
@media (--min-m) {
8+
grid-template:
9+
"menu content" auto /
10+
200px auto;
11+
}
12+
}
13+
14+
.content {
15+
h2:first-child {
16+
margin-top: 4px;
17+
}
18+
}

app/templates/admin/rate-limits.hbs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{{page-title 'Admin Actions'}}
2+
3+
<PageHeader @title="Admin Actions" data-test-heading />
4+
5+
<div local-class="page" ...attributes>
6+
<SideMenu as |menu|>
7+
<menu.Item @link={{link "admin.rate-limits"}}>Increase Rate Limit</menu.Item>
8+
<menu.Item>More actions coming soon</menu.Item>
9+
</SideMenu>
10+
11+
<div local-class="content">
12+
<div local-class='rate-limit'>
13+
<h2>Increase Rate Limit</h2>
14+
<label>email address:</label>
15+
</div>
16+
</div>
17+
18+
</div>

tests/acceptance/admin-test.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { click, currentURL } from '@ember/test-helpers';
2+
import { module, test } from 'qunit';
3+
4+
import percySnapshot from '@percy/ember';
5+
6+
import { setupApplicationTest } from 'cargo/tests/helpers';
7+
8+
import { visit } from '../helpers/visit-ignoring-abort';
9+
10+
module('Acceptance | Admin', function (hooks) {
11+
setupApplicationTest(hooks);
12+
13+
test('shows "page requires admin authentication" error when not logged in', async function (assert) {
14+
await visit('/admin');
15+
assert.equal(currentURL(), '/admin');
16+
assert.dom('[data-test-title]').hasText('This page requires admin authentication');
17+
assert.dom('[data-test-login]').exists();
18+
});
19+
20+
test('shows "page requires admin authentication" error when logged in but not as an admin', async function (assert) {
21+
let user = this.server.create('user', {
22+
login: 'johnnydee',
23+
name: 'John Doe',
24+
email: 'john@doe.com',
25+
avatar: 'https://avatars2.githubusercontent.com/u/1234567?v=4',
26+
admin: false,
27+
});
28+
29+
this.authenticateAs(user);
30+
31+
await visit('/admin');
32+
assert.equal(currentURL(), '/admin');
33+
assert.dom('[data-test-title]').hasText('This page requires admin authentication');
34+
assert.dom('[data-test-login]').doesNotExist();
35+
});
36+
37+
test('shows admin actions when logged in as an admin', async function (assert) {
38+
let user = this.server.create('user', {
39+
login: 'johnnydee',
40+
name: 'John Doe',
41+
email: 'john@doe.com',
42+
avatar: 'https://avatars2.githubusercontent.com/u/1234567?v=4',
43+
admin: true,
44+
});
45+
46+
this.authenticateAs(user);
47+
48+
await visit('/admin');
49+
// Rate limits is the default action.
50+
assert.equal(currentURL(), '/admin/rate-limits');
51+
assert.dom('[data-test-heading]').hasText('Admin Actions');
52+
assert.dom('[data-test-login]').doesNotExist();
53+
});
54+
55+
module('Rate limits', function () {
56+
test('shows "page requires admin authentication" error when not logged in', async function (assert) {
57+
await visit('/admin/rate-limits');
58+
assert.equal(currentURL(), '/admin/rate-limits');
59+
assert.dom('[data-test-title]').hasText('This page requires admin authentication');
60+
assert.dom('[data-test-login]').exists();
61+
});
62+
63+
test('shows "page requires admin authentication" error when logged in but not as an admin', async function (assert) {
64+
let user = this.server.create('user', {
65+
login: 'johnnydee',
66+
name: 'John Doe',
67+
email: 'john@doe.com',
68+
avatar: 'https://avatars2.githubusercontent.com/u/1234567?v=4',
69+
admin: false,
70+
});
71+
72+
this.authenticateAs(user);
73+
74+
await visit('/admin/rate-limits');
75+
assert.equal(currentURL(), '/admin/rate-limits');
76+
assert.dom('[data-test-title]').hasText('This page requires admin authentication');
77+
assert.dom('[data-test-login]').doesNotExist();
78+
});
79+
});
80+
81+
test('shows rate limit actions when logged in as an admin', async function (assert) {
82+
let user = this.server.create('user', {
83+
login: 'johnnydee',
84+
name: 'John Doe',
85+
email: 'john@doe.com',
86+
avatar: 'https://avatars2.githubusercontent.com/u/1234567?v=4',
87+
admin: true,
88+
});
89+
90+
this.authenticateAs(user);
91+
92+
await visit('/admin/rate-limits');
93+
assert.equal(currentURL(), '/admin/rate-limits');
94+
assert.dom('[data-test-heading]').hasText('Admin Actions');
95+
assert.dom('[data-test-login]').doesNotExist();
96+
});
97+
});

0 commit comments

Comments
 (0)