137 行
3.8 KiB
JavaScript
137 行
3.8 KiB
JavaScript
var db = require('../../common/db')
|
|
var auth = require('../../common/auth')
|
|
var log = require('../../common/log')
|
|
var RESPONSE = require('../../common/response').RESPONSE
|
|
var ERROR_CODES = require('../../common/response').ERROR_CODES
|
|
|
|
exports.main_handler = async function (event) {
|
|
try {
|
|
var method = event.httpMethod || 'GET'
|
|
var path = event.path || ''
|
|
var body = parseBody(event)
|
|
|
|
if (method === 'POST' && path === '/api/v1/auth/login') {
|
|
return await wxLogin(body, event)
|
|
}
|
|
|
|
if (method === 'POST' && path === '/api/v1/auth/refresh') {
|
|
return await refreshToken(body)
|
|
}
|
|
|
|
return RESPONSE.error(ERROR_CODES.PARAM_ERROR.code, 'unknown route')
|
|
} catch (err) {
|
|
console.error('auth error:', err)
|
|
return RESPONSE.error(ERROR_CODES.SERVER_ERROR.code, err.message)
|
|
}
|
|
}
|
|
|
|
async function wxLogin(body, event) {
|
|
if (!body.code) {
|
|
return RESPONSE.error(ERROR_CODES.PARAM_ERROR.code, 'missing code')
|
|
}
|
|
|
|
var wxResult = await requestWxSession(body.code)
|
|
if (!wxResult || !wxResult.openid) {
|
|
return RESPONSE.error(ERROR_CODES.INVALID_TOKEN.code, 'wechat login failed')
|
|
}
|
|
|
|
var users = await db.query(
|
|
'SELECT id, openid, nickname, avatar_url, phone, status FROM users WHERE openid = ? AND deleted_at IS NULL LIMIT 1',
|
|
[wxResult.openid]
|
|
)
|
|
|
|
var userId
|
|
var isNew = false
|
|
if (users.length === 0) {
|
|
var result = await db.insert(
|
|
'INSERT INTO users (openid, nickname, avatar_url, status) VALUES (?, ?, ?, 1)',
|
|
[wxResult.openid, body.nickname || null, body.avatar_url || null]
|
|
)
|
|
userId = result.insertId
|
|
isNew = true
|
|
} else {
|
|
userId = users[0].id
|
|
if (body.nickname || body.avatar_url) {
|
|
await db.update(
|
|
'UPDATE users SET nickname = COALESCE(?, nickname), avatar_url = COALESCE(?, avatar_url) WHERE id = ?',
|
|
[body.nickname || null, body.avatar_url || null, userId]
|
|
)
|
|
}
|
|
}
|
|
|
|
var token = auth.generateToken(userId, wxResult.openid)
|
|
|
|
await log.writeLog({
|
|
operator_type: 2,
|
|
operator_id: userId,
|
|
target_type: 'user',
|
|
target_id: String(userId),
|
|
action: isNew ? 'create' : 'login',
|
|
ip_address: getClientIp(event)
|
|
})
|
|
|
|
return RESPONSE.success({
|
|
token: token,
|
|
user_id: String(userId),
|
|
user_info: {
|
|
id: userId,
|
|
nickname: body.nickname || null,
|
|
avatar_url: body.avatar_url || null
|
|
},
|
|
expires_in: 604800
|
|
})
|
|
}
|
|
|
|
async function refreshToken(body) {
|
|
if (!body.refresh_token) {
|
|
return RESPONSE.error(ERROR_CODES.PARAM_ERROR.code, 'missing refresh_token')
|
|
}
|
|
|
|
var decoded = auth.verifyToken(body.refresh_token)
|
|
if (!decoded || decoded.type === 'admin') {
|
|
return RESPONSE.error(ERROR_CODES.TOKEN_EXPIRED.code, 'invalid refresh_token')
|
|
}
|
|
|
|
var token = auth.generateToken(decoded.user_id, decoded.openid)
|
|
return RESPONSE.success({
|
|
token: token,
|
|
expires_in: 604800
|
|
})
|
|
}
|
|
|
|
async function requestWxSession(code) {
|
|
var appId = process.env.WX_APPID || ''
|
|
var appSecret = process.env.WX_APP_SECRET || ''
|
|
var url = 'https://api.weixin.qq.com/sns/jscode2session?appid=' + appId +
|
|
'&secret=' + appSecret +
|
|
'&js_code=' + code +
|
|
'&grant_type=authorization_code'
|
|
|
|
var https = require('https')
|
|
return new Promise(function (resolve) {
|
|
https.get(url, function (res) {
|
|
var data = ''
|
|
res.on('data', function (chunk) { data += chunk })
|
|
res.on('end', function () {
|
|
try {
|
|
resolve(JSON.parse(data))
|
|
} catch (e) {
|
|
resolve(null)
|
|
}
|
|
})
|
|
}).on('error', function () { resolve(null) })
|
|
})
|
|
}
|
|
|
|
function parseBody(event) {
|
|
if (event.body) {
|
|
try { return JSON.parse(event.body) } catch (e) { return {} }
|
|
}
|
|
return event.queryStringParameters || {}
|
|
}
|
|
|
|
function getClientIp(event) {
|
|
var headers = event.headers || {}
|
|
return headers['x-forwarded-for'] || headers['X-Forwarded-For'] || headers['x-real-ip'] || ''
|
|
}
|