Showing posts with label neo4j. Show all posts
Showing posts with label neo4j. Show all posts

Thursday, December 26, 2013

Neo4J user service plugin for secure social (play framework/scala)

SecureSocial-Neo4JUserService

Neo4J user service plugin for secure social (play framework/scala)

Project on GitHub: SecureSocial-Neo4JUserService


Background

Building reactive web applications with play framework and scala often starts with a social login system. One great way to get started here is to use Secure Social. They provide a simple way to get up and running with a large number of providers. Once you are running you will need to store your account information and more the likely the relationships between your social users "friends". This is where Neo4J really shines.

Requirements

Setup

Once you have secure social up and running all you need to do is add this scala file to your play project. I created a app/servicies directory to place the file. Next you simply need to add a line to your play.plugins

play.plugins

9998:service.Neo4JUserService

Neo4J Structure

Users will now be added to your neo4J with the following structure

(u:User)-[:HAS_ACCOUNT]->(p:Provider)

You can also use the utility methods outlined below to make users friends

(u1:User)-[:FRIEND]->(u2:User)

Helper methods

Here are number of usefull methods for helping you to work with secure social and Neo4J

object  Neo4JUserService{
  def socialUserFromMap( umap: Map[String, String]): Identity = {
    ...
  }

  def makeUsersFriends( uuid1: String, uuid2: String ) = future{
    ...
  }

  def socialUserFromToken(provider: String, token: String) = future{
    ...
  }

  def uuidFromProviderInfo( provider: String, id: String, name: String = "" ) = future {
    ...
  }


  private def createUserAndProvider(name: String, id: String, fullname: String) = {
    ...
  }
}

Things to consider.

You will still need a way for users to "link" multiple providers on your back-end. Currently if a user signs in using another provider, they will get another user and provider record in Neo4J. You could try to combat this at the login level by looking for emails that are same as other providers (you would want to verify the email before linking for security reasons)

Another way would be a settings section on your site when a user is loged in, that would allow them to "link" their other accounts. In this manor you would want to create to continue to build a structure like the following

        /[:HAS_ACCOUNT]->(p0:Provider)
(u:User)-[:HAS_ACCOUNT]->(p1:Provider)
        \[:HAS_ACCOUNT]->(p2:Provider)

Friday, November 29, 2013

Zero to Play with Linux Neo4j, Play2 and nginx

This is a guide for taking your (debian like) linux system from a fresh install to staging server.

sudo -s
apt-get update
apt-get dist-upgrade

# install Sun java 7
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
apt-get update
apt-get install oracle-java7-installer

# install scala
apt-get install scala

# build tools
apt-get install build-essential

# install recent nodejs
sudo apt-get update
sudo apt-get install -y python-software-properties python g++ make
sudo add-apt-repository ppa:richarvey/nodejs #or sudo apt-get-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs nodejs-dev npm

# install nginx
apt-get install nginx


# get play
wget http://downloads.typesafe.com/play/2.2.1/play-2.2.1.zip

# unzip this somewhere
vim .bashrc

# add play to path
export PATH=$PATH:/path/to/play

# install neo4j

# start root shell
sudo -s
# Import our signing key
wget -O - http://debian.neo4j.org/neotechnology.gpg.key | apt-key add - 
# Create an Apt sources.list file
echo 'deb http://debian.neo4j.org/repo testing/' > /etc/apt/sources.list.d/neo4j.list
# Find out about the files in our repository
apt-get update
# Install Neo4j, community edition
apt-get install neo4j
# start neo4j server, available at http://localhost:7474 of the target machine
/var/lib/neo4j/bin/neo4j start


# install git
apt-get install git

# clone projects
...
...

# make sure things are good
cd projects/dir/
play compile

# test running the server
play run

# compile staging package
play clean compile stage


# setup your init scripts to keep it alive
vim /etc/init.d/play.myapp

###################################################
## Init Script
###################################################
#!/bin/bash

APPLICATION_PATH=/home/user/projects/myplayapp

start() {
    echo -n "Starting"
    sudo start-stop-daemon --start --background --pidfile ${APPLICATION_PATH}/RUNNING_PID -d ${APPLICATION_PATH} --exec target/start -- -Dhttp.port=9000
    RETVAL=$?

    if [ $RETVAL -eq 0 ]; then
        echo " - Success"
    else
        echo " - Failure"
    fi
    echo
}
stop() {
    echo -n "Stopping"
    sudo start-stop-daemon --stop --pidfile ${APPLICATION_PATH}/RUNNING_PID

    RETVAL=$?

    if [ $RETVAL -eq 0 ]; then
        echo " - Success"
    else
        echo " - Failure"
    fi
    echo
}

  case "$1" in
    start)
      start
  ;;
    stop)
      stop
  ;;
    restart)
      stop
      start
  ;;
    *)
      echo "Usage: play-server {start|stop|restart}"
      exit 1
  ;;
esac
exit $RETVAL



## END INIT



#make it executable 
chmod +x /etc/init.g/play.myapp

# test it
/etc/init.d/play.myapp start

# now make it start on boot
update-rc.d play.myapp defaults


# finally lets get some proxy action
# edit nginx.conf adding servers for each of your projects...
vim /etc/nginx/nginx.conf


######### SAMPLE SECTION TO ADD in http{ ...
# add 1 sever per domain. Also note that you can have wildcards *
 server {
        listen       80;
        server_name  *.mysite.com;
               
        location / {
           proxy_pass http://localhost:9000/;
           proxy_set_header Host $http_host;
        }
# 404 ect...
}

# now restart nginx
/etc/init.d/nginx restart


Lets assume you had a number of sites on one server. You could have a number of play applications running on various ports. Then in nginx.conf you would define a sever rule for each site. Also MAKE sure you pass through the Host header or you will run into issues. (ex: secure_socaiul sending redirect urls as "localhost:9000"

Friday, November 22, 2013

Neo4J Membership Provider



Neo4JMembershipProvider

asp.net Neo4J Membership Provider

Dependencies

Neo4J Graph Database >= v 2.0.0 (Make sure it has label support)
Neo4JClient https://www.nuget.org/packages/Neo4jClient. NOTE: this package is auto installed as a dependency when you use NuGet

Install

NuGet package https://www.nuget.org/packages/Neo4JMembershipProvider/
This is a step by step install for a new MVC application.
First thing to do is to make sure that you have the latest NuGet installed in your Visual Studio. Again, make sure it is the latest version.
ScreenShot
At this point make sure that you have Neo4J up and running and that you can connect to it. Assuming you have Neo4J installed on your localhost you should be able to connect via your web browser with the address.
http://localhost:7474
If you have everything up and running you should see a screen similar to this one. ScreenShot
Create a new MVC 3/4 web application. Once you are looking at the project files, right click on your refrences and choose "Manage NuGet Packages.."
This will open the NuGet Modal. Select "Online" from your list of sources on the left hand side. Next you can search for "Neo4JMembershipProvider" in the top right search menu.
Once you see the package in the main list. Click the install button.
Verify that the package installed by looking for a green checkmark next to the package. See image as refrence ScreenShot
Now we have to make a few changes to the configuration of our application.
First off we will need to modify our web.config file to include the following lines
<configuration>

  ...

 <connectionStrings>
    <add name="DefaultConnection" connectionString="http://localhost:7474/db/data" providerName="Nextwave.Neo4J.Connector.Neo4JClient" />
  </connectionStrings>
  <appSettings>

    ...

    <add key="enableSimpleMembership" value="false" />
    <add key="autoFormsAuthentication" value="false" />
  </appSettings>
  <system.web>

    ...

    <roleManager enabled="true" />
    <machineKey validationKey="C50B3C89CB21F4F1422FE158A5B42D0E8DB8CB6CDA1742572A48722401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE" decryptionKey="8A9BE8FD22AF6979E7D20198CFEA50DD3D3799C77AF2B722" validation="SHA1" />
    <membership defaultProvider="Neo4JMembershipProvider" userIsOnlineTimeWindow="15">
      <providers>
        <clear />
        <add name="Neo4JMembershipProvider" type="Nextwave.Neo4J.Membership.Neo4JMembershipProvider" connectionStringName="DefaultConnection" applicationName="Nextwave" enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" passwordFormat="Hashed" />
      </providers>
    </membership>

    ...

</configuration>
I have also included an image with the highlighted changes.
NOTE: that your connection string may need to change to point to your db location ScreenShot
The last thing you need to do is to modify your "InitializeSimpleMembershipAttribute.cs" This is located in your /filters/InitializeSimpleMembershipAttribute.cs
Make the following code changes
  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
  public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
  {
      private static SimpleMembershipInitializer _initializer;
      private static object _initializerLock = new object();
      private static bool _isInitialized;

      public override void OnActionExecuting(ActionExecutingContext filterContext)
      {
          // Ensure ASP.NET Simple Membership is initialized only once per app start
          LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
      }

      private class SimpleMembershipInitializer
      {
          public SimpleMembershipInitializer()
          {
              try
              {
                  WebSecurity.InitializeDatabaseConnection("DefaultConnection", "User", "Id", "UserName", autoCreateTables: false);
              }
              catch (Exception ex)
              {
                  throw new InvalidOperationException("Something is wrong", ex);
              }
          }
      }
  }
That should be all you need.
You will now be able to start your application and regester / login
Your users will be nodes in neo4J with the "User" label.
So for example you could list all your users with the following Cypher
MATCH u:User RETURN u;

Finally

My solution has only undergone a very small amount of testing.
However, if you have any trouble please contact me and I will be glad to help.
Thanks... and Enjoy the power of your new graph db :)