I create a sort of a company forum. Users can create post to share an information. To do so and at the moment, they complete a form with a basic textarea. My problem is that when they write a word with an apostrophe, the code interpret the apostrophe as single quote and it create en exception. I show you the code and an exemple below.
Html :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
</head>
<body>
<div id="admin">
<div v-if="seenNews" id="news">
<div class="form">
<h4>Create a post</h4>
<form class="newPost" action="/newPost" method="POST">
<label id="titleLabel" for="titleInput">Title : </label>
<input type="text" id="titleInput" name="titleInput" required>
<label id="contentLabel" for="contentInput">Content : </label>
<textarea id="contentInput" name="contentInput" cols="40" rows="5" required></textarea>
<button type="submit">Create</button>
</form>
</div>
</div>
</div>
</body>
</html>
Back-end javascript :
app.js
const Server = require('./server/Server');
const express = require('express');
const DAO = require('./server/DAO');
const server = new Server();
server.start();
const dao = new DAO();
dao.connect();
server.app.post("/newPost", function(req, res) {
try {
dao.newPost(req.body.titleInput, req.body.contentInput).then(value => {
res.redirect('/Admin');
})
} catch (e) {
console.log(e);
}
})
DAO.js
const sql = require('mssql');
class DAO {
constructor() {
this.sqlConfig = {
user: 'username',
password: 'password',
server: 'SERVER',
port:port,
database: 'DB',
options: {
enableArithAbort: false,
encrypt:false
}
}
}
async newPost(title, content) {
try {
let req = 'INSERT INTO DB.dbo.[Table] (title, content) VALUES (\''+title+'\',\''+content+'\')';
console.log(req);
await sql.query(req).then(value => {
return true;
});
} catch (e) {
console.log(e);
return false;
}
}
}
As exemple, if a user create a post with this content : Ms. Smith's keys are at the reception desk, I would have this in console :
RequestError: Unclosed quotation mark after the character string ')'.
Maybe if I create a function to find en encode the character it can fix it, but I don't see how I can do so.
I finally use the JS function replace() to replace simple quote in my string by two simple quote. '' is the equivalent of js \' in sql server.
'INSERT INTO PROFACE.dbo.[Posts] (title, content) VALUES (\''+title.replace(/'/gi,"''")+'\',\''+content.replace(/'/gi,"''")+'\')'
Related
Any help appreciated. I've got an app that pulls data from google books api. From each book page, the user is able to leave a review. The path to the review is /review/${isbn Number}. Each page has a path based on the isbn. The review routes work and I'm able to make the post request through insomnia/postman with no issues, I'm just having trouble with the front-end js in pulling the data from the input boxes to make the post request. I'm not sure if the issue is because the isbn being in the path. Below is my front-end javascript that I am unable to fix.
const newFormHandler = async (event) => {
event.preventDefault();
console.log("testing")
const description = document.querySelector('#description').value;
const reviewTitle = document.querySelector('#reviewTitle').value;
const isbn = window.location.search
if (description) {
const response = await fetch(`api/review/${isbn}`, {
method: 'POST',
body: JSON.stringify({ description, reviewTitle }),
headers: {
'Content-Type': 'application/json',
},
});
if (response.ok) {
document.location.reload();
} else {
alert('Failed to create review');
}
}
};
document
.querySelector('.form-group')
.addEventListener('submit', newFormHandler);
My form is below:
<div class="col form-group">
<div class ="card reviewCard" style = "background-color:#fcf8f3; color: #65625e;">
<form id="blog-form">
<div>
<label for="reviewTitle">Review Title</label>
<input
value="{{title}}"
id="reviewTitle"
name="reviewtitle"
placeholder="Enter Review Title"
type="text"
required="required"
class="form-control"
data-bv-notempty="true"
data-bv-notempty-message="The title cannot be empty"
/>
</div>
<div>
<label for="review">Review</label>
<textarea
id="description"
name="review"
cols="40"
rows="10"
required="required"
class="form-control"
>{{description}}</textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
</div>
</div>
And here is my route that works fine with insomnia, no issues.
router.get('/review/:id', async (req, res) => {
try {
const isbn13 = req.params['id'];
const reviewData = await Review.findAll({ where: {
isbn:isbn13
},
include: [
{
model: User,
attributes: ['name'],
}
]
})
const reviews = reviewData.map((review) => review.get({ plain:true}));
// console.log(isbn13);
res.render('review', {
isbn: isbn13, reviews:reviews
});
} catch (err) {
console.log(err)
}
});
Any help appreciated. I tried to pull in the isbn number from the path, but with no success. I think I have it formatted wrong somehow.
First console log your req
You should see the body containing some data.
In a get request the they are arguments in the URL.
In a Psot request they are in the body of the request.
I am new to working with databases. I've been trying to create a login/register webpage using only HTML, Js and MongoDB in my codes in order to practice. I have successfully made a function for login, yet I've been struggling to create a function for registering using the Fetch API.
I am aware that my register code is used rather for a login function, but I used it as a template for the sign up one.
I'd appreciate it if anyone can help me fix the register function using Fetch() in order to not give me 401 and to be able to add the new user's email and password to my database. Thank you.
const btnAccount = document.querySelector('.account .submit')
btnAccount.addEventListener('click', event => {
event.preventDefault()
const email = emailAccount.value
const pass = passAccount.value
const pass2 = pass2Account.value
if (email && pass && pass2) {
if (pass === pass2) {
// The data i wish to add to my mongoDB users database:
const account = {
strategy: "local",
email : emailAccount.value,
password: passAccount.value
}
fetch('http://localhost:3030/authentication', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(account)
}).then(response => {
return response.json()
}).then(result => {
console.log(result)
document.forms[1].reset();
})
.catch(err => {
// If I got some errors regardings the DB or in the code itself:
console.log('eroare:', err)
alert(`Something's wrong. I can feel it!`)
})
}
else {
// Passwords not the same:
alert('Parolele nu coincid!')
}
}
else {
// Not all fields written:
alert('Completeaza bah campurile...')
}
})
<main>
<form class="account">
<div>
<label for="email">Email:</label>
<input required type="email">
</div>
<div>
<label for="password">Password:</label>
<input required type="password" class="password">
</div>
<div>
<label for="password2">Verify Password:</label>
<input type="password" class="password2">
</div>
<div>
<button class="submit">Create new account</button>
</div>
<div>
I already have an account
</div>
</form>
<button class="fetchItems">Load ITEMS</button>
<div class="output"></div>
</main>
I have a custom form that makes a few requests to a database to verify the user. I noticed that if I have a single google account it works fine but it doesn't with multiple. The other thing I noticed is that the script doesn't throw any error it just doesn't communicate back the result from the custom form.
This is how my custom forms look like:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div class="container select-client">
<div class="client">Client</div>
<select class="client-select">
<option>Select Client</option>
<!-- ...options -->
</select>
<div class="market">Market</div>
<select class="market-select">
<option>Select Market</option>
<!-- ...options -->
</select>
<div class="error-message"></div>
<button class="button" id="select-button" onclick="handleSelect()">Select</button>
</div>
<script>
// ...code to validate the user
function handleSelect() {
var _client = clients.find(
(client) => client.id === parseInt(selectedClient)
);
var _market = markets.find(
(market) => market.id === parseInt(selectedMarkets)
);
if (!_client && !_market) {
return;
}
if (!_client) {
errorMessageClientMarket.innerHTML = 'Please select client';
return;
}
if (!_market) {
errorMessageClientMarket.innerHTML = 'Please select market';
return;
}
google.script.run
.withSuccessHandler()
.loginData({ token, market: _market, client: _client, user: userInfo, platform });
google.script.host.close();
}
</script>
</body>
</html>
This is how I create the custom form using app script
const loginForm = () => {
const html = HtmlService.createHtmlOutputFromFile('loginFormHtml')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
.setWidth(600)
.setHeight(600);
const ui = SpreadsheetApp.getUi();
ui.showModalDialog(html, `Login`);
};
This is the callback function:
const loginData = (data) => { // <--- this function is ignored when a the users has multiple google accounts
console.log('LOGIN FORM');
const { token, market, user, client, platform } = data;
UserProperties.setProperty('token', token);
UserProperties.setProperty('userId', user.id);
UserProperties.setProperty('clientId', client.id);
UserProperties.setProperty('clientName', client.name);
UserProperties.setProperty('marketId', market.id);
UserProperties.setProperty('marketName', market.code_name);
UserProperties.setProperty('username', `${user.first_name} ${user.last_name}`);
UserProperties.setProperty('userEmailAddress', user.email);
UserProperties.setProperty('platform', platform);
const info = UserProperties.getProperties();
console.log('info ---> ', info)
const ui = SpreadsheetApp.getUi();
getMenu(true);
ui.alert('Logged in Successfully');
};
Does anyone know if there's a away to fix this?
Description
I have a table, where i collect values from checkboxes with JavaScript. This values should be send to a protected API route in a Laravel backend.
I use the standard Laravel auth setup (out of the box).
Question
What do I have to send with the JavaScript post request for authentication and how do i do that? Can i add a auth token or something like that to the headers?
At the moment i get the reponse:
"This action is unauthorized".
exception: "Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException"
Edit
At the current point of my research the api token seems to be a simple solution for my case. But i can't figure out how to attach the api token to the JavaScript post request.
Thats the JavaScript function for collecting the values storing them in objects.
import SaveData from "../api/SaveData";
export default async function SaveMultipleReports() {
const table = document.getElementById("reports-dashboard");
const rows = table.querySelectorAll("div[class=report-tr]");
let reports = [];
for (const row of rows) {
const checkbox_visible = row.querySelector("input[name=visible]")
.checked;
const checkbox_slider = document.querySelector(
"input[name=show_in_slider]"
).checked;
const report = {
id: row.id,
visible: checkbox_visible,
show_in_slider: checkbox_slider
};
reports.push(report);
}
console.log(reports);
const response = await SaveData("/api/reports/update", reports);
console.log(response);
}
And that is the SavaData function:
export default async function SaveData(api, data) {
const token = document
.querySelector('meta[name="csrf-token"]')
.getAttribute("content");
const url = window.location.origin + api;
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": token,
Accept: "application/json"
},
body: JSON.stringify(data)
});
const result = await response.json();
return result;
}
And thats the line in the api.php:
Route::middleware("can:administration")->post("reports/update", "ReportsController#UpdateAll");
The whole repo is here.
Thanks for your time in advance :)
Edit 2
For now i managed it without JavaScript. Put all the values, i want to update in form and load a hidden input for the ID of every object (the ID is needed for the controller afterwards).
Thanks to this post.
{!! Form::open(["route" => ["admin.reports.multiupdate"], "method" => "PUT", "class" => "report-table"]) !!}
... // some HTML
#foreach ($reports as $report)
<div class="report-tr">
<input type="hidden" name="reports[{{$loop->index}}][id]" value="{{$report->id}}">
<div class="td-name">
<p class="td-text">{{$report->name}}</p>
</div>
<div class="td-flex">{{$report->body}}</div>
<div class="tr-wrapper">
<div class="checkbox-visible">
<div class="checkbox-container">
<input class="checkbox" type="checkbox" name="reports[{{$loop->index}}][visible]" value="1" checked>
<span class="checkmark"></span>
</div>
<label class="table-label" for="visible">Sichtbar</label>
</div>
<div class="checkbox-slider">
<div class="checkbox-container">
<input class="checkbox" type="checkbox" name="reports[{{$loop->index}}][show_in_slider]" value="1"
{{($report->show_in_slider == 1 ? "checked" : "")}}>
<span class="checkmark"></span>
</div>
<label class="table-label" for="show_in_slider">Im Slider</label>
</div>
<div class="td-buttons">
...
#endforeach
<button class="floating-save">
#svg("saveAll", "saveAll")
</button>
{!! Form::close() !!}
And a snippet from the Controller:
public function MultipleUpate(ReportUpdate $request)
{
$reports = $request->input("reports");
foreach ($reports as $row) {
$report = Report::find($row["id"]);
// giving the checkbox 0, if it isn't checked
$isVisible = isset($row["visible"]) ? 1 : 0;
$inSlider = isset($row["show_in_slider"]) ? 1 : 0;
$report->visible = $isVisible;
$report->show_in_slider = $inSlider;
$report->new = false;
if ($report->save()) {
$saved = true;
}
}
if ($saved == true) {
$request->session()->flash("success", "Ă„nderungen gespeichert!");
} else {
$request->session()->flash("error", "Das hat nicht geklappt!");
}
return back();
The ReportUdpate function contains only that:
public function authorize()
{
return true;
}
public function rules()
{
return [
"visible" => "nullable",
"show_in_slider" => "nullable"
];
}
You are talking about authentication but using an authorization middleware. There is a difference between the two.
Read about it here: https://medium.com/datadriveninvestor/authentication-vs-authorization-716fea914d55
With that being said, what you are looking for is an authentication middleware that protects your routes from unauthenticated users. Laravel provides a middleware called Authenticate out of the box for this specific purpose.
Change your route to be like so:
Route::middleware("auth")->post("reports/update", "ReportsController#UpdateAll");
I'm trying to integrate Chargebee with Braintree using ChargeBee's API+BraintreeJS (easiest to get PCI compliance). Here is the link of methods that could be used (https://www.chargebee.com/docs/braintree.html). Based on that document, I can conclude that these are the steps
1) Generate clientToken using Braintree SDK for .NET
2) Use BraintreeJS to tokenize all hosted fields and send to Braintree API to get payment nonce
3) Use ChargeBee SDK for .NET and send payment nonce to create subscription in ChargeBee
I've managed to do (1) and (2) but my issue is how could I read the payment nonce during postback? I've tried using controller but still getting null value
Here's my code
<script>
var form = document.querySelector('#cardForm');
var authorization = '<%=clientToken%>';
braintree.client.create({
authorization: authorization
}, function (err, clientInstance) {
if (err) {
console.error(err);
return;
}
createHostedFields(clientInstance);
});
function createHostedFields(clientInstance) {
braintree.hostedFields.create({
client: clientInstance,
styles: {
'input': {
'font-size': '16px',
'font-family': 'courier, monospace',
'font-weight': 'lighter',
'color': '#ccc'
},
':focus': {
'color': 'black'
},
'.valid': {
'color': '#8bdda8'
}
},
fields: {
number: {
selector: '#card-number',
placeholder: '4111 1111 1111 1111'
},
cvv: {
selector: '#cvv',
placeholder: '123'
},
expirationDate: {
selector: '#expiration-date',
placeholder: 'MM/YYYY'
},
postalCode: {
selector: '#postal-code',
placeholder: '11111'
}
}
}, function (hostedFieldsErr, hostedFieldsInstance) {
if (hostedFieldsErr) {
console.error(hostedFieldsErr);
return;
}
submit.removeAttribute('disabled');
form.addEventListener('submit', function (event) {
event.preventDefault();
hostedFieldsInstance.tokenize(function (tokenizeErr, payload) {
if (tokenizeErr) {
console.error(tokenizeErr);
return;
}
// If this was a real integration, this is where you would
// send the nonce to your server.
var noncestr = payload.nonce
alert(noncestr); // Confirm nonce is received.
console.log('Got a nonce: ' + payload.nonce);
$('#paymentmethodnonce').attr("value", noncestr); // Add nonce to form element.
form.submit();
});
}, false);
});
}
</script>
<body>
<div class="demo-frame">
<form action="/" method="post" id="cardForm">
<label class="hosted-fields--label" for="card-number">Card Number</label>
<div id="card-number" class="hosted-field"></div>
<label class="hosted-fields--label" for="expiration-date">Expiration Date</label>
<div id="expiration-date" class="hosted-field"></div>
<label class="hosted-fields--label" for="cvv">CVV</label>
<div id="cvv" class="hosted-field"></div>
<label class="hosted-fields--label" for="postal-code">Postal Code</label>
<div id="postal-code" class="hosted-field"></div>
<div class="button-container">
<input type="submit" class="button button--small button--green" value="Purchase" id="submit" />
</div>
<asp:Label runat="server" ID="lblResult"></asp:Label>
</form>
</div>
<script src="https://js.braintreegateway.com/web/3.8.0/js/client.js"></script>
<script src="https://js.braintreegateway.com/web/3.8.0/js/hosted-fields.js"></script>
</body>
</html>
public partial class Default : System.Web.UI.Page
{
protected string clientToken;
private BraintreeGateway gateway = new BraintreeGateway
{
Environment = Braintree.Environment.SANDBOX,
MerchantId = "xxx",
PublicKey = "xxx",
PrivateKey = "xxx"
};
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//generate clienttoken from braintree sdk
clientToken = gateway.ClientToken.generate();
}
else
{
var paymentnonce = Request.Form["paymentmethodnonce"];
}
}
}
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
The callback that you pass to hostedFieldsInstance.tokenize uses a css selector to find an element with ID paymentmethodnonce and store the generated nonce inside of it. However, there's no element with that ID in the HTML that you submitted. Based on the HTML you've shared, that call should fail, and your subsequent attempt to retrieve paymentmethodnonce using Request.Form will also fail.
You should be able to solve this by adding a hidden input element to your form with the id paymentmethodnonce.
<input type="hidden" id="paymentmethodnonce" />
This will give your tokenize callback a place to put the nonce, and it will make the nonce part of the form, which should allow your Request.Form to retrieve it successfully.