All posts tagged "code"

I found 4 posts tagged code

DarkAuth update, and test app.

I found another small glitch in DarkAuth, which stemmed from the major bug after CakePHP 1.2 RC1 was released.

The Controller::render() method has changed, which was integral to DarkAuth's functionality. The change stopped anything from being displayed if Auth was not present or sufficient. To fix it I had to force an exit() into the code.

This exit() then meant that the Component was not setting the $_DarkAuth variable at all, if the "login" or "deny" view where being displayed.

The updated code fixes this, and has been updated on the DarkAuth page.

In addition I introduced a nice utility method, DarkAuthComponent::getUserId() which simply the returns the id of the currently auth'd user. Something I needed often.

Also I decided it would be good to have a "test application", a simple setup of a working DarkAuth + Cake combo. So I have built one, and you can use it to see how DarkAuth works, and to play around with it to your hearts content!

There's 2 versions: one is just the app/ folder, and the other contains the full CakePHP1.2 RC1 code as well:

I put some useful code in there to help create the database config file and set up the required tables, so just extract and play!

Comments (14):

  1. Bill said at 00:28, 7th July 2008:

    Hi Chris, the link DarkAuth.test.inc.cake.zip is off. Great component, thanks
  2. theChrisWalker said at 17:36, 7th July 2008:

    You're right, I mean to update it to the RC2 code anyway... I'll remove for now.
  3. Theo said at 21:30, 9th July 2008:

    Hi, is it not possible for you to add functions to save logins (user/groups) back to the HABTM ? for example a submitted form of username/password and checkboxes for groups? or is there just a easy way to do it in cakephp? thanks
  4. Theo said at 21:44, 9th July 2008:

    sorry i meant 'save logins (user/roles)' not 'save logins (user/groups)' and 'checkboxes for roles' not 'checkboxes for groups'
  5. theChrisWalker said at 09:17, 10th July 2008:

    "or is there just a easy way to do it in cakephp?" Bingo.
  6. itsnotvalid said at 13:02, 11th July 2008:

    Glad that the comment system is up now. I just leave a message here to hope to see a SVN/git repository or a single dark_auth.php download, instead of just hoping through the archive or copying from the website(where sensible person wouldn't do anyway). And this component is a great one and really save me a lot of time. Thank you!!
  7. Theo said at 12:59, 12th July 2008:

    had the wrong case on my models names in my form :/ thats why it wasnt working for me thanks anyways
  8. blablacio said at 15:15, 15th July 2008:

    Hello Chris, I'm developing an application which apparently needs user authentication and I chose your component to help out with this. Everything runs just fine now, but I was wondering if there is a way to do this: <?php class UsersController extends AppController { var $name = 'Users'; var $scaffold; var $_DarkAuth = array('required'=>'Administrators'); function register(){ } function add(){ } } ?> I want to let only users of the group Administrators to do anything within the UsersController, but let regular guests access the register() function only. Any ideas? Thank you for your time and exceptional component!
  9. itsnotvalid said at 12:08, 20th July 2008:

    Also I discovered a bug that, when you are having a login form for a action that also reads from $this->data, e.g. scaffold views (e.g. add), you would also submit empty dataset to those actions. In scaffold add, for example, you would create an empty record. How to fix this?
  10. theChrisWalker said at 20:48, 20th July 2008:

    @ blablacio: I emailed you about this, basically, there is no way "allow" specific actions as yet, but sounds like a good addition for the future.
  11. theChrisWalker said at 20:54, 20th July 2008:

    @itsnotvalid: after successful login, you are redirected using a GET request for the URL, all POST data will be lost - which means the Add scaffold should render a form, not insert a row. Still it will be easy enough to check for valid data before save()'ing the model. The loss of POST is not something easily avoided, so I hope you didn't plan to be able to propagate that.
  12. Lukas said at 16:11, 29th July 2008:

    Hello Chris, I have downloaded your script and I have protected a controller. The login-form appears, but if I submit my username and password, then I get the following error: Fatal error: Cannot use object of type PostsController as array in (...)app\controllers\components\dark_auth.php on line 341 Do you have any advice? thanks, Lukas.
  13. Lukas said at 16:22, 29th July 2008:

    dark_auth.php 341: $this->controller{$this->user_model_name}->belongsTo[$this->group_model_name]['foreignKey']; fix: $this->controller->{$this->user_model_name}->belongsTo[$this->group_model_name]['foreignKey']; Lukas.
  14. Darren said at 08:39, 5th August 2008:

    Great component Chris thanks, just wondering if it was possible to use the component in the cake error pages (404, missing action etc). I've not managed to do it yet. Cheers!

Sorry, comments are closed.

Using DarkAuth with Groups and Roles

I have recently updated the code in /darkauth-2 to be compliant with the newly released CakePHP 1.2 RC. Only a small fix, but it made me think about DarkAuth and how it works best.

When I originally wrote it, I recieved some feedback from several different sources syaing that it was difficult to understand and didn't necessarily work as expected.

This was because DarkAuth has a very specific methodology and and is just as much an Access Control component as an Authentication one.

Authentication and Access Control

  • Authentication is a method of identifying users.
  • Access Control is a method of restricting those user to what they are allowed to do.

DarkAuth has some useful functions that help with both. In the next release of the code I intend to rename all references to "Group" with "Role" as it is really about Role-Based Access Control.

In my usual setup for using DarkAuth I create 5 tables: users, roles, roles_users, groups, groups_roles

The first three are straight forwards, they define the users of the system, any roles that might exist (think roles like "CanAddPosts", "CanEditItems", etc...) and the join table that defines their relationship.

The next two is where I define Groups of Roles. The whole point of this is simply a helper - I can pick which roles I give to my users explicitly, or I can choose a group which contains a certain array of roles. It just makes it easier to manage. Enough talk, on to an example.

Let's see it it action...

Using the following tables:

  1. CREATE TABLE IF NOT EXISTS `users` (
  2.   `id` INT(11) NOT NULL AUTO_INCREMENT,
  3.   `created` DATETIME DEFAULT NULL,
  4.   `modified` DATETIME DEFAULT NULL,
  5.   `email` VARCHAR(64) NOT NULL,
  6.   `pswd` VARCHAR(32) character SET utf8 COLLATE utf8_bin NOT NULL,
  7.   `live` TINYINT(1) NOT NULL DEFAULT '0',
  8.   PRIMARY KEY  (`id`)
  9. ) ENGINE='MyISAM'  DEFAULT CHARSET='utf8';
  10.  
  11. CREATE TABLE IF NOT EXISTS `roles` (
  12.   `id` INT(11) NOT NULL AUTO_INCREMENT,
  13.   `name` VARCHAR(32) NOT NULL,
  14.   PRIMARY KEY  (`id`)
  15. ) ENGINE='MyISAM'  DEFAULT CHARSET='utf8';
  16.  
  17. CREATE TABLE IF NOT EXISTS `roles_users` (
  18.   `role_id` INT(11) NOT NULL,
  19.   `user_id` INT(11) NOT NULL,
  20.   KEY `role_id` (`role_id`,`user_id`)
  21. ) ENGINE='MyISAM'  DEFAULT CHARSET='utf8';
  22.  
  23. CREATE TABLE IF NOT EXISTS `groups` (
  24.   `id` INT(11) NOT NULL AUTO_INCREMENT,
  25.   `name` VARCHAR(24) NOT NULL,
  26.   PRIMARY KEY  (`id`)
  27. ) ENGINE='MyISAM'  DEFAULT CHARSET='utf8';
  28.  
  29. CREATE TABLE IF NOT EXISTS `groups_roles` (
  30.   `group_id` INT(11) NOT NULL,
  31.   `role_id` INT(11) NOT NULL,
  32.   KEY `group_id` (`group_id`,`role_id`)
  33. ) ENGINE='MyISAM'  DEFAULT CHARSET='utf8';

And with some sample data:

  1. INSERT INTO `users` VALUES (1,NOW(),NOW(),'reader@example.com','5f5a3325bce31f27472ececf3f9aee9a',1),  
  2. (2,NOW(),NOW(),'writer@example.com','5f5a3325bce31f27472ececf3f9aee9a',1),
  3. (3,NOW(),NOW(),'moderator@example.com','5f5a3325bce31f27472ececf3f9aee9a',1);
  4. INSERT INTO `roles` VALUES (1, 'Root'), (2, 'CanAddPosts'), (3, 'CanModeratePosts'), (4, 'CanEditOwnPosts'), (5, 'CanEditOtherPeoplesPosts');
  5. INSERT INTO `groups` VALUES (1, 'Reader'), (2, 'Writer'), (3, 'Moderator');
  6. -- Now the clever bit:
  7. INSERT INTO `groups_roles` VALUES (2, 2), (2, 4), (3, 2), (3, 3), (3, 4), (3, 5);

Which creates a mapping of roles to groups. We can then create a function which applies the given set of roles to the user. I put mine in GroupsController for lack of a better place, but I am not sure it should stay there. It goes like this:

  1. function _applyGroup($user_id,$group_id){
  2.     $data['User']['id'] = $user_id;
  3.     $data['Role']['Role'] = array_keys($this->Group->GroupsRole->find('list', array('conditions'=>array('group_id'=>$group_id), 'fields'=>'GroupsRole.role_id,GroupsRole.group_id')));
  4.     if($this->User->exists($user_id)){
  5.       if($this->User->save($data)){
  6.         //Success!
  7.         return true;        
  8.       }else{
  9.         //failure :(
  10.         return false;
  11.       }
  12.     }else{
  13.        //failure, no user found...
  14.        return false;
  15.     }

This function will then allow you to align your users' access to fit all the roles you have associated with the group.

This brings a question, should I links my groups with users directly? and read their security roles from the group. Or do I simply use the groups to define set of roles to Apply to users as I want?

I don't know.

The first sounds better, but then we couldn't do any bespoke customisations (i.e. one-off adding of roles to particular users). The second is what I currently use, but if you update a group the use's dont' automatically update.

I guess there's an answer in there that you update all users' permission's that match the previous role set of a group to the new role set whenever you change a group. Confused? hopefully not too much...

Comments (2):

  1. Bill said at 18:33, 11th July 2008:

    Hi Chris, i dont understand how this modification is usable...only i can see one thing. instead of using groups you are using roles, but the funcionality is the same. I wrong?
  2. theChrisWalker said at 09:16, 14th July 2008:

    You're not wrong, the functionality is the same. I just wanted to point out that DarkAuth is really a role-based authentication system, or was designed as such, where every action that need to be restricted has a "role" which can be granted. This quickly becomes a large set of "roles" and often you apply the same set of access to users. The idea of using the Roles and Groups allows easier management of the system with the benefit of the fine-grained control should you need it.

Sorry, comments are closed.

GeSHI: Syntax Highlighting

I wanted to have a syntax highlighting facility for this site as I knew there would be plenty of code on here. First I just used PHP's highlight_string function, but soon realised it's drawbacks - not XHTML compliant, no line numbers, only works for PHP...

So I did a bit of Googling and found two major contenders, the PEAR::Package::Text_Highlighter library, and GeSHI. The PEAR one looks a little more complex and bulky, but GeSHI seemed perfect.

So I started playing with GeSHI and found it incredibly easy to get to grips with. The highlighting was very customiseable and it natively supported more languages than I would ever need.

The main issue I have with GeSHI was that it killed my lovely lined display. for some reason I couldn't get it to follow the lines. Eventually I realised that it was a Firefox / IE issue, with IE behaving and Firefox being odd (?!). I didn't see that one coming. However I found that by removing all of the inline styles and using CSS instead I managed to allieviate this issue.

Now I have the facility to syntax highlight code in any one of the 53 odd languages GeSHI supports. Pretty nice!

The next step was to integrate this with my existing CakePHP text-to-html converting helper. I created some new BBCode tags like [code syntax='javascript'] to make it easy.

Comments:

Sorry, comments are closed.

Bjax: A Lightweight AJAX helper

Before I embraced frameworks, I created an AJAX Object that was lightweight, easy to use and efficient. I still find it very useful when making small, standalone, single-page type web-apps and certainly proved invaluable when I wasn't.

It's usage is very simple, first include the library:

  1. <script type='text/javascript' src='/js/bjax.js'></script>

Then define what you want to do and away:

  1. <script type='text/javascript'>
  2. // <![CDATA[
  3. function responseHandler( data ){
  4.   alert("the response was" + data.responseText);
  5. }
  6.  
  7. window.onload = function(){
  8.   Bjax.go(
  9.           '/somefile.htm',
  10.           null,
  11.           { "onSuccess" : responseHandler }
  12.   );
  13. }
  14. // ]]>
  15. </script>

The code is nice and efficient, killing and reusing the XMLHttpRequest Objects (or the ActiveX versions of them). So you don't need to worry about it at all.

The go function takes the follow options:

  1. Bjax.go(
  2.            'http://domain.com/path/to/file.ext', //The URL to Request
  3.            'key1=value1&key2=value2...', //Post data, correctly URL encoded
  4.            {  //Object literal containing options
  5.             'onSuccess' : function, //function to be called after successful response.
  6.             'onSend' : function, //function to be called on sending request
  7.             'onError' : function, //function to be called if a non 2xx http response code
  8.             'onTimeout' : function, //function to be called if request times out.
  9.             'timeout' : integer, //this is the number of seconds before we consider a request timed out (default 15)
  10.             'method' : "string" // this sets the request method, defaults to "POST"
  11.             }
  12.   );

If things go wrong, you can debug the AJAX requests easily using the "debug" flag. It will then alert at various stages of the process allowing you to easily see what's going on. To enable, simply set Bjax.debug to true:

  1. Bjax.debug = true;

There's also included a really useful function prototype, which I took the idea from from the Prototype library. The prototype is bind and always you to bind functions to objects so that when the AJAX response comes back, you can call a function in the context you where in when it left off!

If you understood that last paragraph then you know how useful that is, if you didn't, then you will find that you need this functionality at some stage or other...

Anyway, the source is available here: bjax.js (3782B) or the minified version (with debugging removed) bjax.min.js (2406B)

Comments:

Sorry, comments are closed.