Execute PowerShell script in Node.js - javascript

I create register app with node.js and Express.js
So it has name form and password form and submit button.
I want to make it, When I clicked the submit button, run the powershell script. This script means, add local windows user and set the password.
In PowerShell this script works well. And this powershell script should be run as administrator.
$PASSWORD= ConvertTo-SecureString –AsPlainText -Force -String kamisama123##
New-LocalUser -Name "gohan" -Description "sleepy" -Password $PASSWORD
After this command the local user is created.
I use node-powershell package in my code. This code means When I submit the my information and run the PowerShell script and add information in to mongodb
router.post(`/submit`, async function (req, res) {
let name = req.body.name;
let password = req.body.password;
let passwordCheck = req.body.passwordCheck;
let company = req.body.company;
let registerStatus = false;
let executives = req.body.executives;
let registerDate = Date.now();
let ps = new Shell();
let cmd = new PSCommand(`$PASSWORD= ConvertTo-SecureString ?AsPlainText -Force -String ${password}`)
let script = new PSCommand(`New-LocalUser -Name "${name}" -FullName "${name}" -Description "${name}" -PasswordNeverExpires -Password $PASSWORD`)
ps.addCommand(cmd);
ps.addCommand(script);
ㅡㅛ
try {
if (password !== passwordCheck) {
res.redirect('/')
} else {
let encodedPassword = Base64.encode(password);
await User.create({
name,
password: encodedPassword,
company,
registerStatus,
executives,
registerDate
}, (err, result) => {
if (err) throw err;
})
res.redirect(`/success/${name}`)
}
} catch (err) {
throw err;
}
})
But the error throws
(node:21596) UnhandledPromiseRejectionWarning: TypeError: Shell is not a constructor
I don't know where the error comes from.

Constructor is a term from object-oriented programming (OOP), every object in OOP has a constructor function.
For the shell object the constructor can not be empty (shell() has empty brackets)
Normally the constructor of shell has two arguments: execution policy and noProfile
let ps = new shell({
executionPolicy: 'Bypass',
noProfile: true
});
https://rannn505.gitbook.io/node-powershell/start
https://www.jeansnyman.com/posts/executing-powershell-commands-in-a-nodejs-api/
In How to execute Powershell script function with arguments using Node JS? is possibly a solution for this issue. The powershell script has to be wrapped in a promise in nodejs (and possibly be dot-sourced) :
How to execute Powershell script function with arguments using Node JS?
Powershell and potentially also node.js implements the OOP (object-oriented programming) design paradigms and semantics i.e. when writing object-oriented code each class has to have a constructor (new()) and a destructor (remove...) and it should have get() and set() methods to access (read and write) the fields (or attributes) of a class. In ps this is straighlty implemented
It is also possible to use object-oriented design patterns in PS https://dfinke.github.io/powershell,%20design%20patterns/2018/04/13/PowerShell-And-Design-Patterns.html

Related

Not able to use "connect()" method to sign transactions with different account in HARDHAT

I am making a smart contract so that I can send messages and other addresses can also send messages in that contract. So the message, block.timestamp and the sender's address will be stored in an "array of structs" in blockchain which will be done via transaction. Now in scripts/deploy.js file, we need getSigners() method so that we will be able to transact by "metamask" wallet. So, first check this line ---> const [_, randomPerson,addr1, addr2] = await hre.ethers.getSigners().
We know that the 1st value in this array is the owner by default. So, "" _(underscore) "" is the owner in this case. So, firstly please check my "scripts/deploy.js" and "WavePortal.sol" file--->
WavePortal.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0 <0.9.0;
import "hardhat/console.sol";
contract WavePortal {
uint256 totalWaves;
event NewWave(address indexed from, uint timestamp, string message);
struct Wave{
address waver;
string message;
uint timestamp;
}
Wave[] waves;
constructor() {
console.log("Yo yo, I am a contract and I am smart");
}
function wave(string memory _message) public {
totalWaves += 1;
console.log("%s waved with message %s", msg.sender, _message);
waves.push(Wave(msg.sender, _message, block.timestamp));
emit NewWave(msg.sender, block.timestamp, _message);
}
function getAllWaves() public view returns (Wave[] memory){ //Array of waves
return waves;
}
function getTotalWaves() public view returns (uint256) {
console.log("We have %d total waves!", totalWaves);
return totalWaves;
}
}
scripts/deploy.js
const hre = require("hardhat");
const main = async () => {
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
console.log("Contract address:", waveContract.address);
let waveCount;
waveCount = await waveContract.getTotalWaves();
console.log(waveCount.toNumber());
let waveTxn = await waveContract.wave("A message!");
await waveTxn.wait();
const [_, randomPerson, addr1, addr2] = await hre.ethers.getSigners();
console.log("Address of _ is: ",_.address); //Working absolutely fine
console.log("Random Person: ", randomPerson);
console.log("Address of Random Person is: ", randomPerson.address);
waveTxn = await waveContract.connect(randomPerson).wave("Another message!");
await waveTxn.wait();
let allWaves = await waveContract.getAllWaves();
console.log(allWaves);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
Now, when I am deploying it to localhost by running the command npx hardhat node after that I run this command in another terminal npx hardhat run scripts/deploy.js --network localhost, Everything is working absolutely fine. I was getting the address of "_" as well as "randomPerson".
But when I was trying to deploy it by the command npx hardhat run scripts/deploy.js --network rinkeby via Alchemy or Infura, (owner) is working totally fine, but other addresses like randomPerson or addr1 or addr2 is showing undefined when testing with console.log like console.log("randomPerson is: ", randomPerson) gives the output --> undefined. So I am unable to use/call the functions of WavePortal.sol by randomPerson or addr1 or addr2 which we do via connect() method for other addresses. I am only able to use/call its functions with "(underscore)" which is the owner. And so I am also unable to Deploy it on Rinkeby network of Alchemy or Infura via npx hardhat run scripts/deploy.js --network rinkeby.
I have tried each and everything but I am not getting the solution from anywhere.
My hardhat.config.js file is also properly updated as per Rinkeby or Ropsten whichever network I'm using.
So, Please help me regarding this.
If you try to deploy to rinkeby you need actually private key and account to send the tx.
ethers.getSigners() works for the localhost because it creates so called dummy accounts with 1000 ether.
So when you try to deploy to a real network it can't create a dummy account the tx has to be sent from a real account that is specified in the config.
So if you create another real account and specify it in your config it should work.
I got the solution to this question from Hardhat Official Discord channel.
As we know that private keys are different for different Accounts, like I wanna use 2 or more Rinkeby Accounts in this case, so I need to include their private keys also in hardhat.config.js under accounts.
accounts: [privateKey1, privateKey2, ...]
Link --> https://hardhat.org/config

Why wont VS Code track variable types for JavaScript?

I am trying to create a discord bot using JS. I create a .js file for each command I intend to implement and there is a check in the 'main' script that will make calls to the other command scripts. I am going to use pictures to show what I mean when I say that VS code wont tell me the variable type for parameters nor will it tell me any info regarding a method call. Intellisense also seems to not work well in these command .js scripts.
Background Info: I have a lot more experience programming in Java. JS seems to be confusing for me for whatever reason, but I want to learn and understand it better.
I am not going to show all the code, only what is needed for my example.
The main.js script:
require('dotenv').config();
const { Client } = require('discord.js');
const client = new Client();
const prefix = "++";
const fs = require('fs');
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('.src/commands/').filter(file => file.endsWith('.js'));
for(const file of commandFiles){
const command = require(`.src/commands/${file}`);
client.commands.set(command.name, command);
}
client.on('message', (message) => {
if(message.author.bot) return;
console.log(`[${message.author.tag}]: ${message.content}`);
if(!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
if(command === 'ping'){
client.commands.get('ping').execute(message, args);
});
The ping.js script:
module.exports = {
name: 'ping',
description: 'This is a ping command.',
execute(message, args){
message.channel.send('Pong!');
}
}
Images:
It just says any, I assume any variable type, I think... But this just seems messy and hard to follow.
main.js
https://gyazo.com/86f7118513df791743def98bcf052f06
ping.js
https://gyazo.com/06bb2e47a3fd39d2e4445591d8537131
Discord.js send() returns a Promise<(Message)> or Promise<(Array<Message>)> (discord.js docs for channel.send()). Promises are great for sequential tasks in any API but don't seem to be a data type recognized by your environment. If VSCode and IntelliJ (as well as many other IDE's) don't recognize the data type of your method's return value or if it isn't predefined (as it more commonly is in Java compared to JS functions or methods), they will highlight the method's return value as any.

How to have only one mongodb instance?

Im writting a node app to log some informations in a mongo database.
Below is the snippet code that called each time i need to store log in the mongo database.
const mongo = {}
const mongo_cli = require('mongodb').MongoClient
module.exports = {
log (l) {
mongo_cli.connect(the_mongo_url, (error, client) => {
if (error) throw error;
mongo.cli = client;
mongo.db = client.db(the_database);
//insert and update operations
});
}
}
The code above work for now. I mean, I can insert and update logs already inserted at the price of one (or more) connection (s) that I never close due to my lack of control of callback functions.
So, how can i structure it better so that i can just have only one mongo_cli call to not consume too many ressources ?

nodejs-dialogflow library returning TypeError: dialogflow.SessionsClient is not a constructor

I am trying to make a script that takes input from the user, runs it through Dialogflow, then returns it back to the user. The platform I am taking input from only supports Node.js. I am hosting the bot through glitch.com, but I don't think that's what's causing the issue. I wanted to check on here before I submit a bug report onto the GitHub repo.
var bot = 'the platform i use to accept inputs and send outputs'
bot.on("message", async message => {
console.log(message.content); // Log chat to console for debugging/testing
if (message.content.indexOf(config.prefix) === 0) { // Message starts with your prefix
let msg = message.content.slice(config.prefix.length); // slice of the prefix on the message
let args = msg.split(" "); // break the message into part by spaces
let cmd = args[0].toLowerCase(); // set the first word as the command in lowercase just in case
args.shift(); // delete the first word from the args
// You can find your project ID in your Dialogflow agent settings
const projectId = process.env.PROJECT_ID; //https://dialogflow.com/docs/agents#settings
const sessionId = 'quickstart-session-id';
var query = msg;
const languageCode = 'en-US';
// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient();
// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: languageCode,
},
},
};
// Send request and log result
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
})
.catch(err => {
console.error('ERROR:', err);
});
}
return;
});
That is the relevant part of the code. For those wondering, the process.env.PROJECT_ID is something glitch.com uses for anything private. Because I don't want random people getting their hands on my project id, I hide it in there and glitch hides it from anyone I don't explicitly invite.
Every time I execute this and try to query the bot, it returns an error Uncaught Promise Error: TypeError: dialogflow.SessionsClient is not a constructor.
If someone can direct me to what I'm missing, or what the problem is, that would be great!
As per #google-cloud/dialogflow - npm
IMPORTANT NOTE
Version 2.0.0 renames dialogflow to #google-cloud/dialogflow on npm, along with introducing TypeScript types.
So to update the dialogflow to use latest version, first uninstall dialogflow and then install with following command:
npm uninstall dialogflow
npm i #google-cloud/dialogflow
Also, if you were using older version 1.2.0 of dialogflow before then in code, make following changes as per their sample or refer the sample from above link (in require and to get the sessionPath):
const dialogflow = require('#google-cloud/dialogflow');
const sessionPath = sessionClient.projectAgentSessionPath(
projectId,
sessionId
);
It worked fine for me after doing this without any errors.
I figured it out. After many many refreshes, I decided to look at the npm documentation for it. Turns out some idiot listed the earliest version as 4.0.3, and the latest version as 0.7.0. I needed to explicitly tell it to use version 0.7.0 in order for it to work. Thank goodness!
Mine worked by reinstalling the dialogflow package
npm uninstall dialogflow
npm install dialogflow --save
put the code inside try and catch block. In my case by doing this, this error was removed.

Node.JS Child_Process Catching Password Prompt

How do I use node.js child_process to programatically allow me to supply a password.
const spawn = require('child_process').spawn;
const ls = spawn('sudo ls');
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
The above throws an error. I am trying to figure out where exactly I can catch where it is wanting the password input and supply that via an environment variable.
I am hoping I can catch when it says Password check to make sure its saying that and then pass the password.
The error is because you're using the spawn command incorrectly.. It should be:
const ls = spawn('sudo', ['ls']);
Arguments to the child process are specified as the second argument (in an array).
You should then see the prompt for password, and I imagine be able to write to stdin to enter the password (which you're wanting to pass from process.env based on what you've said).
Edit: Quick search on SO seems to suggest it may not be as straight forward as writing to stdin after the prompt..

Categories

Resources