I have a nodejs application,where I want user to go to login page by default if he tries to access any route or any file(html/js).If the credentials are correct he should go to /index page. I've added post call in my main app.js file and it is working from postman,but unaware of how to use in my node app itself.
app.js
app.get('*',function (req, res) {
res.redirect('/login');
res.sendFile(path.join(__dirname+'/login/login.html'));
});
app.get('/index',function(req,res){
res.sendFile(path.join(__dirname+'/index/index.html'));//on success of login it should be here
});
app.post('/login',function(req,res){
var username = req.headers.uname;
var password = req.headers.pwd;
var uname = "*****";
var pwd = "*******";
var login = false;
if(uname == username && pwd == password){
console.log("success");
login = true;
}
else{
console.log("fail");
login = false;
}
if(login == true){
res.send("Hello");//It should route to my /index page
}else{
res.send("Bad luck"); //Invalid credentials
}
});
In login folder I have my login.html and my login .js
login.html
<html>
<head>
<script src="/login.js"></script>
</head>
<body>
<div>
Username:<input type="text" id="uname">
</div>
<div>
Password:<input type="text" id="pwd">
</div>
<div>
<button type="submit" onclick="login();">Login</button>
</div>
</body>
</html>
How can I call login function so that it uses the above post call from my app.js and on success it goes to index page and also by default it should go to login page..Can some one help here
You need to use a middleware in node. In your case, let's call it auth, it will check the credentials, if they are correct it will call the next handler in the chain, if not, it will issue a response with 401 (or 403 if forbidden) status code to the client.
Related
<!-- begin snippet: js hide: false console: true babel: false -->
var unSubscribe=firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
window.location.replace("library.html");
var user = firebase.auth().currentUser;
if(user != null){
var email_id = user.email;
//document.getElementById("user_para").innerHTML = "Welcome User : " + email_id;
}
} else {
// No user is signed in.
window.location.replace("index.html");
}
unSubscribe();
});
function login(){
var userEmail = document.getElementById("email_field").value;
var userPass = document.getElementById("password_field").value;
firebase.auth().signInWithEmailAndPassword(userEmail, userPass).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
window.alert("Error : " + errorMessage);
// ...
});
}
function logout(){
firebase.auth().signOut();
}
<html>
<head>
<title>Firebase Login</title>
<link href="https://fonts.googleapis.com/css?family=Nunito:400,600,700" rel="stylesheet">
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="login_div" class="main-div">
<h3>Firebase Web login Example</h3>
<input type="email" placeholder="Email..." id="email_field" />
<input type="password" placeholder="Password..." id="password_field" />
<button onclick="login()">Login to Account</button>
</div>
<script src="https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.8.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.8.0/firebase-firestore.js"></script>
<script>
// Initialize Firebase
var firebaseConfig = {
apiKey: ,
authDomain: ,
databaseURL: ,
projectId: ,
storageBucket: ,
messagingSenderId:,
appId: ,
measurementId:
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
</script>
<script src="index.js"></script>
</body>
</html>
(library.html also has the same script tags.)
I have seen similar questions and the answers to them were to call the function returned by firebase.auth().onAuthStateChanged(), so I implemented that but the index.html page keeps reloading multiple times. I have implemented the functionality for a single html page by hiding and displaying elements and it worked fine before.
I have also tried inserting the window.location.replace() in the login and logout functions but that on browser gives a blank html page and no errors on inspect.
Please help me with the issue, I am a beginner at javascript and web development.
You say both HTML pages have the same script running. So when you redirect to either page, the code will run again, trying to redirect you again.
If this is indeed the problem, a quick fix might be to pass a query param like redirect=true, and then only execute the code when this param is false.
window.location.replace("library.html?redirect=true");
then parse your url with a regex f.e.
const wasRedirected = new Regex(/[?&]redirect=(true|false)/g).exec(window.location)[1] === 'true'
firebase.auth().onAuthStateChanged() function sets an observer on the Auth Object. And as an observer, it continuously checks for the state of the authorization. That's why the index.html page keeps on reloading. The solution is to call the onAuthStateChanged() function only one time when your window reloads for the first time. Add the following code in the index.js file.
window.onload = unSubscribe;
Hope it helps.
I have had an issue with getting the google scripts page to redirect back towards my custom URL. The script currently executes but I cant get it to redirect back to its previous page after it is finished executing.
Heres the script.gs code:
function doPost(e) {
try {
Logger.log(e); // the Google Script version of console.log see: Class Logger
record_data(e);
// shorter name for form data
var mailData = e.parameters;
var name= String(mailData.name);
var message= String(mailData.message);
var email= String(mailData.email);
var all= ("Name: "+name+"\nReply address: "+email+"\nMessage: "+message);
// determine recepient of the email
// if you have your email uncommented above, it uses that `TO_ADDRESS`
// otherwise, it defaults to the email provided by the form's data attribute
var sendEmailTo = (typeof TO_ADDRESS !== "undefined") ? TO_ADDRESS : mailData.formGoogleSendEmail;
MailApp.sendEmail({
to: String(sendEmailTo),
subject: String(mailData.subject),
replyTo: String(mailData.email), // This is optional and reliant on your form actually collecting a field named `email`
body: String(all)
});
doGet();
return HtmlService.createHtmlOutput('xxxxxxxxxx.com');
} catch(error) { // if error return this
Logger.log(error);
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": error}))
.setMimeType(ContentService.MimeType.JSON);
}
}
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
Here is my HTML code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="2;url=xxxxxxxxxx.com" />
<base target="_top">
</head>
<body>
Click here to go back.
</body>
</html>
What would be the best way to make the script open the index.html page so I could easily redirect back to the custom URL?
Here's a working example of redirecting after processing a POST request.
Code.gs
var REDIRECT_URL = "http://www.stackoverflow.com";
function doPost(e) {
Logger.log("POST request");
Logger.log(e)
return redirect();
}
function doGet() {
Logger.log("GET request");
var template = HtmlService.createTemplateFromFile("form");
template.url = ScriptApp.getService().getUrl();
return template.evaluate();
}
function redirect() {
return HtmlService.createHtmlOutput(
"<script>window.top.location.href=\"" + REDIRECT_URL + "\";</script>"
);
}
form.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form action="<?= url ?>" method="post">
<input type="text" name="test_field" value="test data">
<button type="submit">Submit form</button>
</form>
</body>
</html>
Usage
When I visit the published web app (i.e. using a GET request), I'm presented with the simple form.
Submitting that form (i.e. using a POST request), I'm immediately redirected to http://www.stackoverflow.com.
This output is captured in the script log:
[18-06-19 10:39:04:731 PDT] POST request
[18-06-19 10:39:04:732 PDT] {parameter={test_field=test data}, contextPath=, contentLength=20, queryString=, parameters={test_field=[test data]}, postData=FileUpload}
Regarding your code sample, you have:
doGet();
return HtmlService.createHtmlOutput('xxxxxxxxxx.com');
That doesn't make sense as you're not doing anything with the results of doGet(). In order to make the doGet() call useful, replace the above with the following:
return doGet();
I have a Synology DS212j and already set up the apache and now also SSO Server. In the SSO Server Settings I added a new Application (Name, REdirect URI). My Code now is:
<html>
<head>
<!-- include Synology SSO js -->
<script src="http://NASADRESSE:5555/webman/sso/synoSSO-1.0.0.js"></script>
</head>
<body>
<script>
function setButton (logged) {
if (logged) {
document.getElementById('button').innerHTML = '<button onclick="SYNOSSO.logout()">Logout</button>';
} else {
document.getElementById('button').innerHTML = '<button onclick="SYNOSSO.login()">Login</button>';
}
}
function authCallback(reponse) {
console.log(JSON.stringify(reponse));
if (reponse.status == 'login') {
console.log('logged');
setButton(true);
}
else {
console.log('not logged ' + reponse.status);
setButton(false);
}
}
SYNOSSO.init({
oauthserver_url: 'NASADRESSE:5555',
app_id: '9a23da153795803e0334d9873b0013dd',
redirect_uri: 'NASADDRESSE/?redirect',
callback: authCallback
});
</script>
<h1> Syno SSO test</h1>
<p id='button'></p>
</body>
</html>
NASADRESSE is correct and my Rooter redirect port 5555 to 5000. Wenn I click login, a popup window opens where I can loggin with my NAS user. But it always says its a wrong password. But I entered the right one.
Why in your script link included .ch but in your config the domain have no .ch
http://NASADRESSE.ch:5555/webman/sso/synoSSO-1.0.0.js
SYNOSSO.init({
oauthserver_url: 'NASADRESSE:5555',
app_id: '9a23da153795803e0334d9873b0013dd',
redirect_uri: 'NASADDRESSE/?redirect',
callback: authCallback
});
May it go with wrong config?
1 - install the Directory Server package, enable LDAP server
2 - configure your DSM to connect to it (Control Panel-> Domain/LDAP)
3 - connect using the LDAP users
Task
Perform a POST request from a JS method, so that variable values can be sent as parameters.
Environment
NodeJS
Express
BodyParser
ejs
My first attempt
Frontend:
<html>
<head>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js'></script>
<script type="text/javascript">
function postAnswer() {
$.post('vote', { message: "hello!"}, function(returnedData) {
console.log("Post returned data: " + returnedData);
});
}
</script>
</head>
<body>
<button id='send' onClick='postAnswer()' class='btn btn-success btn-xs'>Svara</button>
</body>
</html>
Server.js:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser());
require('./app/routes.js')(app);
app.set('view engine', 'ejs');
app.use('/public', express.static(__dirname + '/public'));
var server = require('http').createServer(app);
server.listen(8080);
console.log('Server running on port 8080...');
routes.js:
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('vote.ejs', {
message: ''
});
});
app.post('/vote', function(req, res) {
var msg = req.body.message;
console.log("Got POST request with message: " + msg);
res.render('index.ejs', {
message: ''
});
});
};
Result:
The render method won't render a new page. It will however return the entire 'index.ejs' file in the returnedData parameter.
Server:
Client:
Second attempt:
<html>
<head>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js'></script>
<script type="text/javascript">
function postAnswer() {
$.post('vote', { message: "hello!"}, function(returnedData) {
console.log("Post returned data: " + returnedData);
});
return false;
}
</script>
</head>
<body>
<form action='/vote' method='post'>
<button id='send' type='submit' onsubmit='return postAnswer()' class='btn btn-success btn-xs'>Svara</button>
</form>
</body>
</html>
Result:
This does work, but it's not a very clean solution.
My questions:
Why doesn't the first attempt work?
How can I send variables as parameters to a POST request with a nice clean solution?
I'm not a jQuery expert, but I think the first attempt doesn't work because $.post makes an AJAX request, the same way as you would in a single-page app to interact with an API in the background.
Your second example submits a form, which is an in-browser action that performs a navigation action (as specified by the method attribute of the form). In this case, the event listener you add in jQuery is redundant, and should be removed - it's making another background POST request, before the form submits the content of its fields in its request.
As for your second question, the way to submit additional variables with a form submission (presuming that you actually want to do a navigating form submission and not an XHR background request against an API) is to use <input type="hidden"> elements.
So, to summarize, to do what you're describing in your question, your example HTML should look like this (minus the comments):
<!DOCTYPE html> <!-- only you can prevent quirks mode -->
<html>
<head>
<meta charset="UTF-8"> <!-- ༼ つ ◕_◕ ༽つ Give UNICODE -->
</head>
<body>
<form action='/vote' method='post'>
<input type="hidden" name="message" value="hello!">
<button id='send' type='submit' class='btn btn-success btn-xs'>Svara</button>
</form>
</body>
</html>
I have an input form in a HTML file:
<form id="urlarticle">
<input type='text' name='thislink'>
<input type='submit' value='Select'>
</form>
I want, when the submit button is clicked, 2 things to happen, in this order:
TASK 1: Make a POST request to a server, in order to enter new data in a database. Actually it is already working with the following code on the front-end:
<script type='application/javascript'>
$("#urlarticle").submit(function() {
$.ajax({
type: "POST",
url: "/selection/yes",
data: $("#urlarticle").serialize(),
success: function(data)
{alert(data);
}
});
return false;
});
</script>
...and with the following code on the back-end (server made with Express in Node.js):
app.post('/selection/yes', function(req, res) {
link = req.body.thislink;
// part omitted here: function that do several things and then save some data to a database
});
TASK 2: Open a new window, rendered with an EJS view following a GET request on the server-side. TASK 2 has to be performed after TASK 1, because it uses the data saved in the database by TASK 1.
The code on the front-end should look like this:
<script type='application/javascript'>
$("#urlarticle").submit(function() {
var linkValue = $('input[name="thislink"]').val();
window.open('/selection/yes/?value='+linkValue);
});
</script>
...and the task is ready to be handled on the back-end:
app.get('/selection/yes/', function(req, res) {
var thislink = req.param("value");
// parts omitted here
res.render('selection_form.ejs');
});
});
But how can I make this TASK 2 to be executed only after TASK 1 is done? Thank you for your help!
I've created a sample NodeJS application that uses a lot of the same concepts (using Express and some jQuery on the client-side).
WORKING EXAMPLE: http://runnable.com/U3JEKcrGzPc1V8eQ/promises-w-bluebird-for-node-js-and-express
Using a basic Express application where an initial form is rendered using EJS (this is the GET request on /). Form submissions return a POST request to the same URL and are handled with a 2s delay to simulate a database action.
/**
* Create a global storage variable as a example of an
* attached local database
*/
GLOBAL.linkStorage = [];
app.route('/')
.post(function(req, res){
console.log("Submission: " + req.body);
GLOBAL.linkStorage.push(req.body.link);
renderDelayedResponse(res);
})
.get(function(req, res){
res.render('form.ejs');
});
app.route('/2')
.get(function(req, res) {
// No need to pass in GLOBAL.linkValue since it's checked automatically
res.render('submission.ejs');
});
/**
* Delay the response by a few seconds to simulate a database
* create/update action
*/
function renderDelayedResponse(respWriter) {
setTimeout(function() {
GLOBAL.viewCount++;
respWriter.send('Action Completed');
}, 2000);
}
There are going to be problems with calling window.open() after an asynchronous action, the popup blocker fires in all cases through my tests. To workaround this, you can see that the example has an embedded IFRAME that refreshes (after the 2 second database save completes) and displays the submitted value.
The complexity is mostly handled through jQuery where the IFRAME refresh occurs after we know that the POST request has submitted:
<!doctype html>
<html>
<head>
<style>
.busy {
cursor: wait !important;
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-git.js"></script>
<script type="text/javascript">
$('document').ready(function () {
function refreshViewer() {
window.open("/2", "viewer");
document.getElementById('submissionFrame').contentWindow.location.reload(true);
}
$('form input#submitLink').on('click', function () {
var linkValue = $('input#link').serialize();
$('body').addClass('busy');
$.post('/', linkValue)
.done(function(data) {
$('body').removeClass('busy');
$('input#link').val('');
refreshViewer();
});
return false;
});
});
</script>
</head>
<body>
<div class="container">
<form id="urlarticle" method="POST">
<input type="text" name="link" placeholder="Link" id="link" />
<input type="button" value="Submit" id="submitLink" />
</form>
<iframe id="submissionFrame" src="/2" seamless="seamless" width="50%" style="margin-top:100px">
</iframe>
</div>
</body>
</html>