Having trouble listing AdminDirectory groups in Apps Script - google-apps-script

I am trying to get groups in Google Apps Script. My code is as follows:
var list = AdminDirectory.Groups.list({
customer: 'my_customer'
});
I tried the above, and I tried replacing the customer arg with domain: MYDOMAIN (and I tried with a userKey) but I always get the same error:
Executing query for datasource SearchResults: (Error) : We're sorry, a server error occurred. Please wait a bit and try again. [18a249eb]
Is this not the right way to get the groups? (Incidentally, I would ideally like to search for groups rather than listing them all, but I don't see that as an option.)
Thanks for any tips or pointers.

According to the Using the debugger and breakpoints, this error can be one of the following:
Server error occurred, please try again.
There are a couple possible causes for this error:
A Google server or system is temporarily unavailable. Wait for a few moments and try running the script again.
There is an error in your script that doesn't have a corresponding error message. Try debugging your script and see if you can isolate
the problem.
There is a bug in Google Apps Script that is causing this error. Report the error on the issue tracker.
Make sure you're following the List all groups guide correctly:
function listAllGroups() {
var pageToken, page;
do {
page = AdminDirectory.Groups.list({
domain: 'example.com',
maxResults: 100,
pageToken: pageToken
});
var groups = page.groups;
if (groups) {
for (var i = 0; i < groups.length; i++) {
var group = groups[i];
Logger.log('%s (%s)', group.name, group.email);
}
} else {
Logger.log('No groups found.');
}
pageToken = page.nextPageToken;
} while (pageToken);
}

Related

Google Drive API - Permission error with script to update permissions for shared drives members

I am trying to create a Google Apps Script that updates the permissions of members of shared drives, from a Google Sheet, with the shared drive ID in column A, the permission ID in column G (one per row), the permission role in column E (one per row), the additionalRoles (if any, for commenters) in column F (one per row), and the email address of the user in column D.
I have also included (in the script) the additional args "supportsAllDrives: true" and "useDomainAdminAccess: true".
The script has the OAuth2 and the services "Drive" and AdminDirectory".
I'm using a super admin account (I've also tried using a service account with domain-wide delegation and user impersonation), but I always get the same error:
The error messages says: "An error occurred: API call to drive.permissions.patch failed with error: The authenticated user does not have the required access to update the permission."
Despite the error, some permissions are updated. Others aren't, no matter if I try with 1 or with 30 shared drives, or with 1 or 30 members, or with only one type of permissions or with all of them.
But if I use the "Try it" API tool available at https://developers.google.com/drive/api/v2/reference/permissions/patch (in the right-panel), everything works.
The script that I am using is as follows:
function updateSharedDrivePermissions() {
try {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName("GetUsers");
var lastRow = sheet.getLastRow();
var data = sheet.getRange(2, 1, lastRow - 1, 7).getValues();
for (var i = 0; i < data.length; i++) {
var sharedDriveId = data[i][0];
var permissionId = data[i][6];
var key = data[i][4];
// var additionalRoles = data[i][5]; // to use later, for commenters
var email = data[i][3];
var resource = {
role: key,
type: "user",
value: email,
}
// optional arguments to work on Shared drive
var optionalArgs = {
sendNotificationEmails: false,
useDomainAdminAccess: true,
supportsAllDrives: true
}
// set Shared drive permissions
Drive.Permissions.patch(resource, sharedDriveId, permissionId, optionalArgs);
// Send a message to the user
SpreadsheetApp.getUi().alert("Shared drive permissions updated successfully!");
} catch (error) {
// Handle the error
SpreadsheetApp.getUi().alert("An error occurred: " + error.message);
// log error message for debugging purposes
console.log(error.message);
}
}
I've tried everything I can think of.
Additionally, some shared drive let me downgrade the permissions to "reader" while others don't. I believe this must be related to the pre-existence or not of the "commnenter" additionalRoles.
But - also for this - if I use the "Try it" API tool available at https://developers.google.com/drive/api/v2/reference/permissions/patch (in the right-panel), everything works.
Note: the admin/user executing the script is a Manager in all the tested shared drives.
Thanks in advance for any help.

File.makeCopy error

I am using the following code to make a copy of a file:
var backupFolder = DriveApp.getFolderById('1vOnO5aSOSFNWtOLHuAz4Lv2lsRgBwBpS');
var file = DriveApp.getFileById('1TJ_5Khw7wcqlIfbZ_-KLOQ-DsU02FsoRFYR1A3B4qAs');
file.makeCopy(file.getName(), backupFolder);
Most of the time that works without any issue.
Some times I get the following error:
We're sorry, a server error occurred. Please wait a bit and try again
Does anyone know how I can get a more meaningful error message to understand what is the issue?
To build on Anton's and Nancy's answers one useful approach I have found for error logging and catching important issues, is to append the error to a google sheet for reference with a timestamp and to send me a warning email with the failure reason. This gives me an instance notice something is not right, and helps me to keep track of issues.
function someImportantProcess(){
var ss = SpreadsheetApp.getActiveSpreadSheet();
var sheet = ss.getSpreadsheetByName('Sheet1');
try {
someImportant function(){
Logger.log('important stuff')
}
} catch(e){
sheet.appendRow([timestamp, e])
sendEmail(e)
}
}
sendEmail(e){
var subject = '[Important a script failed]';
var body = e;
sendEmail(myemail#google.com, subject, body);
}

How to enable Google Classroom courseWorkList

I've been testing the Google Classroom Api and can't seem to get the courseWorkList method to run getting a caller error
I've basically cut and pasted code from the reference and it works if i remove the classCourseWork line. Otherwise I get a "The caller does not have permission" error. I've enabled the API services, approved it to run, etc. Any help in getting this one sorted?
function listCourses() {
var optionalArgs = {
pageSize: 10
};
var response = Classroom.Courses.list(optionalArgs);
var courses = response.courses;
if (courses && courses.length > 0) {
for (i = 0; i < courses.length; i++) {
var course = courses[i];
var classCourseWork = Classroom.Courses.CourseWork.list(course.id);
}
Logger.log('%s (%s)', course.name, course.id);
} else {
Logger.log('No courses found.');
}
}
I've tried your code, here are the scenarios:
As a student:
Your code is working fine.
As a teacher:
I've also received "The caller does not have permission" error.
You might want to check this open issue tracker, that a teacher cannot access the coursework (or the students' turned-in assignments) in their course, getting the same permission error. It was updated and was filed a ticket internally, we can follow this ticket to be updated.
Hope this helps.
Does this thread sound like the same issue? Http://stackoverflow.com/questions/42796630/google-classroom-apps-script-coursework-list-permission-error

Service invoked too many times in a short time: exec qps. (Google Script)

Recently some of my app scripts are showing errors when executed simultaneously. Everything worked fine for years, apparently the change happened on Google side.
This is the execution transcript result:
Unfortunately, the error does not show file name and line number to debug it properly, but my first line is:
var ss = SpreadsheetApp.getActiveSpreadsheet()
Therefore I assume that calling SpreadsheetApp simultaneously by instances of the app is causing the error. SpreadsheetApp is not in the loop, nor inside any function. It is called to define global variable ss to be used by the app.
My apps are executed under my user name, since users should not have access to the Spreadsheet I'm accessing. I'm afraid I can't keep the entire Spreadsheet in Cache Service - I want app to update the Spreadsheet when it it called.
UPDATE:
Here is some relevant code from one of the apps.
function doGet(e){
var ref = e.parameter.ref;
var ss = SpreadsheetApp.openById('########')
var logsheet = ss.getSheetByName('LOG');
logsheet.appendRow([new Date(),ref,JSON.stringify(e.parameter)])
try{
//Main code goes here
return ContentService.createTextOutput(JSON.stringify({result:"ok"})).setMimeType(ContentService.MimeType.JSON);
}catch(e){
return ContentService.createTextOutput(JSON.stringify(e)).setMimeType(ContentService.MimeType.JSON)}
}
As you can see I have try {} catch(e) in my function, and since the error I'm getting is not caught by it, I assume it happens right before.
Just discovered manual hack to avoid this error:
Open your spreadsheet from private browser mode. This will increase number of document viewers and will increase limits :)
You can put everything in the try-catch block. Also remember to publish a new version of the web app before execution.
function doGet(e) {
var response = {};
try {
SpreadsheetApp.openById('########')
.getSheetByName('LOG')
.appendRow([new Date(), e.parameter.ref, JSON.stringify(e.parameter)]);
response.result = "OK";
} catch (error) {
response.result = "Error: " + error.toString();
}
return ContentService
.createTextOutput(JSON.stringify(response))
.setMimeType(ContentService.MimeType.JSON);
}

Error uploading .xls file and converting to Google Spreadsheet via GAS

Prior Research
Please do not close this question as a duplicate because my question deals with how to resolve the specific error message I am receiving and not the general question of whether my objective is achievable or not — as some other related questions, yielded by my research and below detailed, have asked.
Related questions and why they do not apply here
This question, asked 7/27/2012, does not apply because it: (1) is too old (after 10 months, new solutions/methods might exist) and (2) does not deal with the specific error message I am experiencing.
This question, asked 10/12/2012, fails to apply for similar reasons.
My below code was copied from here which was forked from here. These are presumably, working solutions because they have been referenced as such from other question/answer exchanges here on Stack Overflow.
Objective
Programmatically, I am trying to:
Search my email inbox.
Find Excel (.xls) file attachments.
Upload those .xls file attachments to Google Drive.
While uploading, convert the .xls files into a Google Spreadsheet file format.
Problem
When I execute processInbox() (code shown at the bottom of this question), it fails and I get the error message shown below.
Error Message
Request failed for returned code 403.
Server response:
{
"error":{
"errors":[
{
"domain":"usageLimits",
"reason":"accessNotConfigured",
"message":"AccessNotConfigured"
}
],
"code":403,
"message":"AccessNotConfigured"
}
}
(line 13, file "DriveUpload")
Question
What am I doing wrong? And how can I fix it?
For example, do I need to do something special in my API console relative to setting up my project to, say, access Google Drive or something? What am I missing?
Note: I have not yet successfully implemented oAuth in any of my applications, yet.
Error Source
Line 13
(This is the code line referenced by the error message.)
var uploadRequest = UrlFetchApp.fetch("https://www.googleapis.com/upload/drive/v2/files/?uploadType=media&convert=true&key="+key, params); // convert=true convert xls to google spreadsheet
Code
The complete body of code I am working with is shown below for your reference. I extracted the error-triggering, “line 13,” and highlighted it above to help us focus on the proximate cause of the problem.
DriveUpload.js
function uploadXls(file) {
authorize();
var key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // <-- developer key
var metadata = { title: file.getName() }
var params = {method:"post",
oAuthServiceName: "drive",
oAuthUseToken: "always",
contentType: "application/vnd.ms-excel",
contentLength: file.getBytes().length,
payload: file.getBytes()
};
// convert=true convert xls to google spreadsheet
var uploadRequest = UrlFetchApp.fetch("https://www.googleapis.com/upload/drive/v2/files/?uploadType=media&convert=true&key="+key, params);
var uploadResponse = Utilities.jsonParse(uploadRequest.getContentText());
var params = {method:"put",
oAuthServiceName: "drive",
oAuthUseToken: "always",
contentType: "application/json",
payload: Utilities.jsonStringify(metadata)
};
var metaRequest = UrlFetchApp.fetch("https://www.googleapis.com/drive/v2/files/"+uploadResponse.id+"?key="+key, params)
return DocsList.getFileById(uploadResponse.id);
}
function authorize() {
var oauthConfig = UrlFetchApp.addOAuthService("drive");
var scope = "https://www.googleapis.com/auth/drive";
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oauthConfig.setAuthorizationUrl("https://accounts.google.com/OAuthAuthorizeToken");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
}
function processInbox() {
// get all threads in inbox
var threads = GmailApp.getInboxThreads();
for (var i = 0; i < threads.length; i++) {
// get all messages in a given thread
var messages = threads[i].getMessages();
// iterate over each message
for (var j = 0; j < messages.length; j++) {
// log message subject
var subject = messages[j].getSubject()
//Logger.log(subject);
if ( subject == "with xls attach" ){
Logger.log(messages[j].getSubject());
var attach = messages[j].getAttachments()[0];
var name = attach.getName();
var type = attach.getContentType();
//var data = attach.getDataAsString();
Logger.log( name + " " + type + " " );
var file = uploadXls(attach);
SpreadsheetApp.open(file);
}
}
}
};
Drive API is already built in GAS: https://developers.google.com/apps-script/reference/drive/
Use DriveApp and your problems go away ;-)
This maybe a temp solution
Step 1: Use a Google Form to Collect Data to a Google spreadsheet
Step 2: Add the Zoho Sheet App to your Google Drive
In a Zoho Sheet
Goto
Data Menu
»Link External Data
Select either
CSV
RSS/Atom Feed
or HTML Page
You can schedule it to update at specific time intervals
What I like is the VBA and Macros in Zoho
You can also do Pivot Charts and Tables
You can copy and paste Excel VBA into Zoho !
I have an Unpivot VBA that I will run on my Tabular dataset
before I can do a PivotChart
It is hard to beat all the functionality of Excel and I often fall back on familiar tools !
If I hear of anything I will post it
Good luck