更新票据和监听会议信息变更的前端 API 核心代码 meeting-simple/src/meeting/api.js
// 更新票据 export async function updateTicket(data) { await signIn(); const res = await app.callFunction({ name: "update-ticket-meeting-simple", data, }); return res; } let watcher = null; export async function watchMeeting(meetingId, onChange) { await signIn(); // 如果有监听,关闭监听 watcher && watcher.close(); // 新建数据库监听 watcher = db .collection(MEETING_COLLECTION) .doc(meetingId) .watch({ onChange: (snapshot) => { console.error(snapshot); if ( !snapshot.docChanges || !snapshot.docChanges.length || !snapshot.docChanges[0].doc ) return; // 回调最新的数据库文档信息 onChange(snapshot.docChanges[0].doc); }, onError: (err) => { console.log("watch error", err); }, }); }优化会议信息的获取提升体验
注意监听数据库变化亦需要将数据库设置为公开访问, 即上述第三步中的注意事项 2 所述
匿名用户无法修改其他匿名用户创建的记录. 根据数据库安全策略, 虽同为匿名用户, 但不同客户端的匿名用户标志不一样, 故不能操作他人的记录. 而云函数有用管理员级别的数据库操作权限, 故 「更新 ticket」功能采用了云函数来编写
代码提交记录本步骤对应的 git commit
第 5 步 提升非公开会议访问的安全性, 优化数据库使用 操作步骤将会议密码分表存储
修改“加入会议”的前端 API 核心代码 meeting-simple/src/meeting/api.js
// 加入会议 export async function joinMeeting(data) { await signIn(); // 加入会议改为使用调用云函数校验,保证密码安全 const result = await app.callFunction({ name: "join-meeting-meeting-simple", data, }); if (result.result.code) { throw new Error(result.result.message); } return true; }负责加入会议时进行密码校验的云函数的核心代码 meeting-simple/cloudfunctions/join-meeting-meeting-simple/index.js
const tcb = require("@cloudbase/node-sdk"); const MEETING_COLLECTION = "meeting-simple"; const MEETING_PASS_COLLECTION = "meeting-simple-pass"; const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV, }); const db = app.database(); exports.main = async function (evt) { try { const result = await db.collection(MEETING_COLLECTION).doc(evt.id).get(); if (!result.data || !result.data.length) return { code: 1, message: "meeting not exists" }; const meeting = result.data[0]; if (meeting.hasPass) { // 查询会议密码 const passResult = await db .collection(MEETING_PASS_COLLECTION) .where({ meetingId: evt.id }) .get(); if (!passResult.data || !passResult.data.length) return { code: 2, message: "passcode not found" }; const passInfo = passResult.data[0]; // 对比会议密码 if (passInfo.pass !== evt.pass) return { code: 3, message: "passcode not match", }; } return { code: 0 }; } catch (error) { return { code: 3, message: error.message, }; } };数据库 collection 定期清理旧的无用记录
清理数据的云函数的核心实现meeting-simple/cloudfunctions/autoclear-meeting-meeting-simple/index.js
const tcb = require("@cloudbase/node-sdk"); const MEETING_COLLECTION = "meeting-simple"; const MEETING_PASS_COLLECTION = "meeting-simple-pass"; const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV, }); const db = app.database(); /** * 定时触发, 清理两天前的会议记录 * { "triggers": [ { "name": "clear-time-trigger", "type": "timer", "config": "0 0 2 * * * *" } ] } */ exports.main = async function () { const now = Date.now(); // 2天前 const threshold = now - 2 * 24 * 60 * 60 * 1000; const _ = db.command; try { // 查询创建时间两天前的会议记录,进行删除 await db .collection(MEETING_COLLECTION) .where({ createdAt: _.lte(threshold), }) .remove(); // 查询创建时间两天前的密码记录,进行删除 await db .collection(MEETING_PASS_COLLECTION) .where({ createdAt: _.lte(threshold), }) .remove(); } catch (error) { console.log("failed to batch remove", error); } }; 注意:定期清理数据库使用了云函数的定时触发器
代码提交记录本步骤对应的 git commit
第 6 步 使用 cloudbase framework 一键部署增加静态部署功能, 使用了 website 插件
增加部署云函数功能, 包括云函数定时调用的设置, 使用了function 插件
增加数据 collection 的创建, 包括 collection 访问权限的设置, 使用了 database 插件
在 meeting-simple/.env 文件中声明环境变量信息
PUBLIC_URL=./ ENV_ID=tcb-demo-10cf5b