Skip to content

Commit 1fd4b6f

Browse files
lqs469JacksonTian
authored andcommitted
refactor: admin inject & ut
1 parent 55b3eba commit 1fd4b6f

File tree

7 files changed

+132
-80
lines changed

7 files changed

+132
-80
lines changed

app.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,30 @@ module.exports = app => {
8080
}
8181
return existUser;
8282
});
83+
84+
app.passport.deserializeUser(async (ctx, user) => {
85+
if (user) {
86+
const auth_token = ctx.cookies.get(ctx.app.config.auth_cookie_name, {
87+
signed: true,
88+
});
89+
90+
if (!auth_token) {
91+
return user;
92+
}
93+
94+
const auth = auth_token.split('$$$$');
95+
const user_id = auth[0];
96+
user = await ctx.service.user.getUserById(user_id);
97+
98+
if (!user) {
99+
return user;
100+
}
101+
102+
if (ctx.app.config.admins.hasOwnProperty(user.loginname)) {
103+
user.is_admin = true;
104+
}
105+
}
106+
107+
return user;
108+
});
83109
};

app/controller/user.js

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,7 @@ class UserController extends Controller {
9090
}
9191

9292
const pages = Math.ceil(user.collect_topic_count / limit);
93-
const opt = {
94-
skip: (page - 1) * limit,
95-
limit,
96-
};
93+
const opt = { skip: (page - 1) * limit, limit };
9794

9895
const collects = await service.topicCollect.getTopicCollectsByUserId(user._id, opt);
9996
const ids = collects.map(function(doc) {
@@ -183,12 +180,6 @@ class UserController extends Controller {
183180
const id = ctx.user._id;
184181
const user = await service.user.getUserById(id);
185182

186-
if (!user) {
187-
ctx.status = 404;
188-
ctx.message = '发生错误';
189-
return;
190-
}
191-
192183
if (ctx.request.query.save === 'success') {
193184
user.success = '保存成功。';
194185
}
@@ -263,11 +254,6 @@ class UserController extends Controller {
263254
const user_id = body.user_id;
264255
const user = await service.user.getUserById(user_id);
265256

266-
if (!user) {
267-
ctx.status = 404;
268-
ctx.message = 'user is not exists';
269-
return;
270-
}
271257
user.is_star = !user.is_star;
272258
await user.save();
273259

@@ -278,13 +264,7 @@ class UserController extends Controller {
278264
const { ctx, ctx: { request: req }, service } = this;
279265
const { body: { action } } = req;
280266
const loginname = ctx.params.name;
281-
282267
const user = await service.user.getUserByLoginName(loginname);
283-
if (!user) {
284-
ctx.status = 404;
285-
ctx.message = 'user is not exists';
286-
return;
287-
}
288268

289269
if (action === 'set_block') {
290270
user.is_block = true;
@@ -300,14 +280,7 @@ class UserController extends Controller {
300280
async deleteAll() {
301281
const { ctx, service } = this;
302282
const loginname = ctx.params.name;
303-
304-
305283
const user = await service.user.getUserByLoginName(loginname);
306-
if (!user) {
307-
ctx.status = 404;
308-
ctx.message = 'user is not exists';
309-
return;
310-
}
311284

312285
// 删除主题
313286
await ctx.model.Topic.update({ author_id: user._id }, { $set: { deleted: true } }, { multi: true });

app/middleware/admin_required.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module.exports = () => {
1111
return;
1212
}
1313

14-
if (!ctx.session.is_admin) {
14+
if (!ctx.user.is_admin) {
1515
await ctx.render('notify/notify', { error: '需要管理员权限。' });
1616
return;
1717
}

app/middleware/auth_user.js

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,24 @@ module.exports = () => {
55
return async function(ctx, next) {
66
// Ensure current_user always has defined.
77
ctx.locals.current_user = null;
8-
if (ctx.app.config.debug && ctx.cookies.get('mock_user')) {
9-
const mockUser = JSON.parse(ctx.cookies.get('mock_user'));
10-
ctx.user = new ctx.model.User(mockUser);
11-
if (mockUser.is_admin) {
12-
ctx.user.is_admin = true;
13-
}
14-
return await next();
15-
}
8+
// if (ctx.app.config.debug && ctx.cookies.get('mock_user')) {
9+
// const mockUser = JSON.parse(ctx.cookies.get('mock_user'));
10+
// ctx.user = new ctx.model.User(mockUser);
11+
// if (mockUser.is_admin) {
12+
// ctx.user.is_admin = true;
13+
// }
14+
// return await next();
15+
// }
1616

17-
let { user } = ctx;
18-
if (user) {
19-
const auth_token = ctx.cookies.get(ctx.app.config.auth_cookie_name, {
20-
signed: true,
21-
});
22-
23-
if (!auth_token) {
24-
return await next();
25-
}
26-
27-
const auth = auth_token.split('$$$$');
28-
const user_id = auth[0];
29-
user = await ctx.service.user.getUserById(user_id);
30-
}
17+
const { user } = ctx;
3118

3219
if (!user) {
3320
return await next();
3421
}
3522

36-
if (ctx.app.config.admins.hasOwnProperty(user.loginname)) {
37-
user.is_admin = true;
38-
}
39-
4023
const count = await ctx.service.message.getMessagesCount(user._id);
4124
user.messages_count = count;
4225
ctx.locals.current_user = user;
43-
// 这里需要设置is_admin, 因为ctx.user为只读, 所以使用ctx.session.is_admin
44-
ctx.session.is_admin = user.is_admin;
4526
await next();
4627
};
4728
};

app/middleware/user_required.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
'use strict';
22

33
module.exports = () => {
4-
54
/*
65
* 需要登录
76
*/
7+
88
return async function(ctx, next) {
99
if (!ctx.user || !ctx.user._id) {
1010
ctx.status = 403;

app/view/user/user.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class='user'>
22
<div>
33
<a href="/user/<%= user.loginname %>">
4-
<img class='user_avatar' src="<%= proxy(user.avatar_url) %>" title="<%= user.loginname %>"/>
4+
<img class='user_avatar' src="<%= helper.proxy(user.avatar_url) %>" title="<%= user.loginname %>"/>
55
</a>
66
<span class='user_name'><a class='dark' href="/user/<%= user.loginname %>"><%= user.loginname %></a></span>
77
<div class='space'></div>

test/app/controller/user.test.js

Lines changed: 93 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,31 @@ describe('test/app/controller/user.test.js', () => {
1111

1212
before(async function() {
1313
ctx = app.mockContext();
14-
loginname = `loginname_${Date.now()}`;
14+
loginname = `user_loginname_${Date.now()}`;
1515
email = `${loginname}@test.com`;
1616
user = await ctx.service.user.newAndSave('name', loginname, tools.bhash('pass'), email, 'avatar_url', 'active');
1717
assert(user.loginname === loginname);
1818
});
1919

2020
describe('- Index', () => {
2121
it('should GET /user ok', async () => {
22-
await app.httpRequest().get('/user').expect(404);
23-
await app.httpRequest().get('/user/unexisted_user').expect(404);
24-
await app.httpRequest().get(`/user/${loginname}`).expect(200);
22+
user.url = 'test_url';
23+
await user.save();
24+
25+
const r1 = await app.httpRequest().get('/user');
26+
assert(r1.status === 404);
27+
assert(/<strong>([\S\s]+)<\/strong>/g.exec(r1.text)[1] === 'Not Found');
28+
29+
const r2 = await app.httpRequest().get('/user/unexisted_user');
30+
assert(r2.status === 404);
31+
assert(/<strong>([\S\s]+)<\/strong>/g.exec(r2.text)[1] === '这个用户不存在。');
32+
33+
const res = await app.httpRequest().get(`/user/${loginname}`);
34+
assert(res.status === 200);
35+
assert(/<img src="([^"]+)" title=/g.exec(res.text)[1] === user.avatar);
36+
assert(/<a class="dark">([^"]+)<\/a>/g.exec(res.text)[1] === user.loginname);
37+
assert(/<span class="big">([^"]+)<\/span> /g.exec(res.text)[1] === user.score.toString());
38+
assert(/([\S\s]+)/g.exec(res.text)[1].replace(/[\t\s]+/g, '') === '这家伙很懒,什么个性签名都没有留下。');
2539
});
2640
});
2741

@@ -34,10 +48,14 @@ describe('test/app/controller/user.test.js', () => {
3448
};
3549

3650
it('should GET /setting ok', async () => {
37-
await app.httpRequest().get('/setting').expect(403);
51+
const nologinRes = await app.httpRequest().get('/setting');
52+
assert(nologinRes.status === 403);
53+
assert(nologinRes.text === 'forbidden!');
3854

3955
app.mockContext({ user });
4056
await app.httpRequest().get('/setting').expect(200);
57+
const { text } = await app.httpRequest().get('/setting?save=success');
58+
assert(/<strong>([\S\s]+)<\/strong>/g.exec(text)[1] === '保存成功。');
4159
});
4260

4361

@@ -60,15 +78,37 @@ describe('test/app/controller/user.test.js', () => {
6078
it('should POST /setting change password ok', async () => {
6179
app.mockCsrf();
6280
app.mockContext({ user });
63-
const { status } = await app.httpRequest()
81+
const res1 = await app.httpRequest()
82+
.post('/setting')
83+
.type('form')
84+
.send({
85+
action: 'change_password',
86+
old_pass: '',
87+
new_pass: '',
88+
});
89+
assert(res1.status === 200);
90+
assert(/<strong>([\S\s]+)<\/strong>/g.exec(res1.text)[1] === '旧密码或新密码不得为空');
91+
92+
const res2 = await app.httpRequest()
93+
.post('/setting')
94+
.type('form')
95+
.send({
96+
action: 'change_password',
97+
old_pass: 'worngPass',
98+
new_pass: 'worngPass',
99+
});
100+
assert(res2.status === 200);
101+
assert(/<strong>([\S\s]+)<\/strong>/g.exec(res2.text)[1] === '当前密码不正确。');
102+
103+
const res3 = await app.httpRequest()
64104
.post('/setting')
65105
.type('form')
66106
.send({
67107
action: 'change_password',
68108
old_pass: 'pass',
69109
new_pass: 'newpass',
70110
});
71-
assert(status === 200);
111+
assert(res3.status === 200);
72112

73113
const savedUser = await ctx.service.user.getUserById(user._id);
74114
const equal = tools.bcompare('newpass', savedUser.pass);
@@ -78,36 +118,53 @@ describe('test/app/controller/user.test.js', () => {
78118

79119
describe('- Admin', () => {
80120
async function handleUserPost(url) {
121+
delete user.is_admin;
81122
app.mockCsrf();
82123
app.mockContext({ user });
83124
const { text } = await app.httpRequest()
84125
.post(url)
85-
.type('form')
86126
.send()
87127
.expect(200);
88128
assert(/<strong>([\S\s]+)<\/strong>/g.exec(text)[1] === '需要管理员权限。');
89129
}
90130

91131
async function handleAdminPost(url, body, cb) {
92-
const adminName = Object.keys(app.config.admins)[0];
93-
let admin = await ctx.service.user.getUserByLoginName(adminName);
94-
if (!admin) {
95-
admin = await ctx.service.user.newAndSave(adminName, adminName, 'pass', '[email protected]', 'u', 'active');
96-
}
97-
const auth_token = admin._id + '$$$$';
98-
app.mockCookies({ [app.config.auth_cookie_name]: auth_token });
132+
// const adminName = Object.keys(app.config.admins)[0];
133+
// let admin = await ctx.service.user.getUserByLoginName(adminName);
134+
// if (!admin) {
135+
// admin = await ctx.service.user.newAndSave(adminName, adminName, 'pass', '[email protected]', 'u', 'active');
136+
// }
137+
// const auth_token = admin._id + '$$$$';
138+
// app.mockCookies({ [app.config.auth_cookie_name]: auth_token });
139+
140+
user.is_admin = true;
99141
app.mockCsrf();
100-
app.mockContext({ user: admin });
101-
const res = await app.httpRequest()
102-
.post(url)
103-
.type('json')
104-
.send(body)
105-
.expect(200);
142+
app.mockContext({ user });
143+
const res = await app.httpRequest().post(url).type('json')
144+
.send(body);
145+
assert(res.status === 200);
106146
assert(res.body.status === 'success');
107147
const updatedUser = await ctx.service.user.getUserById(user._id);
108148
cb(updatedUser);
109149
}
110150

151+
it('should POST /passport/local set cookies', async () => {
152+
app.mockCsrf();
153+
const login = await app.httpRequest().post('/passport/local').send({ name: user.loginname, pass: 'newpass' });
154+
assert(login.status === 302);
155+
const cookies = login.headers['set-cookie'];
156+
const authUser = cookies.find(c => c.indexOf('$$$$') > -1);
157+
assert(/=([^$]+)\$/g.exec(authUser)[1] === user._id.toString());
158+
assert(login.headers.location === '/');
159+
});
160+
161+
it('should POST /user/set_star no_login reject', async () => {
162+
app.mockCsrf();
163+
const res = await app.httpRequest().post('/user/set_star').send();
164+
assert(res.status === 200);
165+
assert(/<strong>([\S\s]+)<\/strong>/g.exec(res.text)[1] === '你还没有登录。');
166+
});
167+
111168
it('should POST /user/set_star no_admin reject', async () => {
112169
await handleUserPost('/user/set_star');
113170
});
@@ -159,16 +216,31 @@ describe('test/app/controller/user.test.js', () => {
159216
});
160217
});
161218

219+
describe('- Stars', () => {
220+
it('should GET /stars ok', async () => {
221+
await app.httpRequest().get('/stars').expect(200);
222+
});
223+
});
224+
162225
describe('- Records', () => {
163226
it('should GET /user/:name/collections ok', async () => {
227+
const noExistedUser = await app.httpRequest().get('/user/no_user/collections');
228+
assert(noExistedUser.status === 404);
229+
assert(/<strong>([\S\s]+)<\/strong>/g.exec(noExistedUser.text)[1] === '这个用户不存在。');
164230
await app.httpRequest().get(`/user/${user.loginname}/collections`).expect(200);
165231
});
166232

167233
it('should GET /user/:name/topics ok', async () => {
234+
const noExistedUser = await app.httpRequest().get('/user/no_user/topics');
235+
assert(noExistedUser.status === 404);
236+
assert(/<strong>([\S\s]+)<\/strong>/g.exec(noExistedUser.text)[1] === '这个用户不存在。');
168237
await app.httpRequest().get(`/user/${user.loginname}/topics`).expect(200);
169238
});
170239

171240
it('should GET /user/:name/replies ok', async () => {
241+
const noExistedUser = await app.httpRequest().get('/user/no_user/replies');
242+
assert(noExistedUser.status === 404);
243+
assert(/<strong>([\S\s]+)<\/strong>/g.exec(noExistedUser.text)[1] === '这个用户不存在。');
172244
await app.httpRequest().get(`/user/${user.loginname}/replies`).expect(200);
173245
});
174246
});

0 commit comments

Comments
 (0)