Trying to connect to SQL server using Tedious Connection and Windows Authentication? - javascript

I'm trying to connect to SQL server using tedious connection pool and windows authentication. But I get an error:
message: 'Login failed for user \'\'.', code: 'ELOGIN'
I'm not sure what I'm doing wrong. I'm using the latest version of tedious.
.env file
SQL_SERVER=localhost
SQL_UNAME=Username
SQL_PSWD=Password
SQL_DB=DatabaseName
SQL_DOMAIN=US
dbController.js
const {Request} = require('tedious');
const TYPES = require('tedious').TYPES;
const ConnectionPool = require('tedious-connection-pool');
const dbConfig = require('./dbconfig');
const poolConfig = {
min: 1,
max: 1,
log: true
};
let _rows = [];
const pool = new ConnectionPool(poolConfig, dbConfig);
pool.on('error', (err) => {
console.log(err);
});
dbConfig.js
const dotenv = require('dotenv');
dotenv.config();
module.exports = {
server: process.env.SQL_SERVER,
options: {
instanceName: 'SQLEXPRESS',
encrypt: false,
database: process.env.SQL_DB,
rowCollectionOnDone: true,
useColumnNames: true
},
authentication: {
type: 'ntlm',
options: {
userName: process.env.SQL_UNAME,
password: process.env.SQL_PSWD,
domain: process.env.SQL_DOMAIN
}
}
};

The problem is tedious-connection-pool is using tedious version 1 instead of tedious version 9.
I'm hoping to solve that with tedious-connection-pool2 based on a PR I found that never got merged upstream.
So, wait a day, and find my tedious-connection-pool2 and use the overrideTedious option that should work.

Related

hide privateKey from nodeJS on Heroku?

I've integrate BrainTree Drop-in UI for checkout payment in nodeJS. It's only a demonstration that I needed to create. I had no issues, it was easy enough. The only thing that I would like to do is to hide merchantId, publicKey and privateKey from the code. I would like to add them directly in Heroku Config Vars. I know how to do all this in Python, but I have no idea how to do it in JavaScript. I show you the code changing the keys:
const express = require('express');
const router = express.Router();
const braintree = require('braintree');
router.post('/', (req, res, next) => {
const gateway = new braintree.BraintreeGateway({
environment: braintree.Environment.Sandbox,
// Use your own credentials from the sandbox Control Panel here
merchantId: 'h43jgh5g3gl4543',
publicKey: 'hj45j4h5lh45hl4h5l',
privateKey: 'b5hbhbb45bhbh4kfndnfdkkfnd'
});
// Use the payment method nonce here
const nonceFromTheClient = req.body.paymentMethodNonce;
// Create a new transaction for $10
const newTransaction = gateway.transaction.sale({
amount: '10.00',
paymentMethodNonce: nonceFromTheClient,
options: {
// This option requests the funds from the transaction
// once it has been authorized successfully
submitForSettlement: true
}
}, (error, result) => {
if (result) {
res.send(result);
} else {
res.status(500).send(error);
}
});
});
module.exports = router;
How can I assign those values to Variables that I can then pass to Heroku Config Vars?
Thank you very much for your help!
EDITING THE INTIAL POST:
Sorry I need to add more info about this post. I followed what a user suggested by changing the code in Node.js in this way:
router.post('/', (req, res, next) => {
const gateway = new braintree.BraintreeGateway({
environment: braintree.Environment.Sandbox,
// Use your own credentials from the sandbox Control Panel here
merchantId: process.env.MERCHANT_ID,
publicKey: process.env.PUBLIC_KEY,
privateKey: process.env.PRIVATE_KEY
});
I added those value to Heroku, and it looked it was working, but I also changed the sandbox value in index.hbs:
<script>
var button = document.querySelector('#submit-button');
braintree.dropin.create({
authorization: process.env.SANDBOX_KEY,
container: '#dropin-container',
paypal: {
flow: 'checkout',
buttonStyle: {
color: 'blue',
shape: 'rect',
size: 'medium'
},
amount: '10.00',
currency: 'USD'
}
},
I replace the value 'sanbox_34920hfjh34i23h4oi3' with process.env.SANDBOX_KEY and added that value in Heroku.
But now the interface doesn't work anymore, why?
Thank you very much for your precious help!
You can add Config variables in Heroku dashboard or with the CLI more on that here Configuration and Config Vars. Now, when you done that you can access them in your Node app as process.env.NAME_OF_VARIABLE.

Bypass Shopify auth when developing Shopify apps locally with Koa & Next JS?

So I'm following https://shopify.dev/tutorials/build-a-shopify-app-with-node-and-react but ever since I ngrok'd it's too slow.
Is there any way I can develop locally? I know Shopify is a hosted solution but ngrok makes it way too slow for me.
I'm from India & I think the servers are from US & it's so slow that it takes literally 5 mins & sometimes it doesn't even load properly at all.
Here's my current server.js:
require('isomorphic-fetch')
const dotenv = require('dotenv')
const Koa = require('koa')
const next = require('next')
const { default: createShopifyAuth } = require('#shopify/koa-shopify-auth')
const { verifyRequest } = require('#shopify/koa-shopify-auth')
const session = require('koa-session')
dotenv.config()
const { PORT, NODE_ENV, SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env
const port = parseInt(PORT, 10) || 3000
const dev = NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = new Koa()
server.use(session({ secure: true, sameSite: 'none' }, server))
server.keys = [SHOPIFY_API_SECRET_KEY]
server.use(
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET_KEY,
scopes: ['read_products'],
afterAuth(ctx) {
const { shop, accessToken } = ctx.session
ctx.cookies.set('shopOrigin', shop, {
httpOnly: false,
secure: true,
sameSite: 'none',
})
ctx.redirect('/')
},
})
)
server.use(verifyRequest())
server.use(async (ctx) => {
await handle(ctx.req, ctx.res)
ctx.respond = false
ctx.res.statusCode = 200
return
})
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`)
})
})
Can I set the dev variable somewhere & bypass Shopify auth (Idk much about koa) to code my app locally & then check the final result on Shopify app store?
I even tried serveo, lynk, sish & many other ngrok alternatives. None of them worked. serveo did until it didn't. So I gotta use 8 hours of ngrok but any other solutions are appreciated.

Sequelize with asynchronous configuration in nodejs

I have been bashing my head for days as I cannot find a valid example of async configuration in Sequelize
So as you may know, you can simply config a Sequelize instance like that
const sequelize = new Sequelize('postgres://user:pass#example.com:5432/dbname')
and then declare your Model
const User = sequelize.define('User', {
// Model attributes are defined here
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull defaults to true
}
}, {
// Other model options go here
});
However what happens when the db credentials comes from an external service?
const credentials = await getDbCredentials();
const sequelize = new Sequelize({credentials})
since sequelize models creation are coupled with the instance creation (unlike many others ORMs) this becomes a big problem.
My current solution is the following:
const Sequelize = require("sequelize");
// Models
const { User } = require("./User");
const env = process.env.NODE_ENV || "development";
const db = {};
let sequelize = null;
const initSequelize = async () => {
if (!sequelize) {
let configWithCredentials = {};
if (env === "production") {
const credentials = await getDbCredentials();
const { password, username, dbname, engine, host, port } = credentials;
configWithCredentials = {
username,
password,
database: dbname,
host,
port,
dialect: engine,
operatorsAliases: 0
};
}
const config = {
development: {
// Dev config
},
production: configWithCredentials,
};
sequelize = new Sequelize(config[env]);
sequelize.authenticate().then(() => {
console.log("db authenticated")
});
});
}
db.User = User;
db.sequelize = sequelize;
db.Sequelize = Sequelize;
};
initSequelize().then(() => {
console.log("done");
});
module.exports = db;
However I feel that this is not a good approach because of the asynchronous nature of the initialization and sometimes the db is undefined.
Is there a better way to approach this thing?
Thanks
You can achieve this with beforeConnect hook, something like this:
sequelize = new Sequelize(config.database, '', '', config);
sequelize.beforeConnect(async (config) => {
config.username = await getSecretUsername();
config.password = await getSecretPassword();
});
Leave the initial credentials empty, then use beforeConnect to mutate the config. Not sure if this is the cleanest way to use it but seems to be working.
https://sequelize.org/master/manual/hooks.html
I think your db is sometimes undefined, because in your async function you're not "waiting" for the resolution of sequelize.authenticate(). Change this:
sequelize.authenticate().then(() => {
console.log("db authenticated")
});
To this:
await sequelize.authenticate()
console.log("db authenticated")
What was happening, is that your initSequelize async function would resolve, before sequelize.authenticate promise would. This is a common pitfall in JS. I think this adjustment will solve your problem. Regarding "the best approach", i don't see much that can be done here, but of course i don't have the entire picture.
I found a 'pure' sequelize way to do this through lifecycle hooks:
Basically a generic setup in a db.js file would look like this:
const { Sequelize } = require('sequelize');
const asyncFetch = require('../util/async-fetch');
const sequelize = new Sequelize({
dialect: 'mysql',
database: 'db_name',
host: '127.0.0.1'
});
sequelize.beforeConnect(async (config) => {
const [username, password] = await Promise.all([
asyncFetch('username'),
asyncFetch('password')
]);
config.username = username;
config.password = password;
});
module.exports = sequelize;
The sequelize model definition is really just a plain object so that can be set early. Model initialisation does require a sequelize instance to be passed in.
The setup was a bit clearer to me when using ES6 class definitions for the models. sequelize.define is replaced with a call to Model.init, and this can all be done in an async setup function.
const Sequelize = require('sequelize')
const { Model } = Sequelize
class User extends Model {
static get modelFields(){
return {
id: {
type: Sequelize.UUID,
primaryKey: true,
defaultValue: Sequelize.UUIDV4,
},
name: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
}
}
}
static get modelOptions(){
return {
version: true,
}
}
static init(sequelize){
const options = { ...this.modelOptions, sequelize }
return super.init(this.modelFields, options)
}
static associate(models) {
this.hasMany(models.Task)
}
}
module.exports = User
const User = require('./User')
class Database {
async static setup(){
const credentials = await getCredentials()
this.sequelize = new Sequelize(credentials)
User.init(this.sequelize)
this.User = User
// When you have multiple models to associate add:
this.User.associate(this)
}
}
module.exports = Database
Due to the async credentials requirement, the rest of your app will just need to cope with the delay until the DB is setup. If this is a koa/express app for example, you could delay the server .listen() until the Database.setup() promise has resolved.
As this would have changed a lot of my code. I have ended up by creating a script in golang that gets my credential "asynchronously" before running my server.
I have use some code from this package: https://github.com/telia-oss/aws-env
And then pass my starting script as a command argument so I could "inherit" the environmental variables
./getEnv exec -- node index.js

Knex leaves open server when using Jest (recommendation)

I'm trying to do some TDD with my following stack
Jest
Node
Koa2
SuperTest
Knex
Objection
My problem starts with the open handler of the koa server and I could solve that with the instance of the server and close it with server.close()
However, I have the same problem with knex; It leaves the server open and I have to run the knex.close to stop it. With that i can avoid the following error message
Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't >stopped in your tests. Consider running Jest with --detectOpenHandles to >troubleshoot this issue.
knex.config
const config = {
development: {
client: 'pg',
connection: process.env.DATABASE_URL,
migrations:{
directory:"./migrations/"
},
pool: { min: 0, max: 7 }
},
test: {
client: 'pg',
connection: process.env.DATABASE_URL,
migrations:{
directory:"./migrations/"
},
pool: { min: 0, max: 7 }
},
//TBD
staging: {
client: 'postgresql',
connection: {
database: 'my_db',
user: 'username',
password: 'password'
},
pool: {
min: 2,
max: 10
},
migrations: {
tableName: 'knex_migrations'
}
},
//TBD
production: {
client: 'postgresql',
connection: {
database: 'my_db',
user: 'username',
password: 'password'
},
pool: {
min: 2,
max: 10
},
migrations: {
tableName: 'knex_migrations'
}
}
}
module.exports = config;
user.model.js
'use strict';
const knex = require('../config/db/knex');
const { Model } = require('objection');
Model.knex(knex);
class User extends Model {
// Table name is the only required property.
static get tableName() {
return 'user';
}
// Custom function to close knex
static close() {
knex.destroy();
}
}
module.exports = User;
user.test.js
const supertest = require('supertest');
const server = require('../../server');
var request = require("supertest").agent(server);
describe("Test users routes", () => {
let Model;
beforeAll(async () => {
// do something before anything else runs
console.log('Jest starting!');
Model = require('../../models/user.model')
});
// close the server after each test
afterAll(() => {
server.close();
Model.close();
console.log('server closed!');
});
test("Get /",async () => {
let res = await request.get('/users/');
expect(res.status).toBe(200);
});
});
I'm pretty sure it could be a better approach solution for what I did, maybe something related with the pool or some callback on the knex.cofing but I'm not sure.
Thank you

"MissingSchemaError" when seeding database using mongoose-seeder

I am attempting to seed a database using mongoose-seeder, and I keep getting a MissingSchemaError. I am sure that I am setting up the schema properly, so I am lost as to why this is happening.
The file where I set up the schema looks like this:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
fullName: {
type: String,
required: true,
trim: true
},
emailAddress: {
type: String,
unique: true,
required: true,
match: /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)| .
(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-
Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
},
password: {
type: String,
required: true
}
});
const User = mongoose.model('User', UserSchema);
module.exports.User = User;
and in my main file:
'use strict';
// load modules
const morgan = require('morgan');
const mongoose = require('mongoose');
const seeder = require('mongoose-seeder');
const data = require('./data/data.json');
const express = require('express');
const app = express();
//set up database connection
mongoose.connect("mongodb://localhost:27017/courseapi");
const db = mongoose.connection;
//handle err connecting to db
db.on("error", (err) => console.error("Error connecting to database: ",
err));
//success
db.once("open", () => {
console.log("Connected to database");
seeder.seed(data, {dropDatabase: false}).then(function(dbData){
console.log("Database seeded!");
}).catch(function(err){
console.error("Error seeding database", err);
})
});
any help would be much appreciated!
The mongoose-seeder package is not maintained. Hence suggesting an alternative to import data. You can populate MongoDB in the CLI (command line interface) using mongoimport.It will load a JSON file into a specified MongoDB Instance & Collection. All you need is a mongod instance to be running before execution.
Please go through the walkthrough.
thank you for your help! The project required using a module to seed the data, so I ended up using mongoose-seed instead. (Required some reformatting of the json, but thankfully the file was relatively small)
it's better to use the actively maintained Seedgoose. It's the ultimate mongoose seeder with smart reference support.

Categories