149 lines
5.3 KiB
JavaScript
149 lines
5.3 KiB
JavaScript
'use strict';
|
||
|
||
const uniID = require('uni-id-common');
|
||
const checkVersion = require('./checkVersion');
|
||
|
||
const success = { success: true };
|
||
const fail = { success: false };
|
||
const appListDBName = 'opendb-app-list';
|
||
const appVersionDBName = 'opendb-app-versions';
|
||
|
||
function errorResult(code, message, extra = {}) {
|
||
return { ...fail, code, msg: message, ...extra };
|
||
}
|
||
|
||
function isObject(value) {
|
||
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
||
}
|
||
|
||
function isNonEmptyString(value) {
|
||
return typeof value === 'string' && value.trim().length > 0;
|
||
}
|
||
|
||
function parseRequest(event) {
|
||
if (!isObject(event)) return { error: errorResult(400, '请求参数必须是对象') };
|
||
if (!event.headers) return { data: event };
|
||
|
||
const method = String(event.httpMethod || 'GET').toLowerCase();
|
||
let payload;
|
||
try {
|
||
if (method === 'get') {
|
||
payload = event.queryStringParameters || {};
|
||
if (typeof payload === 'string') payload = JSON.parse(payload || '{}');
|
||
} else if (event.body && typeof event.body === 'object') {
|
||
payload = event.body;
|
||
} else {
|
||
payload = JSON.parse(event.body || '{}');
|
||
}
|
||
} catch (e) {
|
||
return { error: errorResult(400, '请求参数格式错误') };
|
||
}
|
||
if (!isObject(payload)) return { error: errorResult(400, '请求参数必须是对象') };
|
||
return { data: { ...event, ...payload } };
|
||
}
|
||
|
||
function getParams(event) {
|
||
if (isObject(event.data)) return event.data;
|
||
if (isObject(event.params)) return event.params;
|
||
return {};
|
||
}
|
||
|
||
async function checkPermission(uniIDIns, uniIdToken, permission) {
|
||
if (!isNonEmptyString(uniIdToken)) return errorResult(401, '缺少有效的uniIdToken');
|
||
try {
|
||
const checkTokenRes = await uniIDIns.checkToken(uniIdToken);
|
||
if (!checkTokenRes || checkTokenRes.errCode !== 0) {
|
||
return errorResult(401, checkTokenRes && (checkTokenRes.message || checkTokenRes.errMsg) || '登录状态无效');
|
||
}
|
||
const permissions = Array.isArray(checkTokenRes.permission) ? checkTokenRes.permission : [];
|
||
const roles = Array.isArray(checkTokenRes.role) ? checkTokenRes.role : [];
|
||
if (permissions.includes(permission) || roles.includes('admin')) return true;
|
||
return errorResult(403, '权限不足');
|
||
} catch (e) {
|
||
console.error('[checkPermission]', e);
|
||
return errorResult(401, '登录状态校验失败');
|
||
}
|
||
}
|
||
|
||
function validateId(value, fieldName) {
|
||
if (!isNonEmptyString(value) && !(typeof value === 'number' && Number.isFinite(value))) {
|
||
return errorResult(400, `${fieldName}不能为空`);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
exports.main = async (event, context) => {
|
||
const parsed = parseRequest(event);
|
||
if (parsed.error) return parsed.error;
|
||
|
||
const request = parsed.data;
|
||
const params = getParams(request);
|
||
const action = request.action || params.action;
|
||
if (!isNonEmptyString(action)) return errorResult(400, '缺少有效的action');
|
||
|
||
try {
|
||
const db = uniCloud.database();
|
||
const uniIDIns = uniID.createInstance({ context: context || {} });
|
||
|
||
switch (action) {
|
||
case 'checkVersion':
|
||
return await checkVersion({ ...request, ...params }, context || {});
|
||
|
||
case 'deleteFile': {
|
||
const permission = await checkPermission(uniIDIns, request.uniIdToken, 'DELETE_OPENDB_APP_VERSIONS');
|
||
if (permission !== true) return permission;
|
||
if (!Array.isArray(params.fileList) || params.fileList.length === 0 ||
|
||
params.fileList.some(file => !isNonEmptyString(file))) {
|
||
return errorResult(400, 'fileList必须是非空文件路径数组');
|
||
}
|
||
const result = await uniCloud.deleteFile({ fileList: params.fileList });
|
||
return { ...success, ...(result || {}) };
|
||
}
|
||
|
||
case 'setNewAppData': {
|
||
const permission = await checkPermission(uniIDIns, request.uniIdToken, 'UPDATE_OPENDB_APP_LIST');
|
||
if (permission !== true) return permission;
|
||
const idError = validateId(params.id, 'id');
|
||
if (idError) return idError;
|
||
if (!isObject(params.value)) return errorResult(400, 'value必须是对象');
|
||
const value = { ...params.value, create_date: Date.now() };
|
||
const result = await db.collection(appListDBName).doc(String(params.id)).set(value);
|
||
return { ...success, ...(result || {}) };
|
||
}
|
||
|
||
case 'getAppInfo': {
|
||
if (!isNonEmptyString(params.appid)) return errorResult(400, 'appid不能为空');
|
||
const result = await db.collection(appListDBName).where({
|
||
appid: params.appid.trim()
|
||
}).get();
|
||
if (result && Array.isArray(result.data) && result.data.length > 0) {
|
||
return { ...success, ...result.data[0] };
|
||
}
|
||
return errorResult(404, '应用信息不存在');
|
||
}
|
||
|
||
case 'getAppVersionInfo': {
|
||
if (!isNonEmptyString(params.appid) || !isNonEmptyString(params.platform)) {
|
||
return errorResult(400, 'appid和platform不能为空');
|
||
}
|
||
const result = await db.collection(appVersionDBName).where({
|
||
appid: params.appid.trim(),
|
||
platform: params.platform,
|
||
type: 'native_app',
|
||
stable_publish: true
|
||
}).orderBy('create_date', 'desc').get();
|
||
if (result && Array.isArray(result.data) && result.data.length > 0) {
|
||
return { ...result.data[0], ...success };
|
||
}
|
||
return errorResult(404, '应用版本信息不存在');
|
||
}
|
||
|
||
default:
|
||
return errorResult(400, `不支持的action:${action}`);
|
||
}
|
||
} catch (e) {
|
||
console.error('[uni-upgrade-center]', e);
|
||
return errorResult(500, '请求处理失败');
|
||
}
|
||
};
|