Saturday, March 22, 2014

AngularJS and Starrr plugin: updating score variable with directives

I'm using Starrr plugin (https://github.com/dobtco/starrr) with Angular.JS.

When the star rating changes, 'starrr:change' dom event is fired. I have to catch this event and update the score variable in my angular.js scope.  It was hard to find it but found it:
We define a directive in our angular app js file:
myApp.directive('rateable', function(){
        return function(scope, elt, attr){
            elt.bind('starrr:change', function(e, value){
                scope.score = value;
                scope.$apply();
            });
        }
});
In the HTML Code, we use the rateable directive as HTML tag attribute:
<div class="starrr" data-rating="1" id="hearts" rateable></div>
This way, whenever "starrr:change" event is fired from "#hearts", our score variable in the scope is updated. We have to call $apply to let Angular know some changes has been proposed.

Wednesday, March 12, 2014

Error: Failed to find request token in session at Strategy.OAuthStrategy.authenticate [passport-twitter on cluster]


I got the error in the title when I tried to deploy my code on Heroku or Dokku. Possible suspects were:

1) Twitter API KEY and SECRET
2) System Time

And they were correct. Then I found that if we run the module as cluster:

Authentication request was sent by passport-twitter to twitter and some data regarding this request kept in session object. Then the response came from twitter in form of (callback?oauth_token=...&oauth_verifier=...) but could not find session object since it was in another process. By the way, heroku can run 2 processes per web dyno.

So solution was :

not using cluster code and running the http server on a single process. 

Another solution: Use Redis for session storing:

RedisStore = require('connect-redis')(express.session);
var REDIS_URL = process.env.REDISCLOUD_URL || "redis://localhost";
app.use(express.session({ store: new RedisStore({'url': REDIS_URL}), secret: '2342342' })); // session secret

Monday, March 10, 2014

Upstart can't read environment variables

I was trying to configure a gunicorn server with upstart for easily starting/stopping my service. But it turned out to be problematic since upstart does not read environment variables.

How did I encounter this error? I was trying to parse signed_request from Facebook canvas via the following line:

fb_request = facebook.parse_signed_request(signed_request, APP_SECRET)

where

APP_SECRET = os.environ.get('FB_APP_SECRET', 'jhdklu3sh4o8y4o8fh34')

I realized that it couldn't read the environment variable and was using the default app secret so couldn't decrypt the signed request. My environment variables were in .bashrc of both regular user and root but it did not read. So I added them to the upstart script:

script
     export HOME=/home/user/project
     cd $HOME
     export FB_APP_ID=859827u4fhk4vnf
     export FB_APP_SECRET=4ojfo92ufo2489fyuo482fy2
     . venv/bin/activate
     exec gunicorn myapp:app
end script


Wednesday, March 5, 2014

Installing Neo4J on Ubuntu

A simple dockerfile for this purpose. Not sure for the last lines. Fix me if I'm wrong.


FROM dockerfile/ubuntu

# Install Java
RUN apt-get install -y software-properties-common
RUN add-apt-repository -y ppa:webupd8team/java
RUN apt-get update
RUN echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections
RUN echo debconf shared/accepted-oracle-license-v1-1 seen true | debconf-set-selections
RUN apt-get install -y oracle-java7-installer



RUN wget "http://download.neo4j.org/artifact?edition=community&version=1.9.6&distribution=tarball&dlid=notread"
RUN mv artifact\?edition\=community\&version\=1.9.6\&distribution\=tarball\&dlid\=notread neo.tar.gz
RUN tar xvfz neo.tar.gz


RUN mv neo4j-community-1.9.6 /opt/neo4j-community-1.9.6
RUN /opt/neo4j-community-1.9.6/bin/neo4j install



CMD service neo4j-service start



Tuesday, March 4, 2014

POST to Angular.JS by Facebook Canvas App

I was writing a Facebook Canvas App with Flask. Then I decided to move my frontend to AngularJS. I wanted to put the AngularJS static code to a static hosting provider to avoid higher costs. Nevertheless, I realized that I had forgotten that I can't handle POST requests by AngularJS since it doesn't have a dynamic server.

Facebook Canvas performs a POST request with signed_request parameter to your homepage and you should handle that parameter to see who the logged user is.

What I did was: create a Node.JS app with express.js framework. Convert homepage to view, add a hidden input field in the HTML code and handle POST parameter by Node.JS, filling that hidden input.

When I did this, facebook posted the signed_request parameter and I placed that code into the hidden field. Now AngularJS code can post that signed_request code to the backend API server to process it or use it client-side.