This question builds on an answer to a previous question, where I was looking for a solution to share configuration data between actors (nodejs modules) of a system (SDK) without using Factory pattern.
This time I need to make the SDK multi-tenant by providing different configuration data for distinct SDK instances.
app.js
var SDKAcctA = require("./sdk");
SDKAcctA.config = {key: "key", secret: "secret"};
var SDKAcctB = require("./sdk");
SDKAcctB.config = {key: "key2", secret: "secret2"};
// use both of them concurrently without each one overriding the config data of the other
var mA = new SDKAcctA.M1();
mA.doSomething();
var mB = new SDKAcctB.M1();
mB.doSomething();
sdk.js
var SDK = function(){};
SDK.config = {key: null, secret: null};
module.exports = SDK;
require("./m1"); //executing other modules to make it work
m1.js
var SDK = require("./sdk");
var M1 = function(){};
M1.prototype.doSomething = function(){
var config = SDK.config //getting access to main module's config data
};
SDK.M1 = M1;
Question:
Right now the configuration data is getting overriden by the other instance and that's what the issue is. Please advise.
Related
I made a makeshift 'sso server' which I want to connect to Wix Answers. Wix is a CMS. Wix Answers is a help center where you can customer FAQs, have customers receive support videos, and the customer can enter tickets. Wix answers are what Wix uses for Wix's help pages and they make the same app available to users for the same purpose.
My 'sso server' is an AWS API Gateway pointing to a Lambda function. Pretty straight forward. You call the public endpoint and it runs this lambda:
var express = require('express');
var app = express();
var crypto = require('crypto'); //npm install crypto --save
var base64url = require('base64url'); //npm install base64url --save
var bodyParser = require('body-parser');
var KEY_ID = '1234567'; //note it's a uuid
var SECRET = '1234567xxxxxxxxxxxxxxxxxxxxxxxxxxx';
exports.handler = async (event) => {
//this assumes there is a login or some UI that will receive the needed redirect url
app.get('/login-form', function (request, response) {
var url = require('url');
var urlParts = url.parse(request.url, true);
var query = urlParts.query;
var answersRedirectUrl = query.redirectUrl;
//of course, in a real system the data will come from your own user system
var dummyUserData = {
id: 'your-user-id',
email: 'user#email.com',
firstName: 'Bob2',
lastName: 'Bobson',
profileImage: 'https://i.ytimg.com/vi/-90CAdWk27I/maxresdefault.jpg',
timestamp: Date.now()
};
var token = encryptUserData(JSON.stringify(dummyUserData), SECRET);
response.redirect(answersRedirectUrl + '&token=' + token + '&key=' + KEY_ID);
});
};
function encryptUserData(data, key) {
var iv = new Buffer('');
var bytes = new Buffer(key, 'utf-8');
var hashedKey = crypto.createHash('sha1').update(bytes).digest().slice(0, 16);
var cipher = crypto.createCipheriv('aes-128-ecb', hashedKey, iv);
var crypted = cipher.update(data, 'UTF-8', 'hex');
crypted += cipher.final('hex');
return base64url(new Buffer(crypted, 'hex'));
}
This code is a lambda modified version of the code Wix Answers sample js code from, here.
https://help.wixanswers.com/en/article/setting-up-single-sign-on-sso-for-your-users
There are dependencies, and I have loaded them all into a lambda, so its not a dependency issue.
Wix Answers is an easy setup, you give them a url for login and logout. you generate a key inside of Wix answers dashboard, and I have added that key to my lambda below (the ones below are masked obviously). I've added my endpoint to the field in wix answers.
I'm getting a null response and was able to get an object with object.message = "missing auth token"
Focusing on the JS and the lambda, is there anything that I am leaving out that would make this not work. Again not a lot of experience with express and these dependencies, or with SSO.
Thanks!!
Wix Has some good tools but lacks documentation sometimes. Here is how I solved this problem:
tutorial https://help.wixanswers.com/en/article/setting-up-single-sign-on-sso-for-your-users
their JS code from https://gist.github.com/GabiGrin/0c92ecbb071e02e2d91c8d689517acd7#file-answers-sso-example-js
What I did
//encrypt.js
var crypto = require('crypto'); //built in to node
var base64url = require('base64url'); //requires install 'npm install base64url'
var KEY_ID = 'abcedfghijklmnopqrstuvwxyz'; //from Wix Answers
var SECRET = 'fakefakefakefakefakefake'; //from Wix Answers
let user = {
id: '123456',
email: 'email#domain.com',
firstName: 'Homer',
lastName: 'Simpson',
profileImage: 'https://i.ytimg.com/vi/-90CAdWk27I/maxresdefault.jpg',
timestamp: Date.now()
};
function encryptUserData(data, key) {
var iv = new Buffer('');
var bytes = new Buffer(key, 'utf-8');
var hashedKey = crypto.createHash('sha1').update(bytes).digest().slice(0, 16);
var cipher = crypto.createCipheriv('aes-128-ecb', hashedKey, iv);
var crypted = cipher.update(data, 'UTF-8', 'hex');
crypted += cipher.final('hex');
return base64url(new Buffer(crypted, 'hex'));
}
var token = encryptUserData(JSON.stringify(user), SECRET);
console.log(`https://mysite.wixanswers.com/api/v1/accounts/callback/sso?redirectUrl=https%3A%2F%2Fmysite.wixanswers.com%2Fen&token=${token}&key=${KEY_ID}`);
Since my project is a concept, I have not integrated with a real identity server, as you can see i skip the authentication and go right to authorization (for my hard coded user: Homer Simpson). To mkae it work i'd need to add authentication and pass a dynamic user object to an export function in the module.
for the sake of the concept tho:
from the shell 'node encrypt.js'
returns a redirect URL in the console - when followed, successfully signs you into the Wix Answers platform with the proper user object.
i am using the npm module Properties-Reader for reading and writing properties file in Protractor Automation framework. The Utility method created is :
var PropertiesReader = require('properties-reader');
var path = require('path');
//var properties = PropertiesReader('../Resources/test.properties');
var PropertyFileReader = function(){
this.readPropertyFiles = function(filePath){
var fileToRead = filePath;
absolutePath = path.resolve(__dirname, fileToRead);
var properties = PropertiesReader(absolutePath);
return properties;
}
I am successfully get the items stored in the properties files by using the command as
var property = propertyReader.readPropertyFiles('D:/ProtractorDemo/Project05/BE/QA/Utils/sett.properties')
var name = property.get('name');
console.log(name);
But on using the set(), method i am not able to set anything in my properties files. Also. there is no error shown on the console. My properties files still remains empty
property.set('age', '28');
Working on an express project with a SQLite database.
I'm getting an Sequelize TypeError that I've been working on for hours but I'm coming up against a brick wall:
C:\-----\node_modules\sequelize\lib\sequelize.js:392
this.importCache[path] = defineCall(this, DataTypes);
^
TypeError: defineCall is not a function
at Sequelize.import (C:\----\node_modules\sequelize\lib\sequelize.js:392:32)
at C:\----\models\index.js:25:32
After doing some research, it appears that this could be caused when trying to import a non-sequelize object. Below is the problematic index.js file.
index.js:
var Sequelize = require('sequelize');
var config = {
dialect: 'sqlite',
storage: 'library.db'
};
var connection = new Sequelize(config);
var contents = fs.readdirSync(__dirname);
var db = {};
contents = contents.filter(function(file){
var currFileName = __filename.split('/');
var checkOne = file.substr(file.length - 3, 3) === '.js';
var checkTwo = file !== currFileName[currFileName.length - 1];
return checkOne && checkTwo;
});
contents.forEach(function(file){
var path = [__dirname, file].join('/');
var model = connection.import(path);
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName){
var model = db[modelName];
if(model.associate) {
model.associate(db);
}
});
module.exports = {
models: db,
connection: connection
};
I do not have any function called defineCall, any idea where the error is coming from?
This is indeed caused by importing a file that's not a Sequelize model. In my case, it was because my index.js was pulling in my test files as well as the models, which were in the same directory. Try adding another check like checkOne to exclude anything that ends with .test.js.
With the hint from the answer by #Floppy, I got to realise that it would be better if we stored those related files encapsulated in a folder.
For eg. make a folder named Models and store your index.js with all the models (eg. User model, photos model, etc) and then try.
Thanks.
I'm trying to use VersionOne JS SDK in Node.js (https://github.com/versionone/VersionOne.SDK.JavaScript). I'm simply downloading whole library, placing it alongside with my js file:
var v1 = require('./v1sdk/v1sdk.js');
var V1Server = v1.V1Server;
console.log(v1);
console.log(V1Server);
Unfortunately something seems wrong, the output I get after calling
node app.js
is:
{}
undefined
Can somebody point me what I'm doing wrong or check whether the sdk is valid.
Thanks!
You can see in the source where V1Server is defined, that it's a class with a constructor. So you need to use the new keyword and pass the arguments for your environment.
https://github.com/versionone/VersionOne.SDK.JavaScript/blob/master/client.coffee#L37
var server = new V1Server('cloud'); //and more if you need
Can you try the sample.js script that I just updated from here:
https://github.com/versionone/VersionOne.SDK.JavaScript/blob/master/sample.js
It pulls in the two modules like this:
var V1Meta = require('./v1meta').V1Meta;
var V1Server = require('./client').V1Server;
var hostname = "www14.v1host.com";
var instance = "v1sdktesting";
var username = "api";
var password = "api";
var port = "443";
var protocol = "https";
var server = new V1Server(hostname, instance, username, password, port, protocol);
var v1 = new V1Meta(server);
v1.query({
from: "Member",
where: {
IsSelf: 'true'
},
select: ['Email', 'Username', 'ID'],
success: function(result) {
console.log(result.Email);
console.log(result.Username);
console.log(result.ID);
},
error: function(err) { // NOTE: this is not working correctly yet, not called...
console.log(err);
}
});
You might have to get the latest and build the JS from CoffeeScript.
I think I was trying out "browserify" last year and that's how the "v1sdk.js" file got generated. But I'm not sure if that's the best approach if you're using node. It's probably better just to do it the way the sample.js file is doing it.
However, I did also check in a change to v1sdk.coffee which property exports the two other modules, just as a convenience. With that, you can look at sample2.js. The only different part there is this, which is more like you were trying to do with your example:
var v1sdk = require('./v1sdk');
var hostname = "www14.v1host.com";
var instance = "v1sdktesting";
var username = "api";
var password = "api";
var port = "443";
var protocol = "https";
var server = new v1sdk.V1Server(hostname, instance, username, password, port, protocol);
var v1 = new v1sdk.V1Meta(server);
I have an app.js node application. As this file is starting to grow, I would like to move some part of the code in some other files that I would "require" or "include" in the app.js file.
I'm trying things like:
// Declare application
var app = require('express').createServer();
// Declare usefull stuff for DB purposes
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
// THE FOLLOWING REQUIRE DOES NOT WORK
require('./models/car.js');
in car.js:
// Define Car model
CarSchema = new Schema({
brand : String,
type : String
});
mongoose.model('Car', CarSchema);
I got the error:
ReferenceError: Schema is not defined
I'm just looking to have the content of car.js loaded (instead of having everything in the same app.js file) Is there a particuliar way to do this in node.js ?
To place an emphasis on what everyone else has been saying var foo in top level does not create a global variable. If you want a global variable then write global.foo. but we all know globals are evil.
If you are someone who uses globals like that in a node.js project I was on I would refactor them away for as there are just so few use cases for this (There are a few exceptions but this isn't one).
// Declare application
var app = require('express').createServer();
// Declare usefull stuff for DB purposes
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
require('./models/car.js').make(Schema, mongoose);
in car.js
function make(Schema, mongoose) {
// Define Car model
CarSchema = new Schema({
brand : String,
type : String
});
mongoose.model('Car', CarSchema);
}
module.exports.make = make;
The correct answer is usually to use require, but in a few cases it's not possible.
The following code will do the trick, but use it with care:
var fs = require('fs');
var vm = require('vm');
var includeInThisContext = function(path) {
var code = fs.readFileSync(path);
vm.runInThisContext(code, path);
}.bind(this);
includeInThisContext(__dirname+"/models/car.js");
Short answer:
// lib.js
module.exports.your_function = function () {
// Something...
};
// app.js
require('./lib.js').your_function();
you can put
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
at the top of your car.js file for it to work, or you can do what Raynos said to do.
If you just want to test a library from the command line, you could do:
cat somelibrary.js mytestfile.js | node
This approach works for me in Node.js, Is there any problem with this one?
File 'include.js':
fs = require('fs');
File 'main.js':
require('./include.js');
fs.readFile('./file.json', function (err, data) {
if (err) {
console.log('ERROR: file.json not found...')
} else {
contents = JSON.parse(data)
};
})