My app receives a base64 encoded value that is also encrypted. The data can come in a few different ways so I wanted to create chain-able methods to keep the code clean and modular.
I want to be able write: decryptionChain.decodeBase64(b64Value).stringToBuffer().finallyDecrypt();
When I run the code, the last property method "finallyDecrypt" returns as undefined.
Why is the "finallyDecrypt" method coming back as undefined? The rest all works and if I run encryptionChain.decodeBase64(b64Value).stringToBuffer() I get back the Buffer I expect. It is only when the finallyDecrypt is chained in that I error out.
Here is the code:
function decrypt(encrypted) {
var decipher = crypto.createDecipheriv(algorithm, password, iv);
decipher.setAuthTag(encrypted.tag);
var dec = decipher.update(encrypted.content, 'hex', 'utf8');
dec += decipher.final('utf8');
return dec;
}
var decryptionChain = {
currentValue:"",
decodeBase64: function (encryptedValue){
this.currentValue = new Buffer(encryptedValue.toString(), "base64");
return this;
},
stringToBuffer: function() {
if (this.currentValue) {
myBuffer = JSON.parse(this.currentValue, function (key, value) {
return value && value.type === 'Buffer'
? new Buffer(value.data)
: value;
});
}
return myBuffer;
},
finallyDecrypt : function(myBuffer){
if(myBuffer){
decrypt(myBuffer);
}
return this;
}
};
Chaining works by returning this from each method (which points back to the decryptionChain object).
stringToBuffer, however, returns myBuffer, so you're trying to call a method named finallyDecrypt on that buffer (which doesn't have that method, hence the error).
If you want it to work with chaining, use something similar to how you're dealing with currentValue:
stringToBuffer : function() {
...
this.myBuffer = myBuffer;
return this;
},
finallyDecrypt : function() {
if (this.myBuffer) {
...
}
}
The stringToBuffer() function returns a Buffer (or it may return nothing if this.currentValue is falsey). The function you're trying to call is not in Buffer, it's in decryptionChain, so when you try to call a non-existing function on Buffer, it's telling you it's undefined.
Notice in decodeBase64(), you store this.currentValue and then return this. That's why the next chain works, because the decryptionChain object is being returned.
So stringToBuffer() could store it's result in this.bufferedResult, and then stringToBuffer() could return this.
Related
I've been looking around for a way to do this but can't seem to find anything, I have different configuration objects that I need to save as a text in variables for some processing later on, here is a sample:
object:
args.config.config = {
next: null,
final:[],
delimiter: '~', header: false,
step: function (row) {
var item = {
'line_code': row.data[0][0],
'order': row.data[0][1]
}
args.config.config.final.push(item);
},
complete: function (result) {
console.log('Reading data completed. Processing.');
return args.config.config.next(null, args.config.config.final);
},
error: function () {
console.log('There was an error parsing');
}'
}
I need to save this as a string, so something like:
args.config.config = "{object goes here}";
Without putting everything on one giant line or adding break line characters as this will be parsed later to be used in a config, and that will mess things up, any ideas?
UPDATE:
So changing them into text may not be the best solution, these configs will be stored in a mongo database, so it may take them as is (I have not tried it yet).
One of the other problems I was running into was that in the config object I had this:
final.push(item)
and
return next(null, final)
Which will be defined in another file using the config object:
other file:
exports.parse = function(args, next){//next is what I need to call in the config
var final = []; //this is the final referred to in the config object
....
Baby.parse(data, args.config)
}
So the return next(null, final) and final.push(result) have to refer the the var / function in the new file, but I have no idea how to get that to work, that't why I had to add a final array in the config object and a null next function, then assign it like so:
exports.parse = function(args, next){
args.config.next = next;
....
Baby.parse(data, args.config)
}
the object was calling it with the ugly line:
return args.config.config.next(null, args.config.config.final);
If anyone has a way around this, it would be much appreciated.
If you use JSON.stringify with a "replacer" function and
JSON.parse with a "reviver" function along with new Function(), you can do it:
I'm not sure I'm following the second (updated) question you have. Once the object is parsed back into an object, why can't you just initialize the next and final properties to valid objects before calling any of the object's methods? You can even add tests into that method that checks for the existence of final and next before returning anything.
var myObj = {
next: null,
final:[],
delimiter: '~',
header: false,
step: function (row) {
var item = {
'line_code': row.data[0][0],
'order': row.data[0][1]
};
args.config.config.final.push(item);
},
complete: function (result) {
console.log('Reading data completed. Processing.');
return args.config.config.next(null, args.config.config.final);
},
error: function () {
console.log('There was an error parsing');
}
};
// Stringify the object using a replacer function that will explicitly
// turn functions into strings
var myObjString = JSON.stringify(myObj, function(key, val) {
return (typeof val === 'function') ? '' + val : val;
});
// Now, parse back into an object with a reviver function to
// test for function values and create new functions from them:
var obj = JSON.parse(myObjString, function(key, val){
// Make sure the current value is not null (is a string)
// and that the first characters are "function"
if(typeof val === "string" && val.indexOf('function') === 0){
// Isolate the argument names list
var start = val.indexOf("(") + 1;
var end = val.indexOf(")");
var argListString = val.substring(start,end).split(",");
// Isolate the body of the function
var body = val.substr(val.indexOf("{"), val.length - end + 1);
// Construct a new function using the argument names and body
// stored in the string:
return new Function(argListString, body);
} else {
// Non-function property, just return the value
return val;
}
}
);
// Test the method:
obj.error(); // 'There was an error parsing' is written to console.
// Examine the object:
console.log(obj);
I've been looking around for a way to do this but can't seem to find anything, I have different configuration objects that I need to save as a text in variables for some processing later on, here is a sample:
object:
args.config.config = {
next: null,
final:[],
delimiter: '~', header: false,
step: function (row) {
var item = {
'line_code': row.data[0][0],
'order': row.data[0][1]
}
args.config.config.final.push(item);
},
complete: function (result) {
console.log('Reading data completed. Processing.');
return args.config.config.next(null, args.config.config.final);
},
error: function () {
console.log('There was an error parsing');
}'
}
I need to save this as a string, so something like:
args.config.config = "{object goes here}";
Without putting everything on one giant line or adding break line characters as this will be parsed later to be used in a config, and that will mess things up, any ideas?
UPDATE:
So changing them into text may not be the best solution, these configs will be stored in a mongo database, so it may take them as is (I have not tried it yet).
One of the other problems I was running into was that in the config object I had this:
final.push(item)
and
return next(null, final)
Which will be defined in another file using the config object:
other file:
exports.parse = function(args, next){//next is what I need to call in the config
var final = []; //this is the final referred to in the config object
....
Baby.parse(data, args.config)
}
So the return next(null, final) and final.push(result) have to refer the the var / function in the new file, but I have no idea how to get that to work, that't why I had to add a final array in the config object and a null next function, then assign it like so:
exports.parse = function(args, next){
args.config.next = next;
....
Baby.parse(data, args.config)
}
the object was calling it with the ugly line:
return args.config.config.next(null, args.config.config.final);
If anyone has a way around this, it would be much appreciated.
If you use JSON.stringify with a "replacer" function and
JSON.parse with a "reviver" function along with new Function(), you can do it:
I'm not sure I'm following the second (updated) question you have. Once the object is parsed back into an object, why can't you just initialize the next and final properties to valid objects before calling any of the object's methods? You can even add tests into that method that checks for the existence of final and next before returning anything.
var myObj = {
next: null,
final:[],
delimiter: '~',
header: false,
step: function (row) {
var item = {
'line_code': row.data[0][0],
'order': row.data[0][1]
};
args.config.config.final.push(item);
},
complete: function (result) {
console.log('Reading data completed. Processing.');
return args.config.config.next(null, args.config.config.final);
},
error: function () {
console.log('There was an error parsing');
}
};
// Stringify the object using a replacer function that will explicitly
// turn functions into strings
var myObjString = JSON.stringify(myObj, function(key, val) {
return (typeof val === 'function') ? '' + val : val;
});
// Now, parse back into an object with a reviver function to
// test for function values and create new functions from them:
var obj = JSON.parse(myObjString, function(key, val){
// Make sure the current value is not null (is a string)
// and that the first characters are "function"
if(typeof val === "string" && val.indexOf('function') === 0){
// Isolate the argument names list
var start = val.indexOf("(") + 1;
var end = val.indexOf(")");
var argListString = val.substring(start,end).split(",");
// Isolate the body of the function
var body = val.substr(val.indexOf("{"), val.length - end + 1);
// Construct a new function using the argument names and body
// stored in the string:
return new Function(argListString, body);
} else {
// Non-function property, just return the value
return val;
}
}
);
// Test the method:
obj.error(); // 'There was an error parsing' is written to console.
// Examine the object:
console.log(obj);
I'm trying to make an object as a mock to pass into a test.
I don't know if I'm constructing it correctly - I'm getting Error: User() method does not exist.
injectedUser = {
set: function(key, val){
this[key] = val;
}
};
injectedParse = {
Parse: {
User: function() {
return injectedUser;
}
}
};
Parse = function() {
return injectedParse;
};
The desired behavior I'm looking for is for function Parse.User to be called with user = new Parse.User and be able to do user.set("key", "value");
But it seems like I'm not building this object properly? I have another issue but since it is more a javascript thing potentially, I made a new, more general issue about building objects
I also tried
set = function (key, val) {
this[key] = val;
}
mockParse = function(){
this.User()
};
mockParse.prototype.User = function(){
return set
};
$provide.value('Parse', mockParse);
That gave me the same error.
All the information you should know about constructing objects are at: http://ericleads.com/2013/02/fluent-javascript-three-different-kinds-of-prototypal-oo/
In javascript using an object parameter is my preferred way of working with functions. To check that a function has the required parameters I either (Solution 1) loop through all the object parameters properties and throw an error or (Solution 2) wait until a required property is needed and throw an error. Solution two seems efficient but I have to throws in multiple places in the function. Solution 1 seems pragmatic but should probably be a reusable piece of code. Is there another solution I should be looking at?
You can actually do this
var propsNeeded = ["prop1", "prop2", "blah", "blah", "blah"],
obj = {
prop1: "Hi"
}
function hasRequiredProperties(props, obj){
return Object.keys(obj).sort().join() == propsNeeded.sort().join();
}
console.log(hasRequiredProperties(propsNeeded, obj)); // false
You can check for single properties like
function hasProperty(propName, obj){
return obj.hasOwnProperty(propName);
}
For consistency I would create require method and use it always when some property is required.
var require = function (key, object) {
if (typeof object[key] === 'undefined') {
throw new Error('Required property ' + key + ' is undefined');
}
};
I would test if required property exists as soon as I'm certain that property is needed. Like this:
var example = function (args) {
require('alwaysRequired', args);
// some code here which uses property alwaysRequired
if (args.something) {
require('sometimesRequired', args);
// some code here which uses property sometimesRequired
}
};
Using #Amit's answer I'd probably add a method to Object itself:
Object.prototype.hasAllProperties = function(props, fire){
var result = Object.keys(this).sort().join() == propsNeeded.sort().join();
if (fire && !result){
throw new Error('Object does not define all properties');
}
return result;
}
and in your function:
function someFunction(myObject){
var objComplete = myObject.hasAllProperties(["prop1", "prop2", "prop3"], false);
}
Update:
After noticing the problem with #Amit's original answer, here's what I suggest:
Object.prototype.hasAllProperties = function(props, fire){
var result = true;
$(props).each(function(i, e){
if (!this.hasOwnProperty(e) ) {
result = false;
return false;
}
});
if (fire && !result){
throw new Error('Object does not define all properties');
}
return result;
}
This is just a general case of checking for presence of keys on a object, which can be done easily enough with
requiredParams.every(function(prop) { return prop in paramObj; })
It almost reads like natural language. "Taking the required parameters, is EVERY one of them IN the parameter object?".
Just wrap this in function checkParams(paramObj, requiredParams) for easy re-use.
More generally, this is the problem of asking if one list (in this case the list of required parameters) is included in another list (the keys on the params object). So we can write a general routine for list inclusion:
function listIncluded(list1, list2) {
return list1.every(function(e) { return list2.indexOf(e) !== -1; });
}
Then our parameter-checking becomes
function checkParams(paramObj, requiredParams) {
return listIncluded(requiredParams, Object.keys(paramObj));
}
If you want to know if object has at least some properties you can use this function without third parameter:
function hasRequiredProperties(propsNeeded, obj, strict) {
if (strict) return Object.keys(obj).sort().join() == propsNeeded.sort().join();
for (var i in propsNeeded ) {
if (!obj.hasOwnProperty(propsNeeded[i])) return false;
}
return true;
};
Example:
options = {url: {
protocol: 'https:',
hostname: 'encrypted.google.com',
port: '80'
}
};
propsNeeded = ['protocol', 'hostname'];
hasRequiredProperties(propsNeeded, options.url); // true
hasRequiredProperties(propsNeeded, options.url, true); // false
Ok, so I'm a complete newbie to OOP in Javascript, apparently. I thought I understood it, but it appears I only know a small portion. Anyway, what I'm trying to do is setup an object to store and return data from an XML input by using a fairly simple string to retrieve data. I'd like to retrieve the data with a string similar to reader.getItem().getSubItem() or something like that.
Below is an example of what I attempted, but I get the error anonymous is not a function each time I try to do a call to fr.getType().isTexture() so obviously, I need to change something.
//Create the object by passing an XML element containing sub-elements
var fr = new FeatureReader(test.child(i));
alert(fr.getName()); //returns the object's name
alert(fr.getType().isTexture()); //"anonymous is not a function" error
function FeatureReader(feature) {
var feat = feature;
this.getName = function() {
return feat.name;
};
this.getType = new function() {
this.isTexture = new function() {
if (feat.type.texture == "yes") {
return true;
}
return false;
};
this.isModel = new function() {
if (feat.type.model == "yes") {
return true;
}
return false;
};
};
}
Now, obviously I could just remove the surrounding this.getType = function() {} around the this.isTexture and this.isModel to get my data, but for the sake of learning something, I'd like to see how it is recommended that I set this object up to get the returned values using a string similar to what I mentioned in the first and second paragraphs.
When you do this:
this.isTexture = new function() {
if (feat.type.texture == "yes") {
return true;
}
return false;
};
you're setting the "isTexture" property to the object constructed, not to that function. If you drop the new keyword from the statement, you'll be setting "isTexture" to be a function.
An expression of the form new <some-function> evaluates to an object, in other words.
edit — your "getType" property will also be an object, for the same reason. However, I think this would work:
alert( fr.getType.isTexture() );
Also note that your if statement can be simplified:
return feat.type.texture == "yes";
What you can do is simply assign an object instead of using new:
function FeatureReader(feature) {
var feat = feature;
this.getName = function() {
return feat.name;
};
this.getType = {
isTexture: function() {
return feat.type.texture == "yes";
},
isModel: function() {
return feat.type.model == "yes";
}
};
}
Then use the method like:
instance.getType.isTexture()
Note that you don't need to return true or false, as returning an expression that evaluates to boolean like a == b
returns a boolean value.