Skip to content

YACCA Yet Another Cake Component for Auth

When I have finished my first application I had the necessity to create an authorization system to control user access.
I have looked around and founded some very good system especially in the bakery repository.
But in my mind I was thinking at something very simple for management.
My idea was to have an approach by rules. A list of ordered rules with allow/deny actions.
Cake Auth Rules
As you can see it is very intuitive how the system works:

  • The first rule allow all
  • The second rule deny access to all actions of controllers that start with Cake
  • The third rule allow access to Controller CakeLogin (All Actions)
  • The fourth allow only the action changepwd of controller CakeUsers
  • And last rule allow access to welcome page.


To accomplish this task we need four tables

  • users: define who access the system
  • groups: defines the roles
  • users_groups: defines the relations between users and groups
  • rules: defines the set of rules for one group

ER Diagram
ER Diagram

Models

file: cake_user.php

PHP:
  1. <?php
  2. /*
  3. ** cake_user.php
  4. ** users model
  5. */
  6. class CakeUser extends AppModel {
  7.   var $name = 'CakeUser'
  8.   var $useDbConfig = 'cakeauth';
  9.  
  10.   var $validate = Array(
  11.         'login'  => VALID_NOT_EMPTY,
  12.         'username' => VALID_NOT_EMPTY,
  13.         'password' => VALID_NOT_EMPTY
  14.       );
  15.  
  16.   var $hasAndBelongsToMany = array(
  17.         'CakeGroup' => array(
  18.           'className' => 'CakeGroup',
  19.           'joinTable' => 'users_groups',
  20.           'foreignKey' => 'user_id',
  21.           'associationForeignKey' => 'group_id'
  22.         )
  23.       );
  24.  
  25.   // Called from cake_login controller
  26.   // to get user data
  27.   function getAclData( $login='zxcjgjhsw', $passwd='') {
  28.     $this->recursive = 1;
  29.     $data = $this->find("login = '$login' AND passwd = '$passwd'");
  30.     if( $data ) {
  31.       $data['CakeUser']['group_id'] = '(-1,0';
  32.       if( $data['CakeGroup'] ) {
  33.         foreach( $data['CakeGroup'] as $group)
  34.           $data['CakeUser']['group_id'] .= ',' . $group['id'];
  35.       }
  36.       $data['CakeUser']['group_id'] .= ')';
  37.     }
  38.     return $data;
  39.   }
  40. }
  41. ?>

file: cake_group.php

PHP:
  1. <?php
  2. /*
  3. ** cake_group.php
  4. ** groups model
  5. */
  6. class CakeGroup extends AppModel {
  7.   var $name = 'CakeGroup'
  8.   var $useDbConfig = 'cakeauth';
  9.  
  10.   var $validate = Array('group'  =>  VALID_NOT_EMPTY);
  11.  
  12.   var $hasMany = array(
  13.         'CakeRule' => array(
  14.           'className' => 'CakeRule',
  15.           'exclusive' => false,
  16.           'dependent' => true,
  17.           'foreignKey' => 'group_id',
  18.           'order' => 'CakeRule.rulenum ASC'
  19.         )
  20.       );
  21.  
  22.   var $hasAndBelongsToMany = array(
  23.         'CakeUser' => array(
  24.           'className' => 'CakeUser',
  25.           'joinTable' => 'users_groups',
  26.           'foreignKey' => 'group_id',
  27.           'associationForeignKey'=> 'user_id'
  28.         )
  29.       );
  30. }
  31. ?>

file: cake_rule.php

PHP:
  1. <?php
  2. /*
  3. ** cake_rule.php
  4. ** rules model
  5. */
  6. class CakeRule extends AppModel {
  7.   var $name          = 'CakeRule'
  8.   var $useDbConfig   = 'cakeauth';
  9.  
  10.   var $validate = Array('rulenum'  =>  VALID_NOT_EMPTY);
  11.  
  12.   var $belongsTo = array(
  13.         'CakeGroup' => array(
  14.           'className'  => 'CakeGroup',
  15.           'foreignKey' => 'group_id'
  16.         )
  17.       );
  18.  
  19.   /*
  20.    * Function now meets Cake standards and best practices
  21.    * Thanks to Mariano Iglesias for suggestion
  22.    */
  23.   function getRules( $groupId = '(-1)') {
  24.     $conditions = "CakeRule.group_id IN {$groupId}";
  25.     $fields     = 'CakeRule.rulenum, CakeRule.action, CakeRule.allow ';
  26.     $order      = 'CakeRule.group_id ASC, CakeGroup.security_level DESC, CakeRule.rulenum ASC';
  27.     $data       = $this->findAll( $conditions, $fields, $order, null, 1, 0);
  28.     return $data;
  29.   }
  30.  
  31. }
  32. ?>

Now that we have defined our models create the component to manage all the system:
file: cake_auth.php

PHP:
  1. <?php
  2. /*
  3. ** Some code rewritten for changes in CakeRule::getRules
  4. ** And in Session writing and deleting
  5. ** Thanks to mariano and gwoo
  6. */
  7. class CakeAuthComponent extends object {
  8.   var $components = array('Session');
  9.   var $externalId = null; // id of external table for specific jobs
  10.   var $id         = null; // id of the logged in user
  11.   var $username   = null; // username of the logged in user
  12.   var $login      = null; // login of the logged in user
  13.   var $security   = null; // security_level of the logged in user
  14.   var $groupId    = null; // group(s) assigned to the logged in user
  15.   var $errors     = null; // error messages to be displayed
  16.   var $lastUrl    = '/' ; // last url saved just in case of redirection
  17.   var $cacheRules = null; // cached rules for best performance
  18.  
  19.   // Function to save the url that will be chained
  20.   function saveUrl( $url ) {
  21.     $this->Session->write('cakeAuth.lastUrl', $url);
  22.   }
  23.  
  24.   // Function to Set / Get Session Vars
  25.   function set($data='') { // Line 25
  26.     if( $data ) {
  27.       $this->Session->write('cakeAuth', $data);
  28.       $this->Session->write('cakeAuth.cacheRules', serialize($this->getRules($data['group_id']))); // Line 28
  29.       $this->Session->write('cakeAuth.noCheck',   0);
  30.     }
  31.     if($this->Session->check('cakeAuth') && $this->Session->valid('cakeAuth')) {
  32.       $this->id         = $this->Session->read('cakeAuth.id');
  33.       $this->externalId = $this->Session->read('cakeAuth.external_id');
  34.       $this->username   = $this->Session->read('cakeAuth.username');
  35.       $this->login      = $this->Session->read('cakeAuth.login');
  36.       $this->security   = $this->Session->read('cakeAuth.security_level');
  37.       $this->groupId    = $this->Session->read('cakeAuth.group_id');
  38.       $this->lastUrl    = $this->Session->read('cakeAuth.lastUrl');
  39.       $this->cacheRules = unserialize($this->Session->read('cakeAuth.cacheRules') . ''); //Line 39
  40.     }
  41.     elseif($this->Session->error()) {
  42.       return $this->Session->error();
  43.     }
  44.     return ($this->id != null);
  45.   }
  46.    
  47.   // Logout Clean Session
  48.   function logout() { // Line 48
  49.     $this->Session->del('cakeAuth');
  50.     if($this->Session->error()) {
  51.       return $this->Session->error();
  52.     }
  53.   }
  54.    
  55.   function _normalizeCheck($check = "") {
  56.     $check = str_replace('/', '\/', $check);
  57.     $check = str_replace('*', '.*', $check);
  58.     $check = '/' . $check . '/';
  59.     return $check;
  60.   }
  61.  
  62.   function getRules( $gid=null ) {
  63.     if(empty($this->cacheRules)) {
  64.       loadModel("CakeRule");
  65.       $CakeRule = new CakeRule;
  66.       $this->cacheRules = $CakeRule->getRules( $gid );
  67.       for($i=0; $i<count ($this->cacheRules); $i++) {
  68.         $this->cacheRules[$i]['CakeRule']['action'] = $this->_normalizeCheck($this->cacheRules[$i]['CakeRule']['action']);
  69.       }
  70.     }
  71.     return $this->cacheRules;
  72.   }
  73.  
  74.   // Function to check the access for the controller / action
  75.   function check($controller='', $action='') {
  76.  
  77.     $noCheck = $this->Session->read('cakeAuth.noCheck');
  78.     if($noCheck> 0) {
  79.       $this->noCheck( --$noCheck );
  80.       return true;
  81.     }
  82.  
  83.     $checkStr = "{$controller}/{$action}/";
  84.     $allow = false;
  85.     if($this->groupId) {
  86.       $rules = $this->getRules($this->groupId);
  87.       foreach( $rules as $data ) {
  88.         $check = $data['CakeRule']['action'];
  89.         if(preg_match($check, $checkStr, $matches))
  90.           $allow = $data['CakeRule']['allow'];
  91.       }
  92.     }
  93.     return $allow;
  94.   }
  95.  
  96.   function noCheck( $forTimes=1 ) {
  97.     $this->Session->write('cakeAuth.noCheck', $forTimes);
  98.   }
  99.  
  100.   function canDo( $checkStr = "", $debug=false ) {
  101.     $allow = false;
  102.     foreach( $this->cacheRules as $data ) {
  103.       if(preg_match($data['CakeRule']['action'], $checkStr, $matches)) {
  104.         $allow = $data['CakeRule']['allow'];
  105.         if($debug) {
  106.           echo "<pre>";
  107.           echo "preg_match({$data['CakeRule']['action']}, {$checkStr}, {$matches}))\n";
  108.           echo $allow."\n";
  109.           echo "-------------------------------------------------------------------\n";
  110.           echo "</pre>";
  111.         }
  112.       }
  113.     }
  114.     return $allow;
  115.   }
  116. }

The set() function at line 25 serve to set and retrieve data from session.
As you can see at line 28 and 39 the rules where serialized and cached to avoid to query database all the times
The logout() function at line 48 I think need no explain it deletes session data.
The private _normalizeCheck() function is an helper function to avoid the user insert . (dot) in regular expression.
This function permits you to write your rule as Controller/* instead of /Controller\/.*/
The getRules() function simply check if rules are already cached and if not query the database and retrieve it.
It uses the function CakeRule::getRules() defined in cake_rule.php model file.

file: cake_rule.php

PHP:
  1. /*
  2.    * Function now meets Cake standards and best practices
  3.    * Thanks to Mariano Iglesias for suggestion
  4.    */
  5.   function getRules( $groupId = '(-1)') {
  6.     $conditions = "CakeRule.group_id IN {$groupId}";
  7.     $fields     = 'CakeRule.rulenum, CakeRule.action, CakeRule.allow ';
  8.     $order      = 'CakeRule.group_id ASC, CakeGroup.security_level DESC, CakeRule.rulenum ASC';
  9.     $data       = $this->findAll( $conditions, $fields, $order, null, 1, 0);
  10.     return $data;
  11.   }

The function is declared in the model Rule becouse originally it was more complicated but with the evolution of the system and my knowledge of cake I could do things better.
For example load Group model instead of Rule model and perform a findAll with conditions = "Group.id in ($groupId)"
For now I think leave all as is.
The check() function is the core of the system
First of all it verify if must perform check that you can disable with the nocheck parameter, more on this later.
Then scan all rules and set the variable allow for the current controller action.
It is fundamental that you scan all rules becouse of the reg expr you can have first a more restrictive rule overriden next with a more aimed.
The noCheck() function is very useful if you want to disable check for a number of times for example you must use it if you use a requestAction from an allowed controller/action to a denied controller/action one.
For example you have defined a rule that deny access to /options/admin_view (becouse there are values that the users must not see) but your code need to access that from another controller to retrieve some settings, well you can do this:
file: one_not_specified_controller.php

PHP:
  1. function do_something( $id ) {
  2.     $this->CakeAuth->nocheck( 1 );
  3.     $data = $this->requestAction('/options/admin_view/'. $id );
  4. }


And at last the canDo function.
This function is useful if you want hide/show a link or a list of link (a menu for example :) ) that point to specific controller/action.

How to use the system?
Add reference to CakeAuth components:
And write check code in your beforeFilter function of app_controller.php

PHP:
  1. var $components = array('CakeAuth');

PHP:
  1. function beforeFilter() {     
  2.     $this->CakeAuth->set(); // Load data
  3.     if( !$this->CakeAuth->id ) { // Not yet logged in or authenticated
  4.       $this->CakeAuth->saveUrl( $this->here ); // Save url for redirect after logged in
  5.       $this->redirect('/cake_login/'); // Show login page
  6.       exit();
  7.     }
  8.     if ( !$this->CakeAuth->check( $this->name, $this->action) ) { // Logged but not authorized
  9.       $this->Session->setFlash('Warning: Access denied.', null);    // Set Flash message
  10.       $this->redirect('/'); // Redirect to home page
  11.       exit();
  12.     }
  13.     $this->set('CakeAuth', $this->CakeAuth)// Make the CakeAuth object avalaible to views
  14.     return true;
  15.   }

As you can see i am too lazy to write an helper and so I have set the CakeAuth object directly available to view.
That's all for now.
You can build your own interface system to manegement of the data tables most of this can be scaffolded.
The only code i want to show is the login controller.

file: cake_login_controller.php

PHP:
  1. <?php
  2.  
  3. class CakeLoginController extends AppController {
  4.   var $name     = 'CakeLogin';
  5.   var $uses     = array('CakeUser');
  6.  
  7.   function beforeFilter() {
  8.     /*
  9.     ** Override control function for authentication
  10.     ** to avoid infinite loop
  11.     */
  12.     return true;
  13.   }
  14.  
  15.   function index() {
  16.     $this->render('index');
  17.   }
  18.  
  19.   function login() {
  20.     $login  = $this->data['CakeUser']['login'];
  21.     $passwd = $this->data['CakeUser']['passwd'];
  22.     $data   = $this->CakeUser->getAclData($login, md5($passwd));
  23.  
  24.     if(!empty( $data ) ) {
  25.         $this->CakeAuth->set( $data['CakeUser'] );
  26.         $this->redirect($this->CakeAuth->lastUrl);
  27.     }
  28.     else {
  29.         $this->redirect('/cake_login/');
  30.     }
  31.     exit()
  32. }
  33.  
  34.   function logout() {
  35.     $this->CakeAuth->logout();
  36.     $this->redirect('/');
  37.     exit();
  38.   }
  39. }

{ 42 } Comments

  1. Daniel Hofstetter | March 24, 2007 at 9:22 am | Permalink

    Looks interesting. Some questions:

    What's the purpose of the rule number?
    What's the purpose of the security level?
    What's the purpose of the external id?

  2. Marco | March 24, 2007 at 11:18 am | Permalink

    Hello Daniel glad to see you here.
    The rule number purpouse is to have rules ordered correctly.
    Because of the nature of the system the sequence is very important as you can see in figure at top.
    If for example you change rule #20 to became rule #1000 the rule #30 and #40 have no mean because the Cake* controller where never accessible.

    The security level and external id are extra field where you can store values that your application can manages.

    For example I use the external id for storing the id of a table containings detailed data of users that normally vary from application to application, and security level is normally anumber I use for hide/show menu items.

    Hope this answer to your questions.

    Thanks

  3. Daniel Hofstetter | March 24, 2007 at 2:48 pm | Permalink

    Thanks for the explanations!

  4. Mariano Iglesias | March 24, 2007 at 3:23 pm | Permalink

    Interesting approach. I haven't tried this (I either use Cake's built in ACL or the phpGACL plugin for CakePHP when I need more power), but I did find an issue while looking at your code:

    1. You should move the source code for CakeRule::getRule() right into the first source box for cake_rule.php, otherwise it is confusing what you readers should copy.

    2. On file cake_auth.php, line 118 should be changed from:

    $rules = $this->getRules($this->groupId);

    to:

    loadModel("CakeRule");
    $Rule = new CakeRule;
    $rules = $Rule->getRules($this->groupId);

  5. Mariano Iglesias | March 24, 2007 at 4:20 pm | Permalink

    You may also want to change Rule::getRules() to not use manual SQL (so if user specified a prefix it is used, and values are properly escaped, etc. etc.). For example:

    function getRules( $groupId = null) {
    $conditions = array(
    'CakeRule.group_id' => $groupId
    );
    $fields = 'CakeRule.rulenum, CakeRule.action, CakeRule.allow';
    $order = 'CakeRule.group_id ASC, CakeGroup.security_level DESC, CakeRule.rulenum ASC';

    return $this->findAll($conditions, $fields, $order, null, 1, 0);
    }

    This will generate the same result as your manual query (with the exception that models are named CakeRule and CakeGroup)

  6. Marco | March 24, 2007 at 4:33 pm | Permalink

    Hello Mariano thank you.
    I followed your suggestion and copied the code for getRules even in the module source box code.

    Instead the statement on line 118 is right as is, if you look better you can see that the function i am calling is the local CakeAuth::getRules() that return the cached rules list or retrieve them from Rule:getRules()

    As a notice, a security system is for me divided in three parts:

    1. Authentication The user attempt a login and if the credentials are right the system grant him/her the permission to enter

    2. Authorization every request to execute an action is examined and if the user have rights the execution is allowed otherwise is denied

    3. Access (the more complex part) the granularity requested to obtain this is obtained better using the Cake ACL and phpGACL plugin, but these tools are more difficult to project and configuring.

    A complete system must include all 3 aspects (Cooperation between auth and Acl control system), but from my point of view and my experience in 90% of cases a good authorization system can do the job.

    P.S. Yes your second comment is right as you can see I was saying in the articles that this functions is changed on time. The entire Auth system is one of my first code written in cakephp and because it is working for my pourpouse I have never thinked to optimize. I will test your suggestion and adjust the code in the blog because it follows best practice to write cake code.

    CU.

  7. gwoo | March 24, 2007 at 5:32 pm | Permalink

    Hi Marco,
    I was loooking at this on the bakery the other day and hesitated to publish it only because the 20 lines of Session writing and reading. The Session will accept an array and I think you can reduce your code by about 15-20 lines if you use it that way. If you have any question jump into IRC.

    Otherwise great article.
    Thanks.

  8. Franck | March 24, 2007 at 9:43 pm | Permalink

    I like it. Just a general comment about all the Auth components I found, the missing of a "subscriber" level. Ok, I am not that expert in cake, but I have worked and experienced quite large organization, where you can have several John Smith working and they belong to a "division", "branch" or whatever "slicing" that would authorize several people having same user name and group name being able to login. I have made up a cake applicatoin and I needed this "subscriber name" on top of the "classic" hierarchy.
    Anyway, not much to add on on this component to make it work in this context..
    Thanks, great work

  9. Marco | March 25, 2007 at 12:34 am | Permalink

    Added some corrections as suggested from Mariano and Gwoo
    Thanks

  10. Marco | March 29, 2007 at 3:45 pm | Permalink

    This article is also published on bakery

    http://bakery.cakephp.org/articles/view/299

  11. Medroll | April 5, 2007 at 10:04 pm | Permalink

    Very interesting to read this for me.. thanks.

  12. dardo sordi | April 9, 2007 at 3:07 pm | Permalink

    It's great! Thanks!

  13. metaflux | April 15, 2007 at 1:50 pm | Permalink

    sorry, but i have a stupid question. i have a problem with users who are not logged in.

    a user comes onto your website and can't do nothing until he/she loggs in!

  14. Marco | April 16, 2007 at 7:30 am | Permalink

    Yes it's true by design.
    All user must be logged beacuse the check in beforeFilter / app_controller.php.
    You have two options to resolve:
    1. Move the check from app_controller.php onto the controllers you want to perform check for auth.
    2. Override beforeFilter in teh controller you don't want check auth.

    View last example code box for cake_login.php.

  15. tribui | May 8, 2007 at 3:00 am | Permalink

    Marco,

    I have used this type of Authorization system many times in the past. My systems don't use rules as elegantly as yours, but instead use a simplified explicit set of allowed operations.

    I would agree that if an application has a complex authorization model where there are an equal number of allow/disallow rules or lots of exception cases, the rule logic you implement is more appropriate. But for most applications, a simple allowed list of operations is sufficient.

    The only change for a simpler version of your system is to remove the fields allow and rulenum and the default allow all rule(the rule table is thus only id and action). All rules that exist are thus allow = 1 rules and rule processing order becomes irrelevant.

    The reason I suggest this is so that groups to rules can be a Many-to-Many relationship and thus all rules can be re-used amongst different groups. Whereas now it is a One-to-Many which means each group has its own set of rules which most likely would have duplicates.

    Your rule approach is a more powerful authorization model but the explicit allow approach is easier to understand and simpler both in implementation and interpretation.

    Thanks for the great component. I am sure to use it.

    tribui

  16. Marco | May 8, 2007 at 7:06 am | Permalink

    Hello tribui thanks for your comments.
    Here is an extended version of auth system with rules reusage.
    I have not used this version because it is more complicated for end-user and require more usage attention.
    My first release,as you suggest, had no allow/disallow and was a simple set of actions.
    I agree that it is more simple to understand but it results insufficient for day to day use cases.

    Thank you very much

  17. Sam | May 16, 2007 at 2:54 pm | Permalink

    Hey Marco, thanks for posting this implementation, I am really digging the simplicity of it.

    I am looking to integrate into my existing system (which is just barely started at this point), but I have some silly questions that I could use some clarification on.

    It looks like cakeauth is its own database, why would I set it up that way? Why not use my existing database?

    Would there be any problems with using my own user model instead of the cakeUser you've got here?

    What's the difference between username and login?

    I may have more once you response, but I appreciate any help you can provide.

  18. Marco | May 16, 2007 at 3:12 pm | Permalink

    @Sam thanks for your comments.
    1. Yes you can use your existing database without any problems. the models uses the$cakeauth connection provide that too point to your database.

    PHP:
    1. var $cakeauth = array(
    2.     'driver'  => 'mysql',
    3.     'connect'  => 'mysql_connect',
    4.     'host'     => 'localhost',
    5.     'login'    => 'login',
    6.     'password' => '*******',   
    7.     'database' => 'yourdb',
    8.     'persistent' => false,
    9.     'prefix'   => '');

    2. You can use your user model if you prefer or instead You can set the external_id of my user table to point to your table as an hasone association.
    3. Username is a more descriptive name (Like: Mister Boo Jungle) login is the field used for authentication.

  19. Ivan | June 9, 2007 at 1:11 pm | Permalink

    Hello Marco,
    In my case it's not working at it all.

    It only redirects user from any part of application to cake_login/ and from cake_login/ to it's self (infinity loop) - yes beforeFilter() is overwriten in CakeLoginController.

    Can you provide some data samples for db tables ( SQL not image ), and some fully working example ( just two pages - secured and not secured [ login] )

    I'm using php5 , mysql 5 and latest 1.2 build (alpha not nightly)

  20. Marco | June 9, 2007 at 6:41 pm | Permalink

    Hi Ivan,
    Onestly I have not tested the component with cake 1.2, but i am using it with last 1.1 build in every project i do.

    I have built an app for managing the auth system you can download it from here.

    http://blog.nospace.net/uploads/authsample.zip

    In the /sql folder you can find the scriptfor building the sample database.

    for administration:
    login: admin
    password: admin

    For viewing:
    login: view
    password: view

    :)

  21. shatan | June 17, 2007 at 8:49 pm | Permalink

    I have a question... and sry I am new to the cakePHP framework

    I tried your apllication and when I start it I get the following error:

    Fatal error: ConnectionManager::getDataSource - Non-existent data source cakeauth in D:\xampp\cakeSSI\cake\libs\model\connection_manager.php on line 110

    is this an error based on my knowledge leak to the framework or did I do something wrong?

  22. Marco | June 18, 2007 at 7:17 am | Permalink

    Hi shatan,
    I need more infos, have you downloaded the authsample package? see comment #20

    1. Have you created the database for auth data?
    2. Have you executed the script in /sql folder named "authsample.sql" for tables creation and sample data?
    3. Have you modified the app/config/database.php with your data? see cmt #16
    var $cakeauth = array(
    'driver' => 'mysql',
    'connect' => 'mysql_connect',
    'host' => 'localhost',
    'login' => '[Your user for db just created]',
    'password' => '[Your password to access db]',
    'database' => '[The name of db just created]',
    'persistent' => false,
    'prefix' => '');

    That's all, let me know.
    If you have more questions meet me on irc.

  23. Paul Simon | June 25, 2007 at 9:36 pm | Permalink

    Hi, Marco,

    In your example you only show user in one group. I'm wondering how you would order the rules for a user belongs to several different groups?

    Thanks.

  24. Marco AKA LazyCoder | June 25, 2007 at 10:03 pm | Permalink

    Hi Simon, must admit that I have never used this features until now and sincerely it is not clear even for me what is the best method to use such a features (I have inserted as a bonus when I thinked the data structure).
    At this moment the records are in this order ( See the box for cake_rule.php)

    $order = 'CakeRule.group_id ASC, CakeGroup.security_level DESC, CakeRule.rulenum ASC';
    peraphs this could be better
    $order = 'CakeRule.rulenum ASC,CakeGroup.security_level DESC';

    I think that if I need to have a user in more than one group I will filter the group to check based on the application context.

    If you have an idea tell me.
    Ciao and tx for your comment.

  25. RR | July 16, 2007 at 7:01 pm | Permalink

    Hi Marco,

    I have downloaded and installed your authsample code (Posted in Bakery on Jun 11th 2007) . I did the install steps described above but I still get the infinite loop errors with Safari, FireFox etc.
    How can I avoid/fix those?

  26. Marco AKA LazyCoder | July 18, 2007 at 2:39 pm | Permalink

    Hello RR commonly this problem arise when the db is not correctly configured.
    Set your debug level to 2
    Put this 2 lines in the function beforeFilter in app_controller.php.

    CODE:
    1. function beforeFilter() {
    2.     $this->CakeAuth->set(); // Load data
    3. // Insert Here
    4. pr($this->CakeAuth);
    5. return true;
    6. // --------------------------------
    7.     if( !$this->CakeAuth->id ) { // Not yet logged in or authenticated
    8.       $this->CakeAuth->saveUrl( $this->here ); // Save url for redirect after logged in
    9.       $this->redirect('/cake_login/'); // Show login page
    10.       exit();
    11.     }
    12.     if ( !$this->CakeAuth->check( $this->name, $this->action) ) { // Logged but not authorized
    13.       $this->Session->setFlash('Warning: Access denied.', null);    // Set Flash message
    14.       $this->redirect('/'); // Redirect to home page
    15.       exit();
    16.     }
    17.     $this->set('CakeAuth', $this->CakeAuth)// Make the CakeAuth object avalaible to views
    18.     return true;
    19.   }

    Now point your browser to http://yourcakeroot/cake_login
    Lgin and see if CakeAuth object is set correctly
    HTH

  27. Theo Freze | October 20, 2007 at 12:34 pm | Permalink

    One question. What license is this released under? I'm hoping to make a port of this library to CodeIgniter framework but then the license should permit it?

  28. adi | November 13, 2007 at 5:32 am | Permalink

    Hi Marco,

    I have downloaded and it's look promising, so decided to use it in my project, problem arise when I create new user and login with that id , I get the infinite loop error
    How can I fix those ?. this problem not appear if I use admin or view id

    TIA

  29. Marco AKA LazyCoder | November 14, 2007 at 8:21 am | Permalink

    Hello adi, can you post yuor rule list for that user?
    Have downloaded my sample and is it working?
    If you have customized the login have you disabled the check in controller:
    function beforeFilter() {
    /*
    ** Override control function for authentication
    ** to avoid infinite loop
    */
    return true;
    }

  30. Marco AKA LazyCoder | November 14, 2007 at 8:26 am | Permalink

    Hi Theo,
    Onestly I have not in mind any type of licensing for this work.
    I have developed it because I need it for my own projects :) .
    Since you are doing a porting is your work to rewrite the code part in CodeIgniter and I am not a fan of IDEA patenting.
    If You like it, you are free to use it for the part of the project that is my own work.
    The database structure, and all the code presented in my blog is free for you.
    I will be glad if you would maintain a reference to me and my code, but it is not a requirement for me.
    But if you became rich with this code send to me a little percentage :) , don't care am joking.
    Regards and Happy Coding.
    Send me a note when you have done.

  31. Jej | January 24, 2008 at 3:04 pm | Permalink

    Hi Marco,

    Thanks for this simple and powerfull ACL system.

    Do you have any news about a cakephp 1.2 compatible version?

    Jej

  32. Jej | January 24, 2008 at 4:57 pm | Permalink

    Hi again Marco,

    In cake_auth.php line 79, you decrement the local var $noCheck after using it. Isn't it a bug?

    $this->noCheck( $noCheck-- );

    should be

    $this->noCheck( --$noCheck );

    Am I wrong?

    I have a working version of your component for cakephp 1.2. In case you need it, post here.

    Gracie
    Jej

  33. Marco AKA LazyCoder | January 25, 2008 at 8:01 am | Permalink

    Hi Jej thanks for your comments.
    I think the code make no difference written in the two manners.
    When the function uses variabe it is decremented but i will try.

  34. Jej | January 25, 2008 at 10:20 am | Permalink

    Hi Marco,

    Well, maybe I lost my basic knowledge about php... But it seems the manual confirm it : http://www.php.net/manual/en/language.operators.increment.php

    --$a Pre-decrement Decrements $a by one, then returns $a.
    $a-- Post-decrement Returns $a, then decrements $a by one.

    Jej

  35. Marco AKA LazyCoder | January 25, 2008 at 1:20 pm | Permalink

    Hi Jej you are absolutely right.
    Maybe I have never used this utility.
    Apologize with all and immediately correct the code.
    Thank you.

  36. Jej | February 12, 2008 at 9:44 pm | Permalink

    Hi again Marco,

    That's me to thanks you! More explanations here: http://conseil-recherche-innovation.net/authake

    Cheers,
    Jej

  37. Jej | February 14, 2008 at 11:19 pm | Permalink

    I added the feature to disable accounts. Let's test :)

    http://authake.conseil-recherche-innovation.net/

    Ciao

  38. sebastian | April 17, 2008 at 2:57 pm | Permalink

    Hi, this looks great. However, i can't get it work. When it tries to redirect me to the login page, FF says i have a redirect error, i don't know how to fix this. I'm using php5 and cakePHP 1.2
    Thanks

  39. Marco AKA LazyCoder | April 17, 2008 at 7:38 pm | Permalink

    Hello sebastian I have not tried my plugin with cake 1.2 but only 1.1.
    I have tested the Jej porting on 1.2 and seems very well done.
    See comment #37 and follow the link to download his version.
    If you are not satisfied from that repost here and I'll try to help you to debug teh problem.
    Tx

  40. dtk78 | February 19, 2009 at 5:25 pm | Permalink

    Hello
    I have downloaded the sample but it doesn't work, I have the following message
    CakeAuthComponent Object
    (
    [components] => Array
    (
    [0] => Session
    )

    [externalId] =>
    [id] =>
    [username] =>
    [login] =>
    [security] =>
    [groupId] =>
    [errors] =>
    [lastUrl] => /
    [cacheRules] =>
    [_log] =>
    [Session] => SessionComponent Object
    (
    [__active] => 1
    [valid] => 1
    [error] =>
    [_userAgent] => 2abb76718165bba320a9da6fafc00e94
    [path] => /authsample/
    [lastError] =>
    [security] => high
    [time] => 1235060686
    [sessionTime] => 1235061886
    [watchKeys] => Array
    (
    )

    [_log] =>
    [host] => localhost
    [cookieLifeTime] => 0
    )

    )

    url($url, $return); if(defined('JAKE')) { $jake =& Jake::getInstance(); $url = str_replace(FULL_BASE_URL, '', $jake->getUrl($url)); } return $url; } function monthOptionTag($tagName, $value = null, $selected = null, $selectAttr = null, $optionAttr = null, $showEmpty = true) { /** * Returns a SELECT element for months. * * @param string $tagName Prefix name for the SELECT element * @deprecated string $value * @param string $selected Option which is selected. * @param array $optionAttr Attribute array for the option elements. * @param boolean $show_empty Show/hide the empty select option * @return string */ $monthValue = empty($selected) ? date('m') : $selected; $months=array( '01' => 'Gennaio', '02' => 'Febbraio', '03' => 'Marzo', '04' => 'Aprile', '05' => 'Maggio', '06' => 'Giugno', '07' => 'Luglio', '08' => 'Agosto', '09' => 'Settembre', '10' => 'Ottobre', '11' => 'Novembre', '12' => 'Dicembre' ); $option = $this->selectTag($tagName . "_month", $months, $monthValue, $selectAttr, $optionAttr, $showEmpty); return $option; } function formatDateTime($dt=null, $mode=0) { /* * * $mode = 0 Only Date * $mode = 1 Only Time * $mode = 2 Date & Time * $mode = 3 Only Time With seconds * $mode = 4 Date & Time With seconds * */ if(!$dt) return(''); if($dt == '0000-00-00 00:00:00') return(''); $tmpDate = strtotime( $dt ); switch( $mode ) { case 0: return( date( "d/m/Y", $tmpDate ) ); break; case 1: return( date( "H:i", $tmpDate ) ); break; case 2: return( date( "d/m/Y H:i", $tmpDate ) ); break; case 3: return( date( "H:i:s", $tmpDate ) ); break; case 4: return( date( "d/m/Y H:i:s", $tmpDate ) ); break; default: return( '' ); } } } ?>

    Could you tell me where is wrong ?
    Thanks a lot

  41. Marco AKA LazyCoder | February 20, 2009 at 8:26 am | Permalink

    Hi dtk78 ,
    have you correctly setup the database?
    You must create a database called authsample then run the script authsample.sql (It is in the sql folder of the sample), next you must edit your database.php (as ususal with cake) for your credential.
    If you have done every step for database is your app\tmp writable?
    I would remark that this is a cake 1.1 app.
    For a 1.2 revisit of this apps go to Jej site

    http://conseil-recherche-innovation.net/authake

    Ciao
    Marco

  42. dtk78 | February 20, 2009 at 8:47 pm | Permalink

    Thanks Marco,
    It's working fine now

    Dis you have done it with PostgreSQL database ?
    Regards

Post a Comment

You must be logged in to post a comment.