I have an Object array named users.
The object format in this array looks like this:
var userExample = {pub:{name:'John', id:'100'}, priv:{location:'NYC', phone:'000000'}};
As a restful service, clients may request information of all users.
And obviously I just want to send public information to them.
So I want to serialize my data selectively by keys(priv key will be ignored)
Here is my code snippet:
var users = [];
function censor(key, value) {
if (key == priv) {
return undefined;
}
return value;
}
app.get('/listUsers', function(req, res){
res.end(JSON.stringify(users, censor));
});
When I run these code, an error occurred:
ReferenceError: priv is not defined
I'm a Javascript beginner, please help.
Change priv to "priv".
But your approach is dangerous. In similar conditions I usually create a new object to export and I explicitly copy the properties which should be exported, this way there's no risk of leak on future data structure changes. A white list is always more future proof than a black list.
Newer versions of JSON.stringify() have a replacer array
E.g.
```
JSON.stringify(foo, ['week', 'month']);
// '{"week":45,"month":7}', only keep "week" and "month" properties
```
Try with:
if (key == "priv")
This should work.
Related
said simply:
I am trying to create a protective barrier around a JavaScript Object, using a Proxy to set 'traps' for any form of retrieval or manipulation. These traps will require the SessionKey parameter to be provided with any such Object manipulations or else default into clearing out -all- information and properties of the Object.
(This SessionKey is of course the one provided by the User Sign-in PHP which is sent back upon successful sign-in.)
If I have this right, and I'm not the most veteran coder here certainly, the Object will only call functions with the corresponding SessionKey parameter being provided - as this Object knows the SessionKey.
I cannot be 100% to thwart any or all such efforts to get into my code, but perhaps I can set up a 'trip' alarm that makes all such efforts unsuccessful. No SessionKey? NO DOM (.empty()), no WebServices/API. Nothing.
Thank you for your help, I appreciate it immensely.
What you are wanting can't really be done. You CAN create a proxy to trap retrieval/manipulation calls but you can't make the underlying object private in any way.
For example, if you have object
const privateObj = { name: 'John Smith', ssn: '123-45-6789' };
and proxy
const proxy = new Proxy(privateObj, {} /* handler for getter/setter traps */);
you can console log the proxy to get something like this:
[[Handler]]: Object
[[Target]]: Object
[[IsRevoked]]: false
and you can expand [[Target]] to see the properties of the underlying object. So if you want this property to be fully private you won't want to use proxies. Furthermore, if the user can inspect the proxy, they can easily get access to the underlying object and mutate it outside of the proxy traps.
If you want to be able to really protect that object, it would be better to protect it in a function closure and have getter/setter wrappers around that object.
You could try as a first step:
const protectObject = (SessionKey, ...objectProps) => {
const protectedObject = { // Do something here to create the object
...objectProps // and its properties you want to protect
};
return {
accessProp(_SessionKey, prop) {
if (_SessionKey !== SessionKey) throw Error("Your session key doesn't match");
return protectedObject[prop];
},
setProp(_SessionKey, prop, val) {
if (_SessionKey !== SessionKey) throw Error("Your session key doesn't match");
protectedObject[prop] = val;
}
};
};
So now you have a private object that is protected:
const privateObj = protectObject('12345', 'John Smith', '7/20/1992', '123-45-6789');
privateObj.accessProp('12345', 1); // '7/20/1992'
privateObj.accessProp('1234', 2); // Uncaught Error: Your session key doesn't match
privateObj.setProp('12345', 1, '7/21/1993');
privateObj.accessProp('12345', 1); // '7/21/1993'
I'm relatively new to JS and i have come across this scenario, where i need to identify if a method defined in a JS object follows a particular interface.
Let me explain with the help of an example:
let logger1 = {
log: function(message, meta){
//logging functionality
}
};
let logger2 = {
log: function(level, message, meta){
//logging functionality
}
}
There are 2 logger objects (logger1 or logger2), which has its own logging functionalities. They can get passed from the client to a library, that the client consumes. Library expects the log method to be of a particular interface, which is already mentioned in the library documentation. Inside the library, how would we verify if the logger object passed in has the 'log' method that matches the interface, the library is expecting ?
let Library = function(logger){
//Here I can verify if the 'log' function is defined. But how do i make sure the log
//function matches the interface that the library is expecting ?
//Let's say the interface that the library is expecting is function(level,message,meta),
//which is satisfied only by logger2.
if(logger && typeof(logger.log) === 'function'){
this.logger = logger;
}
else{
this.logger = console;
}
}
let lib1 = new Library(logger1);
let lib2 = new Library(logger2);
You cannot really. A Javascript function can omit parameters that it doesn't use, so the function may have fewer parameters and still be compatible. The function may define more parameters which will become undefined if not passed, and hence still be compatible. It may internally use arguments and hence not define any parameters, and still be compatible. It may name any of its parameters any way it wants, and still be compatible, so even inspecting the parameter names won't help you at all.
The only thing you can do it use something like Typescript and add compile-time checks.
Hmm, tricky one.
We would just determine the interface first and then the implementation. In this case we would code logger1 to have the signature: ( message, meta ) and logger2 ( message, meta, level ) .
That way we can call either function with eg. ( 'test', 'extra', 1 ) and logger1 will just ignore the level argument.
If you work with a system that has to juggle alot of different argumented versions, it might be better to just use an object as the only argument every time: function( config ) and just add extra properties when needed.
That way you can also force the interface to stay the same while also being extendable in some way.
There is a property length property for function which gives number of arguments it holds
Example:
let logger1 = {
log: function(message, meta){
//logging functionality
}
};
console.log(logger1.log.length); // 2
let logger2 = {
log: function(level, message, meta){
//logging functionality
}
}
console.log(logger2.log.length); // 3
I am returning a Mongoose document and wish to add some meta data to it before I send it off. I am however unable to add any properties and I am not sure why. I have checked that it is extensible with Object.isExtensible(doc) and it is.
Item.findById(req.params.id).exec(function(err, doc) {
doc.blah = 'hello';
console.log(doc); // No trace of 'blah'. I can change/delete existing props however
})
What could be issue?
Ah.. My object is a Mongoose document which doesn't allow adding properties. The solution is to either convert the returned document to a plain object or to call lean() in the query.
Item.findById(req.params.id).exec(function(err, doc) {
var obj = doc.toObject();
...
});
Item.findById(req.params.id).lean().exec(function(err, doc) {
...
});
I'm doing something like this:
document.properties["my:customProperty"] = getSomehowTheProperty(document);
my:customProperty is a string, which has some allowed values in the content model.
How can I get the allowed values from the content model, so that I don't have to store them in a JavaScript array inside the script?
Or how else can I check, that the function getSomehowTheProperty returned an allowed value?
I tried to wrap it with try-catch:
try {
document.properties["my:customProperty"] = getSomehowTheProperty(document);
document.save();
} catch (e) {
document.properties["my:customProperty"] = "Default Value";
document.save();
}
But it looks like integrity is checked and th error is thrown at the end of executing the script, not inside the try block.
Googling "alfresco js allowed values of node properties" and similar queries gives me nothing.
In order to get that sort of information, you'll have to use the DictionaryService to get the PropertyDefinition
Off the top of my head, you'll want to do something like:
QName customPropertyQ = QName.createQName("my:customProperty", namespaceService);
PropertyDefinition customPropertyT = dictionaryService.getProperty(customPropertyQ);
List allowedValues = customPropertyT.getConstraints();
That'd be in Java, see this blog post for details on how to work with the DictionaryService from JavaScript
Store and retrieve Google Dart objects in JavaScript library containers
In a Dart application I am using an external JavaScript library to do various matrix calculations.
The specific functionality of the library is not important, what it's important is that I need to store and retrieve Dart object that I put in the matrix.
Dart Class - Lets image i have a dart object that which has a parameter called name
MyDartClass mydc = new MyDartClass(something, something);
mydc.name;
// Everything works as planned
Storing
matrix = js.context.matrix
matrix.cell(1,1).store("thing", new MyDartClass(something, something));
Retrieving
matrix.cell(1,1).has_object_of_type("thing");
// true
MyDartClass mydc = matrix.cell(1,1).retrieve("thing");
Do something with the object
mydc.name;
// Exception: The null object does not have a getter 'name'.
// NoSuchMethodError : method not found: 'name'
// Receiver: null
// Arguments: []
Does the library really work?
Yes it does. I have done the exact same thing in pure javascript many times and there are plenty of test to test the behaviour ( in Javascript )
Is Dart Broken?
When I try to use a javascriptified Hash to do the same behavoiur it works like a charm.
var options = js.map({ 'dart' : new MyDartclass(something, something));
var y = options["dart"];
js.context.console.log(y.name);
// Name is printed
What do you get out from the retrieve?
It seems that I get some kind of Dart Proxy
MyDartClass mydc = matrix.cell(1,1). retrieve("thing");
js.context.console.log(mydc);
DartProxy {id: "dart-ref-20", port: DartSendPortSync}
id: "dart-ref-20"
port: DartSendPortSync
__proto__: DartProxy
I belive that the lib stores the objects, deep down, in a hash map. But it seems like when I retrieve the object into the Dart I get something, but not in a way that I can work with it. So i need help since I don't know how to make it work.
Do I need to de-proxify the object?
Perhaps it IS a Dart bug when you try to retrieve objects from hashes inside objects
Perhaps I missunderstod everything that this is not suppose to work.
Passing and retrieving Dart objects inside the same scope is working. There's the following test case in the tests of js-interop to proove it :
test('retrieve same dart Object', () {
final date = new DateTime.now();
js.context.dartDate = date;
expect(js.context.dartDate, equals(date));
});
However there seems to be an issue with multiple scopes (and multiple event loops as well). There is no way to retain a dart object for now. So your dart object reference goes away at the end of scope. Here's a simple test case that fails :
test('retrieve same dart Object', () {
final date = new DateTime.now();
js.scoped(() {
js.context.dartDate = date;
});
js.scoped(() {
expect(js.context.dartDate, equals(date));
});
});
Please file an issue.