[Tutorial] My Second Project - Admin Generator + sfGuardPlugin 

http://www.symfony-project.org/forum/index.php?t=msg&th=5064#msg_21825

For people that turn to framework as complicated as symfony for help, I think 99.9% of time they need some authentication. So the next step in this tutorial is to add authentication capability. We'll add more fields to the author table, ie, login id, email, & phone etc, — just for illustration purpose. The step1.tgz already contains meaningful lookup table drop-down, once the sfGuardPlugin is in, you'll see a working version of many to many relationship capability showcase in symfony.

The official doc is here, http://www.symfony-project.org/book/trunk/06-Inside-the-Controller-Layer#Action%20Security

"Among the symfony plug-ins, the sfGuardPlugin extends the session class to make login and logout easy.": http://www.symfony-project.org/trac/wiki/sfGuardPlugin

[Tutorial] My Second Project - Admin Generator + sfGuardPlugin 

For a newbie like me, the docs in the sfGuard wiki has mile long gaps between them.

Chanages to enable the sfGuard are logged at: http://www.symfony-project.org/forum/index.php?t=msg&th=5071#msg_21849

To Customize sfGuardAuth module templates, the wiki says:

Customize sfGuardAuth module templates

By default, sfGuardAuth module comes with 2 very simple templates:

  • signinSuccess.php

  • secureSuccess.php

If you want to customize one of these templates:

  • Create a sfGuardAuth module in your application

  • Create a template with the name of the template you want to customize in your templates directory

  • Symfony now renders your template instead of the default one

I've been trying to follow the above and fill the gaps within.

here is what I've did:

$ symfony init-module backend sfGuardAuth
$ cp plugins/sfGuardPlugin/modules/sfGuardAuth/templates/secureSuccess.php apps/backend/modules/sfGuardAuth/templates/
$ cp plugins/sfGuardPlugin/modules/sfGuardAuth/templates/signinSuccess.php apps/backend/modules/sfGuardAuth/templates/

I've tweaked all three templates under apps/backend/modules/sfGuardAuth/templates/, I.e., secureSuccess.php, signinSuccess.php & indexSuccess.php, and I've made the following changes:

$ head -5 apps/backend/config/routing.yml
# default rules
homepage:
  url:   /
  param: { module: sfGuardAuth, action: index }

$ cat ./apps/backend/modules/sfGuardAuth/actions/actions.class.php
<?php

require_once(sfConfig::get('sf_plugins_dir').'/sfGuardPlugin/modules/sfGuardAuth/lib/BasesfGuardAuthActions.class.php');

/**
 * sfGuardAuth actions.
 *
 * @package    sfpear
 * @subpackage sfGuardAuth
 * @author     Your name here
 * @version    SVN: $Id: actions.class.php 2692 2006-11-15 21:03:55Z fabien $
 */
class sfGuardAuthActions extends BasesfGuardAuthActions
{
  /**
   * Executes index action
   *
   */
  public function executeIndex()
  {
  }
}

But as the result, none of my customized templates are used. All that I want is that

The solution is http://www.symfony-project.org/forum/index.php?t=msg&goto=22107&#msg_22107

[Tutorial] My Second Project - Admin Generator + sfGuardPlugin 

Initially, I had major problem just to make the sfGuardPlugin work. The symptom was, right after I turn the security on, I get blocked everywhere, even to login page. The whole analysis and solution is logged at http://www.symfony-project.org/forum/index.php?t=msg&th=5071&mid=21751

Then, I was not able to

The solution is at http://www.symfony-project.org/forum/index.php?t=msg&goto=22107&#msg_22107

After that was passed, there were still battles to fight. The sfGuardPlugin is so weired designed that is awfully hard to add those extra field, e.g. first name, last name, email, etc, that I almost wanted to give up the sfGuardPlugin. Check the details at http://www.symfony-project.org/forum/index.php?t=msg&goto=20465#msg_20465

I am working towards a login system, to make things easier a bit. I think the most easy way is to populate them beforehand with fixtures. This is how I did:

data/fixtures/fixtures.00.Category.yml
data/fixtures/fixtures.10.Users.yml
data/fixtures/fixtures.11.Author.yml
data/fixtures/fixtures.12.Admin.yml
data/fixtures/fixtures.15.User.Credentials.yml
data/fixtures/fixtures.20.Post.yml

I'm new to symfony (and quite new to php actually). the login system is what I can do currently. it is not a freely registration system which allows use to register themselves and populate the required fields themselves with validation.

Note that I didn't create the (default) sfGuardUserProfile class, but used the existing Author table for the user profile instead. If you have all the required info, then creating a login system this way is very simple — just maintain the user login info and profile in a separated place and export/convert them into yaml fixtures, then load the yaml fixtures via:

symfony propel-load-data backend

sfGuard user registration 

http://www.symfony-project.org/forum/index.php?t=msg&&th=5239#msg_22622

> What is the best way to create a userregistration module for sfGuard?

Check the subversion repository. Someone is working on a Blog plugin which has user registration built-in using the sfGuard plugin.

http://www.symfony-project.org/trac/browser/plugins/sfBlogPlugin

documented on: 27 February 2007, marckohlbrugge

accessing sfBlogPlugin via svn 

svn co http://svn.symfony-project.org/plugins/sfBlogPlugin/ plugins/sfBlogPlugin

sfGuard and usage of sfGuardUserProfile 

http://www.symfony-project.org/forum/index.php?t=msg&goto=20465&&srch=sfGuard#msg_20465

> I don't get how is sfGuardUserProfile intended to be used (in backend).
> How should i connect sfGuardUserProfile and sfGuardUser?

Profile feature of sfGuardPlugin is intended to enable adding more information to user above standard username and password (etc) available in sfGuardUser.

You can create for example user table, where you want store first name, surname, email, address etc.

To connect 'user' and 'sf_guard_user' tables together, you must add new column (let's say sf_guard_user_id) with "foreign key to sf_guard_user" to your user table.

And then edit app.yml and add following.

all:
  sf_guard_plugin:
    profile_class:      User
    profile_field_name: sf_guard_user_id

(The reason why it cannot be done with real foreign keys is the limitation of Propel.)

Then you can access data from your user table by doing

$this->getUser()->getProfile()->getEmail();

for example.

documented on: 11 February 2007, qube

sfGuard and usage of sfGuardUserProfile 

I think the point that the first two posts are making is that the fields of the 'user' table are not automatically available in the generated sfGuardUser admin module.

If you want to add these fields, you would need to add partials to the sfGuardUser admin generator.yml. One for each field you want to have access to. You would then need to extend the actions and add validation. I'm not sure, but I guess that you can create a module called sfGuardUser and put your actions, partials, generator.yml and validation.yml in there, to override the built in settings.

It would be nice if this could be taken care of automatically by the admin generator, but unfortunately the generated admin modules can only handle a single table.

documented on: 11 February 2007, flat stanley

usage of sfGuardUserProfile 

http://www.symfony-project.org/forum/index.php?t=msg&th=4782#msg_21884

COil wrote on Sat, 17 February 2007 07:42

Well in fact it's easy [to automate setting profile], just make a setProfile() in your myUser.class.php, in this one you will put the profile object in the session, call this function in sfGuardAuth sigin function… and also re-implement getProfile() in myUser to take profile from session and not from database

where is the best place to put the profile object in the session?

I hacked the following, but I get this error:

Fatal error: Call to a member function getProfile() on a non-object in /var/www/my_proj/plugins/sfGuardPlugin/lib/user/sfGuardSecur ityUser.class.php on line 193
$ symfony init-module reqs sfGuardAuth

Define getProfileId in myUser:

$ cat apps/reqs/lib/myUser.class.php
<?php

class myUser extends sfGuardSecurityUser
{
    public function getProfileId()
    {
        return $this->getAttribute('sfGuardProfileId');
    }
}

Save profile ID in the session:

$ cat apps/reqs/modules/sfGuardAuth/actions/actions.class.php
<?php

require_once(sfConfig::get('sf_plugins_dir').'/sfGuardPlugin/modules/sfGuardAuth/lib/BasesfGuardAuthActions.class.php');

/**
 * sfGuardAuth actions.
 *
 * @package    cm
 * @subpackage sfGuardAuth
 * @author     Your name here
 * @version    SVN: $Id: actions.class.php 2692 2006-11-15 21:03:55Z fabien $
 */
class sfGuardAuthActions extends BasesfGuardAuthActions
{
  /**
   * Executes Signin action
   *
   */
    public function executeSignin()
    {
        // pre hook
        // Store data in the user session
        $this->getUser()->
            setAttribute('sfGuardProfileId',
                         $this->getUser()->getProfile()->getId());

        // call the parent method
        parent::executeSignin();

        // post hook
    }
}

How to use it:

$ tail -13 apps/reqs/modules/req/actions/actions.class.php
    protected function saveReq($req)
    {
        // pre save hook
        //$req->setStaffId($this->getUser()->getProfile()->getId());
        //$req->setStaffId($this->getUser()->getAttribute('sfGuardProfileId'));
        $req->setStaffId($this->getUser()->getProfileId());

        // call the parent save() method
        parent::saveReq($req);

        // post save hook
    }
}

Help 

If you want to customize or add methods to the sfGuardAuth:

documented on: 2007.02.27

Get sfGuardProfileId from sfGuard plugin 

Goal 

Store data to the user session after user log in.

COil's solution 

http://www.symfony-project.org/forum/index.php?t=msg&th=4782#msg_22686

> where is the best place to put the profile object in the session?
Example: For sfGuardAuthActions
class sfGuardAuthActions extends BasesfGuardAuthActions
{
    public function executeSignin()
    {
        if ($this->getRequest()->getMethod() == sfRequest::POST) {
            $this->setSessionDatas();
        }

        // Parent
        parent::executeSignin();
    }

    public function setSessionDatas()
    {
        $this->getUser()->setProfile();
    }
Example: In myUser.class.php
class myUser extends sfGuardSecurityUser
{
    // Namespace
    const NS             = 'sfGuardSecurityUser';

    // Cles
    const ADMIN_MENU_KEY = 'admin_menus';
    const PROFILE_KEY    = 'profile';
    const USER_NAME_KEY  = 'user_name';
    const USER_ID_KEY    = 'user_id';

    ...

    public function getProfile()
    {
        return $this->getAttribute(self::PROFILE_KEY, null, self::NS);
    }

    public function setProfile()
    {
        $this->setAttribute(self::PROFILE_KEY, parent::getProfile(), self::NS);
        $this->setAttribute(self::USER_NAME_KEY, parent::getUserName(), self::NS);
    }

documented on: 28 February 2007, COil

My solution 

Solution Synopsis 

Get data in executeSignin.

Solution 

public function executeSignin()
{
    // pre hook
    // Store data in the user session
    if ($this->getUser()->getGuardUser()) {
        $this->getUser()->
            setAttribute('sfGuardProfileId',
                         $this->getUser()->getProfile()->getId());
        // done
        }
// call the parent method
parent::executeSignin();
    // post hook
}

Analysis / Reason 

The executeSignin is called twice when logging in user.

The first time is to show the form, and the 2nd time is to redirect to the $referer page.

Adding a if statement will make sure the data is stored in the user session after user has logged in and before the page will be redirected.

Trying History 

  1. Store data to the user session in pre hook, get the following. NB, the reason that I use pre hook initially is because that the parent::executeSignin uses redirect at the end.

    Fatal error: Call to a member function getProfile() on a non-object in /var/www/cm/plugins/sfGuardPlugin/lib/user/sfGuardSecurityUser.class.php on line 193
  2. Store data to the user session in post hook, as follows, still get the above error.

class sfGuardAuthActions extends BasesfGuardAuthActions { /** * Executes Signin action * */ public function executeSignin() { // pre hook

// call the parent method
parent::executeSignin();
        // post hook
        // Store data in the user session
        $this->getUser()->
            setAttribute('sfGuardProfileId',
                         $this->getUser()->getProfile()->getId());
    }
}

documented on: 2007.02.28

sfGuard Password Rest 

http://www.symfony-project.org/forum/index.php?t=msg&th=5300&

I think the password are saved in Db in encrypted form, because the

$this->getUser()->getGuardUser()->getPassword()

returns a md5 hash value. Therefore there is no way to get the password from Db as clear text, correct?

Further, How to reset password?

sfGuard Password Rest 

jackbravo wrote on Thu, 01 March 2007 14:56

> Yes, the passwords are stored in sha1 (i believe) by default. So you
> should reset the passwords from your backend app (or from a secure
> module). I believe the user administrator that comes with sfGuard already
> does this: module sfGuardUser

Yes,

$sysusr = sfGuardUserPeer::retrieveByUsername('usrname');
$sysusr->setPassword('newpass');
$sysusr->save();

Tested AOK.

documented on: 08 March 2007, sfxpt