Skip to content

Commit e6e64b1

Browse files
authored
添加第三方登录,功能模块
1 parent fe2727b commit e6e64b1

File tree

5 files changed

+330
-0
lines changed

5 files changed

+330
-0
lines changed

social-sign/local/en-US.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/*
2+
Localization
3+
*/
4+
module.exports = {
5+
SOCIAL_SIGN: 'Social sign'
6+
}

social-sign/local/zh-CN.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/*
2+
Localization
3+
*/
4+
module.exports = {
5+
SOCIAL_SIGN: '第三方登录'
6+
}

social-sign/package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "Social-Sign",
3+
"description": "Social signin/signup",
4+
"version": "0.0.1",
5+
"icon": "/social-sign/img/wechat.png",
6+
"main": "svr/social.sign"
7+
}

social-sign/svr/social.sign.js

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
var fs = require('fs')
2+
var path = require('path')
3+
var EventEmitter = require('events').EventEmitter
4+
var util = require('util')
5+
6+
var MAIN_CONFIG = CONFIG.MAIN_CONFIG
7+
var ONCEDOC_CONFIG = CONFIG.ONCEDOC_CONFIG
8+
var SOCIAL_SIGN = CONFIG.SOCIAL_SIGN
9+
10+
11+
OnceDoc.on('ready', function() {
12+
13+
oncedb.extend('user', {
14+
avatar : ''
15+
, city : ''
16+
, nickname : ''
17+
})
18+
19+
OnceDoc.Sign.SUB_LINKS.push('<a href="/social-sign/scan"><i class="fa fa-wechat"></i> {0}</a>'.format(LOCAL.WECHAT_SIGN))
20+
})
21+
22+
app.mod('social-sign', '../web')
23+
24+
app.get('/social-sign/scan', function(req, res) {
25+
//github linkedin facebook 至少配置一个
26+
if (!SOCIAL_SIGN || (SOCIAL_SIGN.github && SOCIAL_SIGN.linkedin && SOCIAL_SIGN.facebook)) {
27+
res.send('SOCIAL_SIGN github/linkedin/facebook is not configuraed')
28+
return
29+
}
30+
31+
OnceDoc.User.getAutoSignin(req.cookies, function(userInfo) {
32+
console.log('autoSign', userInfo)
33+
if (userInfo) {
34+
req.session.user = userInfo
35+
res.model('user', userInfo)
36+
res.render('social.sign.tmpl')
37+
return
38+
}
39+
40+
var model = {}
41+
42+
if (SOCIAL_SIGN.github) {
43+
model.githubUrl = 'https://github.com/login/oauth/authorize?client_id={0}&redirect_uri={1}'.format(
44+
SOCIAL_SIGN.github.client_id
45+
, SOCIAL_SIGN.github.redirect_uri
46+
)
47+
}
48+
49+
if (SOCIAL_SIGN.linkedin) {
50+
model.linkedinUrl = 'https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id={0}&redirect_uri={1}&state={2}&scope=r_liteprofile r_emailaddress'.format(
51+
SOCIAL_SIGN.linkedin.client_id
52+
, SOCIAL_SIGN.linkedin.redirect_uri
53+
, app.id(12)
54+
)
55+
}
56+
57+
if (SOCIAL_SIGN.facebook) {
58+
model.facebook = ''.format(
59+
SOCIAL_SIGN.facebook.client_id
60+
, SOCIAL_SIGN.facebook.redirect_uri
61+
)
62+
}
63+
64+
res.render('social.sign.tmpl', model)
65+
})
66+
})
67+
68+
app.get('/social-sign/oauth/github/callback', function(req, res) {
69+
// 第一步:检查 code 用来交互 access_token; 检查 state 用来写入登录 session
70+
var code = req.query.code
71+
if (!code) {
72+
res.send('no code')
73+
return
74+
}
75+
76+
// 第二步:获取 access_token
77+
OnceDoc.request({
78+
url: 'https://github.com/login/oauth/access_token'
79+
, headers: {
80+
Accept: "application/json"
81+
}
82+
, data: {
83+
client_id : SOCIAL_SIGN.github.client_id
84+
, client_secret : SOCIAL_SIGN.github.client_secret
85+
, code : code
86+
}
87+
, type: 'qs'
88+
}, function(err, response, data) {
89+
//https://api.github.com/user
90+
var access_token = data.access_token
91+
if (!access_token) {
92+
res.send('no access_token')
93+
return
94+
}
95+
96+
// 第三步:获取用户信息,注册必须包含, User-Agent 建议是github用户名或者APP名
97+
OnceDoc.request({
98+
url: 'https://api.github.com/user'
99+
, headers: {
100+
'User-Agent' : 'OnceDB',
101+
'Authorization' : 'token ' + access_token
102+
}
103+
}, function(err, response, data) {
104+
if (!data.id) {
105+
res.send('get user info error')
106+
return
107+
}
108+
109+
console.log(data)
110+
111+
// 第四步:注册并写入session
112+
var userInfo = {
113+
username : 'gh_' + data.login
114+
, password : app.id(12)
115+
, email : data.email
116+
, nickname : data.name
117+
, avatar : data.avatar_url
118+
, city : data.location
119+
}
120+
121+
OnceDoc.User.signup(userInfo, function(err) {
122+
//之前注册过?手动更新用户信息
123+
if (err) {
124+
console.log(err)
125+
126+
oncedb.update('user', userInfo, function() {
127+
console.log(arguments)
128+
})
129+
}
130+
131+
delete userInfo.password
132+
req.session.user = userInfo
133+
134+
//完成,返回主页
135+
res.redirect('/social-sign/scan')
136+
})
137+
})
138+
})
139+
})
140+
141+
app.get('/social-sign/oauth/linkedin/callback', function(req, res) {
142+
// 第一步:检查 code 用来交互 access_token; 检查 state 用来写入登录 session
143+
var code = req.query.code
144+
if (!code) {
145+
res.send('no code')
146+
return
147+
}
148+
149+
// 第二步:获取 access_token
150+
OnceDoc.request({
151+
url: 'https://www.linkedin.com/oauth/v2/accessToken'
152+
, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
153+
, data: {
154+
client_id : SOCIAL_SIGN.linkedin.client_id
155+
, client_secret : SOCIAL_SIGN.linkedin.client_secret
156+
, redirect_uri : SOCIAL_SIGN.linkedin.redirect_uri
157+
, code : code
158+
, grant_type : 'authorization_code'
159+
}
160+
, type: 'qs'
161+
}, function(err, response, data) {
162+
console.trace(data)
163+
164+
//https://api.github.com/user
165+
var access_token = data.access_token
166+
if (!access_token) {
167+
res.send('no access_token')
168+
return
169+
}
170+
171+
// 第三步:获取用户信息,注册必须包含, User-Agent 建议是github用户名或者APP名
172+
OnceDoc.request({
173+
url: 'https://api.linkedin.com/v2/me'
174+
, headers: {
175+
'Authorization' : 'Bearer ' + access_token
176+
}
177+
}, function(err, response, data) {
178+
console.log(data)
179+
180+
if (!data.id) {
181+
res.send('get user info error')
182+
return
183+
}
184+
185+
// 第四步:注册并写入session
186+
var userInfo = {
187+
username : 'in_' + data.id.replace(/[^\w]+/g, '')
188+
, password : app.id(12)
189+
, email : data.id + '@oncedb.com'
190+
, nickname : data.localizedFirstName + ' ' + data.localizedLastName
191+
// , avatar : data.avatar_url
192+
// , city : data.location
193+
}
194+
195+
OnceDoc.User.signup(userInfo, function(err) {
196+
//之前注册过?手动更新用户信息
197+
if (err) {
198+
console.log(err)
199+
200+
oncedb.update('user', userInfo, function() {
201+
console.log(arguments)
202+
})
203+
}
204+
205+
delete userInfo.password
206+
req.session.user = userInfo
207+
208+
//完成,返回主页
209+
res.redirect('/social-sign/scan')
210+
})
211+
})
212+
})
213+
})

social-sign/web/social.sign.tmpl

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<!--#include="/site.meta.tmpl"-->
5+
6+
<title>{{=it.local.SOCIAL_SIGN}} | {{=it.local.SITE_BRIEF_TITLE}}</title>
7+
8+
<link rel="stylesheet" href="/css/bootstrap.css">
9+
<link rel="stylesheet" href="/css/font-awesome.css">
10+
<link rel="stylesheet" href="/css/jquery.bootstrap.css">
11+
<link rel="stylesheet" href="/css/site.css">
12+
<!--#include="/site.script.tmpl"-->
13+
</head>
14+
15+
<body>
16+
17+
<!--#include="/site.header.part"-->
18+
19+
<div class="container">
20+
<div style="margin: 24px">
21+
<ul class="nav nav-tabs" role="tablist">
22+
<li role="presentation" class="active">
23+
<a><i class="fa fa-github"></i> {{=it.local.SOCIAL_SIGN}}</a>
24+
</li>
25+
</ul>
26+
<div class="tab-content" style="border: 1px solid #ddd;border-top: none;padding: 64px 0">
27+
<div class="tab-pane active text-center">
28+
{{?it.user.username}}
29+
<br><br>
30+
<ul class="dropdown-menu dropdown-user show" style="position: static; float: none; width: 240px; margin: 0 auto;text-align: center;">
31+
<li class="dropdown-user-img">
32+
<br>
33+
<div style="color: #999">{{=it.user.username}}</div>
34+
<br>
35+
<div class="img-circle">
36+
<img src="{{=it.user.avatar || '/img/favicon_72.png'}}" />
37+
</div>
38+
<a href="#" title="{{=it.user.nickname || ''}}"> <b>{{=it.user.nickname || ''}}</b> </a>
39+
<br>
40+
</li>
41+
<li role="separator" class="divider"></li>
42+
<li>
43+
<a href="#"> <i class="glyphicon glyphicon-home"></i> {{=(it.user.province || '')+' '+(it.user.city||'')}} </a>
44+
</li>
45+
<li role="separator" class="divider"></li>
46+
</ul>
47+
<div>
48+
<br>
49+
<br>
50+
<a class="btn btn-lg btn-default" href="/sign/out?url=/social-sign/scan">{{=it.local.USER_LOG_OUT}}</a>
51+
<a class="btn btn-lg btn-primary" href="/">{{=it.local.BACK_TO_HOME}}</a>
52+
<br><br>
53+
<br><br>
54+
</div>
55+
{{??}}
56+
<div>
57+
<br><br>
58+
<br><br>
59+
60+
<div class="btn-group-vertical">
61+
{{?it.githubUrl}}
62+
<a class="btn btn-default btn-lg" href="{{=it.githubUrl}}">
63+
<i class="fa fa-github"></i> Sign in via Github
64+
</a>
65+
<br>
66+
{{?}}
67+
68+
{{?it.linkedinUrl}}
69+
<a class="btn btn-default btn-lg" href="{{=it.linkedinUrl}}">
70+
<i class="fa fa-linkedin"></i> Sign in via LinkedIn
71+
</a>
72+
<br>
73+
{{?}}
74+
75+
{{?it.facebookUrl}}
76+
<a class="btn btn-default btn-lg" href="https://github.com/login/oauth/authorize?client_id=f283ce279713c1c9ac3c&redirect_uri=http://localhost:8064/oauth/redirect">
77+
<i class="fa fa-linkedin"></i> Sign in via Facebook
78+
</a>
79+
<br><br>
80+
{{?}}
81+
</div>
82+
83+
<div id="autoSign" style="display: none;">
84+
<a href="/wechat-sign/json/autosign/set" class="btn btn-lg btn-primary">登录成功,<b>10</b> 秒后自动跳转,单击此处,以后自动登录</a>
85+
<br><br>
86+
</div>
87+
<br><br>
88+
</div>
89+
{{?}}
90+
</div>
91+
</div>
92+
</div>
93+
</div>
94+
95+
<!--#include="/site.footer.part"-->
96+
97+
</body>
98+
</html>

0 commit comments

Comments
 (0)