feat: init project with miniprogram, cloud functions and admin console
这个提交包含在:
@@ -0,0 +1,136 @@
|
||||
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'] || ''
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户