Google compute engine instance start/status/stop using api - php

I need to start the google cloud instance and stop if my process is over.
So i tried api calls from https://cloud.google.com/compute/docs/reference/rest/v1/instances/get
Created API Key and oAuth client Id for the same and tried in postman application to test.
Used API Key in header Authorization : Bearer <api_key> and also in URL as key=<api_key>
But both methods are giving error 401 login required.
Then i found API Explorer
https://developers.google.com/apis-explorer/
There also i got same error.
What is the mistake I'm doing.
I need to implement instance start and stop through PHP code as it is background process.
PHP curl response
{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Invalid Credentials"
}
}

I think the easiest way to actually do this using env variable, as the google api php client library has a neat method.
require_once __DIR__ . '/vendor/autoload.php';
putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json');
$client = new Google_Client();
$client->setApplicationName('RandomNameYouNeedToInsert/0.1');
$client->addScope(array('https://www.googleapis.com/auth/compute'));
$client->useApplicationDefaultCredentials();
$service = new Google_Service_Compute($client);
// TODO: Update placeholder values.
project = 'my-project';
$zone = 'my-zone';
$instance = 'my-instance';
$response = $service->instances->start($project, $zone, $instance);
// TODO: Check if the response satisfies your request.

Related

Difficulties getting user's mail from Gmail inbox in Laravel

I'm trying to create a Laravel API to interact with Gmail via the Google API client library for PHP.
However, I encounter issues with the endpoint to get mails.
So far, I could do authorization and get the access token in my DB. This endpoint return JSON of this format:
{
"user_id": 1,
"token": {
"access_token": "ya29.XXXXXXXXXXXX-K_P9Z0Rd0nU5WzSvU3TMlC0TZQRbMLkDHE1XI3j29mbIRP13dt_NGMb4d9trTECGKiwbjM45Ijk7fbhpLzU2JL7w-6w_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"expires_in": 3599,
"scope": "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/gmail.readonly",
"token_type": "Bearer",
"id_token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-yK6GHPRATk64GaPcYCuIVyqTYNNvfvr8gCVuTCKr3RMtUz5J97ROZkJRN5w_AQvyJFL369MNTnHQAiqJoPIN2Wes0OAbeq1urpDRMRaAfF6Nuqun-pmewI8g5OCjkUMqekZTKlzCqRl7Xkm4qQRrwk66SxwGdC78Iy5Z_3VG1OIj681zoY18dQu9_ZqGMnwVuHmffmzNInuAmqHcQ7CLM_I_vJbWV3-UKVRF2UtjHvmUydCdo4PrEpL371i8exwPme5IK_xMcywxdfdjxm4duyv6X_ky2MCYwANNBSyBLMYh214FZPowL8choHmMIms-biJlg",
"created": 1647922921
},
"name": "gmail",
"updated_at": "2022-03-22T04:22:01.000000Z",
"created_at": "2022-03-22T04:22:01.000000Z",
"id": 10
}
My second endpoint is to get the mails by using the access token.
My implementation looks like this.
// Services
public function getEMails($user_id, $access_token){
$this->client->setAccessToken($access_token);
$service = new Gmail($this->client);
$messages = $service->users_messages->listUsersMessages($user_id);
return $messages;
}
// Controller
public function getMails(WebService $web_service, GmailServices $gmail_services){
$access_token = $web_service->token['access_token'];
$user_id = 'me';
if (isset($access_token)){
$mails = $gmail_services->getEMails($user_id, $access_token);
}
return $mails;
}
// api.php (In route middleware)
Route::get('/web-service/{mails}', [WebServiceController::class, 'getMails'])->name('web-service.getMails');
Hitting this endpoint, I get the below error.
"message": "Trying to access array offset on value of type null",
"exception": "ErrorException"
which corresponds to this line
$access_token = $web_service->token['access_token'];
I did some minor research, but I couldn't resolve it. Unfortunately, I'm not advanced in Laravel development, and I'll appreciate any help and feedback.
Furthermore, I equally want to add that my implementation is largely based on Bitfumes test-driven API development on YouTube. Here is the link to the repo https://github.com/bitfumes/laravel-test-driven-api
Thanks!
After trying the above, I was expecting to get the mails and equally work on pagination or querying via LIMIT so that the backend will not over-stress to get all mails at once.
Everything you do should be going though the Google_Client object. Your code is a little confusing to me you have two getEMails methods and neither appear to be using assigning things properly though the client.
When properly initialized it is able to handle everything for you.
$client = new Google_Client();
$client->setApplicationName('Gmail API PHP Quickstart');
$client->setScopes(Google_Service_Gmail::GMAIL_READONLY);
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
You should be testing if the access token has expired. If it is expired then have the Google_Client request a new one.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// request access of the user if it has not been granted.
}
// note after refresh remember to store the new refresh token.
}

How to fixed Project Permission Denied problem for update draft grade and assigned grade of student submission from Google Classroom

I want to update the draft grade and assigned grade from Google Classroom using API. The following problem is seen When I test to update the draft grade and assigned grades using Try this API.
Problem:1
{
"error": {
"code": 403,
"message": "#ProjectPermissionDenied The Developer Console project is not permitted to make this request.",
"status": "PERMISSION_DENIED"
}
}
This error may be due to using an insufficient credential type.
Try using OAuth 2.0.
Localhost Code:
$client = getClient();
$service = new Google_Service_Classroom($client);
$courseId = '393351980716';
$courseWorkId = '393445838699';
$id = 'Cg0Iu5q5vHkQ657M2bkL';
$post_body = new Google_Service_Classroom_StudentSubmission(array(
'assignedGrade' => 10,
'draftGrade' => 90
));
$params = array(
'updateMask' => 'assignedGrade,draftGrade'
);
$list = $service->courses_courseWork_studentSubmissions->patch($courseId, $courseWorkId, $id, $post_body,$params);
Then when I run the above code on localhost I see problem-2:
Problem-2
Fatal error: Uncaught Google\Service\Exception: {
"error": {
"code": 403,
"message": "#ProjectPermissionDenied The Developer Console project is not pe
rmitted to make this request.",
"errors": [
{
"message": "#ProjectPermissionDenied The Developer Console project is no
t permitted to make this request.",
"domain": "global",
"reason": "forbidden"
}
],
"status": "PERMISSION_DENIED"
}
}
How to solve this problem?
According to the Classroom API documentation:
ProjectPermissionDenied indicates that the request attempted to modify a resource associated with a different Developer Console project.
Possible Action: Indicate that your application cannot make the desired request. It can only be made by the Developer Console project of the OAuth client ID that created the resource.
Therefore, if the resource you are trying to modify has been created manually for instance, this means that it is not associated with any developer project, hence the error you are receiving.
You will have to create these resources in the same project in order to be able to execute this request successfully.
Reference
Classroom API Access Errors.
For that API request your API key needs one of the following authorised scopes
Authorization Scopes
Requires one of the following OAuth scopes:
https://www.googleapis.com/auth/classroom.coursework.students
https://www.googleapis.com/auth/classroom.coursework.me

Google Drive API V3, PHP Client, transfer file ownership

I am trying to create a folder and change the owner using Google Drive API PHP Client. Folder gets created properly, and I can set any permission aside from owner, which returns an error. My code:
function createFolder($name, $parents, $mimeType)
{
$client = getClient();
$service = new Google_Service_Drive($client);
$folder = new Google_Service_Drive_DriveFile();
$folder->setName($name);
if ($parents) {$folder->setParents(array($parents));}
$folder->setMimeType($mimeType);
$created_folder = $service->files->create($folder);
$created_folder_id = $created_folder->getId();
$ownerPermission = new Google_Service_Drive_Permission();
$ownerPermission->setEmailAddress("shared#******.com");
$ownerPermission->setType('user');
$ownerPermission->setRole('owner');
$service->permissions->create($created_folder_id, $ownerPermission, array('transferOwnership' => 'true'));
return $created_folder_id;
}
And the return:
Fatal error: Uncaught Google\Service\Exception: {
"error": {
"errors": [
{
"domain": "global",
"reason": "forbidden",
"message": "The transferOwnership parameter must be enabled when the permission role is 'owner'.",
"locationType": "parameter",
"location": "transferOwnership"
}
],
"code": 403,
"message": "The transferOwnership parameter must be enabled when the permission role is 'owner'."
}
Am I not setting the transferOwnership parameter correctly?
#DLateef If you want to make the file shareable, you may want to read more about Permission resource in Drive API. For "shared" to be true, each file permission needs to specify a role, type, and email address or domain. As an owner of the file (Docs, Sheets, etc.), you will need to provide the appropriate permission to be set to.
Here is an example, using the Permissions.create
POST https://www.googleapis.com/drive/v3/files/{fileId}/permissions?key={YOUR_API_KEY}
{
"role": "reader",
"type": "user",
"emailAddress": "xxxxxxxx#xxx.com"
}
Response from the Drive Files.get:
GET https://www.googleapis.com/drive/v3/files/{fileId}?fields=appProperties%2CfileExtension%2Ckind%2CmimeType%2Cshared&key={YOUR_API_KEY}
{
"kind": "drive#file",
"mimeType": "application/vnd.google-apps.document",
"shared": true
}
However, if you are unable to switch to the Drive v3, you can still use the Permission.insert from Drive v2 to do the job.
Or else, you can also try ownerPermission->setTransferOwnership(true);
I was able to get this to work by separating the code for creating the folder an transferring ownership. If called as part of the same createFolder function I get the error described above, but transferring ownership in a separate function, after folder is created, works fine.

Getting authorization error while accessing google merchant product list

I was trying to access Google Merchant Products which was added by Feed and followed the API reference https://developers.google.com/shopping-content/v2/reference/v2/products/list#try-it. When I use Google OAuth 2.0 It asks login to google account and get response of all products and when I use API key "https://www.googleapis.com/content/v2/[MERCHANT_ID]/products?key=[KEY]" I get following response
`
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}
`
API keys can't be used for authentication (it wouldn't be secure), they're only for authorization. In other words, API keys can allow you to call the API, but they can't be used to validate who you are (and thus what data you have permission to access).
As such, it looks like you'll want to use OAuth 2.0 in this case, instead of (or in addition to) an API key.
Or alternately, if you're not looking to authenticate as a machine (a Cloud project) instead of an actual user, you may be able to grant a Service Account access and use that type of authentication instead.

Google API oauth2 token expires?

I have a problem with google api and oauth2 token.
There is an app which allows to synchronize contacts / calendar with your google account by oauth2 token.
When first time user wants to connect with his google account, he needs to grant access , then app is receiving code/token which is saved and will be used for offline synchronization later.
function getClient($app)
{
$client = new Google_Client();
$client->setAuthConfig("path_to_secret.json");
switch($app)
{
case 'contacts':
$client->addScope(Google_Service_Script::WWW_GOOGLE_COM_M8_FEEDS);
$client->addScope(Google_Service_People::USERINFO_EMAIL);
break;
case 'calendar':
$client->addScope(Google_Service_Calendar::CALENDAR);
break;
default:
throw new Exception('API Callback not defined in setup');
}
$client->setAccessType('offline'); // offline access
$client->setIncludeGrantedScopes(true); // incremental auth
$client->setRedirectUri(GOOGLE_APP_URL . $app.'/callback.php');
return $client;
}
(there are different tokens for contacts and calendar)
The synchronization script:
...
try
{
$client = getClient('calendar');
$client->setAccessToken(unserialize($accessToken));
$http = $client->authorize();
$service = new Google_Service_Calendar($client);
...
}
$accessToken is a serialized string like:
a:5:{s:12:"access_token";s:131:"******token_here********";s:10:"token_type";s:6:"Bearer";s:10:"expires_in";i:3598;s:8:"id_token";s:902:"***id_token****";s:7:"created";i:1505178047;}
This is working for first time and couple more times but after some time(hours) there is an error:
Error: {"error": { "errors": [ { "domain": "global", "reason": "authError", "message": "Invalid Credentials", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Invalid Credentials" }}
What I am doing wrong?
What is interesting that for contacts synchronization works fine all the time (access token has the same attributes as in calendar synchronization )
Ok, propably solved - refresh_token is provided for the first time only, so when I was testing it more times then I didn't get refresh token.
When I revoked access in https://myaccount.google.com/u/0/permissions and connected again then I received also refresh token. I assume now it will work properly

Categories