I have an AWS Cognito user pool that is a replacement for an old one that I had to delete because of a custom attribute issue. I am using the same exact code as before though the keys have changed. I have them in a JSON file that I pulled from the AWS URL for getting the keys. I am getting an error now about invalid signature when trying to validate a JWT. I know my code is solid since it hasn't changed but was looking to see from others if there is something else I am missing or should do other than update my pool id, client id, and keys.json file.
Edit 2
I have resolved the issue by deleting and recreating the user pool - I use Terraform so it is quick and easy but also repeatable so this is the exact same config as before but now working
Edit adding my code just incase there is an issue with it though I can't see why if nothing changed
exports.isJWTValid = () => (req, res, next) => {
let idToken = req.headers.authorization
let token = idToken.split(' ')[1]
let header = jwt_decode(token, { header: true });
let keys = keysJSON.keys
let kid = header.kid
let jwk = keys.find(r => r.kid === kid)
let pem = jwkToPem(jwk);
jwt.verify(token, pem, { algorithms: ['RS256'] }, function(err, decodedToken) {
if(err) { // error is showing up in this if(err) and returning to postman
logger.debug(err)
return res.status(401).json({success: false, err})
}
const currentSeconds = Math.floor((new Date()).valueOf() / 1000)
if (currentSeconds >= decodedToken.exp || currentSeconds < decodedToken.auth_time ) {
let message = 'Session has expired, please login again.'
return res.status(401).json({success: false, message});
}
if(decodedToken.aud !== config.ClientId) {
let message = 'Token doen\'t match app client'
return res.status(401).json({success: false, message});
}
if(decodedToken.iss !== `https://cognito-idp.us-east-1.amazonaws.com/${config.UserPoolId}`) {
let message = 'Token doen\'t match user pool'
return res.status(401).json({success: false, message});
}
if(decodedToken.token_use !== 'id' && decodedToken.token_use !== 'access') {
let message = 'Token use case doen\'t match'
return res.status(401).json({success: false, message});
}
logger.debug('decodedToken: ', decodedToken)
next()
});
};
I'm trying to filter for dates in a range, but I've gotten so frustrated that I'm now just trying to query for dates that are less than the current time.
I have this query:
q = { 'recorded_timestamp': { '$lt': '2018-09-12T21:02:05.187Z' } };
I've also tried the following queries and none of them work:
q2 = { 'recorded_timestamp': { '$lt': new Date() } };
q3 = { 'recorded_timestamp': { '$lt': new Date(Date.now()) } };
q4 = { 'recorded_timestamp': { '$lt': new Date().toISOString() } };
When I try to do MyModel.find(q), I get nothing back. However, if I copy that query exactly into a MongoDB shell, I'm getting the results that I expect.
const promise = new Promise(resolve => {
const results = MyModel.find(q)
resolve(results);
});
return promise.then(results => {
return results; // results = [], but they shouldn't
});
What's going on here?
Mongoose version: 4.13.14
MongoDB version: 3.4.17
Node version: 8.11.2
Here's a relevant excerpt of the model:
const MySchema = new Schema({
some_ID: {
type: String,
required: true
},
recorded_timestamp: {
type: Date,
required: true
}
}, { timestamps: true });
module.exports = mongoose.model('MyModel', MySchema);
Here's a snippet of the sample data that gets inserted into the collection.
{ "some_ID": "16499", "recorded_timestamp": "2007-03- 13T07:39:52.959057" }
{ "some_ID": "17158", "recorded_timestamp": "2007-09- 12T15:31:18.244142" }
You need to use callback to see the result.
MyModel.find(q, function(err, result) {
if (err) {console.log(err);}
console.log(result);
})
It turns out that the big JSON file that inserts a bunch of sample data was storing the values as strings (which is why q = { 'recorded_timestamp': { '$lt': '2018-09-12T21:02:05.187Z' } } worked when executed in a MongoDB shell.)
I changed the type of 'recorded_timestamp' in my schema to be a string and now it is working.
This thread helped me diagnose my issue: Mongoose Queries on Date Condition Have No Results, MongoDB Shell Works
Sails v12.14 connecting to MongoDB with Waterline
Is there a way to do a find query for all records created within the last 7 days from the current date? I've tried searching for an answer, but I'm guessing I'm not hitting the right keywords to come up with the answer I need.
For example, here's my function:
getOpen: function getOpen(req, res) {
Ticket.find({
status: "open",
open_date: [insert magic here]
}).then(function response(findModelResults) {
res.json(200, findModelResults);
})
.catch(function error(findModelError) {
sails.log.error('TicketController.getOpen', findModelError);
res.json(500, findModelError);
});
}
This works fine for pulling all tickets, but I'm not sure how to filter for only the last 7 days.
I have used momentJS for date formatting. Following code snippet should work.
getOpen: function getOpen(req, res) {
const date = new Date();
Ticket.find({
status: "open",
open_date: {
'>=': moment(new Date(date.getFullYear(), date.getMonth(), date.getDate() - 7))
.utc()
.toISOString();
}
})
.then(function response(findModelResults) {
res.json(200, findModelResults);
})
.catch(function error(findModelError) {
sails.log.error('TicketController.getOpen', findModelError);
res.json(500, findModelError);
});
}
This will retrieve tickets with open_date greater than 24h * 7days (168 hours)
getOpen: function getOpen(req, res) {
var sevenDaysAgo = new Date();
sevenDaysAgo.setTime(new Date().getTime() - (7 * 24 * 3600 * 1000));
Ticket.find({
status: "open",
open_date: {
'>=': sevenDaysAgo
}
})
.then(function response(findModelResults) {
res.json(200, findModelResults);
})
.catch(function error(findModelError) {
sails.log.error('TicketController.getOpen', findModelError);
res.json(500, findModelError);
});
}
Before, my code was working well and returning Long value for timestamp from firestore. Since the release of firestore 1.0, the code is returning [object Object] as the result. Though it saves the timestamp as June 5, 2018 at 10:38:44 AM UTC+3meaning it is not currently saved as a long value in the firestore database. I have tried some possible solutions from last night but not working. Is there any solution?
exports.get_time = functions.https.onRequest((request, response) => {
// if (!request.headers.authorization) {
// console.error('No Firebase ID token was passed');
// response.status(403).send('Unauthorized');
// return;
// }
var fieldValue = require("firebase-admin").firestore.FieldValue;
db.collection('times').doc('servertime').set({servertime: fieldValue.serverTimestamp()}).then((ref) => {
db.collection('times').doc('servertime').get().then((snapshot) => {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(String(snapshot.data()));
response.end();
return null;
}).catch((error) => {
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("Error\n" + error);
response.end();
});
return null;
}).catch((error) => {
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("Error\n" + error);
response.end();
});
});
Your problem may come from the changes that were introduced in Firestore SDK recent release (version 5.0.3 for the JavaScript SDK):
With this release the behavior for Date objects stored in Firestore changed: "timestamps stored in Cloud Firestore are read back as
Firebase Timestamp objects instead of as system Date objects."
You need to "update your code expecting a Date to instead expect a Timestamp", as follows:
// Old:
const date = snapshot.get('created_at'); // <- 'created_at' is an example of field name
// New:
const timestamp = snapshot.get('created_at');
const date = timestamp.toDate();
Also, you should chain your promises a bit differently as well as change the way you send the response. You can watch the following video for more details on how to write an HTTP Function: https://www.youtube.com/watch?v=7IkUgCLr5oA
exports.get_time = functions.https.onRequest((request, response) => {
var fieldValue = require("firebase-admin").firestore.FieldValue;
db.collection('times').doc('servertime').set({servertime: fieldValue.serverTimestamp()})
.then((ref) => {
return db.collection('times').doc('servertime').get();
})
.then((snapshot) => {
response.send(snapshot.data());
// return null; no need to return here since it is an HTTP Function
})
.catch((error) => {
response.status(500).send(error)
});
});
As the title suggests I'm having problems with mongoose save method, which fails but does not produce an error.
I actually know why it fails, which is down to the userId field being marked as required but not being provided... but I don't know why it doesn't throw an error. I've exhausted google and stackoverflow looking at similar suggestions with no luck, so throwing it open to anyone who can help me!
Here's the code...
Model.js
var mongoose = require('mongoose');
var TimeSchema = new mongoose.Schema({
client: String,
matter: String,
activity: String,
tags: String,
description: String,
comments: [String],
startTime: Date,
startTimeUTC: Number,
endTime: Date,
endTimeUTC: Number,
duration: Number,
durationRnd: Number,
durationUnits: Number,
billable: Boolean,
rate: Number,
total: Number,
user: String,
userId: { type: mongoose.Schema.ObjectId, required: true }
}, {safe: true});
mongoose.model("Time", TimeSchema);
Controller.js
exports.addTime = function (req, res) {
console.log('Adding time: ' + JSON.stringify(req.body));
var time = new Time(req.body);
time.save(function (err) {
if (err) { res.send({'error' : err}); }
res.send(time);
});
}
EDIT - To clarify the callback is being called, take the following code for example.
exports.addTime = function (req, res) {
console.log('Adding time: ' + JSON.stringify(req.body));
var time = new Time(req.body);
console.log("time = " + time);
// TODO user
time.save(function (err) {
if (err) { handleError(res, err); }
console.log("ok");
Time.findById(time._id, function (err, found) {
console.log("found = " + found);
});
res.send(time);
});
}
and here's the console output
Adding time: {"description":"test","client":"","matter":"","activity":"","rate":
"","startTime":"2013-11-30T19:58:43.000Z","startTimeUTC":"1385841523000","endTim
e":"2013-11-30T19:58:45.000Z","endTimeUTC":"1385841525000","startLocale":"19:58"
,"startTimeLocale":"19:58:43","endLocale":"19:58","endTimeLocale":"19:58:45"}
time = { description: 'test',
client: '',
matter: '',
activity: '',
rate: null,
startTime: Sat Nov 30 2013 19:58:43 GMT+0000 (GMT Standard Time),
startTimeUTC: 1385841523000,
endTime: Sat Nov 30 2013 19:58:45 GMT+0000 (GMT Standard Time),
endTimeUTC: 1385841525000,
startTimeLocale: '19:58:43',
endTimeLocale: '19:58:45',
_id: 529a43750a366b6419000001,
comments: [] }
ok
POST /api/times 200 14ms - 313b
found = null
It is very possible to run into this error by naively not connecting to the database. Has happened several times to me. Make sure your mongoose.connect() is in place.
Problem solved, thanks to robertkelp.
Here's my revised code in case if ever helps anyone, but it appears the error was being thrown I just wasn't handling it correctly.
exports.addTime = function (req, res) {
console.log('Adding time: ' + JSON.stringify(req.body));
var time = new Time(req.body);
time.save(function (err) {
if (err) {
handleError(res, err);
}
else {
res.send(time);
}
});
}
My Problem was not solved by using findOne, it was solved by defining the fields i updated , in the model schema. so my code was like that:
User.findOne({email:data.userData.email}, function (err, user) {
if (!err && user!=undefined){
console.log(user);
var userDiscounts = user.discounts;
for(var i=0;i<userDiscounts.length;i++){
if (userDiscounts[i]!=undefined && userDiscounts[i].code=="XXXXXX"){
userDiscounts[i].claimed = true;
console.log('discount claimed');
}
}
user.discounts = userDiscounts;
user.fbDiscountClaimed = true;
user.save(function(err) {
if (err) console.log(err);
console.log('Saved Hashve-FB as claimed');
});
}
});
}
}
But the schema of the discount and user model was missing the definition of types of user.discounts so i added the following:
var UserSchema = new Schema({
name: String,
email: { type: String, lowercase: true },
role: {
type: String,
default: 'user'
},
hashedPassword: String,
provider: String,
salt: String,
messages:[],
discounts:[{
"name": String,
"description": String,
"created_at": String,
"updated_at": String,
"code": String,
"claimed": Boolean
}
],
facebook: {},
fbDiscountClaimed:false,
twitter: {},
google: {},
github: {}
});
UserSchema.pre('save',function(next){
var currentDate=new Date();
this.updatedAt=currentDate;
if(!this.createdAt){
this.createdAt=currentDate;
};
next();
});
When I use the .pre('save',fn) to create time, I forgot the next(), causing the data store to fail without error,I hope can help somebody!
For anyone can face a similar issue, I found that when populating a mongoose schema object from a json object that actually owns its “_id” property (even set to “null”), insert fails with no error.
Example:
var json = JSON.parse(req.body.time);
var time = new Time(json);
assuming that json._id is defined, no matter it's declared as a new "Time", when you try to insert with:
time.save(function (error) {
if (error) { res.send({'error' : error}); }
res.send(time);
});
error variabile is null but item was never inserted.
In this case I solved by deleting "_id" property before populating mongoose object so final code as follows:
var json = JSON.parse(req.body.time);
delete json._id;
var time = new Time(json);
time.save(function (error) {
if (error) { res.send({'error' : error}); }
res.send(time);
});
Regards
Angelo
Not directly related to the scenario described in the post, but I was getting the same error.
The issue was that I was not calling next(); at the end of the pre('save') function on the model definition.
For example:
cartSchema.pre('save', function(next) {
const currentDate = new Date();
this.modified = currentDate;
if (this.isNew) {
this.created = currentDate;
this.cartid = uuidv4();
}
next(); // this was missing :'(
});
I had a situation where the save callback was getting called, but the document wasn't changing. I haven't yet tracked down the root cause (some sort of validation thing probably) but the problem had something to do with one of the changes I made. So I just tried the changes one by one until I found the culprit.
(Feel free to edit this answer if you figure out more of this phenomenon)