Я пытаюсь сделать веб-приложение на Google Apps Script с использованием сервисного аккаунта, чтобы не давать пользователям прямого доступа к одной из Google-таблиц, которую я использую в качестве базы данных. Я создал сервисный аккаунт в консоли Google Cloud и добавил email сервисного аккаунта редактором таблицы базы данных. В проекте Apps Script подключил библиотеку OAuth 2 и сервис Google Sheets API.
Для начала протестировал авторизацию и запись данных в другую таблицу, к которой дал доступ тестовому пользователю. Сделал шаблон HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Hello</h1>
<p>You are logged in as <?= activeUser ?></p>
</body>
</html>
И прописал следующий код:
function doGet() {
const htmlTemplate = HtmlService.createTemplateFromFile("index");
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("Logs");
const activeUser = Session.getActiveUser().getEmail();
const effectiveUser = Session.getEffectiveUser().getEmail();
htmlTemplate.activeUser = activeUser;
const htmlService = htmlTemplate.evaluate();
ws.appendRow([activeUser,effectiveUser]);
return htmlService;
}
Развернул приложение с параметрами:
Execute as: User accessing the web app
Who has access: Anyone with Google account
Результат: тестовый пользователь после авторизации попал на страницу `main` и увидел свой email.
Далее добавил авторизацию сервисного аккаунта и запись данных в таблицу базы данных, к которой не должен иметь прямого доступа тестовый пользователь:
function getSheetsAuthService() {
var service = OAuth2.createService('sheetsAuthService')
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
.setPrivateKey("PRIVATE_KEY")
.setClientId('EMAIL')
.setScope('https://www.googleapis.com/auth/spreadsheets')
.setPropertyStore(PropertiesService.getScriptProperties())
.setCache(CacheService.getUserCache())
.setParam('access_type', 'offline')
.setParam('approval_prompt', 'force');
return service;
}
function writeData() {
var service = getSheetsAuthService();
if (service.hasAccess()) {
const ssTestID = "ID_DATABASE_SPREADSHEET";
const ssTestSheet1 = SpreadsheetApp.openById(ssTestID).getSheetByName("Sheet1");
var values = [
['Value1', 'Value2', 'Value3'],
['Value4', 'Value5', 'Value6'],
['Value7', 'Value8', 'Value9']
];
for (var i = 0; i < values.length; i++) {
ssTestSheet1.appendRow(values[i]);
}
}
}
Ну и соответственно добавил в doGet вызов writeData().
Сделал новую версию развертывания. В результате тестовый пользователь увидел ошибку "Exception: У вас нет разрешения на доступ к этому документу. (строка 17, файл sheets)".
17 строка: const ssTestSheet1 = SpreadsheetApp.openById(ssTestID).getSheetByName("Sheet1");
Почему так происходит и как правильно использовать сервисный аккаунт, чтобы от имени других пользователей записывать данные в таблицу, но при этом не давать им прямого доступа к ней?