I am new to Symfony and have started reading and toying about. I was able to install Symfony2 and a NEO4j database. I was also able to include bootstrap into my Symfony project and display a basic homepage.
I would now like to connect my project to the database. I would like to start with basic functionallity such as registration and user system.
I am currently using following (installed via composer):
"everyman/neo4jphp": "dev-master",
"hirevoice/neo4jphp-ogm": "dev-master",
"klaussilveira/neo4j-ogm-bundle": "dev-master"
These should give me the functionality I need. I have then created a UserBundle under src with following folder structure:
src
|-Controller
|-DependencyInjection
|-Entity
|-Form
|-Ressources
|-UserBundle.php
I would now like to go through the tutorial at http://symfony.com/doc/current/cookbook/doctrine/registration_form.html but instead of using their database, I would like to use Neo4j. Could someone point out where and how I should manipulate the code of the tutorial to be able to register a user into the neo4j graph? I have tried myself but the documentation is scarse of the neo4j-ogm and I have only produced errors upon errors. I have now deleted the Bundle and created it again to start anew.
I am especially interessted if their are steps that are assumed to be common knowledge and are thus left out?
I have now been able to set up everything so that the registration form is shown. But when submitting, following error is shown:
Unable to commit batch [401]:
Headers: Array
(
[Date] => Sun, 05 Jul 2015 13:08:20 GMT
[Content-Type] => application/json; charset=UTF-8
[WWW-Authenticate] => None
[Content-Length] => 139
[Server] => Jetty(9.2.4.v20141103)
)
Body: Array
(
[errors] => Array
(
[0] => Array
(
[message] => No authorization header supplied.
[code] => Neo.ClientError.Security.AuthorizationFailed
)
)
)
500 Internal Server Error - Exception
I am assuming that my connection authentication is not working. In my config.yml I have defined following connection:
# Neo4j config
neo4j_ogm:
transport: 'curl'
host: 'localhost'
port: 7474
username: 'foo'
password: 'bar'
debug: true
But this does not seem to work. Where else do I have to set up the connection details?
Update
Thank you Christophe Willemsen for your answer.
The error was produced because the authentication did not work. By navigating to the Neo4j installation folder and editing the "neo4j-server.properties" file to allow all access, I am now able to save simple data to the graph. I have not tried to implement any checks or passwort encryptions, but the very basic "create a node with properties" now works.
What I would like to accomplish now would be:
- Make it possible to password protect the Neo4j connection and have the connection information stored in a config.yml file
- Create and implement various checks (is email address already in DB / Is password strong enough...)
- Create and implement password encryption
- Create member-system which gets data out of the neo4j database
If you have any tips on where I can get more information on this topic or if you have already done something similar, help would be appreciated.
Have added the files to my post below in case these are useful for someone else. Be aware: I have only just begun learning Symfony and Neo4j and the code could contain errors or major vulnerabilities. I will also try to update this post if I have any luck implementing further neo4j related things.
In the file "neo4j-server.properties" (located under "/etc/neo4j" on my install) edit following lines as such:
# Let the webserver only listen on the specified IP. Default is localhost (only
# accept local connections). Uncomment to allow any connection. Please see the
# security section in the neo4j manual before modifying this.
org.neo4j.server.webserver.address=0.0.0.0
# Require (or disable the requirement of) auth to access Neo4j
dbms.security.auth_enabled=false
In my UserBundle, following files could be of interesst to others: "/src/UserBundle/Controller/AccountController.php"
<?php
// src/Acme/AccountBundle/Controller/AccountController.php
namespace UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use UserBundle\Form\Type\RegistrationType;
use UserBundle\Form\Model\Registration;
use Symfony\Component\HttpFoundation\Request;
// use HireVoice\Neo4j\EntityManager as EntityManager;
class AccountController extends Controller
{
public function registerAction()
{
$registration = new Registration();
$form = $this->createForm(new RegistrationType(), $registration, array(
'action' => $this->generateUrl('account_create'),
));
return $this->render(
'UserBundle:Account:register.html.twig',
array('form' => $form->createView())
);
}
public function createAction(Request $request)
{
$em = $this->container->get('neo4j.manager');
//$repo = $em->getRepository('Entity\\User');
$form = $this->createForm(new RegistrationType(), new Registration());
$form->handleRequest($request);
if ($form->isValid()) {
$registration = $form->getData();
$em->persist($registration->getUser());
$em->flush();
return $this->redirectToRoute('account_success');
// return $this->redirect('http://4740.hostserv.eu/twohive/web/app_dev.php/register/success');
}
return $this->render(
'UserBundle:Account:register.html.twig',
array('form' => $form->createView())
);
}
public function successAction()
{
return $this->render('UserBundle:Account:success.html.twig');
}
}
"/src/UserBundle/Entity/User.php"
<?php
// src/UserBundle/Entity/User.php
namespace UserBundle\Entity;
use HireVoice\Neo4j\Annotation as OGM;
/**
* @OGM\Entity
*/
class User
{
/**
* @OGM\Auto
*/
protected $id;
/**
* @OGM\Property
* @OGM\Index
*/
protected $email;
/**
* @OGM\Property
*/
protected $plainPassword;
public function getId()
{
return $this->id;
}
public function getEmail()
{
return $this->email;
}
public function setEmail($email)
{
$this->email = $email;
}
public function getPlainPassword()
{
return $this->plainPassword;
}
public function setPlainPassword($password)
{
$this->plainPassword = $password;
}
}
"/src/UserBundle/Form/Model/Registration.php" (As described in the Symfony-Book)
<?php
// src/Acme/AccountBundle/Form/Model/Registration.php
namespace UserBundle\Form\Model;
use Symfony\Component\Validator\Constraints as Assert;
use UserBundle\Entity\User;
class Registration
{
/**
* @Assert\Type(type="UserBundle\Entity\User")
* @Assert\Valid()
*/
protected $user;
/**
* @Assert\NotBlank()
* @Assert\True()
*/
protected $termsAccepted;
public function setUser(User $user)
{
$this->user = $user;
}
public function getUser()
{
return $this->user;
}
public function getTermsAccepted()
{
return $this->termsAccepted;
}
public function setTermsAccepted($termsAccepted)
{
$this->termsAccepted = (bool) $termsAccepted;
}
}
"/src/UserBundle/Form/Type/RegistrationType.php" (As described in the Symfony-Book)
<?php
// UserBundle/Form/Type/RegistrationType.php
namespace UserBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('user', new UserType());
$builder->add(
'terms',
'checkbox',
array('property_path' => 'termsAccepted')
);
$builder->add('Register', 'submit');
}
public function getName()
{
return 'registration';
}
}
"/src/UserBundle/Form/Type/UserType.php" (As described in the Symfony-Book)
<?php
// UserBundle/Form/Type/UserType.php
namespace UserBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('email', 'email');
$builder->add('plainPassword', 'repeated', array(
'first_name' => 'password',
'second_name' => 'confirm',
'type' => 'password',
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'UserBundle\Entity\User'
));
}
public function getName()
{
return 'user';
}
}
"/src/UserBundle/Resources/config/routing.yml"
account_register:
path: /register
defaults: { _controller: UserBundle:Account:register }
account_create:
path: /register/create
defaults: { _controller: UserBundle:Account:create }
account_success:
path: /register/success
defaults: { _controller: UserBundle:Account:success }
I have now created a new repository which seems to work up till now:
https://github.com/JoranBeaufort/Neo4jUserBundle
Be careful: Like I stated, I am not an expert in Symfony or programming in general. The Bundle may have serious security issues. Hints of improvement are welcome.
I did this implementation some time ago (~ two years) but didn't updated it due to the fact I don't use these vendors anymore.
This was splitted in two bundles, and that might give you some ideas and examples :
https://github.com/ikwattro/KwattroNeo4jOGMBundle
https://github.com/ikwattro/Neo4jUserBundle
Basically steps are common and lot of information can be found in the Symfony documentation.
Create your user entity base on the neo4jphp-ogm annotations
Create a User provider -> security
Create a User Manager that will retrieve the users when the authentication happens
Concerning your last error concerning the authentication, by looking at the
klaussilvera/neo4j-ogm-bundle
last commit date, chance is high that it doesn't support neo4j authentication added in 2.2.You might want to disable the neo4j authentication for your first tests or fork the current repository and create a PR adding the authentication parameters in the ConfigDefinition of the bundle.