Google drive Public - javascript

I am working with Google drive picker, where once an item is selected from Google drive a url is produced. The problem is that that url is only accessible by the owner, and hence not public. I want the URL to be publicly accessible.
Hence, i've looked into the following guide:
https://developers.google.com/picker/docs/reference#Response.Documents
and feel that the Document.AUDIENCE class would be best applicable, however I do not know how to add that criteria into the below google drive picker example code.
Any help would be greatly appreciated.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = 'xxxxxxxYYYYYYYY-12345678';
// The Client ID obtained from the Google Developers Console. Replace with your own Client ID.
var clientId = "1234567890-abcdefghijklmnopqrstuvwxyz.apps.googleusercontent.com"
// Scope to use to access user's photos.
var scope = ['https://www.googleapis.com/auth/photos'];
var pickerApiLoaded = false;
var oauthToken;
// Use the API Loader script to load google.picker and gapi.auth.
function onApiLoad() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onAuthApiLoad() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object for picking user Photos.
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var picker = new google.picker.PickerBuilder().
addView(google.picker.ViewId.PHOTOS).
setOAuthToken(oauthToken).
setDeveloperKey(developerKey).
setCallback(pickerCallback).
build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
var url = 'nothing';
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
url = doc[google.picker.Document.URL];
}
var message = 'You picked: ' + url;
document.getElementById('result').innerHTML = message;
}
</script>
</head>
<body>
<div id="result"></div>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>

To add public permissions to the selected file. You will need to use the drive api to add file permissions
Please see https://developers.google.com/drive/v2/reference/permissions/insert
You will need to insert a permission to the file with role set to 'reader' and the type to 'anyone'
You can refer to the javascript implementation in the example
/**
* Insert a new permission.
*
* #param {String} fileId ID of the file to insert permission for.
* #param {String} value User or group e-mail address, domain name or
* {#code null} "default" type.
* #param {String} type The value "user", "group", "domain" or "default".
* #param {String} role The value "owner", "writer" or "reader".
*/
function insertPermission(fileId, value, type, role) {
var body = {
'value': value,
'type': type,
'role': role
};
var request = gapi.client.drive.permissions.insert({
'fileId': fileId,
'resource': body
});
request.execute(function(resp) { });
}

To elaborate on #Sam's answer, here is how you would do it without using the gapi.client.drive Javascript API.
Let's say that some_id is your document id:
request = gapi.client.request({
path: '/drive/v2/files/some_id/permissions',
method: 'POST',
body: {
role: 'reader'
type: 'anyone'
}
});
request.execute(function (res) {
console.log(res);
})
Which generates a request to https://content.googleapis.com/drive/v2/files/some_id/permissions?alt=json with this body: {role: "reader", type: "anyone"}
Here is the result you will get:
{
"kind": "drive#permission",
"etag": "some etage",
"id": "anyone",
"selfLink": "https://www.googleapis.com/drive/v2/files/some_id/permissions/anyone",
"role": "reader",
"type": "anyone"
}

Related

Google Sheets API throwing 401 error while append rows to spreadsheet without login

Objective: Submit a form and store data to google spreadsheet
documentation: link
What I've done so far:
var CLIENT_ID = 'my_client_id.apps.googleusercontent.com';
var API_KEY = 'MY_API_KEY';
var DISCOVERY_DOCS = ["https://sheets.googleapis.com/$discovery/rest?version=v4"];
var SCOPES = "https://www.googleapis.com/auth/spreadsheets";
var authorizeButton = document.getElementById('authorize_button');
var signoutButton = document.getElementById('signout_button');
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
})
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
//authorizeButton.style.display = 'none';
//signoutButton.style.display = 'block';
//listMajors();
} else {
//authorizeButton.style.display = 'block';
//signoutButton.style.display = 'none';
}
}
function appendPre(message) {
var pre = document.getElementById('content');
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
function update_docs(data) {
var params = {
spreadsheetId: '1YXMlr_-I45AWM2b9QnLkuLQoI6dq6wEuVOcttOMv9hU',
range: 'A:I', // TODO: Update placeholder value.
valueInputOption: 'RAW',
insertDataOption: 'INSERT_ROWS',
};
var valueRangeBody = {
"range": 'A:I', // 9 cols
"majorDimension": 'ROWS',
"values": [
[
data[0].value,//nom,
data[1].value,//prenom,
data[2].value,//email,
data[3].value,//user_phone,
data[4].value,//company_name,
data[5].value,//user_type,
data[6].value,//account_name,
data[7].value,//password,
data[8].value,//comptes_sources,
]
]
};
var request = gapi.client.sheets.spreadsheets.values.append(params, valueRangeBody);
request.then(function(response) {
console.log(response.result);
}, function(reason) {
console.error('error: ' + reason.result.error.message);
});
}
I can successfully append rows to the spreadsheet if I'm logged in to my google account.
Question: Can I append row without logging in(if yes please provide some docs/code)?
Because if I submit the form from a private window it throws 401 error.
error message: error: Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential.
I think before you start working on this you need to understand a few things.
There is a difference between private and public data.
Public data, Searching publicly uploaded youtube videos
Private data, My person gmail account, drive account, calendar account.
Even setting the sheet to public will not help you as with it public using an api key you will only be allowed to read the sheet not update it.
Answer: No you can not append a row without the application being authenticated and having access to the data.
Assuming that this is a sheet that you personally own you could set up a service account authenticate and grant the service account access to the sheet it will then be able to make the changes for you without you having to login. However this depends upon how your application works and what language you are using. I dont think that javascript supports service account authentication.

Events created with Calendar API not showing up in the calendar

I'm experimenting with Google Calendar API in an attempt to set reminders for users. I think setting a calendar event and setting a reminder to it could do what I need.
I'm using this sample code from google to try the API, I'm getting Back the description of the event I created. But if I sign in to my Google calendar I can't see the event there.
<!DOCTYPE html>
<html>
<head>
<title>Google Calendar API Quickstart</title>
<meta charset='utf-8' />
</head>
<body>
<p>Google Calendar API Quickstart</p>
<!--Add buttons to initiate auth sequence and sign out-->
<button id="authorize-button" style="display: none;">Authorize</button>
<button id="signout-button" style="display: none;">Sign Out</button>
<pre id="content"></pre>
<script type="text/javascript">
// Client ID and API key from the Developer Console
var CLIENT_ID ='781531190408-u3gh34li8b0um74r11m8hsbcofbpj4jf.apps.googleusercontent.com';
// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = "https://www.googleapis.com/auth/calendar.readonly";
var authorizeButton = document.getElementById('authorize-button');
var signoutButton = document.getElementById('signout-button');
/**
* On load, called to load the auth2 library and API client library.
*/
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
/**
* Initializes the API client library and sets up sign-in state
* listeners.
*/
function initClient() {
gapi.client.init({
discoveryDocs: DISCOVERY_DOCS,
clientId: CLIENT_ID,
scope: SCOPES
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
});
}
/**
* Called when the signed in status changes, to update the UI
* appropriately. After a sign-in, the API is called.
*/
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
listUpcomingEvents();
// Refer to the JavaScript quickstart on how to setup the environment:
// https://developers.google.com/google-apps/calendar/quickstart/js
// Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
// stored credentials.
var event = /*{
'summary': 'Google I/O 2015',
'location': '800 Howard St., San Francisco, CA 94103',
'description': 'A chance to hear more about Google\'s developer products.',
'start': {
'dateTime': '2017-07-28T09:00:00-07:00',
'timeZone': 'America/Los_Angeles'
},
'end': {
'dateTime': '2017-07-28T17:00:00-07:00',
'timeZone': 'America/Los_Angeles'
},
'recurrence': [
'RRULE:FREQ=DAILY;COUNT=2'
],
'attendees': [
{'email': 'lpage#example.com'},
{'email': 'sbrin#example.com'}
],
'reminders': {
'useDefault': false,
'overrides': [
{'method': 'email', 'minutes': 24 * 60},
{'method': 'popup', 'minutes': 10}
]
}
};*/{
"reminders": {
"useDefault": false,
"overrides": [
{
"method": "email",
"minutes": 15
},
{
"method": "popup",
"minutes": 15
},
{
"method": "popup",
"minutes": 5
}
]
},
"start": {
"dateTime": "2017-07-12T10:30:00.0z"
},
"end": {
"dateTime": "2017-07-12T11:30:00.0z"
},
"description": "Just a test description "
};
var request = gapi.client.calendar.events.insert({
'calendarId': 'primary',
'resource': event
});
request.execute(function(event) {
appendPre('Event created: ' + event.description);
});
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
/**
* Sign in the user upon button click.
*/
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
/**
* Sign out the user upon button click.
*/
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
/**
* Append a pre element to the body containing the given message
* as its text node. Used to display the results of the API call.
*
* #param {string} message Text to be placed in pre element.
*/
function appendPre(message) {
var pre = document.getElementById('content');
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
/**
* Print the summary and start datetime/date of the next ten events in
* the authorized user's calendar. If no events are found an
* appropriate message is printed.
*/
function listUpcomingEvents() {
gapi.client.calendar.events.list({
'calendarId': 'primary',
'timeMin': (new Date()).toISOString(),
'showDeleted': false,
'singleEvents': true,
'maxResults': 10,
'orderBy': 'startTime'
}).then(function(response) {
var events = response.result.items;
appendPre('Upcoming events:');
if (events.length > 0) {
for (i = 0; i < events.length; i++) {
var event = events[i];
var when = event.start.dateTime;
if (!when) {
when = event.start.date;
}
appendPre(event.description + ' (' + when + ')')
}
} else {
appendPre('No upcoming events found.');
}
});
}
</script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body>
</html>
Am I doing something wrong? Thanks.
I've tried the JavaScript Quickstart and insert an event using this sample code and I got a successful response. Maybe the problem is how you handle your authorization. You may check this tutorial.
Some additional references:
Need good example: Google Calendar API in Javascript
Events added through Google API PHP client not showing in Calendar
Google Calendar Api is not showing event list

Use custom image for google signin button

I want to provide users a facility to sign in with google. However, I want to use my image(only image, no css) as "sign in with google" button. I am using the following code:
<div id="mySignin"><img src="images/google.png" alt="google"/></div>
I am also using gapi.signin.render function as mentioned on google developer console. The code is:
<script src="https://apis.google.com/js/client:platform.js" type="text/javascript"></script>
<script>
function render(){
gapi.signin.render("mySignIn", {
// 'callback': 'signinCallback',
'clientid': 'xxxx.apps.googleusercontent.com',
'cookiepolicy': 'single_host_origin',
'requestvisibleactions': 'http://schema.org/AddAction',
'scope': 'profile'
});
}
The problem is that google signin popup is not opening and I cannot figure out how to solve it. Please suggest. Thanks in advance.
<script type="text/JavaScript">
/**
* Handler for the signin callback triggered after the user selects an account.
*/
function onSignInCallback(resp) {
gapi.client.load('plus', 'v1', apiClientLoaded);
}
/**
* Sets up an API call after the Google API client loads.
*/
function apiClientLoaded() {
gapi.client.plus.people.get({userId: 'me'}).execute(handleEmailResponse);
}
/**
* Response callback for when the API client receives a response.
*
* #param resp The API response object with the user email and profile information.
*/
function handleEmailResponse(resp) {
var primaryEmail;
var jsonobj=JSON.stringify(resp);alert(jsonobj);
var uid= jsonobj.id;
var user_name1= jsonobj.name;
for (var i=0; i < resp.emails.length; i++) {
if (resp.emails[i].type === 'account') primaryEmail = resp.emails[i].value;
}
/* document.getElementById('response').innerHTML = 'Primary email: ' +
primaryEmail + '<br/>id is: ' + uid; */
}
To use an image as your "Google Sign-in" button, you can use the GoogleAuth.attachClickHandler() function from the Google javascript SDK to attach a click handler to your image. Replace <YOUR-CLIENT-ID> with your app client id from your Google Developers Console.
HTML example:
<html>
<head>
<meta name="google-signin-client_id" content="<YOUR-CLIENT-ID>.apps.googleusercontent.com.apps.googleusercontent.com">
</head>
<body>
<image id="googleSignIn" src="img/your-icon.png"></image>
<script src="https://apis.google.com/js/platform.js?onload=onLoadGoogleCallback" async defer></script>
</body>
</html>
Javascript example:
function onLoadGoogleCallback(){
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: '<YOUR-CLIENT-ID>.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
scope: 'profile'
});
auth2.attachClickHandler(element, {},
function(googleUser) {
console.log('Signed in: ' + googleUser.getBasicProfile().getName());
}, function(error) {
console.log('Sign-in error', error);
}
);
});
element = document.getElementById('googleSignIn');
}
For those who come to here trying to get the button work out: The code below should do the trick.
It looks like the 'callback' method doesn't seem to work not sure if this is something to do with Vue as I am building it on Vue, or Google changed it as this was posted 5 years ago. Anyways, use the example below.
window.onload =() =>{
var GoogleUser = {}
gapi.load('auth2',() =>{
var auth2 = gapi.auth2.init({
client_id: '<client-unique>.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
scope: 'profile'
});
auth2.attachClickHandler(document.getElementById('googleSignup'), {},
(googleUser) =>{
console.log('Signed in: ' + googleUser.getBasicProfile().getName());
},(error) =>{
console.log('Sign-in error', error);
}
);
});
}
Change 'client_id' to your client id, and element id to your customized button id.
I hope this saves time for anyone!
Plus: I ended up using the code below, which is clearer:
window.onload = () => {
gapi.load('auth2', () => {
let auth2 = gapi.auth2.init({
client_id: '<client_id>.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
scope: 'profile email'
});
document.getElementById('googleSignup').addEventListener('click',() => {
auth2.signIn().then(() => {
let profile = auth2.currentUser.get().getBasicProfile();
... profile functions ...
}).catch((error) => {
console.error('Google Sign Up or Login Error: ', error)
});
});;
});
}

Google Drive API authentication, JavaScript

I am running on a virtual host (as well as a Python SimpleHTTPServer) and I have been following Google's instructions, but I can't get the Google drive authorization to pop up on page refresh.
https://developers.google.com/drive/web/auth/web-client
Ive placed the first block of code in my index.html file, and Ive placed the following 2 snippets in <script> tags within <body>. I filled in the CLIENT_ID with the ID I created in the Google developer console...what am I missing?
<html>
<head>
<script type="text/javascript">
var CLIENT_ID = '1052173400541-355uhjrflurk7fmlon0r5umnn12i9ag3.apps.googleusercontent.com';
var SCOPES = [
'https://www.googleapis.com/auth/drive.file',
'email',
'profile',
// Add other scopes needed by your application.
];
/**
* Called when the client library is loaded.
*/
function handleClientLoad() {
checkAuth();
}
/**
* Check if the current user has authorized the application.
*/
function checkAuth() {
gapi.auth.authorize(
{'client_id': CLIENT_ID, 'scope': SCOPES, 'immediate': true},
handleAuthResult);
}
/**
* Called when authorization server replies.
*
* #param {Object} authResult Authorization result.
*/
function handleAuthResult(authResult) {
if (authResult) {
// Access token has been successfully retrieved, requests can be sent to the API
} else {
// No access token could be retrieved, force the authorization flow.
gapi.auth.authorize(
{'client_id': CLIENT_ID, 'scope': SCOPES, 'immediate': false},
handleAuthResult);
}
}
</script>
<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
</head>
<body>
<h1>welcome to google_drive.local</h1>
<script type='text/javascript'>
/**
* Load the Drive API client.
* #param {Function} callback Function to call when the client is loaded.
*/
function loadClient(callback) {
gapi.client.load('drive', 'v2', callback);
}
/**
* Print a file's metadata.
*
* #param {String} fileId ID of the file to print metadata for.
*/
function printFile(fileId) {
var request = gapi.client.drive.files.get({
'fileId': fileId
});
request.execute(function(resp) {
if (!resp.error) {
console.log('Title: ' + resp.title);
console.log('Description: ' + resp.description);
console.log('MIME type: ' + resp.mimeType);
} else if (resp.error.code == 401) {
// Access token might have expired.
checkAuth();
} else {
console.log('An error occured: ' + resp.error.message);
}
});
}
</script>
</body>
</html>
By setting immediate=true you are suppressing the auth popup.
It should be false the first time through and is generally set to true thereafter for each hourly refresh.

#me called by anonymous error when using google plus api inside a gwt project

I'm using the google api javascript client to get information about the user profile inside a gwt project hosted in google app engine.
In localhost, the data is being retrieved correctly. I get a json with the google plus profile. When I deploy to appengine, the response is 401, "#me called by anonymous".
Here is my Code:
<script src="https://apis.google.com/js/client.js"></script>
<script type="text/javascript">
$(function() {
auth();
});
var API_KEY = "***************************************";
var CLIENT_ID = "************.apps.googleusercontent.com";
var scopes = 'https://www.googleapis.com/auth/plus.me';
function auth() {
var config = {
'client_id' : CLIENT_ID,
'scope' : scopes,
'key' : API_KEY,
};
gapi.client.load('plus', 'v1', function() {
api.client.setApiKey(API_KEY);
gapi.auth.authorize(config, function() {
var request = gapi.client.plus.people.get({
'userId' : 'me',
});
request.execute(function(resp) {
console.log(resp);
});
});
});
}
</script>
What i tried:
call to api.client.setApiKey at the begining.
create a new google api access with the google api console
update:
This is the complete response error message:
{
"error": {
"code": 401,
"message": "me called by anonymous",
"data": [
{
"domain": "global",
"reason": "authError",
"message": "me called by anonymous",
"locationType": "header",
"location": "Authorization"
}
]
},
"id": "gapiRpc"
}
There are other messages that may be related:
This is one of them:
Skipping duplicate osapi method definition chili.people.list on transport googleapis; others may exist, but suppressing warnings cb=gapi.loaded1 (línea 119)
Skipping duplicate osapi method definition pos.plusones.list on transport googleapis; others may exist, but suppressing warnings cb=gapi.loaded1 (línea 119)
Skipping duplicate osapi method definition chili.activities.list on transport googleapis; others may exist, but suppressing warnings cb=gapi.loaded1 (línea 119)
Skipping duplicate osapi method definition googleapis.newHttpRequest on transport googleapis; others may exist, but suppressing warnings
this is the other:
Invalid auth token. 1025***** vs 140186****
I could finally resolve the issue with the following settings or steps:
1) In the google apis console, I left the Redirect URIs section empty and completed the JavaScript origins section with the url of my site, repeating it with the https protocol:
JavaScript origins:
http://example.com
https://example.com
I put the script that loads the api before the end body tag:
<script src="https://apis.google.com/js/client.js"></script>
This script comes inside the body, before the api script:
<script type="text/javascript">
var API_KEY = "***************************************";
var CLIENT_ID = "************.apps.googleusercontent.com";
var scopes = 'https://www.googleapis.com/auth/plus.me';
function auth() {
var scopes = 'https://www.googleapis.com/auth/plus.me';
gapi.client.setApiKey(API_KEY);
window.setTimeout(checkAuth, 1000);
function checkAuth() {
gapi.auth.authorize({
client_id : CLIENT_ID,
scope : scopes,
immediate : false
}, handleAuthResult);
}
function handleAuthResult(authResult) {
if (authResult) {
makeApiCall();
} else {
checkAuth();
}
}
function makeApiCall() {
gapi.client.load('plus', 'v1', function() {
var request = gapi.client.plus.people.get({
'userId' : 'me'
});
request.execute(function(resp) {
$("#image").attr("src", resp.image.url);
});
});
}
}
</script>
Then I call the function auth() when the user clicks to see his picture.

Categories

Resources