I am trying to figure out the registration process of the FosUserBundle and have been unable to do so.
I want to be able to register a user manually using custom fields and have been unable to see that in the code.
I have the registerAction in FosUserBundle and following it anywhere does not show me where the information is actually stored in the database:
public function registerAction()
{
$form = $this->container->get('fos_user.registration.form');
$formHandler = $this->container->get('fos_user.registration.form.handler');
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
$process = $formHandler->process($confirmationEnabled);
if ($process) {
$user = $form->getData();
if ($confirmationEnabled) {
$this->container->get('session')->set('fos_user_send_confirmation_email/email', $user->getEmail());
$route = 'fos_user_registration_check_email';
} else {
$this->authenticateUser($user);
$route = 'fos_user_registration_confirmed';
}
$this->setFlash('fos_user_success', 'registration.flash.user_created');
$url = $this->container->get('router')->generate($route);
return new RedirectResponse($url);
}
return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.'.$this->getEngine(), array(
'form' => $form->createView(),
'theme' => $this->container->getParameter('fos_user.template.theme'),
));
}
How do I register a user manually?
Thanks
Have you read this in the FOSUserBundle docs?
Using the UserManager
Apparently the service UserManager has the responsibility to actually save and update the user, you could create your own UserManager by following the guide.
Edit: Symfony has incorporated the documentation for the FOSUserBundle into their own documentation, as so the new link for the documentation is:
https://symfony.com/doc/master/bundles/FOSUserBundle/index.html
Related
Lets say that my page has 10 sections, in 6 of them I have to check if the user is logged in, and if not, redirect him to the "login/register" page.
I found myself repeating this code in the controller of those 6 pages:
public function actionthatneedsauthAction()
{
$sl = $this->getServiceLocator();
$authService = $sl->get('doctrine.authenticationservice.orm_default');
$user = $authService->getStorage()->read(); //is the user logged in?
if ($user) { //auth successful
//-------------/*CODE FOR THIS SPECIFIC CONTROLLER GOES HERE*/--------
return new ViewModel(array(
'user' => $user,
'somethingelse' => $somethingelse
));
} else { //auth denied
return $this->redirect()->toRoute(user, array('action' => 'login'));
}
}
I tried to encapsulate that into a service, called islogged (this is a model, not a controller), but I couldn't make it work because I couldn't find a way to redirect to a controller from inside a model, I only know how to redirect to a controller via another controller.
So in my usermanager.php I had a function like this one:
public function islogged()
{
$sl = $this->getServiceLocator();
$authService = $sl->get('doctrine.authenticationservice.orm_default');
$user = $authService->getStorage()->read(); //is the user logged in?
if ($user) { //auth successful
return $user;
} else {
/*
redirect to the login screen, dont know how to do it,
this code doesnt work here:
return $this->redirect()->toRoute(NULL, array(
'controller' => 'user',
'action' => 'login'
));
*/
}
}
so the idea was that in my controllers I only had to write:
$user = islogged();
and all the code repetition I mentioned won't be necessary anymore.
Is it a good practice what I tried to do with the usermanager.php islogged function?
If it is a good practice, how am I supposed to redirect to a controller from inside a model?
If is not a good practice, which will be the way to avoid all that code repetition that I'm having in my controllers?
I know that I can put the authentication step into the onboostrap() but in that case the auth will be triggered for all of my pages, and I just want it in some of them.
I would advise you to implement Doctrine Authentication with official DoctrineModule Authentication described in the docs folder of the repo.
Read this - Link to DoctrineModule Authentication
Then you can handle your Authentication check via the zf2 own Controller and View Helpers identity. See example in the docs here.
I use this ACL Module on my apps: https://github.com/ZF-Commons/zfc-rbac
My Customer overview controller then looks as so:
<?php
namespace RoleBasedCustomer\Controller;
use RoleBasedUser\Service\AuthenticationService;
use RoleBasedUser\Service\UserService;
use RoleBasedUser\Controller\AbstractMultiModelController;
class OverviewController extends AbstractMultiModelController
{
public function __construct(
AuthenticationService $authService,
UserService $userService
) {
$this->authService = $authService;
$this->userService = $userService;
}
public function indexAction()
{
if ( ! $this->authService->hasIdentity() ) {
return $this->redirect()->toRoute('customer/login');
}
}
}
The only thing i had to do is replace these two lines:
$authService = $this->getServiceLocator()
->get('doctrine.authenticationservice.orm_default');
$user = $authService->getStorage()->read(); //is the user logged in?
with this one:
$user = $this->identity();
I study ZF2 and have problem with login process. I have two modules login and moduleExample.
Login module is based on http://samsonasik.wordpress.com/2012/10/23/zend-framework-2-create-login-authentication-using-authenticationservice-with-rememberme/
I can redirect moduleExample to login route with condition hasIdentity() in Controllers, but can I set redirecting to this module at one place? Controllers will probably be more. I've already tried in onBootstrap method (Module.php), but then it is redirected everywhere (in all modules).
Where I can do what I describe?
It is possible to handle the login redirection at one place, one way is to define a custom event which is called in the routing event chain. To do this, you have to add the handler in your Module.php (preferably in the authentication module):
class Module
{
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$sm = $e->getApplication()->getServiceManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
//attach event here
$eventManager->attach('route', array($this, 'checkUserAuth'), 2);
}
public function checkUserAuth(MvcEvent $e)
{
$router = $e->getRouter();
$matchedRoute = $router->match($e->getRequest());
//this is a whitelist for routes that are allowed without authentication
//!!! Your authentication route must be whitelisted
$allowedRoutesConfig = array(
'auth'
);
if (!isset($matchedRoute) || in_array($matchedRoute->getMatchedRouteName(), $allowedRoutesConfig)) {
// no auth check required
return;
}
$seviceManager = $e->getApplication()->getServiceManager();
$authenticationService = $seviceManager->get('Zend\Authentication\AuthenticationService');
$identity = $authenticationService->getIdentity();
if (! $identity) {
//redirect to login route...
$response = $e->getResponse();
$response->setStatusCode(302);
//this is the login screen redirection url
$url = $e->getRequest()->getBaseUrl() . '/auth/login';
$response->getHeaders()->addHeaderLine('Location', $url);
$app = $e->getTarget();
//dont do anything other - just finish here
$app->getEventManager()->trigger(MvcEvent::EVENT_FINISH, $e);
$e->stopPropagation();
}
}
}
what you tried is correct, so then you just need this little bit here
$controller = $e->getTarget();
$params = $e->getApplication()->getMvcEvent()->getRouteMatch()->getParams();
if(!$params['controller'] == 'your login conroller path e.g. RouteFolder/Controller/LoginControllerName'){
return $controller->redirect()->toRoute('your redirect route')
}
do a
print_r($params['controller'])
and see what it returns and you will understand what i mean
so the event onBoostrap wont redirect you if your current location is the controller where the user comes to login
I'am a new in Yii and I'm trying to do a RBAC control in my web application. I write an authorization and registration pages and everything working perfect. But when I trying to read current user's role using Yii::app()->user->role I'm getting an error with the following content:
PHP warning
include(User.php): failed to open stream: No such file or directory
I did everything like in official cookbook. Honestly, I don't know why this happens that's why if someone could help me to solve this problem I will be very appreciated.
Here I wrote the steps which I did when writing the role based user control.
As mentioned in official Yii cookbook I created a simple database table named users where I defined the role attribute. Then I write a WebUser class:
class WebUser extends CWebUser {
private $_model = null;
function getRole() {
if($user = $this->getModel()){
return $user->role;
}
}
private function getModel(){
if (!$this->isGuest && $this->_model === null){
$this->_model = User::model()->findByPk($this->id, array('select' => 'role'));
}
return $this->_model;
}
}
Next step I changed the default realization of the UserIdentity::authentificate() method, where I trying to assign role to the current user:
public function authenticate()
{
$users = Users::model()->find('LOWER(name)=?', array(strtolower($this->name)));
if($users === null)
$this->errorCode = self::ERROR_USERNAME_INVALID;
else if ($users->validatePassword(md5($this->password)))
$this->errorCode = self::ERROR_PASSWORD_INVALID;
else
{
$this->_id = $users->id;
$this->username = $users->name;
$auth=Yii::app()->authManager;
echo "user role = ".$users->role.", user id = ".$this->_id;
if(!$auth->isAssigned($users->role,$this->_id))
{
if($auth->assign($users->role,$this->_id))
{
Yii::app()->authManager->save();
}
}
$this->errorCode=self::ERROR_NONE;
}
return $this->errorCode == self::ERROR_NONE;
}
...
Finally, I declare all this components in the main web config file:
...
'import'=>array(
'application.models.*',
'application.components.*',
),
...
'components'=>array(
'user'=>array(
// enable cookie-based authentication
'class'=>'WebUser',
'allowAutoLogin'=>true,
),
'authManager' => array(
'class' => 'PhpAuthManager',
'defaultRoles' => array('guest'),
),
...
In getModel() you're using User::model(), but in authenticate() you're calling Users::model(), could it be that you're trying to call the wrong model class (it's Users instead of User)?
i'm currently writing a Application based on YII.
My action for index:
public function actionIndex() {
$data = array();
$data['server'] = Server::model()->findByPk(1);
$data['dataProvider'] = new CActiveDataProvider('ServerUserPermission', array('criteria' => array('condition' => 'serverID=:id', 'params' => array(':id' => 1))));
$this->render('index', $data);
}
my ajax action:
public function actionAddPermission($server) {
if(Util::checkServerPower($server, Permission::MODIFY_SERVER)) {
$perm = new ServerUserPermission;
$perm->userID = 1;
$perm->serverID = $server;
$perm->power = 10;
try {
if ($perm->save()) {
echo "OK";
} else {
echo Util::print_r($perm->getErrors());
}
} catch (Exception $e) {
echo 'Critical Error Code: ' . $e->getCode();
}
} else {
echo 'No Permissions';
}
}
My view links to the addPermission action by using a button:
echo CHtml::ajaxButton("Insert New Player", array('addPermission', 'server' => $server->serverID), array('success'=>'refresh'));
My function Util::checkServerPower(...) checks the current User of the Application. Consequence: Ajax requests in YII are handled by an Guest AuthWeb User, but i need to check whether the User is actually allowed to add permissions or not. I currently cannot think of a secured solution to protect malicious data send by other guests or not. Is it somehow possible to get the (server-side) userID of the Ajax-call?
Thanks anyway
sincerly
I would do it by using the built in access control and extending CWebUser.
It might seem lengthy but I think it's a clean solution. (We already have Yii::app()->user->isGuest and the like, so why not check all permissions here?)
1) Activate the access control filter.
(In one controller or in /components/controller.php for all your controllers at once)
public function filters()
{
return array( 'accessControl' ); // Tell Yii to use access rules for this controller
}
2) Add an access rule
In the concerned controller. (Sorry, I didn't bother with your index-action.)
public function accessRules()
{
return array(
[
'allow',
'actions'=>['AddPermission'],
'expression'=>'$user->has(Permission::MODIFY_SERVER)'
],
['deny'], // Deny everything else.
);
}
3) Extend CWebUser
// components/WebUser.php
class WebUser extends CWebUser {
public function has( $permission)
{
// Check database for permissions using Yii::app()->user->id
...
}
}
4) Configure your app to use your new WebUser instead of CWebUser
// config/main.php
'components'=>[
'user'=>[
'class' => 'WebUser',
],
],
Does anyone have an example or any idea how one would implement the FOSRestBundle together along with the FOSUserBundle. I have a Web app already developed with Symfony 2 and the FOSUserBundle, but I would like to add the FOSRestBundle for an api layer. I want to be able to pass it a username and password and receive some type of token from the FOSUserBundle that represents the logged in user that I can then pass and forth between other api calls. Does anyone know of a good way to do this?
FOSUserBundle should be natively "restful" meaning that it may follow the REST recommandations.
However, it is not designed to work natively with FOSRestBundle, the simplest way to do that is to override the UsersController in your Bundle and adapt your actions.
For example, to allow RESTFul registration, you may write the following action:
public function postUsersAction()
{
$form = $this->container->get('fos_user.registration.form');
$formHandler = $this->container->get('fos_user.registration.form.handler');
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
$process = $formHandler->process($confirmationEnabled);
if ($process) {
$user = $form->getData();
$authUser = false;
if ($confirmationEnabled) {
} else {
$authUser = true;
}
$response = new Response();
if ($authUser) {
/* #todo Implement authentication */
//$this->authenticateUser($user, $response);
}
$response->setStatusCode(Codes::HTTP_CREATED);
$response->headers->set(
'Location',
$this->generateUrl(
'api_users_get_user',
array('user' => $user->getId()),
true
)
);
return $response;
}
return RestView::create($form, Codes::HTTP_BAD_REQUEST);
}