How does one copy the users on protected ranges of Google Sheets with the REST API?
<p>I am trying to copy a Google sheet using an HTTP get request. The following is an excerpt from my code.</p>

<pre><code>    data = {"title": name_gdocs, "description": record_url, "parents": fields_dict['parents']}
    request_url = "https://www.googleapis.com/drive/v2/files/%s/copy?access_token=%s" % (template_id, access_token)
    headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
    data_json = json.dumps(data)

    req = urllib2.Request(request_url, data_json, headers)
    content = urllib2.urlopen(req, timeout=TIMEOUT).read()
    content = json.loads(content)
</code></pre>

<p>The sheet is coppied and so are the protected ranges from the sheet but the copied document's protected ranges are only able to be accessed by the owner as apposed to the original document's specified users.</p>

<p>I can verify that the users that had access to the original document still have access in the new new one. They just lost access to the protected range.</p>

<p>Is there some sort of flag I can use to make a deep copy or something of the like?</p>

<p>Additionally, I would prefer doing it, only, with the drive API because I don't have access to the sheets API for this project. Otherwise I would just use that.</p>

<p>The solution <em>is</em> to use the Sheets API. The Drive API does not have the functionality to duplicate the owners on the protected ranges. Keep in mind that I used the REST API but the same function calls should essentially be made with language specific libraries.</p>

<h1>Making the copy</h1>

<p>The url syntax, as specified in the <a href="https://developers.google.com/drive/v2/reference/files/copy" rel="nofollow">documentation</a> to make the copy is <code>POST https://www.googleapis.com/drive/v2/files/{fileId}/copy</code></p>

<p>This can be called with something like:</p>

<pre><code>data = {"title": name_of_doc, "description": short_description, "parents": list_of_parent_folders}
# On absence of parents folder,the copy will be places in the root directory of the drive.

data_json = json.dumps(data)
request_url = "https://www.googleapis.com/drive/v2/files/%s/copy?access_token=%s" % (template_id, access_token)
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
req = urllib2.Request(request_url, data_json, headers)
content_json = urllib2.urlopen(req, timeout=TIMEOUT).read()
content = json.loads(content_json)
</code></pre>

<h1>Getting the protected-range owners</h1>

<p>The <a href="https://developers.google.com/sheets/reference/rest/v4/spreadsheets/get" rel="nofollow">documentation</a> says that the request needs to use the GET method as follows <code>GET https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}</code></p>

<p>Note: The function <code>update_protected_range_to_google_sheet</code> will be defined later on</p>

<pre><code>if content.get('id') and content.get('mimeType','') == 'application/vnd.google-apps.spreadsheet':
# Make sure that the document is a Google Sheet

    request_url = "https://sheets.googleapis.com/v4/spreadsheets/%s?access_token=%s" % (template_id, access_token)
    s_req = urllib2.Request(request_url, None, headers)
    s_content = urllib2.urlopen(s_req, timeout=TIMEOUT).read()
    s_content = json.loads(s_content)
    for sheet in s_content.get('sheets', []):
        for pr in sheet.get('protectedRanges', []):
            update_protected_range_to_google_sheet(access_token, content.get('id'), pr)
</code></pre>

<h1>Applying the owners</h1>

<p>The <a href="https://developers.google.com/sheets/samples/ranges" rel="nofollow">documentation</a> says to use the batch update call to the Sheets API as the name suggests, many requests can be done at once but in this case, the function will be called once per update for illustrative purposes. Here is the function I used that will be called:</p>

<pre><code>def update_protected_range_to_google_sheet(self,access_token, sheet_id,range_info):
    headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
    request_url = "https://sheets.googleapis.com/v4/spreadsheets/%s:batchUpdate?access_token=%s" % (sheet_id, access_token)
    data = {
             "requests": [
                    {
                      "updateProtectedRange": {
                        "protectedRange": range_info,
                        "fields": "namedRangeId,warningOnly,editors"
                      }
                    }
             ]
           }
    data_json = json.dumps(data)
    req = urllib2.Request(request_url, data_json, headers)
    content_json = urllib2.urlopen(req, timeout=TIMEOUT).read()
    content = json.loads(content_json)
</code></pre>

<h1>Conclusion</h1>

<p>The main reason I couldn't use the Sheets API was that the system I was using, had a custom built wrapper around the Drive API and the authentication was hardcoded to point to a project owned by the library's creator.</p>

<p>This wouldn't do, so I created my own project on the <a href="https://console.cloud.google.com/" rel="nofollow">console</a> and generated a token from that. The new project had the Drive API enabled <em>as well</em> as the Sheets API - something the original project apparently didn't have.</p>

python http google-drive-sdk