如何在Apps Script服务器函数中为单个Web用户设置全局属性?
问题原因
你遇到的UserProperties失效问题,核心是Web应用的执行身份设置:如果部署时选择了"以开发者身份执行",所有服务器端函数都会以你的账号运行,此时getUserProperties()获取的是你的个人属性,而非当前登录用户的。
解决方案
方案1:修正Web应用部署设置(首选)
如果业务允许,将Web应用部署为**"以访问者身份执行"**:
- 部署时,在"执行身份"下拉框选择"用户访问Web应用时"
- 权限设置选择"任何人,甚至匿名"或"域内任何人"(根据你的需求)
修改后,服务器端函数会以当前登录用户的身份运行,UserProperties就能正确存储每个用户的专属设置。同时需要修正代码里的判断逻辑(你当前设置的是TRUE/FALSE,但判断的是enabled,两者不匹配):
修改frontend_toggleSlack:
function frontend_toggleSlack(form) { const slackToggle = form.slackToggle; // 'enable' or 'disable' const userProperties = PropertiesService.getUserProperties(); if (slackToggle === 'enable') { userProperties.setProperty('SLACK_POST', 'enabled'); } else if (slackToggle === 'disable') { userProperties.setProperty('SLACK_POST', 'disabled'); } else { throw new Error(`Invalid Slack posting setting applied!`); } }
sendSlackString保持原逻辑即可,现在每个用户的设置会独立存储。
方案2:用全局属性存储用户专属配置(强制以开发者身份执行时用)
如果必须以开发者身份执行(比如需要调用只有管理员权限的API),可以用ScriptProperties(全局属性存储),但给每个用户的键加上邮箱前缀,确保唯一性:
修改frontend_toggleSlack:
function frontend_toggleSlack(form) { const slackToggle = form.slackToggle; const userEmail = Session.getActiveUser().getEmail(); const scriptProperties = PropertiesService.getScriptProperties(); const key = `SLACK_POST_${userEmail}`; if (slackToggle === 'enable') { scriptProperties.setProperty(key, 'enabled'); } else if (slackToggle === 'disable') { scriptProperties.setProperty(key, 'disabled'); } else { throw new Error(`Invalid Slack posting setting applied!`); } }
修改sendSlackString:
function sendSlackString(slackBody) { const userEmail = Session.getActiveUser().getEmail(); const scriptProperties = PropertiesService.getScriptProperties(); const SLACK_POST = scriptProperties.getProperty(`SLACK_POST_${userEmail}`) || 'enabled'; // 默认开启 if (SLACK_POST === 'enabled') { const template = { "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": `${slackBody}` } } ] }; sendSlackMessage(template); } else { console.info(`Slack posting disabled for message\n\n${slackBody}`); } }
方案3:从前端传递开关状态
如果不想用属性存储,可以在前端保存开关状态(比如用localStorage),每次调用后端函数时把状态作为参数传递:
前端JS修改:
// 保存开关状态到localStorage function toggleSlackSuccess() { const slackToggle = document.querySelector('input[name="slackToggle"]:checked').value; localStorage.setItem('SLACK_POST', slackToggle); } // 调用后端函数时带上状态 function callModifyFunction(formData) { const slackEnabled = localStorage.getItem('SLACK_POST') || 'enable'; google.script.run .withFailureHandler(showFail) .frontend_modifyForwardingDelegation({ ...formData, slackEnabled: slackEnabled }); }
后端frontend_modifyForwardingDelegation修改:
function frontend_modifyForwardingDelegation(formObject) { // ...其他逻辑 modifyGmailACLs(raw_sourceUser, raw_targetUser, option, action, formObject.slackEnabled); } function modifyGmailACLs(raw_sourceUser, raw_targetUser, option, action, slackEnabled) { // ...其他逻辑 sendSlackString(message, slackEnabled); } function sendSlackString(slackBody, slackEnabled) { if (slackEnabled === 'enable') { const template = { "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": `${slackBody}` } } ] }; sendSlackMessage(template); } else { console.info(`Slack posting disabled for message\n\n${slackBody}`); } }
注意事项
- 方案1需要确保用户有足够权限调用AdminDirectory等API,如果普通用户不需要这些权限,建议用此方案。
- 方案2的
ScriptProperties有存储上限(总存储量不超过9KB),如果用户量较大或存储其他配置,需要注意容量。 - 方案3的状态存在前端,用户清除浏览器缓存后会丢失,适合临时设置或对持久化要求不高的场景。
内容的提问来源于stack exchange,提问作者Ian Hyzy
相关产品推荐
相关产品推荐

