
Features of working with the Google Drive API
Recently, we needed to make a simple app for Google Drive. The application was supposed to form a list of users on whom documents in the specified folder were shared with the possibility of editing. The task, in principle, is simple, so without thinking twice, I deployed the project blank on angularJS and started coding. Google, I thought, this is a big company, it should have an understandable and stable API, and I will do it in a couple of days.
I was too naive.
The application implied the absence of a server part (only client js), therefore, for authorization and identification, it was decided to use Google authorization. Logging in is easy! But it was not there. To identify the user between the application screens, he decided to store an authorization object, which is returned by the gapi.auth.getToken () method. Regular method, everything is as if created for this. But when serializing this object, the funny error "Permission denied to access property 'toJSON'” constantly occurred. The error is "intuitive" understandable, so I spent half a day on it. It turned out that the object that this function returns has a circular reference to itself. The loopback link was contained in the g-oauth-window variable. So simple code solved this problem:
The next problem with client authorization is the resumption of the client session. An authentication session using only client authentication is stored for 1 hour. But how to renew it or extend it is not clear. My dances with a tambourine with re-authorization and other shamanism could not help me, so until now the client part has authorized me for 1 hour. For convenience, I brought to the top menu the time remaining before the invalidation of the session. In principle, 1 hour is enough for this tool.
And there were some problems. The first problem I encountered was how to get an external link to a document? If everything is fine with ordinary documents - it is taken from the alternateLink property of the file object, then there is some magic with the folder. Any folder is returned as a link to the strange folderview interface that I have never seen before. Googling did not lead to anything, so I had to fix it with an ugly code:
I built the entire array of document owners with respect to userId, which gives Google. I thought it was unique and gives a full understanding that this is the same user. But it was not so. According to the documentation of drive.permissions.list, the user identifier ( proflink ) is returned as id . But in reality, it turned out that this is not the identifier I'm looking for. Why is this - for me it still remains a mystery. Therefore, for identification and "recognition" of the user in the list of owners, I used email. But this is still half the trouble.
This confusion with identifiers leads to another funny bug. If the current authorized user is a reader of the document, then permission.list will not return a list of access rights. Therefore, to show that I am a reader - I use the information from userInfo of the current user. And if the same person then will be in permission.list of another file, for example, the owner of the document, then he will have a completely different identifier. This leads to the fact that in the list of users the current authorized user can be duplicated.

Conclusion: the user ID cannot be trusted, because it can change. It is better to use email to identify the user, although, theoretically, he may be absent. For example, if a document is shared to a corporate domain, then in this case there will be no email, as it is shared to all users who belong to this domain.
There were a couple of little things that had already flown out of my head. For example, in the object with the file information there were not several variables described in the documentation. Honestly, I don’t remember which ones, but these are trifles.
PS What came of this all can be observed here . If you have ideas how to supplement the service, write in the comments - I’ll implement it.
PPSIf you know a beautiful solution to the problems described in the article, write in a personal or in the comments. I think I'm not the first to encounter these problems.
I was too naive.
Login
The application implied the absence of a server part (only client js), therefore, for authorization and identification, it was decided to use Google authorization. Logging in is easy! But it was not there. To identify the user between the application screens, he decided to store an authorization object, which is returned by the gapi.auth.getToken () method. Regular method, everything is as if created for this. But when serializing this object, the funny error "Permission denied to access property 'toJSON'” constantly occurred. The error is "intuitive" understandable, so I spent half a day on it. It turned out that the object that this function returns has a circular reference to itself. The loopback link was contained in the g-oauth-window variable. So simple code solved this problem:
var oAuthObj = gapi.auth.getToken();
oAuthObj['g-oauth-window'] = null;
$window.localStorage.setItem('googlerSession', JSON.stringify(oAuthObj));
The next problem with client authorization is the resumption of the client session. An authentication session using only client authentication is stored for 1 hour. But how to renew it or extend it is not clear. My dances with a tambourine with re-authorization and other shamanism could not help me, so until now the client part has authorized me for 1 hour. For convenience, I brought to the top menu the time remaining before the invalidation of the session. In principle, 1 hour is enough for this tool.
Work with documents
And there were some problems. The first problem I encountered was how to get an external link to a document? If everything is fine with ordinary documents - it is taken from the alternateLink property of the file object, then there is some magic with the folder. Any folder is returned as a link to the strange folderview interface that I have never seen before. Googling did not lead to anything, so I had to fix it with an ugly code:
var fileLink = fileObject.alternateLink;
if (fileLink.indexOf("folderview") != -1) {
fileLink = fileLink.replace("folderview?id=", "#folders/");
fileLink = fileLink.replace("&usp=drivesdk", "");
fileLink = fileLink.replace("docs.google.com", "drive.google.com");
}
Document Rights
I built the entire array of document owners with respect to userId, which gives Google. I thought it was unique and gives a full understanding that this is the same user. But it was not so. According to the documentation of drive.permissions.list, the user identifier ( proflink ) is returned as id . But in reality, it turned out that this is not the identifier I'm looking for. Why is this - for me it still remains a mystery. Therefore, for identification and "recognition" of the user in the list of owners, I used email. But this is still half the trouble.
This confusion with identifiers leads to another funny bug. If the current authorized user is a reader of the document, then permission.list will not return a list of access rights. Therefore, to show that I am a reader - I use the information from userInfo of the current user. And if the same person then will be in permission.list of another file, for example, the owner of the document, then he will have a completely different identifier. This leads to the fact that in the list of users the current authorized user can be duplicated.

Conclusion: the user ID cannot be trusted, because it can change. It is better to use email to identify the user, although, theoretically, he may be absent. For example, if a document is shared to a corporate domain, then in this case there will be no email, as it is shared to all users who belong to this domain.
There were a couple of little things that had already flown out of my head. For example, in the object with the file information there were not several variables described in the documentation. Honestly, I don’t remember which ones, but these are trifles.
PS What came of this all can be observed here . If you have ideas how to supplement the service, write in the comments - I’ll implement it.
PPSIf you know a beautiful solution to the problems described in the article, write in a personal or in the comments. I think I'm not the first to encounter these problems.