Logging in to firedrive using casperjs - forms

I'm trying to log in to Firedrive using casperjs 1.1.0-beta3 with phantomjs 1.9.0. The form does not have an id so I use findone to find the form elements.
Here is the code which runs without throwing any exceptions but doesn't log in as can be seen by capturing the output (document html) and searching for the word 'anonymous'.
Any ideas would be welcome.
Run like this:
casperjs firedrive1.js http://www.firedrive.com/myfiles username password
firedrive1.js:
// Expects url, user, and password on command line.
/*jshint strict:false*/
/*global CasperError, console, phantom, require*/
var casper = require("casper").create();
var dump = require("utils").dump;
var url = casper.cli.args[0]
var user = casper.cli.args[1]
var pass = casper.cli.args[2]
// print out all the messages in the headless browser context
casper.on('remote.message', function(msg) {
this.echo('remote message caught: ' + msg);
});
// print out all the messages in the headless browser context
casper.on("page.error", function(msg, trace) {
this.echo("Page Error: " + msg, "ERROR");
});
casper.start(url, function() {
console.log("page loaded");
this.evaluate(function(user, pass) {
console.log("user: " + user);
console.log("pass: " + pass);
__utils__.findOne('#username').value = user;
__utils__.findOne('#password').value = pass;
console.log("user set to: " + __utils__.findOne('#username').value);
console.log("pass set to: " + __utils__.findOne('#password').value);
__utils__.findOne('#header_login_btn').click();
}, {user: user,
pass: pass})
});
casper.thenEvaluate(function(){
console.log("Page Title " + document.title);
console.log('doc: ' + document.documentElement.innerHTML);
});
casper.run();
The trick seems to be to separate the retrieval of the page using casper.start from the filling in of the form by putting that in a separate casper.then.
Here is an outline of what finally worked. Notice that the class of the form is different from the one I thought it was, this is because the page is actually a different page from the one I captured by hand from Firefox:
casper.start(url, function(){
// do nothing or log something
});
casper.then(function() {
this.fill('form.form-horizontal', {
'user': user,
'pass': pass
}, true);
});
casper.thenEvaluate(function(){
// check that the user name appears in the text of a link
});

It is possible that the issue is the click() which is the DOM click and likely does not work in PhantomJS. You should use the casper.click for this after the evaluate call:
this.evaluate(function(user, pass) {...}, {...})
this.click('#header_login_btn');
If this does not solve the problem you may try it with the various casper.fill functions. They work on forms and include the optional submit argument which you would set to true.
this.fillSelectors('form.il_login_form', {
'#username': user,
'#password': pass
}, true);
It looks like the selector for the login form on the firedrive page is form.il_login_form.
It is also possible that you need to include a casper.wait or casper.waitForSelector after login, if it is only an AJAX driven login.
If this still does not work, you may need to update PhantomJS to newest version (currently 1.9.7-15).

Related

Javascript injection goes wrong

In our Android project (download manager) we need to show built-in web browser so we able to catch downloads there with the all data (headers, cookies, post data) so we can handle them properly.
Unfortunately, WebView control we use does not provide any way to access POST data of the requests it makes.
So we use a hacky way to get this data. We inject this javascript code in the each html code the browser loads:
<script language="JavaScript">
HTMLFormElement.prototype._submit = HTMLFormElement.prototype.submit;
HTMLFormElement.prototype.submit = formSubmitMonitor;
window.addEventListener('submit', function(e) {
formSubmitMonitor(e);
}, true);
function formSubmitMonitor(e) {
var frm = e ? e.target : this;
formSubmitMonitor_onsubmit(frm);
frm._submit();
}
function formSubmitMonitor_onsubmit(f) {
var data = "";
for (i = 0; i < f.elements.length; i++) {
var name = f.elements[i].name;
var value = f.elements[i].value;
//var type = f.elements[i].type;
if (name)
{
if (data !== "")
data += '&';
data += encodeURIComponent(name) + '=' + encodeURIComponent(value);
}
}
postDataMonitor.onBeforeSendPostData(
f.attributes['method'] === undefined ? null : f.attributes['method'].nodeValue,
new URL(f.action, document.baseURI).href,
data,
f.attributes['enctype'] === undefined ? null : f.attributes['enctype'].nodeValue);
}
XMLHttpRequest.prototype.origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
// these will be the key to retrieve the payload
this.recordedMethod = method;
this.recordedUrl = url;
this.origOpen(method, url, async, user, password);
};
XMLHttpRequest.prototype.origSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
if (body)
{
postDataMonitor.onBeforeSendPostData(
this.recordedMethod,
this.recordedUrl,
body,
null);
}
this.origSend(body);
};
const origFetch = window.fetch;
window.fetch = function()
{
postDataMonitor.onBeforeSendPostData(
"POST",
"test",
"TEST",
null);
return origFetch.apply(this, arguments);
}
</script>
Generally, it works fine.
But in Google Mail web interface, it's not working for some unknown reason. E.g. when the user enters his login name and presses Next. I thought it's using Fetch API, so I've added interception for it too. But this did not help. Please note, that we do not need to intercept the user credentials, but we need to be able to intercept all, or nothing. Unfortunately, this is the way the whole system works there...
Addition #1.
I've found another way: don't override shouldInterceptRequest, but override onPageStarted instead and call evaluateJavascript there. That way it works even on Google Mail web site! But why the first method is not working then? We break HTML code somehow?

How do I remove a user in mongoDB from the terminal by username?

My question is this: How can I remove a user from the users db by username, or at all even?
I have a meteor application with a custom registration, and when an account is created you can login and manage your account and what have you.. My problem is that, on the local host for testing, I created a few extra user accounts that I want to delete individually (not a complete reset). I am on OS X so I went to terminal, typed in 'show dbs' but users came up empty and when I typed 'show users' nothing came up. If I type 'db.users.findOne()' information appears and I can get a username and _id. I know there is users and this command shows that there is at least one but the rest of the commands indicate that I can't manage them.
Below is some code for the registration page, specifically the Accounts.createUser I'm not sure it will mater for the response but I wanted to be thorough.
Template.SignUp.events({
'submit form': function(event, template){
event.preventDefault();
var UsernameVar = template.find('#username').value;
var emailVar = template.find('#Email').value;
var passwordVar = template.find('#password').value;
var ConfirmPasswordVar = template.find('#Cpassword').value;
if(ConfirmPasswordVar == passwordVar)
{
document.getElementById("NotValid").style.display = 'none';
Accounts.createUser({
username: UsernameVar,
email: emailVar,
password: passwordVar
}, function(err, result){
if(err)
{
document.getElementById("Unavailable").style.display = 'block';
}
else{
document.getElementById("Unavailable").style.display = 'none';
}
});
}
else{
document.getElementById("NotValid").style.display = 'block';
}
}
});
I've done a lot of searching on this issue and all I've found is how to grant users the right to remove profiles but I want to do it from terminal, even when the application launches I will be the only one to be using this feature so I don't want to start giving those rights to users.
If there is anything else I should provide please let me know.
meteor mongo
db.users.find({username: "someusername"}) // ensure that your query returns the correct user that you want to remove
db.users.remove({username: "someusername"})

pagerjs access url parameters in withOnShow

I'd like to (asynchronously) fetch model-data each time a page is shown. The path may have additional parameters telling the withOnShow-handler what fields to fetch, for example:
..#!/navigation/href_with_params/users/123?fields=a,b,c,d
How would you access the "fields"-param inside the withOnShow handler?
Cool.loadUser = function(callback, page) {
$.get('users/' + page.currentId + "?fields=" + <fields>, function(data) {
callback(ko.mapping.fromJSON(data));
});
};
you could do something like
var fields = page.ctx.field();
inside your withOnShow. Hope this helps.

Azure Mobile Service Single Sign on Microsoft Account

I have implemented single sign on using the WL api, but I only recently realized that I need to call mobileService.login on top of that to use the nice authentication features of Azure Mobile Services.
I followed this tutorial
http://www.windowsazure.com/en-us/develop/mobile/tutorials/single-sign-on-windows-8-js/#add-authentication
and added this piece of code:
var login = function () {
return new WinJS.Promise(function (complete) {
WL.init();
WL.login({ scope: ["wl.signin", "wl.basic", "wl.birthday", "wl.emails"] }).then(function (result) {
session = result.session;
WinJS.Promise.join([
WL.api({ path: "me", method: "GET" }),
mobileService.login("microsoftaccount", session.authentication_token)
]).done(function (results) {
var profile = results[0];
var mobileServicesUser = results[1];
var title = "Welcome " + profile.first_name + "!";
var message = "You are now logged in as: " + mobileServicesUser.userId;
var dialog = new Windows.UI.Popups.MessageDialog(message, title);
dialog.showAsync().done(complete);
});
}, function (error) {
session = null;
var dialog = new Windows.UI.Popups.MessageDialog("You must log in.", "Login Required");
dialog.showAsync().done(complete);
});
});
}
however on this line
mobileService.login("microsoftaccount", session.authentication_token)
my session.authentication_token is undefined. (I have an access_token)
If I don't pass the token, I am prompted to sign in every time I launch the app, which defeats the purpose of the integrated sign on.
Any ideas?
To get the authentication token, you need to pass the redirect URI to the call to WL.init:
WL.init({
redirect_uri: "<< INSERT REDIRECT DOMAIN HERE >>"
});
Where the redirect domain must be the same as the one in your Live Connect application.

Mongoose + Everyauth weird behavior

Using everyauth, when I login with a never autenticated before user on my website, the following code is launched. Checks if the user is already in my mongodb, if not it writes it. The issue right now is that works for the first authenticated user, then if a second user logins, my joiningUser._id parameters is properly initiated, but all the other parameters of my schema are from the first ever saved user, its like my parameters are never reinitialised... weird, my console.log shows the right new parameters, and not what is actually written in the database. My authentication is done via the everyauth module, I use the express framework.
exports.findOrCreateFacebookUser = function(fbUserData, promise){
User.findOne({_id:fbUserData.id}, function(err, user) {
if(err) {
console.log("Error in finding user for auth. Check Db");
promise.fail(err);
return;
}
else if(user){
console.log("User found ");
promise.fulfill(user);
}
else{
var joiningUser = new User();
joiningUser._id = fbUserData.id;
joiningUser.firstName = fbUserData.first_name;
joiningUser.lastName = fbUserData.last_name;
joiningUser.email = fbUserData.email;
//console.log(JSON.stringify(joiningUser));
joiningUser.save(function(err){
if(err){
console.log("Couldnt save new user: " + err);
promise.fail(err);
return;
}
else{
console.log("User wasnt existant, it is now created: " + JSON.stringify(joiningUser));
promise.fulfill(joiningUser);
}
});
}
});
};
Use mongoose-auth. It takes care of the combination of mongoose and everyauth for you.
There seems to be an issue with assigning _id with a forced value. So I created another id for the profile specific id (ex: facebookId).