Skip to content

Commit 99adab7

Browse files
lqs469JacksonTian
authored andcommitted
refactor: setting page & auth expired check & admin (#43)
* refactor: user page when no signin * refactor: user page with data * refactor: user page(collectTopics, topics, replies) * refactor: middleware errorPage * refactor: user page when no signin * refactor: replace lodash function * fix: use lodash sortBy * refactor: move avatar_hostname to default.config * refactor: inject helper in middleware ctx.locals * refactor: setting page with session user data * refactor: user setting post * fix: setting post failure * refactor: set auth cookies * refactor: admin(toggleStar, blockUser, deleteAllReply) * fix: admin_user_name * test: user contorller UT 1/2 * refactor: middleware errorPage * refactor: move avatar_hostname to default.config * refactor: inject helper in middleware ctx.locals * refactor: setting page with session user data * fix: setting post failure * refactor: set auth cookies * refactor: admin(toggleStar, blockUser, deleteAllReply) * fix: admin_user_name
1 parent 8e01055 commit 99adab7

File tree

19 files changed

+436
-85
lines changed

19 files changed

+436
-85
lines changed

app.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ module.exports = app => {
2323

2424
const passhash = existUser.pass;
2525
// TODO: change to async compare
26-
const equal = tools.bcompare(passhash, password);
27-
26+
const equal = tools.bcompare(password, passhash);
2827
// 密码不匹配
2928
if (!equal) {
3029
return null;
@@ -67,6 +66,24 @@ module.exports = app => {
6766
app.passport.verify(async (ctx, user) => {
6867
ctx.logger.debug('passport.verify', user);
6968
const handler = user.provider === 'github' ? githubHandler : localHandler;
70-
return handler(ctx, user);
69+
const existUser = await handler(ctx, user);
70+
if (existUser) {
71+
// id存入Cookie, 用于验证过期.
72+
const auth_token = existUser._id + '$$$$'; // 以后可能会存储更多信息,用 $$$$ 来分隔
73+
const opts = {
74+
path: '/',
75+
maxAge: 1000 * 60 * 60 * 24 * 30,
76+
signed: true,
77+
httpOnly: true,
78+
};
79+
ctx.cookies.set(app.config.auth_cookie_name, auth_token, opts); // cookie 有效期30天
80+
}
81+
return existUser;
82+
});
83+
84+
app.passport.serializeUser(async (ctx, user) => {
85+
// 默认会注入session.passport.user, 为方便使用改为session.user (?)
86+
ctx.session.user = user;
87+
return user;
7188
});
7289
};

app/controller/user.js

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
const _ = require('lodash');
44
const utility = require('utility');
5-
5+
const tools = require('../common/tools');
6+
const validator = require('validator');
67
const Controller = require('egg').Controller;
78

89
class UserController extends Controller {
@@ -177,6 +178,145 @@ class UserController extends Controller {
177178
});
178179
}
179180

181+
async showSetting() {
182+
const { ctx, service } = this;
183+
const id = ctx.session.user._id;
184+
const user = await service.user.getUserById(id);
185+
186+
if (!user) {
187+
ctx.status = 404;
188+
ctx.message = '发生错误';
189+
return;
190+
}
191+
192+
if (ctx.request.query.save === 'success') {
193+
user.success = '保存成功。';
194+
}
195+
196+
return await ctx.render('user/setting', { user });
197+
}
198+
199+
async setting() {
200+
const { ctx, ctx: { request: req }, service } = this;
201+
// 显示出错或成功信息
202+
async function showMessage(msg, data, isSuccess) {
203+
data = data || req.body;
204+
const user = {
205+
loginname: data.loginname,
206+
email: data.email,
207+
url: data.url,
208+
location: data.location,
209+
signature: data.signature,
210+
weibo: data.weibo,
211+
accessToken: data.accessToken,
212+
};
213+
if (isSuccess) {
214+
user.success = msg;
215+
} else {
216+
user.error = msg;
217+
}
218+
return await ctx.render('user/setting', { user });
219+
}
220+
221+
// post
222+
const { body, body: { action } } = req;
223+
if (action === 'change_setting') {
224+
const url = validator.trim(body.url);
225+
const location = validator.trim(body.location);
226+
const weibo = validator.trim(body.weibo);
227+
const signature = validator.trim(body.signature);
228+
229+
const user = await service.user.getUserById(ctx.session.user._id);
230+
user.url = url;
231+
user.location = location;
232+
user.signature = signature;
233+
user.weibo = weibo;
234+
user.save();
235+
236+
ctx.session.user = user.toObject({ virtual: true });
237+
return ctx.redirect('/setting?save=success');
238+
}
239+
240+
if (action === 'change_password') {
241+
const oldPass = validator.trim(req.body.old_pass);
242+
const newPass = validator.trim(req.body.new_pass);
243+
if (!oldPass || !newPass) {
244+
return showMessage('旧密码或新密码不得为空');
245+
}
246+
247+
const user = await service.user.getUserById(ctx.session.user._id);
248+
const equal = tools.bcompare(oldPass, user.pass);
249+
if (!equal) {
250+
return showMessage('当前密码不正确。', user);
251+
}
252+
253+
const newPassHash = tools.bhash(newPass);
254+
user.pass = newPassHash;
255+
user.save();
256+
return showMessage('密码已被修改。', user, true);
257+
}
258+
}
259+
260+
async toggleStar() {
261+
const { ctx, ctx: { request: req }, service } = this;
262+
const { body } = req;
263+
const user_id = body.user_id;
264+
const user = await service.user.getUserById(user_id);
265+
266+
if (!user) {
267+
ctx.status = 404;
268+
ctx.message = 'user is not exists';
269+
return;
270+
}
271+
user.is_star = !user.is_star;
272+
user.save();
273+
274+
ctx.body = { status: 'success' };
275+
}
276+
277+
async block() {
278+
const { ctx, ctx: { request: req }, service } = this;
279+
const { body: { action } } = req;
280+
const loginname = ctx.params.name;
281+
282+
const user = await service.user.getUserByLoginName(loginname);
283+
if (!user) {
284+
ctx.status = 404;
285+
ctx.message = 'user is not exists';
286+
return;
287+
}
288+
289+
if (action === 'set_block') {
290+
user.is_block = true;
291+
user.save();
292+
ctx.body = { status: 'success' };
293+
} else if (action === 'cancel_block') {
294+
user.is_block = false;
295+
user.save();
296+
ctx.body = { status: 'success' };
297+
}
298+
}
299+
300+
async deleteAll() {
301+
const { ctx, service } = this;
302+
const loginname = ctx.params.name;
303+
304+
305+
const user = await service.user.getUserByLoginName(loginname);
306+
if (!user) {
307+
ctx.status = 404;
308+
ctx.message = 'user is not exists';
309+
return;
310+
}
311+
312+
// 删除主题
313+
ctx.model.Topic.update({ author_id: user._id }, { $set: { deleted: true } }, { multi: true });
314+
// 删除评论
315+
ctx.model.Reply.update({ author_id: user._id }, { $set: { deleted: true } }, { multi: true });
316+
// 点赞数也全部干掉
317+
ctx.model.Reply.update({}, { $pull: { ups: user._id } }, { multi: true });
318+
ctx.body = { status: 'success' };
319+
}
180320
}
181321

182322
// var User = require('../proxy').User;

app/middleware/admin_required.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
11
'use strict';
22

3-
module.exports = (options, app) => {
4-
3+
module.exports = () => {
54
/**
65
* 需要管理员权限
76
*/
7+
88
return async function(ctx, next) {
99
if (!ctx.session.user) {
10-
await ctx.render('notify/notify', {
11-
error: '你还没有登录。'
12-
});
10+
await ctx.render('notify/notify', { error: '你还没有登录。' });
1311
return;
1412
}
1513

1614
if (!ctx.session.user.is_admin) {
17-
await ctx.render('notify/notify', {
18-
error: '需要管理员权限。'
19-
});
15+
await ctx.render('notify/notify', { error: '需要管理员权限。' });
2016
return;
2117
}
2218

app/middleware/auth_user.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module.exports = () => {
1414
return await next();
1515
}
1616

17-
let user = ctx.session.user;
17+
let { user } = ctx.session;
1818
if (user) {
1919
const auth_token = ctx.cookies.get(ctx.app.config.auth_cookie_name, {
2020
signed: true,
@@ -37,7 +37,7 @@ module.exports = () => {
3737
user.is_admin = true;
3838
}
3939

40-
const count = await this.service.message.getMessagesCount(user._id);
40+
const count = await ctx.service.message.getMessagesCount(user._id);
4141
user.messages_count = count;
4242
ctx.session.user = user;
4343
ctx.locals.current_user = user;

app/middleware/locals.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const Loader = require('loader');
4+
const helper = require('../extend/helper');
45

56
module.exports = (options, app) => {
67
// assets
@@ -24,6 +25,7 @@ module.exports = (options, app) => {
2425
ctx.locals.Loader = Loader;
2526
ctx.locals.assets = assets;
2627
ctx.locals.csrf = ctx.csrf;
28+
ctx.locals = Object.assign({}, ctx.locals, helper);
2729
await next();
2830
};
2931
};

app/middleware/proxy.js

Lines changed: 0 additions & 47 deletions
This file was deleted.

app/middleware/user_required.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
'use strict';
22

3-
module.exports = (options, app) => {
4-
3+
module.exports = () => {
54
/**
65
* 需要登录
76
*/
7+
88
return async function(ctx, next) {
9-
if (!ctx.session || !ctx.session.user || !ctx.session.user._id) {
9+
const { session } = ctx;
10+
if (!session || !session.user || !session.user._id) {
1011
ctx.status = 403;
1112
ctx.body = 'forbidden!';
1213
return;

app/router.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,17 @@ module.exports = app => {
4949

5050
// user controller
5151
router.get('/user/:name', user.index); // 用户个人主页
52-
// router.get('/setting', userRequired, user.showSetting); // 用户个人设置页
53-
// router.post('/setting', userRequired, user.setting); // 提交个人信息设置
52+
router.get('/setting', userRequired, user.showSetting); // 用户个人设置页
53+
router.post('/setting', userRequired, user.setting); // 提交个人信息设置
5454
router.get('/stars', user.listStars); // 显示所有达人列表页
5555
router.get('/users/top100', user.top100); // 显示积分前一百用户页
5656
router.get('/user/:name/collections', user.listCollectedTopics); // 用户收藏的所有话题页
5757
router.get('/user/:name/topics', user.listTopics); // 用户发布的所有话题页
5858
router.get('/user/:name/replies', user.listReplies); // 用户参与的所有回复页
59-
// router.post('/user/set_star', adminRequired, user.toggleStar); // 把某用户设为达人
60-
// router.post('/user/cancel_star', adminRequired, user.toggleStar); // 取消某用户的达人身份
61-
// router.post('/user/:name/block', adminRequired, user.block); // 禁言某用户
62-
// router.post('/user/:name/delete_all', adminRequired, user.deleteAll); // 删除某用户所有发言
59+
router.post('/user/set_star', adminRequired, user.toggleStar); // 把某用户设为达人
60+
router.post('/user/cancel_star', adminRequired, user.toggleStar); // 取消某用户的达人身份
61+
router.post('/user/:name/block', adminRequired, user.block); // 禁言某用户
62+
router.post('/user/:name/delete_all', adminRequired, user.deleteAll); // 删除某用户所有发言
6363

6464
// // message controler
6565
// router.get('/my/messages', userRequired, message.index); // 用户个人的所有消息页

app/view/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<% include ./sidebar.html %>
1+
<% include sidebar.html %>
22

33
<div id="content">
44
<div class="panel">

app/view/sidebar.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<span class='col_fade'>个人信息</span>
77
</div>
88
<div class='inner'>
9-
<%- include('../user/card.html', { object: typeof user === 'undefined' ? current_user : user, as: 'user' }) %>
9+
<%- include('./user/card.html', { user: typeof user === 'undefined' ? current_user : user }) %>
1010
</div>
1111
<% } else { %>
1212
<div class='inner'>
@@ -50,7 +50,7 @@
5050
<div class='inner'>
5151
<% if (no_reply_topics.length > 0) { %>
5252
<ul class="unstyled">
53-
<%- include('topic/small', { collection: no_reply_topics, as: 'topic' }) %>
53+
<%- include('topic/small', { topic: no_reply_topics }) %>
5454
</ul>
5555
<% } else { %>
5656
<p></p>

0 commit comments

Comments
 (0)