首次完整推送,

V:1.20240808.006
This commit is contained in:
fm453
2024-08-13 18:32:37 +08:00
parent 15be3e9373
commit c62d15b288
939 changed files with 111777 additions and 0 deletions

View File

@ -0,0 +1,59 @@
const methodPermission = require('../config/permission')
const {
ERROR
} = require('../common/error')
function isAccessAllowed (user, setting) {
const {
role: userRole = [],
permission: userPermission = []
} = user
const {
role: settingRole = [],
permission: settingPermission = []
} = setting
if (userRole.includes('admin')) {
return
}
if (
settingRole.length > 0 &&
settingRole.every(item => !userRole.includes(item))
) {
throw {
errCode: ERROR.PERMISSION_ERROR
}
}
if (
settingPermission.length > 0 &&
settingPermission.every(item => !userPermission.includes(item))
) {
throw {
errCode: ERROR.PERMISSION_ERROR
}
}
}
module.exports = async function () {
const methodName = this.getMethodName()
if (!(methodName in methodPermission)) {
return
}
const {
auth,
role,
permission
} = methodPermission[methodName]
if (auth || role || permission) {
await this.middleware.auth()
}
if (role && role.length === 0) {
throw new Error('[AccessControl]Empty role array is not supported')
}
if (permission && permission.length === 0) {
throw new Error('[AccessControl]Empty permission array is not supported')
}
return isAccessAllowed(this.authInfo, {
role,
permission
})
}

View File

@ -0,0 +1,17 @@
module.exports = async function () {
if (this.authInfo) { // 多次执行auth时如果第一次成功后续不再执行
return
}
const token = this.getUniversalUniIdToken()
const payload = await this.uniIdCommon.checkToken(token)
if (payload.errCode) {
throw payload
}
this.authInfo = payload
if (payload.token) {
this.response.newToken = {
token: payload.token,
tokenExpired: payload.tokenExpired
}
}
}

View File

@ -0,0 +1,8 @@
module.exports = {
auth: require('./auth'),
uniIdLog: require('./uni-id-log'),
validate: require('./validate'),
accessControl: require('./access-control'),
verifyRequestSign: require('./verify-request-sign'),
...require('./rbac')
}

View File

@ -0,0 +1,39 @@
const {
ERROR
} = require('../common/error')
function hasRole (...roleList) {
const userRole = this.authInfo.role || []
if (userRole.includes('admin')) {
return
}
const isMatch = roleList.every(roleItem => {
return userRole.includes(roleItem)
})
if (!isMatch) {
throw {
errCode: ERROR.PERMISSION_ERROR
}
}
}
function hasPermission (...permissionList) {
const userRole = this.authInfo.role || []
const userPermission = this.authInfo.permission || []
if (userRole.includes('admin')) {
return
}
const isMatch = permissionList.every(permissionItem => {
return userPermission.includes(permissionItem)
})
if (!isMatch) {
throw {
errCode: ERROR.PERMISSION_ERROR
}
}
}
module.exports = {
hasRole,
hasPermission
}

View File

@ -0,0 +1,39 @@
const db = uniCloud.database()
module.exports = async function ({
data = {},
success = true,
type = 'login'
} = {}) {
const now = Date.now()
const uniIdLogCollection = db.collection('uni-id-log')
const requiredDataKeyList = ['user_id', 'username', 'email', 'mobile']
const dataCopy = {}
for (let i = 0; i < requiredDataKeyList.length; i++) {
const key = requiredDataKeyList[i]
if (key in data && typeof data[key] === 'string') {
dataCopy[key] = data[key]
}
}
const {
appId,
clientIP,
deviceId,
userAgent
} = this.getUniversalClientInfo()
const logData = {
appid: appId,
device_id: deviceId,
ip: clientIP,
type,
ua: userAgent,
create_date: now,
...dataCopy
}
if (success) {
logData.state = 1
} else {
logData.state = 0
}
return uniIdLogCollection.add(logData)
}

View File

@ -0,0 +1,7 @@
module.exports = function (value = {}, schema = {}) {
const validateRes = this.validator.validate(value, schema)
if (validateRes) {
delete validateRes.schemaKey
throw validateRes
}
}

View File

@ -0,0 +1,85 @@
const crypto = require('crypto')
const createConfig = require('uni-config-center')
const { verifyHttpInfo } = require('uni-cloud-s2s')
const { ERROR } = require('../common/error')
const s2sConfig = createConfig({
pluginId: 'uni-cloud-s2s'
})
const needSignFunctions = new Set([
'externalRegister',
'externalLogin',
'updateUserInfoByExternal'
])
module.exports = function () {
const methodName = this.getMethodName()
const { source } = this.getUniversalClientInfo()
// 指定接口需要鉴权
if (!needSignFunctions.has(methodName)) return
// 非 HTTP 方式请求拒绝访问
if (source !== 'http') {
throw {
errCode: ERROR.ILLEGAL_REQUEST
}
}
// 支持 uni-cloud-s2s 验证请求
if (s2sConfig.hasFile('config.json')) {
try {
if (!verifyHttpInfo(this.getHttpInfo())) {
throw {
errCode: ERROR.ILLEGAL_REQUEST
}
}
} catch (e) {
if (e.errSubject === 'uni-cloud-s2s') {
throw {
errCode: ERROR.ILLEGAL_REQUEST,
errMsg: e.errMsg
}
}
throw e
}
return
}
if (!this.config.requestAuthSecret || typeof this.config.requestAuthSecret !== 'string') {
throw {
errCode: ERROR.CONFIG_FIELD_REQUIRED,
errMsgValue: {
field: 'requestAuthSecret'
}
}
}
const timeout = 20 * 1000 // 请求超过20秒不能再请求防止重放攻击
const { headers, body: _body } = this.getHttpInfo()
const { 'uni-id-nonce': nonce, 'uni-id-timestamp': timestamp, 'uni-id-signature': signature } = headers
const body = JSON.parse(_body).params || {}
const bodyStr = Object.keys(body)
.sort()
.filter(item => typeof body[item] !== 'object')
.map(item => `${item}=${body[item]}`)
.join('&')
if (isNaN(Number(timestamp)) || (Number(timestamp) + timeout) < Date.now()) {
console.error('[timestamp error], timestamp:', timestamp, 'timeout:', timeout)
throw {
errCode: ERROR.ILLEGAL_REQUEST
}
}
const reSignature = crypto.createHmac('sha256', `${this.config.requestAuthSecret + nonce}`).update(`${timestamp}${bodyStr}`).digest('hex')
if (signature !== reSignature.toUpperCase()) {
console.error('[signature error], signature:', signature, 'reSignature:', reSignature.toUpperCase(), 'requestAuthSecret:', this.config.requestAuthSecret)
throw {
errCode: ERROR.ILLEGAL_REQUEST
}
}
}