Modifying values in json responses - node.js

I'm looking to modify a few values in a returning json api response that gets intercepted from the endpoint and passed through a server back to my app.
I can get it to work with changing the user part of the json response but I can't get it to include the resident part of the response
The following code changes user.require_pin and user.enable_logs from true to false. I'm looking to add resident.login_active to false from true in the same response but each time I try, I receive the error : resident: {
^^^^^^^^
SyntaxError: Unexpected identifier
How do I add it? Here is my current code and same json response. Thanks in advance!
let dat = response.data
if(
(req.path === '/sessions' || req.path === '/sessions/')
&& (req.method === 'POST')
) {
dat = {
...dat,
user: {
...dat.user,
require_second_pin: false,
enable_photo_log: false
}
resident: {
...dat.resident,
login_active: false
}
}
}
This is a sample of the server json response
{
"token": "19f2ef14-14d7-4653-907e-1b5243900e96",
"id": "19f2ef14-14d7-4653-907e-1b5243900e96",
"warning": "",
"resident": {
"id": 18016522,
"resident_id": 264668672,
"name": "JOHN DOE",
"login_active": true
},
"user": {
"id": 12727533,
"transfer_photo": false,
"enable_log": true,
"photo_capture_interval": 10,
"no_of_photos": 1,
"require_pin": true
}
}

You are just missing a comma:
let dat = response.data
if(
(req.path === '/sessions' || req.path === '/sessions/')
&& (req.method === 'POST')
) {
dat = {
...dat,
user: {
...dat.user,
require_second_pin: false,
enable_photo_log: false
}, // <-- this comma was missing
resident: {
...dat.resident,
login_active: false
}
}
}

Related

writefilesync not writing all variables to a json file

I have this code:
circular = () => { //fix circular stuff for json.stringify
seen = new WeakSet();
return (key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
var gameon = 1;
var fighter1 = {"userid":"97","username":"john","items":{},"ailments":{}};
var fighter2 = {"userid":"91","username":"james","items":{},"ailments":{}};
var resume = 30;
all = {gameon:gameon,fighter1:fighter1,fighter2:fighter2,resume:resume,inturn:fighter1,outturn:fighter2};
fs.writeFileSync(file,JSON.stringify(all,circular()),{encoding:'utf8',flag:'w'});
I expect to have the next output written to file:
{
"gameon":1,
"fighter1":{
"userid":"97",
"username":"john",
"items": {},
"ailments":{}
},
"fighter2":{
"userid":"91",
"username":"james",
"items":{},
"ailments":{}
},
"resume":"",
"inturn":{
"userid":"97",
"username":"john",
"items":{},
"ailments":{}
},
"outturn":{
"userid":"91",
"username":"james",
"items":{},
"ailments":{}
}
but this is what I get instead:
{
"gameon":1,
"fighter1":{
"userid":"97",
"username":"john",
"items":{},
"ailments":{}
},
"fighter2":{
"userid":"91",
"username":"james",
"items":{},
"ailments":{}
},
"resume":""
}
Please notice how the string truncates after "resume" like it couldn't read the variables fighter1 and fighter2 despite it could do it for the first iteration.
Why is that?
Thank you.

Azure Function disabled setting "user" field to HTTP request object on the 26th of April 2022

(!) Issue cannot be reproduced locally.
Azure Function Version ~4
Node Version 14.18.1
Creating a simple HTTP triggered Azure Function and setting just two simple properties we get the following code:
module.exports = async function (context, req) {
req.auth = {authField: 'some value'}
req.user = {userField: 'some value'}
context.log(`${JSON.stringify(req,null,2)}`);
context.res = {
body: 'responseMessage'
};
}
The logger prints the following object:
{
"method": "POST",
"url": "xxx",
"originalUrl": "xxx",
"headers": {
/// ...
},
"query": {},
"params": {},
"body": { "name": "Azure" },
"rawBody": "{\"name\":\"Azure\"}",
"auth": { "authField": "some value" }
}
As you see only auth is set and not user.
The same failing behavior can be seen in version 4.2.0.
When I test with Azure Function ~3 the output looks like this:
{
"method": "POST",
"url": "xxx",
"originalUrl": "xxx",
"headers": {
// ...
},
"query": {},
"params": {},
"body": { "name": "Azure" },
"rawBody": "{\"name\":\"Azure\"}",
"auth": { "authField": "some value" },
"user": { "userField": "some value" }
}
As you see the field is set.
The following custom v4 4.1.0-17156 also sets the user field.
The field user was used by us through the express-jwt (v6.1.0) which is using it when no value is provided for requestProperty.
I could not yet reproduce it but in out transpiled from Typescript project, we get the following runtime error:
FailureException: Cannot set property user of [object Object] which has only a getterStack: TypeError: Cannot set property user of [object Object] which has only a getterat Object.run
The issue started at the beginning of the day of 26th of April 2022.
Questions:
what is the reason?
is a quick roll back to the functioning Azure Function custom version possible?
I found the culprit in this PR, which was added for Azure Function runtime v4.2.0.
The user field was added with only a getter.
We took the code and made the minimal example:
class Request {
#cachedUser?: string | null;
constructor() {
}
get user(): string | null {
if (this.#cachedUser === undefined) {
this.#cachedUser = "some value";
}
return this.#cachedUser;
}
}
and got the following transpilied version:
var __classPrivateFieldGet =
(this && this.__classPrivateFieldGet) ||
function (receiver, state, kind, f) {
if (kind === 'a' && !f) throw new TypeError('Private accessor was defined without a getter')
if (typeof state === 'function' ? receiver !== state || !f : !state.has(receiver))
throw new TypeError('Cannot read private member from an object whose class did not declare it')
return kind === 'm' ? f : kind === 'a' ? f.call(receiver) : f ? f.value : state.get(receiver)
}
var __classPrivateFieldSet =
(this && this.__classPrivateFieldSet) ||
function (receiver, state, value, kind, f) {
if (kind === 'm') throw new TypeError('Private method is not writable')
if (kind === 'a' && !f) throw new TypeError('Private accessor was defined without a setter')
if (typeof state === 'function' ? receiver !== state || !f : !state.has(receiver))
throw new TypeError('Cannot write private member to an object whose class did not declare it')
return kind === 'a' ? f.call(receiver, value) : f ? (f.value = value) : state.set(receiver, value), value
}
var _Request_cachedUser
class Request {
constructor() {
_Request_cachedUser.set(this, void 0)
}
get user() {
if (__classPrivateFieldGet(this, _Request_cachedUser, 'f') === undefined) {
__classPrivateFieldSet(this, _Request_cachedUser, 'some value', 'f')
}
return __classPrivateFieldGet(this, _Request_cachedUser, 'f')
}
}
_Request_cachedUser = new WeakMap()
// this section is added for testing
const request = new Request()
request.user = 'new value'
console.log(JSON.stringify(request.user))
So, it always returns the the initial value, which in our example is "some value" but in the original code is simply undefined and does not allow to set it.

Why is displayStart (Datatable 1.10) not working for me?

I am using Datable (1.10.3) and whatever value I set in the diplayStart field, the start parameter of the server request always goes as 0.
Here is my code:
this.table = $('#table').DataTable({
displayStart: 100,
order: [[0, 'desc']],
processing: true,
serverSide: true,
searching: true,
pageLength: 50,
searchDelay: 1000,
language: {
lengthMenu: 'Show _MENU_ records per page'
},
dom: '<"top"il>rt<"bottom"p><"clear">',
ajax: {
url: <url>,
type: 'POST',
headers: {
authorization: <token>
},
data: function (d) {
//setting request data
},
dataSrc: (json) =>{
return json.data;
},
error: function (xhr, error, thrown) {
if (xhr.status + '' === '401') {
location.href = '/';
}
}
},
columns: this.getColumns(),
drawCallback: function () {
//some operations
}
});
It seems to work fine if I initialise the table like the older version, like this:
this.table = $('#table').dataTable({...
But this initialisation breaks other preexisting function calls (like search and row) in the code.
Can anyone suggest where I am going wrong and how can I fix this?
I am not sure if displayStart works with server side.
I realize this is not an ideal solution if you dont find any other you can override the pipeline method forcing it to use whatever you want:
$.fn.dataTable.pipeline = function ( opts ) {
return function ( request, drawCallback, settings ) {
request.start = 20;
return $.ajax( {
"type": opts.method,
"url": opts.url,
"data": request,
"dataType": "json",
"success": drawCallback
} );
}
};
Taken the example from: https://datatables.net/examples/server_side/pipeline.html

Conflict in _local

Occasionally I am getting something along the lines of:
http://myhosted.couchdb.com:5984/userdb-6938/_local/H73d9PBjwCczSUMy4NZ6bA%3D%3D
409 (Conflict)
The header response is: {"error":"conflict","reason":"Document update conflict."}
The request payload is:
{
"_id": "_local/f.kaEuoL4i41KgUTkCHAyg==",
"_rev": "0-10",
"session_id": "735AF8E9-BF62-191F-9A63-760C922E1259",
"history": [{
"last_seq": 77,
"session_id": "735AF8E9-BF62-191F-9A63-760C922E1259"
},
{
"last_seq": 67,
"session_id": "908B46C9-06C4-A60D-9189-CCE33ECEB252"
},
{
"last_seq": 59,
"session_id": "7B7A1737-D6AB-23F2-B3C3-954DFAC3F91A"
},
{
"last_seq": 52,
"session_id": "A7B639E5-CCEF-E1DE-91B2-8E27AB4AFB5B"
},
{
"last_seq": 45,
"session_id": "D8A322C2-5421-D493-91FB-DD85258D2194"
}],
"replicator": "pouchdb",
"version": 1,
"last_seq": 77
}
This is happening when performing some actions using pouchDb i.e This code will sometimes trigger it:
try {
await db.bulkDocs(toBeSaved)
} catch (err) {
errorCallback(err, importObj)
}
I understand local docs are docs that don't get replicated but do I need to worry about the error message that shows? The docs do explain about handling conflicts but this appears to be one I can't do anything about. Also, as this is a bulk operation, which document exactly is causing the conflict?
EDIT
My getLocalDb call (which sorts the connection to pouch / couch):
getLocalDb: function (onSyncCompleteDispatch) {
var localDb = new PouchDb(this.databaseName, {auto_compaction: true})
var liveDb = this.getLiveDb()
var self = this
// Only send a db object once it has sync'd with the remote host.
return new Promise(function (resolve, reject) {
resolve(localDb)
// We're not using continuous sync because the loading bars on the app will go wild
// We don't need to get data without users clicking anything at this point.
localDb.sync(liveDb, {
live: false,
retry: false
}).on('complete', function (info) {
var requiresReload = info.pull.docs_written > 0 || info.pull.docs_read > 0 || info.push.docs_written > 0 || info.push.docs_read > 0
if (requiresReload) {
typeof self.onSyncCompleteCallback === 'function' && self.onSyncCompleteCallback(info)
}
}).on('error', function (err) {
if (err.message === 'getCheckpoint rejected with ') {
// Don't need to resolve anything here as we resolved it above and nothing will have
// changed as no connection is available.
console.log('No live connection available, return local (without sync).')
} else {
typeof self.onSyncErrorCallback === 'function' && self.onSyncErrorCallback(err)
reject(err)
}
})
})
}

Firebase Flashlight (ElasticSearch) filtering, sorting, pagination

I am using Flashlight Firebase plugin
I am using this example and it's working fine
In the example you can see example.js file have method for query as below
// display search results
function doSearch(index, type, query) {
var ref = database.ref().child(PATH);
var key = ref.child('request').push( { index: index, type: type, query: query } ).key;
ref.child('response/'+key).on('value', showResults);
}
above function returning me the results when I pass values like following JSON
{ index: index, type: type, query: query }
It returning me nothing when i am trying to pass values like following JSON
{ index: index, type: type, query: { "from" : 1, "size" : 5 , "query": query }
but the following ElasticSearch API returning me the result
http://localhost:9200/firebase/user/_search?q=*mani*&pretty&size=5&from=1
and How do i filtering the query using Flashlight like following
{
"query": {
"filtered": {
"query": {
"query_string": {
"query": "drama"
}
},
"filter": {
//Filter to apply to the query
}
}
}
}
I am using following security rules
{
"rules": {
".read": false,
".write": false,
"search": {
"request": {
"$recid": {
// I can only read records assigned to me
".read": "auth.id === data.child('id').val() || auth.uid === data.child('id').val()",
// I can only write new records that don't exist yet
".write": "!data.exists() && (newData.child('id').val() === auth.id || newData.child('id').val() === auth.uid)",
".validate": "newData.hasChildren(['query', 'index', 'type'])",
"index": {
// accepts arrays or strings
".validate": "(newData.isString() && newData.val().length < 1000) || newData.hasChildren()",
"$child": {
".validate": "newData.isString() && newData.val().length < 1000"
}
},
"type": {
// accepts arrays or strings
".validate": "(newData.isString() && newData.val().length < 1000) || newData.hasChildren()",
"$child": {
".validate": "newData.isString() && newData.val().length < 1000"
}
},
"query": {
// structure of the query object is pretty open-ended
".validate": "newData.isString() || newData.hasChildren()"
},
"$other": {
".validate": false
}
}
},
"response": {
"$recid": {
// I can only read/write records assigned to me
".read": "auth.id === data.child('id').val() || auth.uid === data.child('id').val()",
".write": "auth.id === data.child('id').val() || auth.uid === data.child('id').val()",
// Assumes that Flashlight will be writing the records using a secret or a token that has admin: true
// The only thing a logged in user needs to do is delete results after reading them
".validate": false
}
}
}
}
}
Please let me know how to perform complex queries and filtering with Flashlight
Finally I did it myself
here is the solution
You need to update SearchQueue.js
_process: function (snap) {
var dat = snap.val();
var key = snap.key;
if (this._assertValidSearch(key, dat)) {
// get your query string
var q = dat.query.query;
console.log('search', "test", JSON.stringify(dat, null, 2));
// build your ES query
//var q1 = {"query":{"match":{"_all":q}}};
// Perform (a very simple) ElasticSearch query
this.esc.search({
index: dat.index,
type: dat.type,
// add options
from : dat.query.from,
size : dat.query.size,
// add ES Query
//body : q1
q:dat.query.query
}, function (error, response) {
if (error) {
this._reply(key, {error: error, total: 0});
} else {
this._reply(key, response);
}
}.bind(this));
}
}
and update Example.js
// display search results
function doSearch(index, type, query) {
var ref = database.ref().child(PATH);
var jsonOBJ = {
index: index,
type: type,
query: { size:1, from:0, query:query},
};
var key = ref.child('request').push(jsonOBJ).key;
console.log('search', key, JSON.stringify(jsonOBJ, null, 2));
ref.child('response/'+key).on('value', showResults);
}

Resources