Skip to content

Commit 8e58d71

Browse files
authored
fix: login with github (#87)
* fix: login with github * use ctx.ip instead of
1 parent 79b26a7 commit 8e58d71

File tree

10 files changed

+89
-18
lines changed

10 files changed

+89
-18
lines changed

app.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,16 @@ module.exports = app => {
3939

4040
const githubHandler = async (ctx, { profile }) => {
4141
const email = profile.emails && profile.emails[0] && profile.emails[0].value;
42-
const existUser = await ctx.service.user.getUsersByQuery({
43-
githubId: profile.id,
44-
});
42+
let existUser = await ctx.service.user.getUserByGithubId(profile.id);
4543

4644
// 用户不存在则创建
47-
// TODO
4845
if (!existUser) {
49-
return null;
46+
existUser = new ctx.model.User();
47+
existUser.active = true;
5048
}
5149

5250
// 用户存在,更新字段
53-
// existUser.loginname = profile.username;
54-
existUser.githubId = profile.id;
51+
existUser.loginname = profile.username;
5552
existUser.email = email || existUser.email;
5653
existUser.avatar = profile._json.avatar_url;
5754
existUser.githubUsername = profile.username;
@@ -76,6 +73,7 @@ module.exports = app => {
7673
};
7774
ctx.cookies.set(app.config.auth_cookie_name, auth_token, opts); // cookie 有效期30天
7875
}
76+
7977
return existUser;
8078
});
8179

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
'use strict';
2+
23
const moment = require('moment');
34

45
module.exports = ({ perDayPerUserLimitCount = 10 }) => {
56

6-
return async function(ctx, next) {
7+
return async function createTopicLimit(ctx, next) {
78
const { user, service } = ctx;
89
const YYYYMMDD = moment().format('YYYYMMDD');
910
const key = `topics_count_${user._id}_${YYYYMMDD}`;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
3+
const moment = require('moment');
4+
5+
module.exports = limitCount => {
6+
7+
return async function createUserLimit(ctx, next) {
8+
const { service } = ctx;
9+
const realIP = ctx.ip;
10+
11+
const YYYYMMDD = moment().format('YYYYMMDD');
12+
const key = `user_count_${realIP}_${YYYYMMDD}`;
13+
14+
let todayTopicsCount = (await service.cache.get(key)) || 0;
15+
if (todayTopicsCount >= limitCount) {
16+
ctx.status = 403;
17+
ctx.body = {
18+
success: false,
19+
error_msg: '频率限制:当前操作每天可以进行 ' + limitCount + ' 次',
20+
};
21+
return;
22+
}
23+
24+
await next();
25+
26+
if (ctx.status === 302) {
27+
// 新建话题成功
28+
todayTopicsCount += 1;
29+
await service.cache.incr(key, 60 * 60 * 24);
30+
ctx.set('X-RateLimit-Limit', limitCount);
31+
ctx.set('X-RateLimit-Remaining', limitCount - todayTopicsCount);
32+
}
33+
};
34+
};
35+

app/router.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
module.exports = app => {
77
const { router, controller, config, middleware } = app;
88

9-
const { site, sign, user, topic, rss, search, page, reply, message } = controller;
9+
const { site, sign, user, topic, rss,
10+
search, page, reply, message } = controller;
1011

1112
const userRequired = middleware.userRequired();
1213
const adminRequired = middleware.adminRequired();
13-
const topicPerDayLimit = middleware.topicPerDayLimit(config.topic);
14+
const createTopicLimit = middleware.createTopicLimit(config.topic);
15+
const createUserLimit = middleware.createUserLimit(config.create_user_per_ip);
1416

1517
// home page
1618
router.get('/', site.index);
@@ -24,7 +26,7 @@ module.exports = app => {
2426
// 跳转到注册页面
2527
router.get('/signup', sign.showSignup);
2628
// 提交注册信息
27-
router.post('/signup', sign.signup);
29+
router.post('/signup', createUserLimit, sign.signup);
2830
} else {
2931
// 进行github验证
3032
router.redirect('/singup', '/auth/github');
@@ -79,7 +81,7 @@ module.exports = app => {
7981
router.post('/topic/:tid/delete', userRequired, topic.delete);
8082

8183
// // 保存新建的文章
82-
router.post('/topic/create', userRequired, topicPerDayLimit, topic.put);
84+
router.post('/topic/create', userRequired, createTopicLimit, topic.put);
8385

8486
router.post('/topic/:tid/edit', userRequired, topic.update);
8587
router.post('/topic/collect', userRequired, topic.collect); // 关注某话题

app/service/user.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ class UserService extends Service {
2929
return this.ctx.model.User.findOne(query).exec();
3030
}
3131

32+
/*
33+
* 根据 githubId 查找用户
34+
* @param {String} githubId 登录名
35+
* @return {Promise[user]} 承载用户的 Promise 对象
36+
*/
37+
getUserByGithubId(githubId) {
38+
const query = { githubId };
39+
return this.ctx.model.User.findOne(query).exec();
40+
}
41+
3242
/*
3343
* 根据用户ID,查找用户
3444
* @param {String} id 用户ID

app/view/sidebar.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
1919
<a href='/signup'>注册</a>
2020
, 也可以
21-
<a href="/auth/github">
21+
<a href="/passport/github">
2222
<span class="span-info">
2323
通过 GitHub 登录
2424
</span>
@@ -51,7 +51,7 @@
5151
<% if (no_reply_topics.length > 0) { %>
5252
<ul class="unstyled">
5353
<% no_reply_topics.forEach(topic => { %>
54-
<%- include('./topic/small.html', { topic }) %>
54+
<%- include('./topic/small.html', { topic }) %>
5555
<% }) %>
5656
</ul>
5757
<% } else { %>

config/config.default.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,5 +147,8 @@ module.exports = appInfo => {
147147

148148
config.list_topic_count = 20;
149149

150+
// 每个 IP 每天可创建用户数
151+
config.create_user_per_ip = 1000;
152+
150153
return config;
151154
};

test/app/controller/sign.test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,4 +231,14 @@ describe('test/app/controller/sign.test.js', () => {
231231
assert(res.statusCode === 422);
232232
assert(res.text.includes('用户名或邮箱已被使用。'));
233233
});
234+
235+
it('should GET /passport/github', async () => {
236+
const res = await app.httpRequest()
237+
.get('/passport/github');
238+
239+
assert(res.statusCode === 302);
240+
const patt = /https:\/\/github\.com\/login\/oauth\/authorize\?response_type=code\&redirect_uri=http%3A%2F%2F127\.0\.0\.1%3A(\d+)%2Fpassport%2Fgithub%2Fcallback&client_id=test/;
241+
assert(patt.test(res.headers.location));
242+
});
243+
234244
});

test/app/controller/user.test.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,21 +174,25 @@ describe('test/app/controller/user.test.js', () => {
174174
assert(/=([^$]+)\$/g.exec(authUser)[1] === user._id.toString());
175175
assert(login.headers.location === '/');
176176

177-
const login1 = await app.httpRequest().post('/passport/local').send({ name: user.loginname, pass: 'pass' });
177+
const login1 = await app.httpRequest().post('/passport/local')
178+
.send({ name: user.loginname, pass: 'pass' });
178179
assert(login1.status === 302);
179180
assert(login1.headers.location === '/signin');
180181

181-
const login2 = await app.httpRequest().post('/passport/local').send({ name: user.email, pass: 'newpass' });
182+
const login2 = await app.httpRequest().post('/passport/local')
183+
.send({ name: user.email, pass: 'newpass' });
182184
assert(login2.status === 302);
183185
assert(login2.headers.location === '/');
184186

185-
const login3 = await app.httpRequest().post('/passport/local').send({ name: 'noExistedUser', pass: 'pass' });
187+
const login3 = await app.httpRequest().post('/passport/local')
188+
.send({ name: 'noExistedUser', pass: 'pass' });
186189
assert(login3.status === 302);
187190
assert(login3.headers.location === '/signin');
188191

189192
user.active = false;
190193
await user.save();
191-
const login4 = await app.httpRequest().post('/passport/local').send({ name: user.loginname, pass: 'newpass' });
194+
const login4 = await app.httpRequest().post('/passport/local')
195+
.send({ name: user.loginname, pass: 'newpass' });
192196
assert(login4.status === 302);
193197
assert(login4.headers.location === '/signin');
194198
});

test/app/service/user.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ describe('test/app/service/user.test.js', () => {
4545
assert(user.loginname === loginname);
4646
});
4747

48+
it('getUserByGithubId should ok', async function() {
49+
// 创建 ctx
50+
const ctx = app.mockContext();
51+
52+
const user = await ctx.service.user.getUserByGithubId('githubid');
53+
assert(user === null);
54+
});
55+
4856
it('getUserById should ok', async function() {
4957
// 创建 ctx
5058
const ctx = app.mockContext();

0 commit comments

Comments
 (0)