Trying to get user email storage from google admin api - node.js

I am building a little script, that access the Google Reseller api that gets all the domains, then finds the users in those domains, to which it then looks at the emails for those users. That part all works.
The issue is that after I have gotten the users emails, I need to check the email storage so that I can then send an alert once the storage is nearly full.
I have searched the internet and tried various different methods, but seem to have hit a roadblock with the final step.
This is as far a I got with code
let privatekey = require("./spartan-concord-344213-d46691ffcd02.json");
let spreadsheetPriKey = require("./spreadsheet_service_account.json");
const {JWT} = require('google-auth-library');
// configure a JWT auth client
let jwtClient = new JWT({
email: privatekey.client_email,
key: privatekey.private_key,
subject: 'subject#email.com',
scopes:['https://www.googleapis.com/auth/apps.order',
'https://www.googleapis.com/auth/admin.reports.audit.readonly',
'https://www.googleapis.com/auth/admin.reports.usage.readonly',
'https://www.googleapis.com/auth/admin.directory.user',
'https://www.googleapis.com/auth/admin.directory.user.readonly',
],
});
let jwtSpreadsheetClient = new JWT({
email: spreadsheetPriKey.client_email,
key: spreadsheetPriKey.private_key,
scopes:['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/spreadsheets.readonly'],
});
const sites = []
//authenticate request
jwtSpreadsheetClient.authorize(async function (err, tokens) {
if (err) {
console.log(err);
return;
} else {
google.options({ auth: jwtSpreadsheetClient });
const client = google.sheets({ version: "v4" });
const supportEmail = await client.spreadsheets.values.get({ spreadsheetId: 'ID', range:'Sites!C2:C',});
let suppEmails = supportEmail.data.values;
suppEmails.forEach(element => {
if(element[0] != null){
sites.push(element[0]);
}
});
}
});
//authenticate request
jwtClient.authorize(async function (err, tokens) {
if (err) {
console.log(err);
return;
} else {
google.options({ auth: jwtClient });
const service = google.reseller({version: 'v1'});
const res = await service.customers.get({
'customerId': 'testDomain',
});
// console.log(res);
const services = google.admin({version: 'directory_v1'});
respo = await services.users.get({
userKey: 'test#email.com',
projection: 'FULL',
viewType: 'admin_view'
});
// console.log(respo);
const servicess = google.admin({version: 'reports_v1'});
// const response = await servicess.userUsageReport.get({
// userKey: 'all',
// date: '2022-10-11',
// parameters: 'gmail:is_gmail_enabled',
// customerId: 'customerId'
// });
const response = await servicess.activities.list({
userKey: 'all',
applicationName: 'drive',
maxResults: 10,
customerId: 'customerId'
});
console.log(response.data);
}
});
Any information is much appreciated :)

It appears you can get this information from the Reports API via userUsageReport.get with a delay.
Which provides the following useful Account Parameters with applicationName=accounts.
drive_used_quota_in_mb
gmail_used_quota_in_mb
gplus_photos_used_quota_in_mb
total_quota_in_mb
used_quota_in_mb
used_quota_in_percentage
Found here.
const { JWT } = require('google-auth-library');
const keys = require('./jwt.keys.json');
async function main() {
const client = new JWT({
email: keys.client_email,
key: keys.private_key,
scopes: [
'https://www.googleapis.com/auth/admin.reports.audit.readonly',
'https://www.googleapis.com/auth/admin.reports.usage.readonly'
],
});
const userKey = 'example#gmail.com';
const threeDaysAgo = new Date();
threeDaysAgo.setDate(new Date().getDate() - 3);
const date = datethreeDaysAgo.toISOString().split('T').slice(0, 1)[0]
const url = `https://admin.googleapis.com/admin/reports/v1/usage/users/${userKey}/dates/${date}?parameters=accounts:used_quota_in_percentage,accounts:total_quota_in_mb,accounts:used_quota_in_mb,accounts:drive_used_quota_in_mb,accounts:gmail_used_quota_in_mb,accounts:gplus_photos_used_quota_in_mb`;
const res = await client.request({ url });
console.log(res.data);
/*
{
"kind": "admin#reports#usageReports",
"etag": "\"iOcWZfmq3FoTN4bnM3qjxTbCKtrhwribSW4KdcAqWMQ/jldXIL3cW34P49N2Row7rqWkykQ\"",
"usageReports": [
{
"kind": "admin#reports#usageReport",
"date": "2022-10-17",
"etag": "\"iOcWZfmq3FoTN4bnM3qjxTbCKtrhwribSW4KdcAqWMQ/vroqtrwJo5ZJIWScePvwODh5ZGI\"",
"entity": {
"type": "USER",
"customerId": "FVdfugb32",
"userEmail": "example#gmail.com",
"profileId": "2350766532076257332587"
},
"parameters": [
{
"name": "accounts:used_quota_in_percentage",
"intValue": "0"
},
{
"name": "accounts:total_quota_in_mb",
"intValue": "-1"
},
{
"name": "accounts:used_quota_in_mb",
"intValue": "858"
},
{
"name": "accounts:drive_used_quota_in_mb",
"intValue": "461"
},
{
"name": "accounts:gmail_used_quota_in_mb",
"intValue": "397"
},
{
"name": "accounts:gplus_photos_used_quota_in_mb",
"intValue": "0"
}
]
}
]
}
*/
}
main().catch(console.error);

Related

How to attach a Google Meet link to a Calendar Event (created with a Service Account)?

I am trying to create a simple API call to create a Google Calendar Event with a Google Meet link in it but it seems I am unable to do so.
I looked up the Calendar API Documentation and have seen various examples but it still doesn't work for me. I am using a Service Account on NodeJS and a React frontend. Here below is the source code of my project.
const { google } = require('googleapis');
const { GoogleAuth } = require('google-auth-library');
var express = require('express');
var router = express.Router();
const SCOPES = ['https://www.googleapis.com/auth/calendar', 'https://www.googleapis.com/auth/calendar.addons.execute', 'https://www.googleapis.com/auth/calendar.settings.readonly', 'https://www.googleapis.com/auth/calendar.events'];
const GOOGLE_PRIVATE_KEY = "MY_PRIVATE_KEY"
const GOOGLE_CLIENT_EMAIL = "MY_SERVICE_ACCOUNT"
const GOOGLE_PROJECT_NUMBER = "MY_PROJECT_NUMBER"
const GOOGLE_CALENDAR_ID = "MY_CALENDAR_ID"
const jwtClient = new google.auth.JWT(
GOOGLE_CLIENT_EMAIL,
null,
GOOGLE_PRIVATE_KEY,
SCOPES,
"MY_PERSONAL_EMAIL"
);
const calendar = google.calendar({
version: 'v3',
project: GOOGLE_PROJECT_NUMBER,
auth: jwtClient
});
const auth = new GoogleAuth({
keyFile: 'credentials.json',
scopes: 'https://www.googleapis.com/auth/calendar', //full access to edit calendar
});
auth.getClient();
router.get("/demo", (req, res) => {
var event = {
'summary': 'My first event!',
'location': 'Hyderabad,India',
'description': 'First event with nodeJS!',
'start': {
'dateTime': '2022-06-28T09:00:00-07:00',
'timeZone': 'Asia/Dhaka',
},
'end': {
'dateTime': '2022-06-29T17:00:00-07:00',
'timeZone': 'Asia/Dhaka',
},
'attendees': [],
'reminders': {
'useDefault': false,
'overrides': [
{ 'method': 'email', 'minutes': 24 * 60 },
{ 'method': 'popup', 'minutes': 10 },
],
},
"conferenceData": {
'createRequest': {
"requestId": getRandomString(),
"conferenceSolution": {
"key": {
"type": "hangoutsMeet",
}
},
}
}
};
calendar.events.insert({
auth: auth,
calendarId: GOOGLE_CALENDAR_ID,
requestBody: event,
conferenceDataVersion: 1,
}, function (err, event) {
if (err) {
console.log('There was an error contacting the Calendar service: ' + err);
return;
}
console.log('Event created: %s', event.data);
res.jsonp("Event successfully created!");
});
})
Did you solve the Issue?
I also looked into this part because of a side project, and I'll share the code I've had success with.
I'm not sure which part is different when I look at it.
I hope this code helps.
/* index.js */
const fs = require('fs').promises;
const path = require('path');
const process = require('process');
const {authenticate} = require('#google-cloud/local-auth');
const {google} = require('googleapis');
const { v4: uuidv4 } = require('uuid');
const express = require('express');
const app = express()
// OAuth scope
const SCOPES = ['https://www.googleapis.com/auth/calendar.events'];
const TOKEN_PATH = path.join(process.cwd(), 'token.json');
const CREDENTIALS_PATH = path.join(process.cwd(), 'credentials.json');
/* Reads previously authorized credentials from the save file. */
async function loadSavedCredentialsIfExist() {
try {
const content = await fs.readFile(TOKEN_PATH);
const credentials = JSON.parse(content);
return google.auth.fromJSON(credentials);
} catch (err) {
return null;
}
}
/* Serializes credentials to a file compatible with GoogleAUth.fromJSON. */
async function saveCredentials(client) {
const content = await fs.readFile(CREDENTIALS_PATH);
const keys = JSON.parse(content);
const key = keys.installed || keys.web;
const payload = JSON.stringify({
type: 'authorized_user',
client_id: key.client_id,
client_secret: key.client_secret,
refresh_token: client.credentials.refresh_token,
});
await fs.writeFile(TOKEN_PATH, payload);
}
/* Load or request or authorization to call APIs. */
async function authorize() {
let client = await loadSavedCredentialsIfExist();
if (client) {
return client;
}
client = await authenticate({
scopes: SCOPES,
keyfilePath: CREDENTIALS_PATH,
});
if (client.credentials) {
await saveCredentials(client);
}
return client;
}
/**
* #param {google.auth.OAuth2} auth An authorized OAuth2 client.
*/
async function inserEvent(auth) {
const calendar = google.calendar({version: 'v3', auth});
const event = {
summary: 'Demo',
description: 'Demo for Google Meet',
start: {
dateTime: '2022-11-20T09:00:00+09:00',
timeZone: 'Asia/Seoul',
},
end: {
dateTime: '2022-11-20T09:30:00+09:00',
timeZone: 'Asia/Seoul',
},
conferenceData: {
createRequest: {
conferenceSolutionKey: {type: 'hangoutsMeet'},
requestId: uuidv4(),
},
},
attendees: [
{email: '${email1}'}, /* insert email */
{email: '${email2}'}, /* insert email */
],
reminders: {
useDefault: false,
overrides: [
{method: 'email', minutes: 60},
{method: 'popup', minutes: 10},
],
},
};
calendar.events.insert({
auth: auth,
calendarId: 'primary',
resource: event,
conferenceDataVersion: 1,
}, function(err, event) {
if (err) {
console.log('There was an error contacting the Calendar service: ' + err);
return;
}
console.log('Event created, google meet link : %s', event.data.hangoutLink);
});
}
app.get("/demo", (rqe, res) => {
authorize().then(inserEvent).catch(console.error);
res.send('Good');
})
app.listen(3000, () => {
console.log('listening on port 3000');
})

How to resolve 'system:error:invalid-token' In Nexmo Vonage SDK changing to a new app in the same account

I am using "#vonage/server-sdk": "2.10.7-beta-2" package on server to create users in Vonage.
To create the user, I used this API
const Vonage = require('#vonage/server-sdk');
const v = new Vonage({
apiKey: config.voipConfig.key,
apiSecret: config.voipConfig.secret,
applicationId: config.voipConfig.appId,
privateKey: config.voipConfig.privateKeyPath
};
v.users.create({
"name": payload.username,
"display_name": payload.displayName
}, (error: any, result: any) => {
});
Everything was working fine. But when I created a new application in vonage account and used new configs, it started to throw the following error
{
description: 'You did not provide a valid token. Please provide a valid token.',
code: 'system:error:invalid-token'
}
I have checked the details multiple times and not sure what is wrong.
The new credentials are from completely new account.
Any help would be much appreciated.
Looks like you are using the Vonage Conversations API to create a user. In good practice, we usually use dotenv to store our .env variables. If you are using a public github repo, remember to add *.env to your .gitignore.
npm install dotenv
// .env
API_KEY=
API_SECRET=
APPLICATION_ID=
APPLICATION_PRIVATE_KEY_PATH=
TO_NUMBER=<YOUR CELL NUMBER>
VIRTUAL_NUMBER=<VONAGE VIRTUAL NUMBER>
NGROK_URL=https://<URL>.ngrok.io
For testing purposes. Can you make an outbound call with the snippet below? That'll test your credentials.
Make sure to store the private.key in same directory as .env and outbound-call.js
// outbound-call.js
require("dotenv").config();
const API_KEY = process.env.API_KEY;
const API_SECRET = process.env.API_SECRET;
const APPLICATION_ID = process.env.APPLICATION_ID;
const APPLICATION_PRIVATE_KEY_PATH = process.env.APPLICATION_PRIVATE_KEY_PATH;
const TO_NUMBER = process.env.TO_NUMBER;
const VIRTUAL_NUMBER = process.env.VIRTUAL_NUMBER;
if (!API_KEY || !API_SECRET) {
console.log("šŸ”„ API_KEY or API_SECRET missing");
process.exit(1);
}
if (!APPLICATION_ID || !APPLICATION_PRIVATE_KEY_PATH) {
console.log("šŸ”„ APPLICATION_ID or APPLICATION_PRIVATE_KEY_PATH missing");
process.exit(1);
}
if (!TO_NUMBER || !VIRTUAL_NUMBER) {
console.log("šŸ”„ TO_NUMBER or VIRTUAL_NUMBER missing");
process.exit(1);
}
const Vonage = require("#vonage/server-sdk");
const vonage = new Vonage({
apiKey: API_KEY,
apiSecret: API_SECRET,
applicationId: APPLICATION_ID,
privateKey: APPLICATION_PRIVATE_KEY_PATH,
});
vonage.calls.create({
to: [
{
type: "phone",
number: process.env.TO_NUMBER,
},
],
from: {
type: "phone",
number: process.env.VIRTUAL_NUMBER,
},
ncco: [
{
action: "talk",
text: "This is a text to speech call from Vonage",
},
],
});
To test the Conversations API, you will need to enable Voice for your Vonage Application and set the answer Webhook. I use NGROK as well, so it should look like this. https://<URL>.ngrok.io/webhooks/answer
When working with Conversations API, I usually do:
Create a Conversation
Create a User
Create a Member
and put that into the /webhooks/answer
//server.js
require('dotenv').config();
let express = require('express');
let cookieParser = require('cookie-parser');
let logger = require('morgan');
let app = express();
let port = 5001;
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static('public'));
const NGROK_URL = process.env.NGROK_URL;
const Vonage = require('#vonage/server-sdk');
const vonage = new Vonage({
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
applicationId: process.env.APPLICATION_ID,
privateKey: process.env.APPLICATION_PRIVATE_KEY_PATH
});
app.post('/webhooks/answer', async (req, res) => {
console.log('šŸšš answer', req.body);
let result = req.body;
const createCallConversationPromise = (ConvName, ConvDisplayName) => new Promise((resolve, reject) => {
vonage.conversations.create({
"name": ConvName,
"display_name": ConvDisplayName,
}, (error, result) => error ? reject(error) : resolve(result));
});
const createCallUserPromise = (Name, DisplayName) => new Promise((resolve, reject) => {
vonage.users.create({
name: Name,
display_name: DisplayName,
}, (error, result) => error ? reject(error) : resolve(result));
});
const createCallMemberPromise = (ConvId, UserId) => {
vonage.conversations.members.create(ConvId, {
"action": "join",
"user_id": UserId,
"channel": {
"type": "app"
}
}, (error, result) => {
if(error) {
console.log('\nšŸ”„ Error Creating Member', error);
}
else {
console.log('\nāœ… Created Member with ConvId', ConvId, 'and UserId',UserId)
console.log(result);
}
})
};
try {
let ConvName = result.from + result.to + result.conversation_uuid;
console.log('nāœ… ConvName', ConvName);
let ConvDisplayName = result.from + result.to + result.conversation_uuid;
const conversation = await createCallConversationPromise(ConvName, ConvDisplayName);
process.env.CONVERSATION_ID = conversation.id;
console.log('\nāœ… CONVERSATION_ID', process.env.CONVERSATION_ID);
let Name = result.from + result.conversation_uuid;
let DisplayName = result.from;
const callUser = await createCallUserPromise(Name, DisplayName);
console.log('\nāœ… UserId', callUser.id)
let ConvId = conversation.id;
let UserId = callUser.id;
const memberUser = await createCallMemberPromise(ConvId, UserId);
let ncco = [
{
action: "talk",
text: "<speak><lang xml:lang='en-GB'>Welcome to Vonage Development inbound call testing</lang></speak>",
voiceName: "Emma"
},
];
res.json(ncco);
} catch (error) {
console.log("šŸ”„ Error", error);
let ncco = [
{
"action": "talk",
"text": "<speak><lang xml:lang='en-GB'>Error on Process Answer</lang></speak>",
"voiceName": "Emma"
}
];
res.json(ncco);
}
});

paypal-rest-sdk "MALFORMED_REQUEST_JSON" on execution

I'm trying to implement PayPal payments on my website, I can create a payment once the user requests and I send him the redirect approval URL, after clients pay I call the execution on my backend with the payment ID and buyer ID, but I receive the error below
{"response":{"name":"VALIDATION_ERROR","message":"Invalid request - see details","debug_id":"4f3a6da7e0c7d","details":[{"location":"body","issue":"MALFORMED_REQUEST_JSON"}],"links":[],"httpStatusCode":400},"httpStatusCode":400}
I have been trying everything for a few hours, I tried to copy the create payment JSON from anywhere including PayPal API example and still, nothing works.
Also, I wanna redirect the client to success page just after transaction is approved (execute), it has to be handled by the front?
Code
const paypal = require('paypal-rest-sdk');
const dbService = require('../../services/mongodb-service');
const { ObjectId } = require('mongodb');
const getProducts = async () => {
const products = await dbService.getCollection('products');
return await products.find({}).toArray();
}
paypal.configure({
'mode': 'sandbox',
'client_id': 'id',
'client_secret': 'secret'
});
const createPayment = async (productId) => {
const products = await dbService.getCollection('products');
const product = await products.findOne({ '_id': ObjectId(productId) })
if (!product) return Promise.reject('Product not found');
const payment = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"transactions": [{
"amount": {
"currency": "USD",
"total": product.price,
},
"description": product.description,
"payment_options": {
"allowed_payment_method": "IMMEDIATE_PAY"
},
"item_list": {
"items": [{
"name": product.name,
"description": product.description,
"quantity": 1,
"price": product.price,
"tax": 0,
"sku": product._id,
"currency": "USD"
}]
}
}],
"redirect_urls": {
"return_url": "http://localhost:3000/purchase-success",
"cancel_url": "http://localhost:3000/purchase-error"
}
}
const transaction = await _createPay(payment);
const redirect = transaction.links.find(link => link.method === 'REDIRECT');
return redirect;
}
const _createPay = (payment) => {
return new Promise((resolve, reject) => {
paypal.payment.create(payment, (err, payment) => err ? reject(err) : resolve(payment));
});
}
const executePayment = async (paymentId, payerId) => {
try {
const execute = await _executePay(paymentId, payerId);
console.log(execute);
return execute;
} catch (err) { console.log(JSON.stringify(err)) }
}
const _executePay = (paymentId, payerId) => {
return new Promise((resolve, reject) => {
console.log(paymentId, payerId);
paypal.payment.execute(paymentId, payerId, (error, payment) => {
return error ? reject(error) : resolve(JSON.stringify(payment));
})
})
}
module.exports = {
createPayment,
executePayment,
getProducts
}
should be
const _executePay = (paymentId, payerId) => {
return new Promise((resolve, reject) => {
console.log(paymentId, payerId);
var payerIdObj = { payer_id: payerId };
paypal.payment.execute(paymentId, payerIdObj, (error, payment) => {
return error ? reject(error) : resolve(JSON.stringify(payment));
})
})
}
the doc
I was able to resolve it by doing a post request, code:
const _executePay = async (paymentId, payerId) => {
const response = await axios.post(`https://api.sandbox.paypal.com/v1/payments/payment/${paymentId}/execute`, { 'payer_id': payerId }, {
auth: {
username: CLIENT_ID,
password: CLIENT_SECRET
}
})
return response;
}

Update user using google admin directory api returns 200 but does not update. Malformed request body?

I have a user in my google admin console with the email dog#jopfre.com.
I can auth successfully and add and delete users using the api.
Now I am trying to update the user using the api.
Here is a simplified version of my code:
const admin = google.admin({version: 'directory_v1', auth});
admin.users.update({
userKey: "dog#jopfre.com",
requestBody: {
primaryEmail: "cat#jopfre.com"
}
},(err, data) => {
console.log(err || data);
});
This returns json of the request and a 200 status.
The nearest example I can find in the docs is this:
admin.members.insert({
groupKey: 'my_group#example.com',
requestBody: { email: 'me#example.com' },
auth: jwt
}, (err, data) => {
console.log(err || data);
});
So it looks pretty similar to me.
I have tried with and without quotation marks on the requestBody key and have also tried updating different key values like givenName and suspended. I'm guessing my request is malformed somehow but I can't work out how as no error is returned.
Any clue or ideas of what to try next?
Here are some of the more relevant lines from the returned json:
status: 200,
params: { requestBody: { primaryEmail: 'cat#jopfre.com' } },
_hasBody: true,
header: 'PUT /admin/directory/v1/users/dog#jopfre.com?requestBody%5BprimaryEmail%5D=cat%40jopfre.com HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/x-www-form-urlencoded\r\nAuthorization: Bearer ya29.GlwXBi796knRrOTbzvJ1ihzBaQqHKk3HYA9-3pxUgCxaCvPKxZLYGRrghq_RcFHbZYqyKEqUV6yOWusBui2Vh1DLd50MsKQ5o4MoqzutVr8P280ULY2cYzSYLtGOyw\r\nUser-Agent: google-api-nodejs-client/1.6.1\r\nHost: www.googleapis.com\r\nConnection: close\r\nContent-Length: 0\r\n\r\n',
path: '/admin/directory/v1/users/dog#jopfre.com?requestBody%5BprimaryEmail%5D=cat%40jopfre.com',
responseUrl: 'https://www.googleapis.com/admin/directory/v1/users/dog#jopfre.com?requestBody%5BprimaryEmail%5D=cat%40jopfre.com',
_requestBodyLength: 0,
Not sure if the requestBodyLength should be 0, that seems off.
Using resource instead of requestBody works in v33.0.0 of googleapis.
const admin = google.admin({version: 'directory_v1', auth});
admin.users.update({
userKey: "dog#jopfre.com",
resource: {
primaryEmail: "cat#jopfre.com"
}
},(err, data) => {
console.log(err || data);
});
Effective release of googleapis version 30.0.0 resource and requestBody are equally accepted.
Below are working examples for users.insert, users.list, users.update, users.get and users.delete functions, all tested with googleapis version 30.0.0
async function insertUser(auth) {
const service = google.admin({version: 'directory_v1', auth});
console.log("Inserting user");
const response = await service.users.insert({
"requestBody":{
"name": {
"familyName": "Friends",
"givenName": "John Smith",
},
"password": "**********",
"primaryEmail": "j.smith#jopfre.com",
}
})
// Log the results here.
console.log(`status: ${response.status}\nprimary email: ${response.data.primaryEmail}\nupdated familyName: ${response.data.name.fullName}`)
console.log("\n"); // insert a line break.
}
async function listUsers(auth) {
console.log('Listing users')
const service = google.admin({version: 'directory_v1', auth});
const response = await service.users.list({
customer: 'my_customer',
maxResults: 150,
orderBy: 'email',
})
const users = response.data.users;
if (users.length) {
console.log('Users:');
users.forEach((user) => {
console.log(`${user.primaryEmail} -(${user.name.fullName})`);
});
} else {
console.log('No users found.');
}
console.log("\n"); // insert a line break.
}
async function updateUserInfo(auth) {
console.log('Updating user info')
const service = google.admin({version: 'directory_v1', auth});
const response = await service.users.update({
"userKey": "j.smith#jopfre.com",
"requestBody": {
"name": {
"familyName": "Work"
},
"primaryEmail": "john.smith#jopfre.com"
}
})
// Log the results here.
console.log('User info is updated successfully')
console.log(`status: ${response.status}, prime email: ${response.data.primaryEmail} updated familyName: ${response.data.name.familyName}`)
for (i = 0; i < response.data.emails.length; i++) {
console.log(`address: ${response.data.emails[i]["address"]}`)
}
console.log("\n"); // insert a line break.
}
async function getUserMeta(auth) {
console.log('Getting user info')
const service = google.admin({version: 'directory_v1', auth});
const response = await service.users.get({
"userKey" : "j.smith#jopfre.com"
})
console.log('User info is obtained successfully')
console.log(`primary email: ${response.primaryEmail}, full name: ${response.data.name.fullName}`)
console.log("\n"); // insert a line break.
}
async function deleteUser(auth) {
console.log('Deleting user')
const service = google.admin({version: 'directory_v1', auth});
const response = await service.users.delete({
"userKey" : "j.smith#jopfre.com"
})
if (response.data == "") {
console.log("User is deleted successfully");
}
}

Google Analytics - invalid_grant: Invalid JWT Signature

I need to authorize from Google analytics to get the response data.
var google = require('googleapis'),
q = require('q'),
SERVICE_ACCOUNT_EMAIL = '838823084353-cjjoiv9di67fuh7geqgggociibataf9v#developer.gserviceaccount.com',
SERVICE_ACCOUNT_KEY_FILE = __dirname + '/google-services-private-key.pem';
var def = q.defer();
var gAnalytics = google.analytics('v3');
var authClient = new google.auth.JWT( SERVICE_ACCOUNT_EMAIL, SERVICE_ACCOUNT_KEY_FILE, null, ['https://www.googleapis.com/auth/analytics.readonly']);
console.log(authClient)
authClient.authorize(function (err, tokens) {
if (err) {
console.log("err is: " + err, tokens);
return;
}
But it fails to authorize
getting error
JWT { transporter: DefaultTransporter {}, clientId_: undefined,
clientSecret_: undefined, redirectUri_: undefined, opts: {},
credentials: { refresh_token: 'jwt-placeholder', expiry_date: 1 },
email:
'838823084353-cjjoiv9di67fuh7geqgggociibataf9v#developer.gserviceaccount.com',
keyFile:
'/home/aaa/Desktop/ampretailer/server/google-services-private-key.pem',
key: null, scopes: [
'https://www.googleapis.com/auth/analytics.readonly' ], subject:
undefined, gToken: [Function: GoogleToken] } err is: Error:
invalid_grant: Invalid JWT Signature. { access_token: null,
token_type: 'Bearer', expiry_date:null }
I recommend you try using Google Analytics v4 instead of v3 there are a number of dimensions and metrics which you will not have access to using V3.
'use strict';
const { google } = require('googleapis');
const sampleClient = require('../sampleclient');
const analyticsreporting = google.analyticsreporting({
version: 'v4',
auth: sampleClient.oAuth2Client
});
async function runSample () {
const res = await analyticsreporting.reports.batchGet({
resource: {
reportRequests: [{
viewId: '65704806',
dateRanges: [
{
startDate: '2018-03-17',
endDate: '2018-03-24'
}, {
startDate: '14daysAgo',
endDate: '7daysAgo'
}
],
metrics: [
{
expression: 'ga:users'
}
]
}]
}
});
console.log(res.data);
return res.data;
}
// if invoked directly (not tests), authenticate and run the samples
if (module === require.main) {
const scopes = ['https://www.googleapis.com/auth/analytics'];
sampleClient.authenticate(scopes)
.then(c => runSample())
.catch(e => console.error);
}
// export functions for testing purposes
module.exports = {
runSample,
client: sampleClient.oAuth2Client
};
Code ripped from analyticsReporting/batchGet.js
Service account - To use the service account based samples, create a new service account in the cloud developer console, and save the file as jwt.keys.json in the samples directory.
'use strict';
const {google} = require('googleapis');
const path = require('path');
/**
* The JWT authorization is ideal for performing server-to-server
* communication without asking for user consent.
*
* Suggested reading for Admin SDK users using service accounts:
* https://developers.google.com/admin-sdk/directory/v1/guides/delegation
*
* See the defaultauth.js sample for an alternate way of fetching compute credentials.
*/
async function runSample () {
// Create a new JWT client using the key file downloaded from the Google Developer Console
const client = await google.auth.getClient({
keyFile: path.join(__dirname, 'jwt.keys.json'),
scopes: 'https://www.googleapis.com/auth/analytics.readonly'
});
// Obtain a new drive client, making sure you pass along the auth client
const analyticsreporting = google.analyticsreporting({
version: 'v4',
auth: client
});
// Make an authorized request to list Drive files.
const res = = await analyticsreporting.reports.batchGet({
resource: {
reportRequests: [{
viewId: '65704806',
dateRanges: [
{
startDate: '2018-03-17',
endDate: '2018-03-24'
}, {
startDate: '14daysAgo',
endDate: '7daysAgo'
}
],
metrics: [
{
expression: 'ga:users'
}
]
}]
}
});
console.log(res.data);
return res.data;
}
if (module === require.main) {
runSample().catch(console.error);
}
// Exports for unit testing purposes
module.exports = { runSample };
code ripped from samples/jwt.js

Resources