google calenderID nodejs doesn't work with specified CalendarID - node.js

I would like to use a google calendar, if I choose the calendar ID not as primary but with the specified one, I get an error message in line 46 (const eventsArray = res.data.calendars.calID.busy). The Error message looks like this (node:49993) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'calendar' of undefined. So basicly, i believe, it can't read the calender ID, can enyone help me to find my fault?
const { google } = require('googleapis');
const { OAuth2 } = google.auth;
const oAuth2Client = new OAuth2(
'id_works_with_primary_calender',
'key_works_with_primary_calender'
)
oAuth2Client.setCredentials({
refresh_token:
'works_with_primary',
})
const calendar = google.calendar( { version: 'v3', auth: oAuth2Client } );
const eventStartTime = new Date()
eventStartTime.setDate(eventStartTime.getDay() + 2)
const eventEndTime = new Date()
eventEndTime.setDate(eventEndTime.getDay() + 2)
eventEndTime.setMinutes(eventEndTime.getMinutes() + 45)
const event = {
summary: 'Meet with David',
location: '295 California St, San Francisco, CA 94111',
description: 'Meeting with David to talk about the new client Project and drink some stuff',
colorId: 1,
start: {
dateTime: eventStartTime,
timeZone: 'Europe/Zurich',
},
end: {
dateTime: eventEndTime,
timeZone: 'Europe/Zurich',
},
}
calendar.freebusy.query( {
resource: {
timeMin: eventStartTime,
timeMax: eventEndTime,
timeZone: 'Europe/Zurich',
items: [ { id: 'gd3q30fhkprf0ubsk3pnqkc64k#group.calendar.google.com' } ],
},
}, (err, res) => {
if (err) return console.error('Free Busy Query Error: ', err)
//Here is the error
const eventsArray = res.data.calendars.gd3q30fhkprf0ubsk3pnqkc64k#group.calendar.google.com.busy
if(eventsArray.length === 0)
return calendar.events.insert( {
calendarId: 'gd3q30fhkprf0ubsk3pnqkc64k#group.calendar.google.com',
resource: event,
},
err => {
if (err) return console.error('Calender Event Creation: ' + err)
return console.log('Event Created: ' + event)
})
return console.log("I'm Busy")
})

Issue:
The problem seems to be that the id includes several dots, and the program thinks these are used to access nested properties. Because of this, it is looking for the property calendar of the id gd3q30fhkprf0ubsk3pnqkc64k#group and, of course, it's not finding it, because the correct id is gd3q30fhkprf0ubsk3pnqkc64k#group.calendar.google.com.
Solution:
Therefore, assuming that this id is getting returned by res.data.calendars, the problem should be solved by changing the syntax with which you are accessing the key property, from dot notation to bracket notation.
That is to say, replace this:
const eventsArray = res.data.calendars.gd3q30fhkprf0ubsk3pnqkc64k#group.calendar.google.com.busy
With this:
const eventsArray = res.data.calendars["gd3q30fhkprf0ubsk3pnqkc64k#group.calendar.google.com"].busy
Reference:
Property accessors

Related

Can't retrieve embedded object from a MongoDB document - MERN stack

I am using the MERN stack for my current project. So I am facing this problem:
Let's say that I have the following document in MongoDB :
{
name: "Tesla Inc.",
category: "Automotive",
contact: {
state : {
name: "Texas",
city: "Austin",
address: {
streetName: "Tesla Road",
number: '1'
}
}
}
}
What I get as response after using findOne({ name : "Tesla"}) is :
{_id: '637e4397f6723844191aa03d', name: 'Tesla', category:
'Automotive', contact: {…}}
As you can see contact object is undefined
Follows my coding process
This is my Express route for quering the database :
storeRoutes.route("/enterprise").get(function (req, res) {
let db_connect = dbo.getDb("res");
const query = { name : "Tesla"};
db_connect
.collection("stores")
.findOne(query,function (err, result) {
if (err) throw err;
res.json(result);
});
});
Result: After typing browser url http://localhost:5000/enterprise returns the expected value:
{"_id":"637e4397f6723844191aa03d","name":"Tesla","category":"Automotive","contact":{"state":{"name":"Texas","city":"Austin","address":{"streetName":"Tesla Road","number":"1"}}}}
This a Retriever Data Function that returns the data object:
function GetEnterprise() {
const [store, setStore] = useState({
})
useEffect(() => {
async function fetchData() {
const response = await fetch(`http://localhost:5000/enterprise`);
if (!response.ok) {
const message = `An error has occurred: ${response.statusText}`;
window.alert(message);
return;
}
const record = await response.json();
if (!record) {
// window.alert(`Record with id ${id} not found`);
window.alert(`Record with id not found`);
return;
}
setStore(record);
}
fetchData();
return;
}, [1]);
//debugging
console.log('tesla: ' + store);
window.store = store;
let res_json = JSON.stringify(store);
console.log('res_json :' + res_json);
return store;
}
Result:
Before GetEnterprise() function returns store I have added these 4 lines of code for debugging:
console.log('tesla: ' + store);
window.store = store;
let res_json = JSON.stringify(store);
console.log('res_json :' + res_json);
1st line logs [object Object] which is not that informative for what I am getting back as a response.
So I came up with 2nd line which enables to debug directly from the browser console.
After I type store my console logs:
{_id: '637e4397f6723844191aa03d', name: 'Tesla', category: 'Automotive', contact: {…}}
So my contact object is missing(undefined).
Now fun fact is the 3rd and 4rd lines :
let res_json = JSON.stringify(store);
console.log('res_json :' + res_json);
My console logs the whole object as expected:
{"_id":"637e4397f6723844191aa03d","name":"Tesla","category":"Automotive","contact":{"state":{"name":"Texas","city":"Austin","address":{"streetName":"Tesla Road","number":"1"}}}}
Which is really weird.
I guess it has something to do with the async and await functions. But I am not sure.
What am I doing wrong?
Any suggestions ..?

Maching ids doesn't return true when compared

I'm trying to make some comprobations on my API (Node.js + Mongodb)
I want to check if the proposerId is equal to the eventOrganizer. To do so
I'm sending this on the body:
{
"participantId": "6238a608170aff10d16ccd89",
"proposerId": "62385d8caee17d13a1762b39", // this guy id is also an organizer
"gender": "female",
"groupId": "623aea21fcfad83bcf8d5bc4"
}
in my PATCH controller to add a user I have this verification:
exports.addParticipantToEvent = async (req, res, next) => {
// Group Organizer constants
const eventId = req.params.eventId;
const groupId = req.body.groupId;
const proposerId = req.body.proposerId; // it can be an admin adding someone to the participants list
// Participant constants
const participantId = req.body.participantId;
const gender = req.body.gender;
// EVENT
// Does the event even exist?
const eventData = await Event.findById(eventId);
if (!eventData) {
return res.status(406).json({
code: 'EVENT_DOESNT_EXIST',
message: 'The event is not valid.',
});
}
console.log(eventData);
// What kind of users can participate in this event?
const allowedParticipants = eventData.allowedParticipants;
// whos the event organizer?
const eventOrganizer = eventData.organizer._id;
console.log('Organizer: ' + eventOrganizer);
console.log('Proposer: ' + proposerId);
console.log('Result: ' + proposerId === eventOrganizer);
try {
return res.status(200).json({
message: 'The participant can be added',
participantId: participantId,
gender: gender,
allowedParticipants: allowedParticipants,
});
} catch (err) {
return res.status(400).json({ message: err });
}
};
I want to verify is the proposerId is an admin or an organizer of the event, so I console.log the eventData entirely and later I console log all the constants I want to verify and the result, it gives me false all the time.
Maybe I need to specify better something?
{
location: { province: 'Barcelona' },
_id: new ObjectId("634ffee75990124926431e6f"),
title: 'Test open close 14',
sport: new ObjectId("622ce6ca672c3d4447676705"),
group: new ObjectId("623aea21fcfad83bcf8d5bc4"),
organizer: new ObjectId("62385d8caee17d13a1762b39"),
participants: [ new ObjectId("62385d8caee17d13a1762b39") ],
replacements: [],
invitations: [],
when: 2022-10-09T13:43:02.999Z,
open: true,
costPerParticipant: 4.4,
skill: 'novice',
allowedGender: 'female',
minParticipants: 2,
maxParticipants: 5,
visible: false,
externalLink: 'https://www.komoot.es/tour/731122050?ref=wta',
allowInvitations: true,
allowReplacements: false,
allowedParticipants: 'only-members',
createdAt: 2022-10-19T13:43:03.006Z,
updatedAt: 2022-10-19T13:43:03.006Z,
__v: 0
}
Organizer: 62385d8caee17d13a1762b39
Proposer: 62385d8caee17d13a1762b39
false
As you can see, both Organizer and proposer are same id, yet I get false.
After lurking some more, I have found that to validate mongos object ids with strings I need to use equals(). So now I have the solution.

How to add an object to an array of objects in Nodejs?

I'm creating a backend for my React web application and I'm trying to subscribe a user to a match, this match is an object that have an array called "players" and when I click on the join button the username and profilePicture of the user are being dispatched to my backend. The first user info is sent perfectly but when a second user is subscribed the info of the first one is replaced for the second one.
This is my function that push the data:
const playerJoined = async (req, res) => {
const torneoId = req.params.id;
const uid = req.uid;
const profilePicture = req.profilePicture;
const username = req.username;
console.log(req.params);
try {
const torneo = await Torneo.findById(torneoId);
if (!torneo) {
return res.status(404).json({
ok: false,
msg: "Torneo no existe por ese ID",
});
}
const newPlayer = {
profilePicture: profilePicture,
username: username,
};
const nuevoTorneo = {
...req.body,
players: newPlayer,
};
const torneoActualizado = await Torneo.findByIdAndUpdate(
torneoId,
nuevoTorneo,
{
new: true,
}
);
res.json({
ok: true,
torneo: torneoActualizado,
});
} catch (error) {
console.log(error);
res.status(500).json({
ok: false,
msg: "Hable con el administrador",
});
}
};
My frontend is working well because when I added more users the array of objects shows all the players like this:
players: (2) [{…}, {…}]
But on my mongo DB shows only the last user info added like I mentioned before.
I really appreciate any help.
You seem to be replacing the players property instead of pushing into it.
const nuevoTorneo = {
...req.body,
players: newPlayer,
};
When you grab the torneo by id, you should have access to that players property already, so spread that array into your nuevoTorneo as well:
const nuevoTorneo = {
...req.body,
players: [...torneo.players, newPlayer],
};
It is because you always put your newPlayer into the "player" field of your nuevoTorneo and updated the same document. I assume you are using mongoose, You probably should just modify the "torneo" after your query and do something like this:
const torneo = await Torneo.findById(torneoId);
const newPlayer = {
profilePicture: profilePicture,
username: username,
};
torneo.nuevoTorneo.players.push(newPlayer);
await torneo.save();
Or to simply modify your code as:
const nuevoTorneo = {
...req.body,
players: [...torneo.nuevoTorneo.players,newPlayer],
};
I recommend the first method, let me know if you have any questions.

Writing to MongoDB fails silently during Neo4j session.run() but works fine normally

The problem is that everything works fine in isolation, but as soon as I combine the Log.create(obj) into the Neo4j result stream, it stops working and what I assume is some Promise behaviour is eating all log information so I can't figure out why exactly it's not working or how to force it to display meaningful information.
I have been trying to diagnose this for the past 2 days, but I can't figure out why.
I have 2 files:
example.js and E1Logger/index.js
The logger file is simply the schema and models for a method that writes an object to MongoDB. It works fine if I comment out the bottom half of example.js.
I've tried probably like 20 different combinations of chaining promises, catching, done, exec, making it more asynchronous, making it more synchronous, and I can't seem to get any meaningful information.
I'm dying to know what is required to make it work.
example.js
//var config = require('./config');
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/major', error => { if (error) { console.error('ERROR: ' + error) }});
//mongoose.Promise = global.Promise;
var neo4j = require('neo4j-driver').v1;
var config = {};
config.neo4jHost = 'bolt://localhost:7687';
config.neo4jUser = 'neo4j';
config.neo4jPassword = 'garbagepassword';
var driver = neo4j.driver(config.neo4jHost, neo4j.auth.basic(config.neo4jUser, config.neo4jPassword));
var E1Logger = require('./E1Logger');
let newInfoLog = {
logType: 'INFO',
eventType: 'Purge Stale Invite',
result: 'Success',
invitedByUser: {
neo4jNodeID: 123,
name: 123 + ' ' + 321,
email: 123
},
purgedUser: {
neo4jNodeID: 123,
email: 123
},
createdAt: 123,
expirationAt: 123
};
let newErrorLog = {
logType: 'ERROR',
eventType: 'Purge Stale Invite',
result: 'Fail',
reason: 123,
attemptedQuery: 123,
};
E1Logger.info(newInfoLog);
E1Logger.error(newErrorLog);
// Calculate cutoff time for expired invites and form the Cypher Query
var currentTime = new Date().getTime();
var sliceTime = currentTime - 604800000; // 604800000 milliseconds in one week
var cypherQuery = 'MATCH (e:Person)-[r:INVITED_TO_APP]->(x) WHERE r.expirationAt<=\'' + sliceTime + '\' AND r.status=\'pending\' RETURN id(e) as invitedByUserId, e.given_name as invitedByUserFirstName, e.family_name as invitedByUserLastName, e.email as invitedByUserEmail, r.createdAt as createdAt, r.expirationAt as expirationAt, id(x) as purgedUserId, x.email as purgedUserEmail';
// Execute Purge Event
var session = driver.session();
session
.run(cypherQuery)
.then(function(result){
result.records.forEach(function(record) {
// Generate log for each expired invite
let newInfoLog = {
logType: 'INFO',
eventType: 'Purge Stale Invite',
result: 'Success',
invitedByUser: {
neo4jNodeID: record.get('invitedByUserId').low,
name: record.get('invitedByUserFirstName') + ' ' + record.get('invitedByUserLastName'),
email: record.get('invitedByUserEmail')
},
purgedUser: {
neo4jNodeID: record.get('purgedUserId').low,
email: record.get('purgedUserEmail')
},
createdAt: record.get('createdAt'),
expirationAt: record.get('expirationAt')
};
// Log result
console.log('PURGED: ' + JSON.stringify(newInfoLog));
E1Logger.info(newInfoLog);
});
session.close();
driver.close();
})
.catch(function(error) {
// Generate log for failed purge
let newErrorLog = {
logType: 'ERROR',
eventType: 'Purge Stale Invite',
result: 'Fail',
reason: error,
attemptedQuery: cypherQuery,
};
// Log result
console.log('ERROR: ' + JSON.stringify(newErrorLog));
E1Logger.error(newErrorLog);
//session.close();
//driver.close();
});
mongoose.disconnect();
E1Logger/index.js
const mongoose = require('mongoose');
// Define Info Log Schema
const InfoLogModel = mongoose.model('Infolog', new mongoose.Schema({
logType: String,
loggedAt: { type: Number, default: new Date().getTime() },
eventType: String,
result: String,
invitedByUser: {
neo4jNodeID: Number,
name: String,
email: String
},
purgedUser: {
neo4jNodeID: Number,
email: String
},
createdAt: Number,
expirationAt: Number
}));
// Define Error Log Schema
const ErrorLogModel = mongoose.model('Errorlog', new mongoose.Schema({
logType: String,
loggedAt: { type: Number, default: new Date().getTime() },
eventType: String,
result: String,
reason: String,
attemptedQuery: String,
}));
module.exports = {
// Define Info Log Model
info: function(eventData) {
InfoLogModel.create(eventData, (error, addedEvent) => {
if (error) throw error;
console.log('INFO: ' + addedEvent);
});
},
// Define Error Log Model
error: function(eventData) {
ErrorLogModel.create(eventData, (error, addedEvent) => {
if (error) throw error;
console.log('ERROR: ' + addedEvent);
});
}
};
I suspect the problem is at ErrorLogModel.create(eventData). I've never been able to get it to write to MongoDB from inside session.run(). A had a couple combinations that were showing something about a promise rejection, but that's as close as I got. I recall something like ErrorLogModel.create(eventData).catch( err => console.log('ok') ); made it do that.
Am I missing something about promises here? Why does functional code working code through Neo4j session.run().then() cause it to stop working? Is it maybe a bug I should report to Mongoose or Neo4j?

Node.JS cradle and couchDB assistance

I am a noob with Node.JS.
I am using CouchDB and Cradle.
In couchDB I have a database named 'test' and inside it I have a document named 'exercise'.
The document has 2 fields: "FullName" and "Age".
The code in order to save the data is as follows:
var cradle = require('cradle');
var connection = new(cradle.Connection)('http://127.0.0.1', 5984, {
auth: { username: 'toto_finish', password: 'password' }
});
var db = connection.database('test');
db.save('exercise', {
FullName: param_name, Age: param_age
}, function (err, res) {
if (err) {
// Handle error
response += ' SAVE ERROR: Could not save record!!\n';
} else {
// Handle success
response += ' SUCESSFUL SAVE: The record was saved in CouchDB!\n';
}
http_res.end(response);
});
this code works well and it saves the data to the CouchDB.
My problem is when I want to read the data.
The code that I wrote is:
var cradle = require('cradle');
var connection = new(cradle.Connection)('http://127.0.0.1', 5984, {
auth: { username: 'toto_finish', password: 'password' }
});
var db = connection.database('test');
db.view('exercise/all', {descending: true}, function(err, res)
{
console.log(res);
res.forEach(function (row) {
response = 'FullName: ' + row.FullName + '\n Age: ' + row.Age + '\n';
});
});
http_res.end(response);
when I am trying to print response, response is empty and I don't know what I am doing wrong. I know that it does not go inside the forEach loop but I don't understand why.
the console output is:
[ { id: 'exercise',
key: null,
value:
{ _id: 'exercise',
_rev: '1-7042e6f49a3156d2099e8ccb3cc7d937',
FullName: 'Toto Finish',
Age: '30' } } ]
Thanks in advance for any response or answer.
Try moving the http_res.send() call inside the callback provided to db.view - the anonymous function( err, res ) { }.
I'm not sure however about the .forEach statement, you'll only get the last value from your query in the response variable, you should look into that as well.
spotirca is right
The db.view function is async so http_res.end(response) gets called before the view returns any data.
You can prove this by returning the date in both the console.log and http_res.end
console.log(res, new Date())
and
http_res.end(response, new Date());
The http response will have the earlier date/Time.

Resources