Reputation: 239
I have few accounts where I need to transfer the ownership to another account. I have the list listed in google sheets with all the email addresses. I am using the code below to hopefully execute it but I am not sure what to use to execute the code.
function dataTransfer() {
var ss = SpreadsheetApp.openById("SHEETID")
var sheet = ss.getSheetByName("SHEETNAME");
var start = 2;
var end = sheet.getLastRow();
var range = sheet.getRange(start,1,end,sheet.getLastColumn());
var values = range.getValues();
for (var i = 0; i < values.length-1; i++) {
/* transfer the data ownership to */
var A = "[email protected]";
var B = "[email protected]";
var C = "[email protected]";
var email = values[i][0];
var company = values[i][1];
var status = values[i][3];
if (status === "Complete") {continue;}
if (company == "A") {
/* transfer of the ownership of user data between users. */
var transferObject = {
"kind": "admin#datatransfer#DataTransfer",
"oldOwnerUserId": email,
"newOwnerUserId": A,
"applicationDataTransfers": [
{
"applicationId": XXXXXX,
"applicationTransferParams": [{
"key": "PRIVACY_LEVEL",
"value": [
"PRIVATE",
"SHARED"
]
}],
"applicationId": XXXXX,
"applicationTransferParams": [{
"key": "RELEASE_RESOURCES",
"value": true
}],
}],
}
**admin.datatransfer....** /* what do I use here to execute the above code */
sheet.getRange(start+i,4,1,1).setValue("Complete");
}
}
}
}
Upvotes: 0
Views: 1578
Reputation: 1
I was looking for an instruction on the exact same use case, and I found Rafas answer informative, but there is a simpler way to do this. So to help my Fellow scripters I've wrote a complete instruction below.
First of all, it can be done in Apps Script with the standard GCP account, so no need to meddle with Google Cloud Console. You do however need to have a super admin account in Google Workspace.
You also need to add the Admin SDK API to the project and enable it. Click on the plus sign to the right of "Services" when in the editor and add the API from the list.
Then you open the project settings (cog wheel on the left) and enable "Show manifest appsscript.json in the editor", go back to the editor, open appsscript.json and add
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/admin.datatransfer",
"https://www.googleapis.com/auth/admin.directory.user.readonly"
]
The reason you need to do this manually is that Apps Script won't detect the needed scopes automatically when we use the UrlFetchApp. The appsscript.json should then look something like:
{
"timeZone": "Europe/Berlin",
"dependencies": {
"enabledAdvancedServices": [
{
"userSymbol": "AdminDirectory",
"version": "directory_v1",
"serviceId": "admin"
}
]
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/admin.datatransfer",
"https://www.googleapis.com/auth/admin.directory.user.readonly"
]
}
I completed the snippets from the previous response, and the complete code to transfer all data from user A to user B would look like this. :-)
(Note that the applicationIds for the data transfer has changed)
/**
* Source and target primary email for the data that should move
*/
function transferData(sourceEmail, targetEmail) {
let sourceID=getUserID(sourceEmail);
let targetID=getUserID(targetEmail);
const url = "https://admin.googleapis.com/admin/datatransfer/v1/transfers";
let payload=buildPayload(sourceID,targetID);
let headers ={
"Authorization": 'Bearer ' + ScriptApp.getOAuthToken(),
};
let param = {
method: "POST",
headers: headers,
contentType: "application/json",
payload: JSON.stringify(payload)
};
let done=false;
do{
try {
let response = JSON.parse(UrlFetchApp.fetch(url,param).getContentText());
Logger.log(JSON.stringify(response).getContentText());
done=true;
}
catch (e) {
Utilities.sleep(500);
}
}while (!done)
}
function buildPayload (sourceUserId, targetUserId) {
let payload = {
kind: "admin#datatransfer#DataTransfer",
oldOwnerUserId: sourceUserId,
newOwnerUserId: targetUserId,
applicationDataTransfers: [
{
applicationId: "55656082996",
applicationTransferParams: [
{
key: "PRIVACY_LEVEL",
value: [
"PRIVATE",
"SHARED"
]
}
]
},
{
applicationId: "435070579839",
applicationTransferParams: [
{
key: "RELEASE_RESOURCES",
value: [
"TRUE"
]
}
]
}
]
}
return payload;
}
function getUserID(primaryEmail)
{
return AdminDirectory.Users.get(primaryEmail).id;
}
Upvotes: 0
Reputation: 15377
Using UrlFetchApp
you need to make a POST
request to https://admin.googleapis.com/admin/datatransfer/v1/transfers
. You have to set up a GCP Project and enable the Data Transfer API to do this.
The prerequisites for using the Data Transfer API, as per this page state (emphasis my own):
You need the following basic configuration before you can use the Data Transfer API:
- Have a Google account and create an administrator. The API applies to Google Workspace, Education, Government, Reseller, and ISP accounts.
- Be familiar with your Google Workspace Admin console found at admin.google.com. For more information about the Admin console, see Use your Admin console.
- Enable API access from the Google Workspace Admin console in order to make requests to the Data Transfer API.
You can do this by going to console.cloud.google.com and creating a new project from the drop-down menu next to Google Cloud Platform
on the upper menu bar.
Then, using the hamburger menu follow ≡ > APIs & Services > Library
and search for Admin SDK API
. Click on the matching result, and on the new page click the ENABLE
button.
Next, you will need to link this GCP Project to your Apps Script Project.
Going back to the Hamburger menu, follow ≡ > Home > Dashboard
and copy the 12-digit project number displayed in under the Project info
area.
Going back to your Script, follow the Resources > Cloud Platform project...
menu item, paste in that 12-digit number and click Set Project
. This will link your Apps Script Project to the newly created GCP project wit the enabled API.
You can safely close this modal now.
As per the documentation on the transfers.insert
method:
Inserts a data transfer request.
HTTP request
POST https://admin.googleapis.com/admin/datatransfer/v1/transfers
Request body
The request body contains an instance of
DataTransfer
.
Firstly, as a quick code fix, the applicationDataTransfers/applicationTransferParams/value
needs to be an array of strings, and so should be:
"applicationId": XXXXX,
"applicationTransferParams": [
{
"key": "RELEASE_RESOURCES",
"value": [
"TRUE"
]
}
],
// ...
As well as this, the oldOwnerUserId
and newOwnerUserId
values must be the user ID values obtained from the users.list
endpoint. The Google email address does not work as a replacement for this. A full example request would be as follows:
var payload = {
"kind": "admin#datatransfer#DataTransfer",
"oldOwnerUserId": "113412843513541354193",
"newOwnerUserId": "118387348413214353832",
"applicationDataTransfers": [
{
"applicationId": "14186345432",
"applicationTransferParams": [
{
"key": "PRIVACY_LEVEL",
"value": [
"PRIVATE",
"SHARED"
]
}
]
},
{
"applicationId": "546343454353",
"applicationTransferParams": [
{
"key": "RELEASE_RESOURCES",
"value": [
"TRUE"
]
}
]
}
]
}
As for making the HTTP
request:
const url = "https://admin.googleapis.com/admin/datatransfer/v1/transfers";
var headers ={
"Authorization": 'Bearer ' + ScriptApp.getOAuthToken(),
};
var options = {
"method": "POST",
"headers": headers,
"contentType": "application/json",
"payload": JSON.stringify(payload)
};
Important Note: As you are using the API directly with the Script's token as your OAuth Token, you will need to update the Apps Script manifest with your required scopes.
Follow the View > Show manifest file
menu item, and add your scopes to the project. The full manifest file should look something like this:
{
"timeZone": "Europe/Paris",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/admin.datatransfer"
]
}
The script.external_request
is required so you can call UrlFetchApp
, and the admin.datatransfer
is the scope required to make the call to the directory insert endpoint.
Upvotes: 1