Google Drive API v2: Transfer file ownership to admin user - google-drive-api

Is it possible for a super admin to take ownership of a file that is currently owned by an arbitrary user? If so, which end point can do this? I've spent time digging through the API documentation and I'm not coming up with a clear answer. Everything I've found is related to the 1st version of the API.
https://developers.google.com/drive/v2/reference/

yes its possible.
look at how to use oauth2 for "delegation of authority". https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
read the drive api docs on how to use delegation on their api.
look at the drive api that changes ownership. https://developers.google.com/drive/v2/reference/permissions/update
the key part is calling that api using the service account that is impersonating that user.
beware of rate quotas using this method. if you have many files to change, you need to take care the rate is not too fast (say one per second).

Yes, the current owner can transfer ownership of a file to another user.
https://developers.google.com/drive/v2/reference/permissions/update
transferOwnership boolean Whether changing a role to 'owner'
downgrades the current owners to writers. Does nothing if the
specified role is not 'owner'. (Default: false)

Related

Cannot Get Total Shared Drive Size using Google Drive API

We use the Drive API in a few scripts to get info on all our Shared Drives. Using the “useDomainAdminAccess” parameter in the drives list/get methods, we can get just about all drive details without adding the script account as owner on the target drives. One detail we cannot get using this method is total drive size. It appears there is no native property for drive size when querying details at the drive level. We can get a size param when querying individual files (but we must add the script account as an owner on the drive).
In summary, to get drive size we must add the script account as an owner on the drive. Then iterate through all files within the drive, getting the size param for each and adding it to a global variable which we return as total drive size at the end of the iteration. After this we remove the script account from the drive. This, of course, seems very inefficient for getting a single property. Do we know if Google plans to include a size param within the drives.list/drives.get api, or add the “useDomainAdminAccess” param to the files.list/files.get api or maybe there is another Google API that can provide this detail with less effort (reporting / gws admin api)? Thanks
https://developers.google.com/drive/api/v3/reference/drives/list
https://developers.google.com/drive/api/v3/reference/files/list
You may benefit from filing a feature request on Google's Issue Tracker and provide all the necessary details there.
I suggest you fill in this template here.
As for an alternative for your current workaround, I suggest you take a look at service accounts and domain-wide delegation in order to impersonate the owner of the drive and perform the request on their behalf.
A service account is a special kind of account used by an application or a virtual machine (VM) instance, not a person. Applications use service accounts to make authorized API calls.
Reference
Service Accounts;
Drive API Perform Google Workspace Domain-Wide Delegation of Authority.

Using Actions on Google and Google Drive together?

I'm a hobbyist student developer playing around with the Actions on Google to create a simple "text adventure" game on Google Home. Since Google Home will be speaking to the player rather than the player reading the text, I'm hoping this will create an experience similar to the "Dungeons and Dragons" roleplaying game, with the computer working as the "Dungeon Master." With the natural language assistance offered by API.AI and Actions on Google, it seemed like a good fit, since the player can respond "naturally." Here's an example of an Amazon Alexa skill that does essentially what I'm going for.
However, every time I boot up the game, it's always a new game. I'd like to store a savegame with the user's previous state in a JSON file hosted on the user's Google Drive -- Since I'm just a student doing this for fun, I don't actually have an official website or anything beyond a free Heroku server I'm running the app from, making storing saves on my end pretty much out of the question.
I've walked through the Google Drive REST quickstart for Node.js, and I've gotten that working in the console just fine. The only problem is in that quickstart, the user has to click a link to authorize the application to read the stuff in their Google Drive account, and I'm not sure how I'd be able to "click a link" and give back an access token via voice on Google Home.
Is there a way to do this via Google Drive? Or is there a better way to provide persistent data between sessions? I don't normally work in web development, so any help would be appreciated.
The bad news is you won't be able to get away from the need for a user to use his web browser to authorise your app to access his Drive.
The good news is that you only need to do this once. When your app requests authoirsation, it should specify "offline", which will result in you being given a refresh token. You should save this somewhere in your database of users. Whenever you need to access the user's Drive, you can use the saved refresh token to request an access token and you're good to go.
You have a few problems that you need to solve here, and while they seem related, they're not as related as you might hope:
You need to get authorization to access a user's Drive space
You need to authenticate the user's Home (so you know this person has come back)
You have to connect the two relationships - so you know what Drive space to use for the Home device that is talking to you
You've found the answers to (1) already, and as noted, you'll need to use a browser for them to authorize you to access their Drive. You'll then store the refresh token and will be able to access it in the future.
But that is only part of the problem. Home does not provide you access to the user's Google account directly, so you'll have to manage your own account mechanism and tie it to Home. There are a few solutions here:
Home provides anonymous user identity in the JSON sent to your webhook. You can access this using getUser().user_id if you're using the Actions API library, or access this in the data.user.user_id field in the JSON. While this is similar to a browser cookie, it only stores the user ID and can't store additional data. There is also no concept of "local storage". On the plus side, this ID is consistent across devices.
You can request user information such as their name and address. But it doesn't have anything unique or account information, so this probably isn't useful to you.
You can implement an OAuth2 server and do account linking. Note that this is the other side from what you need to do with Google Drive - you'll be providing the access and refresh tokens to authenticate and authorize access to your account and the Google Home device will send these tokens back to you so you can determine who the user is. You don't actually need to store account information - you can provide token information using JSON Web Tokens (JWT) or other methods and have them store account information in a secure way. Users will use the Google Home app to actually sign-in to your service as a one-time event.
In order to handle (3), you may be thinking that (1) lets you get tokens and the OAuth solution for (2) requires you to hand out tokens. Can the two be combined? Well... probably, but it isn't as straightforward. You can't just give the Google OAuth2 endpoints to Home - they explicitly block that and you need to control your OAuth2 endpoints. You may, however, be able to build proxy endpoints - but I haven't explored the security implications of doing so.
I think you're on the right track - using Drive is a good place to store users' information. Using Home's account linking gives you a place where they have to come to your web site to authenticate and authorize their Home, and you can use this to do the same for their Drive.

Google Drive SDK, How to check if a file has been shared outside of the domain by using Permission feed

I am using Google Drive SDK for .NET. Everything is working as expected, except that whenever I get the permission feed for a particular document. I get the Id, kind, name, role, selflink and type fields on permission.
There is no mention of the email address of the user which is stopping me from recognizing by reading the permissions, whether a file has been shared inside the domain or outside of the domain.
I can't use Google Docs API to get the ACL on doc because I am writing an app for users over 200000 users and I will need speed which is provided by Google API Console.
What should I do?
Thanks
You can use the Documents List API to get the email addresses. I'm curious why you believe Drive is faster than Documents List, for most API calls they have a comparable response time.
https://developers.google.com/google-apps/documents-list/#retrieving_the_acl_for_a_document_file_or_collection
Thanks for the idea but can I use Document List API with the Service Accounts provided through API Console?
Why do I believe that Google Drive SDK is better? Because we don't have any control over Document List API where we can set QPS (Query per second) limits or not that I know of.
Secondly, with Document List API when you make request to servers, in the past I had to create a fault tollerent algorithm in such a way that if one request fails second should go after 2 seconds if that fails then make your next request after 5 seconds until 7 second delay.
So, I don't think that Document List API would be a good fit for processing documents over 200000 users everyday unless Google has changed the way their API used to behave?

Transfer ownership for ALL files in user's google drive - using google-api-java-client and the Drive SDK

We have a google corporate account and need to transfer ALL of a user's google drive files to another account in certain instances. We want to do what is described at the following link for "all files" but programatically via the latest Drive API http://support.google.com/a/bin/answer.py?hl=en&answer=1247799
We are currently using the following API version(s) below, coupled with domain wide authority delegation as described at https://developers.google.com/drive/delegation and are able to see a user's files, iterate over them etc.
google-api-services-drive 1.14.2-beta
google-api-client 1.14.1-beta
My question is this: it appears that the only way to change permissions is by fileId by fileId etc. Instead of having to traverse and iterate over an entire set of user's files, if we just want to transfer ALL of a user's files to another particular user: is there a way in the API to do this (ownership transfer for ALL files) rather than individual requests file/by file?
Also when transferring ownershisp, must the transferee be in the same #domain or can it be another #domain we manage? I read somewhere that you can only transfer to owners in the same domain. Does this still hold true? For instance we manage #myCompany.com and have our corporate account registered under that, however that shell account has several sub-domains within it. We would like to transfer files from users in the sub-domains to a central user in the #myCompany domain.
You need to change permissions file by file, there is no updateAll type of functionality at the moment.
You cant transfer the ownership to another domain's user. Ownership can only be transferred to another user in the same domain as the current owner.
This answer doesn't directly answer your question, but it could be helpful for both you and future visitors.
As of now, you can mass transfer files to new users with Google's new Admin console. It doesn't let you filter for specific folders, but it does allow you to transfer all of one user's Drive files to a second user.
I know you were trying to create something which uses the API to iterate through folders and files, and you probably have a very specific use-case in mind. However, in the case where you have employees leaving, or you need to transfer everything, using the following method is fast and simple.
Open the Google Admin console
Go to Google Apps > Drive
Click on "Transfer ownership"
Fill out both user fields and submit
This process will even email both users once the process is completed.
You can do this with a single call to the Data Transfer API
Exactly what is needed but only with API!
Open the Google Admin console
Go to Google Apps > Drive
Click on "Transfer ownership"
Fill out both user fields and submit
This process will even email both users once the process is completed.
If this is not possible via API calls, then there is no point deleting a user using API.

value attribute for Permissions Resource not populated in responses

Looking at:
https://developers.google.com/drive/v2/reference/permissions#resource
the values attribute which contains the email address value for the ACL is not returned by the API. It's not clear why the value isn't returned, I assume it's a privacy issue but it means Drive SDK can't support document migration (from one Google account to another) use cases where the old Documents List API v3 can:
https://developers.google.com/google-apps/documents-list/#retrieving_the_acl_for_a_document_file_or_collection
for now I'm looking at adding both Drive API and Docs v3 API scopes for my project and just using the Docs API call to retrieve the ACLs but ideally I'd be able to use just Drive API calls. Am I missing anything? Could a special scope be added to Drive API that allows ACL email address retrieval or is there some other way to handle this?
Jay
Thanks for your question Jay and thanks your answer Ali Afshar!
Unfortunately I do not understand how Google believes the following scenario should work without the email address of the users:
In Documents List API v3 you could copy a file A to file B, retrieve the ACL-information of file A (including the users email adresses) and simply add them as ACL to file B.
With Drive API you can retrieve almost the same Permission information, but without the user email address, which is still required to re-share file B to the same users.
As a sidenote: If you use GAS DefaultService DocsList, you can still receive the editor/viewers with getEditors() or getViewers(). If you manually share a file you can see all email addresses as well.
So if you ask me, the privacy issue is a valuable argument, but it does simply not apply here.
Jan
Since this question was posted, Drive API has been updated to allow permissionId to be sent on permissions.insert() (the id attribute). This allows for migration of ACLs without ever needing to know the email addresses (just straight copy the permissionIds over to the new file).
Additionally:
the permissions.getIdForEmail() API call provides a quick way to get the ID for a given email address
when returning permissions for a file with permissions.get() or permissions.insert(), the domain attribute is included which should help determine if the ACL raises security concerns.
I believe these features cover most use cases where the actual ACL email address retrieval was needed.
You are absolutely correct, the email address is hidden for privacy. It is not right that a user should see the email addresses of all other users that have access to the file. But I'm not sure I quite get the problem. Are you migrating using service accounts, or are users individually authorizing the migration?
The value in the permissions feed is consistent for each user, and that value is available in the about feed for a user. I assume you know the email address of the users, so you can authorize for each of them With a service account, and you can migrate the data.
You should not need the Drive API scope and the Docs v3 API scope, they are pretty much the same scope.
Also resurrecting this old thread, I had the same issue while migrating documents.
A workaround:
- Create a temporary folder
- Insert a permission for the user
- retrieve the id from the permission
Not nice, but works for me.