I have a google slides addon in marketplace which lets users to create slides from Drive picked images
This addon currently uses the following scopes
"https://www.googleapis.com/auth/presentations",
"https://www.googleapis.com/auth/script.container.ui",
"https://www.googleapis.com/auth/drive" ISSUE: I am advised by Oauth Verification process to narrow down the scopes and use drive.file (narrower) instead using a drive scope (broader)
The email stated me -
"Since your app services only require per-file selection, your use case does not meet the minimum scope requirement of the Google Drive API user data and developer policy for access to restricted Drive API scopes. You should migrate your application to use the non-sensitive drive.file scope instead of the restricted scope. "
THE ERROR/PROBLEMAfter the scopes are narrowed, the app no longer works and gives the error
Error: Exception: You do not have permission to call DriveApp.getFileById. Required permissions: (
https://www.googleapis.com/auth/drive.readonly ||
https://www.googleapis.com/auth/drive)
WHAT I AM ASKING FOR: I am aware of scopes and their definitions
https://developers.google.com/drive/api/guides/api-specific-auth. The
https://www.googleapis.com/auth/drive.file scope can Create new Drive files, or modify existing files, that you open with an app or that the user shares with an app while using the Google Picker API or the app's file picker.
I could have used
https://www.googleapis.com/auth/drive.readonly but this again is a restricted scope
Using this narrow scopes, How do I fix my below code so that it can place picked google drive images to slides? The OAuth team is not satisfied with the Drive scope and strictly suggest Drive.file scope
https://www.googleapis.com/auth/drive.file scope can Create new Drive files, or modify existing files, that you open with an app or that the user shares with an app while using the Google Picker API or the app's file picker.
Using this narrow scopes, how do I fix my below code so that it can place picked google drive images to slides?
The OAuth team is not satisfied with the Drive scope and strictly suggest Drive.file scope
TO MAKE A COPY OF THE CODE FILE: https://docs.google.com/presentation/d/1l1WvLlo3-4fLepWgvk9Bkj785NhxleY_c-0Lvv1rxyU/copy//appsscript.json
{
"timeZone": "Etc/GMT",
"dependencies": {
"enabledAdvancedServices": [
{
"userSymbol": "Drive",
"version": "v3",
"serviceId": "drive"
}
]
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/presentations",
"https://www.googleapis.com/auth/script.container.ui",
"https://www.googleapis.com/auth/drive.file"
]
}
//Code.gs
var ANAME = "Create Slides from Images";
var PICKER_ORIGIN = "\"https://docs.google.com\"";
function onOpen(e) {
SlidesApp.getUi().createMenu("Create Slides from Images")
.addItem('Open', 'showPickerImages')
.addToUi();
}
function getOAuthToken() {
return ScriptApp.getOAuthToken();
}
function showAlert(msg) {
var ui = SlidesApp.getUi();
var result = ui.alert(
ANAME,
msg + '',
ui.ButtonSet.OK);
}
function showPickerImages() {
try {
var html = HtmlService.createTemplateFromFile("Picker")
.evaluate()
.setWidth(650).setHeight(500).setTitle("Select images folder")
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
SlidesApp.getUi().showModalDialog(html, "Create slides from Drive images");
} catch (e) {
showAlert("Error: " + e + ' ' + e.lineNumber);
}
}
function insertImages(imageIds) {
try {
var deck = SlidesApp.getActivePresentation();
var firstSlide = deck.getSlides()[0];
var title = firstSlide.getPageElements()[0];
var subtitle = firstSlide.getPageElements()[1];
title.asShape().getText().setText(ANAME);
subtitle.asShape().getText().setText("Google Apps Script\nSlides Service demo");
// Iterate through the imageIds and call addImageSlide for each imageId
imageIds.forEach(function(imageId) {
var slide = deck.appendSlide(SlidesApp.PredefinedLayout.BLANK);
slide.insertImage(DriveApp.getFileById(imageId).getBlob());
//I have tried with this, but this fails too saying image must be publicly accessible, the images are in users drive and cannot be shared publicly
//slide.insertImage(`https://drive.google.com/uc?export=download&id=${imageId}`);
});
} catch (e) {
showAlert("Error: " + e + ' ' + e.lineNumber);
}
}
//Picker.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<script type="text/javascript">
var pickerApiLoaded = false;
var fO;
function onApiLoad() {
gapi.load('picker', {
'callback': function() {
pickerApiLoaded = true;
}
});
google.script.run.withSuccessHandler(createPicker).withFailureHandler(function(e){alert(e)}).getOAuthToken();
}
function createPicker(token) {
if (pickerApiLoaded && token) {
var docsView = new google.picker.DocsView()
.setOwnedByMe(true)
.setIncludeFolders(true)
.setSelectFolderEnabled(true)
.setMimeTypes("image/png,image/jpeg,image/jpg,image/gif,image/heif");
var docsViewSharedDrive = new google.picker.DocsView()
.setOwnedByMe(true)
.setIncludeFolders(true)
.setEnableDrives(true)
.setMimeTypes("image/png,image/jpeg,image/jpg,image/gif,image/heif");
var docsViewSharedFiles = new google.picker.DocsView()
.setOwnedByMe(false)
.setIncludeFolders(true)
.setMimeTypes("image/png,image/jpeg,image/jpg,image/gif,image/heif");
var uploadView = new google.picker.DocsUploadView()
.setIncludeFolders(true);
var picker = new google.picker.PickerBuilder()
.addView(docsView)
.addView(docsViewSharedDrive)
.addView(docsViewSharedFiles)
.addView(uploadView)
.hideTitleBar()
.setSize(600 - 2, 425 - 2)
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.enableFeature(google.picker.Feature.SIMPLE_UPLOAD_ENABLED)
.enableFeature(google.picker.Feature.SUPPORT_DRIVES)
.setOAuthToken(token)
.setCallback(fileSelected)
.setOrigin(<?!=PICKER_ORIGIN?>)
.build();
picker.setVisible(true);
} else {
google.script.run.showAlert('Unable to load the file picker.');
}
}
function fileSelected(images) {
var files = [],
folders = [],
imgs = []
var action = images[google.picker.Response.ACTION];
if (action == google.picker.Action.PICKED) {
var documents = images[google.picker.Response.DOCUMENTS];
for (var i = 0; i < documents.length; i++) {
imgs.push(documents[i].id);
}
google.script.run.insertImages(imgs);
} else if (action == google.picker.Action.CANCEL) {
}
}
</script>
</head>
<body>
<script type="text/javascript" src="https://apis.google.com/js/api.js"></script>
<script>
onApiLoad();
</script>
</body>
</html>