login page not working (javascript, firebase) - javascript

HELP!
I'm not sure what's going on, but my login page isn't working. It simply reloads even though I'm entering valid user/password.
I think the problem is it's getting stuck on issues with my data-structure, security-rules, and app.js, but I'm at a loss.
I was provided a sinatra/ruby simple api to work with users & groups (just a small project).
here's the site:
https://starter-vicks9985.firebaseapp.com/index.html
here's the code:
$.post/("https://starter-vicks9985.firebaseapp.com/main.rb",
{
"name": "admin",
"email": "admin#example.com",
"password": "secret",
"admin": true,
"role-value": 99,
}
), console.log("success");
{
"rules": {
".read": true,
"users": {
"$user": {
//can add a message if authenticated
".write": "auth.uid === $user"
}
},
"rooms": {
"$room": {
"users": {
// can write to the users list only if ADMINISTRATOR
"$user": {
"write":"newData.parent().child(auth.uid).val() === 99"
}
}
}
},
"messages": {
"$room": {
"$message": {
//can add a message if they are a MEMBER (if there was message/chat capability)
".write": "(!data.exists() && newData.exists() && root.child('rooms/' + $room + '/users/' + auth.uid).val() >= 10)"
}
}
}
}
}
$(document).ready(function() {
/**
*Set initial firebase ref. Use set to write in first admin user.
*/
var ref = new Firebase("https://starter-vicks9985.firebaseio.com/");
ref.set({
"name": "Admin",
"email": "admin#example.com",
"password": "secret",
"admin": true
});
/** Get email address from loginform, format email, get password
* Firebase keys cannot have a period (.) in them, so this converts the emails to valid keys
*/
var emailAddress = function emailToKey(emailAddress){
return btoa(emailAddress);
};
var password = document.getElementById('password');
/**
* Authorize user with email and password, passing in values from form.
*/
ref.authWithPassword({
email : emailAddress,
password : password,
}, function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
return authData;
}
});
/**
* If user is logged in (valid), redirect to user profile
*/
ref.onAuth(function(authData) {
window.open="https://starter-vicks9985.firebaseio.com/userprofile/userprofile.html";
})
});

Like #Kato said, this is a code dump so please consider creating an mcve. Although, first check out my comments below.
The Code You Posted
After glancing at your code, I see some errors that I will point out:
1. Your jQuery post syntax is incorrect, and wouldn't work even if it was correct.
Most importantly, you are making a post request to a Ruby file. Firebase Hosting is not a server, it is hosting for static files.
See this answer by Frank. He says:
Firebase hosting is a product to serve so-called static application, which consist only of files that the client interprets. Firebase's servers will not interpret any code that you upload. So Firebase hosting is not suited to host your Ruby-on-Rails application.
To quote Firebase hosting's documentation:
We deliver all your static content (html, js, images, etc)
That being said, take a look at the jQuery documentation for $.post().
See my comments on your code:
$.post/("https://starter-vicks9985.firebaseapp.com/main.rb",
// ^ What is this '/'?
{
"name": "admin",
"email": "admin#example.com",
"password": "secret",
"admin": true,
"role-value": 99,
}
), console.log("success");
// ^ You are closing the function call, 'console.log' falls outside of it.
What it should look like:
$.post("https://starter-vicks9985.firebaseapp.com/main.rb", {
"name": "admin",
"email": "admin#example.com",
"password": "secret",
"admin": true,
"role-value": 99,
}, function() {
console.log("success");
});
2. What's even going on with the login functions?
Assuming you fix Uncaught SyntaxError: Unexpected token { in data-structure.js:14...
If you take a look at the console, you will see Uncaught Error: Firebase.authWithPassword failed: First argument must contain the key "email" with type "string".
That is because you are passing a function, emailAddress to .authWithPassword().
You declare emailAddress() like so:
var emailAddress = function emailToKey(emailAddress){
return btoa(emailAddress);
};
So the email parameter in the following is being passed emailAddress(), not a string that is an email address.
ref.authWithPassword({
email : emailAddress,
password : password,
}, function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
return authData;
}
});
Most importantly, all of these login functions are being called immediately after the page loads. Nothing in your code (app.js) waits for, and responds to, the submission of the form.
The Code on Your Website
I also went on your page, looked at your source code, and found some more issues.
1. Error in form HTML in index.html
<section class="loginform cf">
<form id= "login" form name="login" form type= "submit" accept-charset="utf-8">
<!-- extra^space ^duplicate "form"^ ^again, space -->
...
</form>
</section>
2. Syntax Errors in data-structures.js
Again, you have the same errors here as I described above ('/' and closing parentheses), but the object that you're passing the post is incorrectly formatted
$.post/("https://starter-vicks9985.firebaseapp.com/main.rb",
{
"users" //missing ':' after users
//the following objects do not have keys - should be {"users":{"someUserKey1":{...},"someUserKey2":{...}}} etc.
{
"name": "admin",
"email": "...",
"password": "...",
"admin": true,
"role-value": 99,
},
{
"name": "aaa",
...
},
{
"name": "bbb",
...
}
},
), console.log("success");
And the same things apply for the post call for "groups".
I hope that provides some clarity.
I would suggest reading over other answers here on StackOverflow, like:
jQuery AJAX submit form
jQuery form submit
And search for more answers like:
https://stackoverflow.com/search?q=jquery+form+submit
In conclusion, I'd suggest doing some more research and reading documentation :)

Related

Dialogflow Fulfilment webhook call failed

I am new to dialogflow fulfillment and I am trying to retrieve news from news API based on user questions. I followed documentation provided by news API, but I am not able to catch any responses from the search results, when I run the function in console it is not errors. I changed the code and it looks like now it is reaching to the newsapi endpoint but it is not fetching any results. I am utilizing https://newsapi.org/docs/client-libraries/node-js to make a request to search everything about the topic. when I diagnoise the function it says " Webhook call failed. Error: UNAVAILABLE. "
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const http = require('http');
const host = 'newsapi.org';
const NewsAPI = require('newsapi');
const newsapi = new NewsAPI('63756dc5caca424fb3d0343406295021');
process.env.DEBUG = 'dialogflow:debug';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((req, res) =>
{
// Get the city
let search = req.body.queryResult.parameters['search'];// search is a required param
// Call the weather API
callNewsApi(search).then((response) => {
res.json({ 'fulfillmentText': response }); // Return the results of the news API to Dialogflow
}).catch((xx) => {
console.error(xx);
res.json({ 'fulfillmentText': `I don't know the news but I hope it's good!` });
});
});
function callNewsApi(search)
{
console.log(search);
newsapi.v2.everything
(
{
q: 'search',
langauge: 'en',
sortBy: 'relevancy',
source: 'cbc-news',
domains: 'cbc.ca',
from: '2019-12-31',
to: '2020-12-12',
page: 2
}
).then (response => {console.log(response);
{
let articles = response['data']['articles'][0];
// Create response
let responce = `Current news in the $search with following title is ${articles['titile']} which says that
${articles['description']}`;
// Resolve the promise with the output text
console.log(output);
}
});
}
Also here is RAW API response
{
"responseId": "a871b8d2-16f2-4873-a5d1-b907a07adb9a-b4ef8d5f",
"queryResult": {
"queryText": "what is the latest news about toronto",
"parameters": {
"search": [
"toronto"
]
},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"intent": {
"name": "projects/misty-ktsarh/agent/intents/b52c5774-e5b7-494a-8f4c-f783ebae558b",
"displayName": "misty.news"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {
"webhook_latency_ms": 543
},
"languageCode": "en"
},
"webhookStatus": {
"code": 14,
"message": "Webhook call failed. Error: UNAVAILABLE."
},
"outputAudio": "UklGRlQqAABXQVZFZm10IBAAAAABAAEAwF0AAIC7AAACABAAZGF0YTAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... (The content is truncated. Click `COPY` for the original JSON.)",
"outputAudioConfig": {
"audioEncoding": "OUTPUT_AUDIO_ENCODING_LINEAR_16",
"synthesizeSpeechConfig": {
"speakingRate": 1,
"voice": {}
}
}
}
And Here is fulfillment request:
{
"responseId": "a871b8d2-16f2-4873-a5d1-b907a07adb9a-b4ef8d5f",
"queryResult": {
"queryText": "what is the latest news about toronto",
"parameters": {
"search": [
"toronto"
]
},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"intent": {
"name": "projects/misty-ktsarh/agent/intents/b52c5774-e5b7-494a-8f4c-f783ebae558b",
"displayName": "misty.news"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {
"webhook_latency_ms": 543
},
"languageCode": "en"
},
"webhookStatus": {
"code": 14,
"message": "Webhook call failed. Error: UNAVAILABLE."
},
"outputAudio": "UklGRlQqAABXQVZFZm10IBAAAAABAAEAwF0AAIC7AAACABAAZGF0YTAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... (The content is truncated. Click `COPY` for the original JSON.)",
"outputAudioConfig": {
"audioEncoding": "OUTPUT_AUDIO_ENCODING_LINEAR_16",
"synthesizeSpeechConfig": {
"speakingRate": 1,
"voice": {}
}
}
}
Also here is the screenshot from the firebase console.
Can anyone guide me what is that I am missing in here?
The key is the first three lines in the error message:
Function failed on loading user code. Error message: Code in file index.js can't be loaded.
Did you list all required modules in the package.json dependencies?
Detailed stack trace: Error: Cannot find module 'newsapi'
It is saying that the newsapi module couldn't be loaded and that the most likely cause of this is that you didn't list this as a dependency in your package.json file.
If you are using the Dialogflow Inline Editor, you need to select the package.json tab and add a line in the dependencies section.
Update
It isn't clear exactly when/where you're getting the "UNAVAILABLE" error, but one likely cause if you're using Dialogflow's Inline Editor is that it is using the Firebase "Spark" pricing plan, which has limitations on network calls outside Google's network.
You can upgrade to the Blaze plan, which does require a credit card on file, but does include the Spark plan's free tier, so you shouldn't incur any costs during light usage. This will allow for network calls.
Update based on TypeError: Cannot read property '0' of undefined
This indicates that either a property (or possibly an index of a property) is trying to reference against something that is undefined.
It isn't clear which line, exactly, this may be, but these lines all are suspicious:
let response = JSON.parse(body);
let source = response['data']['source'][0];
let id = response['data']['id'][0];
let name = response['data']['name'][0];
let author = response['author'][0];
let title = response['title'][0];
let description = response['description'][0];
since they are all referencing a property. I would check to see exactly what comes back and gets stored in response. For example, could it be that there is no "data" or "author" field in what is sent back?
Looking at https://newsapi.org/docs/endpoints/everything, it looks like none of these are fields, but that there is an articles property sent back which contains an array of articles. You may wish to index off that and get the attributes you want.
Update
It looks like that, although you are loading the parameter into a variable with this line
// Get the city and date from the request
let search = req.body.queryResult.parameters['search'];// city is a required param
You don't actually use the search variable anywhere. Instead, you seem to be passing a literal string "search" to your function with this line
callNewsApi('search').then((output) => {
which does a search for the word "search", I guess.
You indicated that "it goes to the catch portion", which indicates that something went wrong in the call. You don't show any logging in the catch portion, and it may be useful to log the exception that is thrown, so you know why it is going to the catch portion. Something like
}).catch((xx) => {
console.error(xx);
res.json({ 'fulfillmentText': `I don't know the news but I hope it's good!` });
});
is normal, but since it looks like you're logging it in the .on('error') portion, showing that error might be useful.
The name of the intent and the variable I was using to make the call had a difference in Casing, I guess calls are case sensitive just be aware of that

Publish and Subscribe do not work correctly

Publish and Subscribe did not work. Please find the solution as an answer down below.
Initial question:
I am trying to publish the facebook first_name which is automatically retrieved when logging in with the accounts facebook package in Meteor (stored in the user collection under services.facebook). I have autopublish and insecure removed.
What I have tried so far looks like this:
Server side
Meteor.publish("facebook_name", function() {
return Meteor.users.find({_id: this.userId},
{fields: {'services.facebook.first_name' : true} });
});
Client side
Meteor.subscribe('facebook_name');
What I am using in my template to display it is this
<div class="Name"><p>{{currentUser.services.facebook.first_name}}</p></div>
Before removing autopublish the name showed up in the template.
Found the solution to my problem:
When setting up your meteor project in your client/main.js it will show import './main.html'; if you are working with routing and templates and not the main.html template this will prevent publish and subscribe to work correctly.
When user is logged in via facebook oauth API and the authentication was implemented using meteor accounts-facebook, then all needed data is stored in current user object ( Meteor.user() ).
So, the schema of user in your case looks similar to this:
{
"_id": "Ap85ac4r6Xe3paeAh",
"createdAt": "2015-12-10T22:29:46.854Z",
"services": {
"facebook": {
"accessToken": "XXX",
"expiresAt": 1454970581716,
"id": "XXX",
"email": "ada#lovelace.com",
"name": "Ada Lovelace",
"first_name": "Ada",
"last_name": "Lovelace",
"link": "https://www.facebook.com/app_scoped_user_id/XXX/",
"gender": "female",
"locale": "en_US",
"age_range": {
"min": 21
}
},
"resume": {
"loginTokens": [
{
"when": "2015-12-10T22:29:46.858Z",
"hashedToken": "XXX"
}
]
}
},
"profile": {
"name": "Sashko Stubailo"
}
}
Thus, if you want to retrieve a name of a user, all you need to do is to publish current user to a client and then get username from user object.
// server
Meteor.publish("userData", function () {
return Meteor.users.find({_id: this.userId});
});
// client
Meteor.subscribe("userData");
Template.templateName.helpers({
// this function returns username
Username : function(){
// if user is logged in using facebook; otherwise user is logged in using password
if (Meteor.user().profile.name)
return Meteor.user().profile.name;
else
return Meteor.user().username;
}
Now you can display a name of a user in your view: {{Username}}
Here is more info...

Creating an envelope from a template returning "UNSPECIFIED_ERROR"

When I try to create an envelope from a template I get a response of:
{ errorCode: 'UNSPECIFIED_ERROR',
message: 'Non-static method requires a target.' }
Here's what I'm doing so far:
First I login, which returns
{ loginAccounts:
[ { name: '*****',
accountId: '*****',
baseUrl: 'https://demo.docusign.net/restapi/v2/accounts/******',
isDefault: 'true',
userName: '***** ********',
userId: '*******-*****-*****-*****-*********',
email: '********#*******.com',
siteDescription: '' } ] }
So then I take the baseUrl out of that response and I attempt to create the envelope. I'm using the hapi framework and async.waterfall of the async library, so for anyone unfamiliar with either of these my use of the async library uses the next callback to call the next function which in this case would be to get the url for the iframe, and with our usage of the hapi framework AppServer.Wreck is roughy equivalent to request:
function prepareEnvelope(baseUrl, next) {
var createEntitlementTemplateId = "99C44F50-2C97-4074-896B-2454969CAEF7";
var getEnvelopeUrl = baseUrl + "/envelopes";
var options = {
headers: {
"X-DocuSign-Authentication": JSON.stringify(authHeader),
"Content-Type": "application/json",
"Accept": "application/json",
"Content-Disposition": "form-data"
},
body : JSON.stringify({
status: "sent",
emailSubject: "Test email subject",
emailBlurb: "My email blurb",
templateId: createEntitlementTemplateId,
templateRoles: [
{
email: "anemailaddress#gmail.com",
name: "Recipient Name",
roleName: "Signer1",
clientUserId: "1099", // TODO: replace with the user's id
tabs : {
textTabs : [
{
tabLabel : "acct_nmbr",
value : "123456"
},
{
tabLabel : "hm_phn_nmbr",
value : "8005882300"
},
{
tabLabel : "nm",
value : "Mr Foo Bar"
}
]
}
}
]
})
};
console.log("--------> options: ", options); // REMOVE THIS ====
AppServer.Wreck.post(getEnvelopeUrl, options, function(err, res, body) {
console.log("Request Envelope Result: \r\n", JSON.parse(body));
next(null, body, baseUrl);
});
}
And what I get back is:
{ errorCode: 'UNSPECIFIED_ERROR',
message: 'Non-static method requires a target.' }
From a little googling it look like 'Non-static method requires a target.' is a C# error and doesn't really give me much indication of what part of my configuration object is wrong.
I've tried a simpler version of this call stripping out all of the tabs and clientUserId and I get the same response.
I created my template on the Docusign website and I haven't ruled out that something is set up incorrectly there. I created a template, confirmed that Docusign noticed the named form fields, and created a 'placeholder' templateRole.
Here's the templateRole placeholder:
Here's one of the named fields that I want to populate and corresponding data label:
As a side note, I was able to get the basic vanilla example working without named fields nor using a template using the docusign node package just fine but I didn't see any way to use tabs with named form fields with the library and decided that I'd rather have more fine-grained control over what I'm doing anyway and so I opted for just hitting the APIs.
Surprisingly when I search SO for the errorCode and message I'm getting I could only find one post without a resolution :/
Of course any help will be greatly appreciated. Please don't hesitate to let me know if you need any additional information.
Once I received feedback from Docusign that my api call had an empty body it didn't take but a couple minutes for me to realize that the issue was my options object containing a body property rather than a payload property, as is done in the hapi framework.

Redirection after the login succeeds or fails in loopback framework

I have recently started with loopback framework and made a simple login functionality by creating a 'customer' model inheriting from base 'User' like this:
CUSTOMER.JSON
{
"name": "customer",
"base": "User",
"idInjection": true,
"properties": {
"email":{
"type":"string",
"required":false
},
"username":{
"type":"string",
"required":false
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
CUSTOMER.JS
module.exports = function(customer){
}
I then made a entry in model-config.json like this:
"customer": {
"dataSource": "mango-database",
"public": true
}
And yes I was able to login and logout easily. I have a login screen with fields username and password. I submit this form to customers/login and as soon as it gets the login, I get a screen:
{
id: "lvrTjKBKXCFPTMFej6AyegQUFYe5mSc1BiYbROZwCBM0jqae7kZ7v8ZfGujfDGgy",
ttl: 1209600,
created: "2014-12-07T08:12:17.572Z",
userId: "5483e88b5e9cf2fe0c64dd6c"
}
Now I want that instead of this screen, I should be able to redirect user to some other page (dashboard) and if the login fails, it should go back to the login screen.
I googled up a lot on this and all i found was the suggestions to use hooks. But hooks doesn't have such event. Where do I write the redirection functionality? My guess is CUSTOMER.JS
I found the documentation quiet confusing !
Use context.res provided in a remote hook. For example:
Customer.afterRemote('create', function(context, customer, next) {
var res = context.res; //this is the same response object you get in Express
res.send('hello world');
})
Basically, you have access to request and response objects, so just respond as you would in Express. See http://expressjs.com/4x/api.html for more info.

How to correctly use Google's Javascript OAuth2.0 library

I am trying to access some google APIs from my javascript client using Oauth2. I've succeeded in getting the user to authenticate requests, but there's some unexpected behaviour when running the code below that'd I'd like to understand. When I click the 'authorize' button the first time, the result is:
'[ { "error": { "code": 401, "message": "Login Required", "data": [ { "domain": "global", "reason": "required", "message": "Login Required", "locationType": "header", "location": "Authorization" } ] }, "id": "gapiRpc" } ] '
on the second click the result is
[ { "id": "gapiRpc", "result": { "id": "1115793426680xxxx", "email": "xxxxx#gmail.com", "verified_email": true } } ]
here is the code for the page I am testing
<div id='sign in'>
<button onclick="init();">Authorize</button>
</div>
<p id="output">hello</p>
<script type="text/javascript">
function init() {
document.getElementById('output').innerHTML='loading oauth2 api'
gapi.client.load('oauth2', 'v2', auth);
}
function auth() {
var config = {
client_id: '2264xxxxx-odt0g7jn8vspa3ot9ogjxxxxxxxxx.apps.googleusercontent.com',
scope: 'https://www.googleapis.com/auth/userinfo.email',
immediate:true
};
document.getElementById('output').innerHTML='authorizing'
gapi.auth.authorize(config, authed());
}
function authed() {
document.getElementById('output').innerHTML='authorized'
var request = gapi.client.oauth2.userinfo.get().execute(
function(resp, raw) {
document.getElementById('output').innerHTML=raw
}
);
}
</script>
<script src="https://apis.google.com/js/client.js"></script>
<!--<script src="https://apis.google.com/js/client.js?onload=init"></script>-->
Could you please explain why I would get a 'login required' on the first execution of the code and a successful authentication on the second execution?
Due to the parentheses immediately after "authed" in the call to gapi.auth.authorize, the authed() callback is run immediately, prior to the call to gapi.auth.authorize.
Also, in your authed() handler you need to check to see whether the authorization check with immediate: true succeeded; for more details, see the reference documentation here:
https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiauthauthorize
Also refer to the section on pop-up blocking here:
https://developers.google.com/api-client-library/javascript/features/authentication#popup
When the "immediate" authorization fails, the authed callback will be invoked with a null token object, or a token object containing an "error" field; in these cases you need to present a user interface element the user can click which will re-run the gapi.auth.authorize call but with "immediate" set to false (or omitted). This allows the authorization pop-up to be opened without running afoul of your browser's pop-up blocker.

Categories

Resources