creating DELETE request using nodejs on sql database - mysql

New to node.js and learning how to use mysql with node. I have a form.html that has two buttons to input a department_no and a department_name. I am succecfully able to insert into mysql database but I have no clue on how to delete a specific dept_no. What I want to be able to do is enter a dept_no and the dept_name and then DELETE from my database based on the dept_no. Also I want to be able to check what the user enters to make sure that it is a valid dept_no and dept_name. Any ideas on how to get started or what to look into to be able to do this would be extremely helpful. I will paste my node.js and form.html down below.
node.js
// DELETE BELOW
app.delete("/deleteEmp/", (req, res) => {
console.log("Department number is " + req.body.department_no);
console.log("Department name is " + req.body.department_name);
const deptNumber = req.body.department_no;
const deptName = req.body.department_name;
const connection = mysql.createConnection({
host: "localhost",
user: "root",
database: "employees"
});
const queryString = "DELETE departments WHERE dept_no = ?";
connection.query(queryString, [department_no], (err, results, fields) => {
if (err) {
console.log("Could not delete" + err);
res.sendStatus(500);
return;
}
console.log("Deleted department_no with dept_name");
res.end();
});
});
form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>SQLFORM</title>
<style>
#space {
margin-top: 20px;
}
</style>
</head>
<body>
<div>Fill Form Below</div>
<hr />
<div id="space">
<form action="/deleteEmp" method="DELETE">
<input placeholder="Enter Department Number" name="department_no" />
<input placeholder="Enter Department Name" name="department_name" />
<button>Submit</button>
</form>
</div>
</body>
</html>

HTML forms do not support DELETE requests in general. Node apps can use a work-around like this one - https://github.com/expressjs/method-override

Another alternative is to perform an AJAX request that doesn't have restrictions on allowed methods. A simplified example:
document.querySelector('#space form').addEventListener('submit', (event) => {
event.preventDefault();
let formData = new FormData();
formData.append('department_no', document.querySelector("input[name='department_no']").value);
formData.append('department_name', document.querySelector("input[name='department_name']").value);
fetch('https://yoururl.com/deleteEmp', {
method: 'DELETE',
headers: {
"Content-type": "application/x-form-urlencoded"
},
body: formData
});
});

Related

GAS troubles with cors and fetching data to spreadsheet from html

I need to send data from html form to spreadsheet, but I got mistake after clicking button.
I tried to copy the steps from this video
https://www.youtube.com/watch?v=yiPnkBEHqf0&list=PLRmEk9smitaVGAAhgU0Pdc2sEs7yxDrEk
in js and html I wrote this:
const url = "https://script.google.com/macros/s/AKfycbzZe824lIxa-hNsO71xoFfq5qXbFaDKhHZeACrQgLMCjU_EjvY/exec";
var loginText = document.getElementById("tLogin");
var tableText = document.getElementById("tTable");
var orderText = document.getElementById("tOrder");
//var kommText = document.getElementById("tKomm");
function testGS(){
var userInfo = {
login: loginText.value,
table: tableText.value,
order: orderText.value,
tdate: new Date().toLocaleDateString(),
//komm: kommText.value,
};
fetch(url, {
method: 'POST',
//mode: 'no-cors', // no-cors, *cors, same-origin
body: JSON.stringify(userInfo)
})
.then((res) => res.text())
.then((res) => console.log(res));
console.log(userInfo);
}
document.getElementById("del").addEventListener("click", testGS);
<!doctype html>
<html lang="en">
<head>
<title>CLR: PACKING</title>
<meta charset = "UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="CSS/main_page_style.css">
<link rel="icon" href="Image/favicon.png" type="png">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
</head>
<body>
<div class="conteiner">
<form novalidate>
<h6 class="title">PACKING</h6>
<img src="Image/mainImg.jpg" class="img-fluid" alt="...">
<div class="dws-input">
<div class="col-md-3"></div>
<div>
<div>
<button id="del" type="button"><======СБРОС</button>
</div>
<div class="form-floating mb-3 mt-3">
<input type="text" class="form-control" novalidate id="tLogin" name= "username" placeholder= "Логин:" autofocus >
<label for="tLogin">Логин:</label>
</div>
<div class="form-floating mb-3 mt-3">
<input type="text" class="form-control" novalidate id="tTable" name= "text" placeholder= "Номер стола:" >
<label for="tTable">Номер стола:</label>
</div>
</div>
<div class="form-floating mb-3 mt-3">
<input type="text" novalidate class="form-control" id="tOrder" name= "text" placeholder= "Заказ:" >
<label for="type3">Заказ:</label>
</div>
</div>
</form>
</div>
<script src="JS/fetchNew.js"></script>
</body>
</html>
in apps script I wrote this:
function doGet() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("LOG_history");
const data = ws.getRange("A1").getDataRegion().getValues();
const headers = data.shift();
const jsonArray = data.map(r => {
let obj = {};
headers.forEach((h , i) => {
obj[h] = r[i];
});
return obj;
})
const response = [{status: 200, data: jsonArray}];
return sendJSON_(response);
}
function doPost(e){
let jsonResponse;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("LOG_history");
const headers = ws.getRange(1,1,1,ws.getLastColumn()).getValues()[0];
const headersOriginalOrder = headers.slice();
headersOriginalOrder.shift();
//remove id columns header
headers.shift();
headers.sort();
const body = e.postData.contents;
const bodyJSON = JSON.parse(body);
const headersPassed = Object.keys(bodyJSON).sort();
if(!compareTwoArray_(headers, headersPassed)){
jsonResponse = [{status:500, message:"Invalid Arguments Passed"}];
return sendJSON_(jsonResponse);
}
const arrayOfData = headerOriginalOrder.map(h => bodyJSON[h]);
const aoaIds = ws.getRange(2,1,ws.getLastRow()-1,1).getValues();
const newIDNumber = getMaxFromArrayOfArray_(aoaIds) + 1;
arrayOfData.unshift(newIDNumber);
ws.appendRow(arrayOfData);
return ContentService.createTextOutput("ok");
}
//return true if all ites are the same
function compareTwoArray_(arr1, arr2){
if (arr1.length !== arr2.length) return false;
for (let i = 0; i < arr1.length; i ++){
if (arr1[i] !== arr2[i]) return false;
}
return true;
}
function sendJSON_(jsonResponse){
return ContentService
.createTextOutput(JSON.stringify(jsonResponse))
.setMimeType(ContentService.MimeType.JSON);
}
//return the highest number / id
function getMaxFromArrayOfArray_(aoa){
let maxID = 0;
aoa.forEach(r => {
if (r[0] > maxID) maxID = r[0];
});
return maxID;
}
I aloweed all the permissions I know but I have this mistakes on picture with core and fetch. Help!!!
(Important edit at end)
Make sure you are only sending plain text information
Modify your function sendJSON_ to
function sendJSON_(jsonResponse){
return ContentService
.createTextOutput(JSON.stringify(jsonResponse))
// .setMimeType(ContentService.MimeType.JSON); // Remove this line
}
That or set it to .setMimeType(ContentService.MimeType.PLAIN_TEXT)
You can also try setting the header from the client-side JS to "Content-Type": "text/plain"
fetch(url, {
method: 'POST',
headers: {"Content-Type": "text/plain"},
body: JSON.stringify(userInfo)
})
.then((res) => res.text())
.then((res) => console.log(res));
This should then work without issues.
If you are still not getting success, and if you don't need a response from the web app, but just need to send info. You can activate no-cors. The request will get sent, but any response it gives will not be available to the client-side.
fetch(url, {
method: 'POST',
mode: 'no-cors',
body: JSON.stringify(userInfo)
})
.then((res) => res.text())
.then((res) => console.log(res));
Minimal Example:
Start a new project.
Paste this code into Apps Script:
function doPost(e) {
return ContentService.createTextOutput("ok");
}
Navigate to Deploy > New Deployment
Select type 'Web app'
Execute as: "Me".
Who has Access: "Anyone".
"Deploy"
Take a note of the exec URL.
On a local machine, in a local server or in the browser console execute:
url = "[YOUR_DEPLOYMENT_URL]"
fetch(url, {
method: 'POST',
headers: {"Content-Type": "text/plain"},
body: JSON.stringify({"test":1})
})
.then(r => r.text())
.then(t => console.log(t))
When I followed these steps, I get on the console:
ok
Reference
Using Fetch
Apps Script MIME TYPES
CORS
Edit
Even after making these changes it seemed that the CORS error persisted on the project.
After some debugging I found that simply by changing the property name in userInfo from tdate to anything else, made it work.
I don't know why tdate as a property in a strigified JSON would cause issues, but it seems to be a reserved word of sorts.
That said, I have tried to reproduce this issue in a new project and can't seem to do so!

Insert email with unique id node js

How am I working with nodejs, mysql, forEach trying to save the email in my DB with a unique id, using the textarea tag, based on this question
Insert multiple email to mysql using single textarea
For-each over an array in JavaScript
javascript split on non-alphanumeric an keep delemiters at start
<form class="" action="/registration/instudent/{{id_school}}/{{mat}}/{{grade}}" method="post">
<textarea name="email" ></textarea>
<button class="btn btn-lg">Save</button>
</form>
Using the example in PHP base, in my example.js file I have this code, try to save all three variables.
router.post('/instudent/:id_school/:mat/:grade', isLoggedIn, async (req,res) => {
const { id_school, mat, grade } = req.params;
const { email } = req.body;
var uStudent = {
id_school,
mat,
grade,
email
}
Object.keys(uStudent).forEach(function (key){
console.log(uStudent[key]);
db.query('INSERT INTO date set ?', uStudent);
});
//res.redirect('/');
});
When saving to my database, incorrectly insert the texts.
In my database it inserts me in this way.
Any guide to see what I am doing wrong and that every email in the textarea tag gets a unique id?
correct form
I can't find where in the code you are setting the email value to be save.
there are some question here:
You are looping base on your object keys(is this the correct behavior)?
where did you update the uStudent to update its email?
I think you should loop based on splitted email:
router.post('/instudent/:id_school/:mat/:grade', isLoggedIn, async (req,res) => {
const { id_school, mat, grade } = req.params;
const { emails } = req.body;
const uStudent = {
id_school,
mat,
grade
};
// loop base on email
let _emails = emails.split(/\r?\n/);
_emails.forEach(email => {
// update uStudent email field
uStudent.email = email;
// insert the uStudent
db.query('INSERT INTO date set ?', uStudent);
});
});

How can i upload audio file to Cloudinary with Node.js?

i deeply need help with this audio file upload to cloudinary issue I have had for several days now. I tried many times to make it work, but i am still struggling. I am a beginner backend developer, so please any help is appreciated.
It is an mp3 player App. When i upload a song, the title gets saved in DB, but the Audio isn't. This is the MP3 PLAYER page screenshot. It shows the title being saved and rendered from DB but not the audio file.
Audio upload form
<form class="ui form" action="/albums/<%= album._id %>/songs" method="POST" enctype="multipart/form-data">
<div class="field">
<label>Song Title:</label>
<input type="text" id="title" name="song[title]" placeholder="song title...." required>
</div>
<div class="field">
<label>Song file:</label>
<input type="file" id="song" name="audio" accept="audio/*" required>
</div>
<div class="field">
<input class="fluid ui green button" type="submit" id="submit" value="Enter">
</div>
Exit
</form>
Song model
var mongoose = require("mongoose");
//Album Schema
var audioSchema = new mongoose.Schema({
title: String,
audio: String,
date: {type: Date, default: Date.now()}
});
//exporting the Schema
module.exports = mongoose.model("Audio", audioSchema);
Backend code/ROUTE
var express = require("express"),
router = express.Router({mergeParams: true}),
middleware = require("../middleware"),
Album = require("../models/album"),
Song = require("../models/songs"),
multer = require("multer")
var storage = multer.diskStorage({
filename: function(req, file, callback) {
callback(null, Date.now() + file.originalname);
}
});
//uploader
var upload = multer({ storage: storage});
var cloudinary = require('cloudinary');
cloudinary.config({
cloud_name: 'proccess.env.CLOUDINARY_NAME',
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
});
//Songs new Route
router.get("/albums/:id/songs/new", middleware.isLoggedIn, function(req, res) {
//find Album by id
Album.findById(req.params.id, function(err, album) {
if(err) {
console.log(err);
} else {
res.render("songs/new", {album: album});
}
});
});
//Song POST route
router.post("/albums/:id/songs", middleware.isLoggedIn, upload.single("audio"), function(req, res) {
cloudinary.uploader.upload(req.file.path, function(result) {
// add cloudinary url for the mp3 to the album object under audio property
req.body.song.audio = result.secure_url;
//find Album by ID
Album.findById(req.params.id, function(err, album) {
if(err) {
console.log(err);
res.redirect("/albums/" + req.params.id);
} else {
//Creating Album and saving it to DB
Song.create(req.body.song, function(err, song) {
if(err) {
console.log("Opps something went wrong!" + err);
res.redirect("back");
} else {
//save the song to DB
song.save();
//this saves the songs object inside
album.songs.push(song);
//save album
album.save();
res.redirect("/albums/" + album._id);
}
});
}
});
});
});
module.exports = router;
cloudinary.uploader.upload(req.file.path, resource_type: "video", function(result)
That's because you will need to use GridFS from MongoDB to store data from a file.
https://docs.mongodb.com/manual/core/gridfs/#use-gridfs
As you are using Mongoose, please check this module : https://www.npmjs.com/package/mongoose-gridfs
The mongoose-gridfs module wrap the gridfs-stream module, and seems to fit to binary data upload. If you want, you can still do it yourself, by following this tutorial : http://niralar.com/mongodb-gridfs-using-mongoose-on-nodejs/

how to friend invite send to mail?

(Update)Hi all i want to invite friend sent to mail using Nodejs. Mainly server side user and pass which can be use? and mail also can't sent then i tried many ways but unable to get the solution if any one knows the solution please help me.....
myplunker
HTML:-
<div id="container">
<center>
<input id="to" type="text" placeholder="Enter E-mail ID" /><br><br>
<input id="subject" type="text" placeholder="Write Subject" /><br><br>
<textarea id="content" cols="40" rows="5" placeholder="Message"></textarea><br><br>
<button id="send_email">Send Email</button>
</center>
<span id="message"></span>
</div>
Server:-
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "Gmail",
use_authentication: true,
auth: {
user: "sample#gmail.com",
pass: "password"
}
});
app.get('/',function(req,res){
res.sendfile('index.html');
});
app.get('/send',function(req,res){
var mailOptions={
to : req.query.to,
subject : req.query.subject,
text : req.query.text
}
console.log(mailOptions);
smtpTransport.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
res.end("error");
}else{
console.log("Message sent: " + response.message);
res.end("sent");
}
});
});
The Following steps may help you:
Add var nodemailer=require("nodemailer") to the top of your server
script
Add var express=require("express"); var app=express() to the top of your server script
To Test that the email is being sent move what is in your app.get("/send") script outside the function and comment everything else (For Now) should Look similar to this:
var nodemailer=require("nodemailer");
var express=requre("express");
var app=express();
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "Gmail",
use_authentication: true,
auth: {
user: "email#domain.com",
pass: "PASS"
}
});
var mailOptions={
to : "email#domain.com",
subject :"SUBJECT",
text : "MESSAGE"
}
console.log(mailOptions);
smtpTransport.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
}else{
console.log("Message sent: " + response.message);
}
});
/*
app.get('/',function(req,res){
res.sendfile('index.html');
});
app.get('/send',function(req,res){
var mailOptions={
to : req.query.to,
subject : req.query.subject,
text : req.query.text
}
console.log(mailOptions);
smtpTransport.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
res.end("error");
}else{
console.log("Message sent: " + response.message);
res.end("sent");
}
});
});*/
Make sure you have this turned on for the email you are trying to send an email with: https://www.google.com/settings/security/lesssecureapps
Make Sure your version of nodemailer is correct, It should be 0.71v for the setup you have: How to downgrade this node.js module to specific version and prevent automatic upgrade later?
Run the server script with a terminal: node fileName.js (If none of the tips help could you please copy the error stack?)
If everything works uncomment everything and delete the mailOptions and smtpTransport that are outside the app.get. Everything should work now...
Good Luck, And I'll be happy to help if you have any more problems.

HTML POST Request doesn't send all the data

I am using Node.js + Express.js to build a very basic search engine for a Library database. My HTML has a POST form that sends either a title or keyword to the app in order to query a MySQL database for the book/books. The search by title is working fine but the keyword is giving me a hard time. See below.
HTML
<form id="searchForm" action="" method="post">
<select class="form-control" id="searchType">
<option class="" value="0">Search by title</option>
<option class="" value="1">Search by keyword</option>
</select>
<select class="form-control" id="titles" name="titles">
<% for (var title in titles) {;%>
<option class=""><%=titles[title].TITLE%></option>
<% }; %>
</select>
<textarea class="form-control" name="keyword" contenteditable="false" id="keyword" placeholder="Enter keyword here..."></textarea> <!-- placeholder is only supported in a few browesers
(Firefox 3.7+, Chrome, Safari, IE 10). Could use
jQuery but ah-->
<input class="btn btn-default" type="submit" value="Search"></input>
</form> <!-- /searchForm -->
Express code
app.post('/getBooksByTitle', function (req, res) {
connection.getConnection(function(err, tempCon) {
if (err) {
tempCon.release();
console.log('ERROR IN SQL CONNECTION!');
}
else {
console.log('CONNECTED TO SQL');
tempCon.query('SELECT * FROM BOOKS WHERE TITLE=?', req.body.titles, function(err, rows) {
if (err) {
console.log('BAD QUERY');
}
else {
console.log(req.body.titles);
res.json(rows);
}
tempCon.release();
});
}
});
});
app.post('/getBooksByKeyword', function (req, res) {
connection.getConnection(function(err, tempCon) {
if (err) {
tempCon.release();
console.log('ERROR IN SQL CONNECTION!');
}
else {
console.log('CONNECTED TO SQL');
tempCon.query('SELECT * FROM BOOKS WHERE (AUTHOR LIKE ? || TITLE LIKE ? || GENRE LIKE ? || DESCRIPTION LIKE ?)', '%' + req.body.keyword + '%', function(err, rows) {
if (err) {
console.log('BAD QUERY');
console.log(req.body);
}
else {
res.json(rows);
console.log(req.body.keyword);
}
tempCon.release();
});
}
});
});
I am pulling the form data to node with req.body.(field_name) but it doesn't seem to gather the text box. If I console.log(req.body) I see only the title field. Where have I messed up?
EDIT: The jQuery script that handles the action and some animations.
$(document).ready(function () {
toggleFields(); //call this first so we start out with the correct visibility depending on the selected form values
//this will call our toggleFields function every time the selection value of our searchType field changes
$("#searchType").change(function () {
toggleFields();
});
});
//this toggles the visibility of our input fields depending on the current selected value of the searchType field.
//also it toggles the action of the submit form to the appropriete post call.
function toggleFields() {
if ($("#searchType").val() == 0) {
$("#searchForm").attr('action', '/getBooksByTitle');
$("#titles").slideDown();
$("#keyword").slideUp();
}
else {
$("#searchForm").attr('action', '/getBooksByKeyword');
$("#titles").slideUp();
$("#keyword").slideDown();
}
}
Thanks for the help you tried to provide. I fixed the problem by changing the <textarea> field to an <input> field. Now the post sends both my title and keyword back to the server.