SitePoint Sponsor

User Tag List

Page 8 of 11 FirstFirst ... 4567891011 LastLast
Results 176 to 200 of 267
  1. #176
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Zoef
    Or maybe it is because it failed to live up to its title?

    "Patterns Tutorial Series"?

    Better title might be... "Discussion on making a simple problem complex beyond the understanding of 99% of the php community by some gurus that can't agree on anything."

    I'd actually be really interested in a "Patterns Tutorial Series", but this isn't it.

    Rik
    I'm with you Zoef. I would like to get this topic back to its original purpose. Hopefully, we can do that by starting extremely simple as Lastcraft has suggested with his most recent test case. What do you think of this test case?

    JT

  2. #177
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Zoef
    Or maybe it is because it failed to live up to its title?

    "Patterns Tutorial Series"?

    Better title might be... "Discussion on making a simple problem complex beyond the understanding of 99% of the php community by some gurus that can't agree on anything."

    I'd actually be really interested in a "Patterns Tutorial Series", but this isn't it.

    Rik
    No, but it's pretty typical in my experience. You start with a problem that seems simple. Then you try to code it, and it turns out to be not nearly as simple as you thought it would be. Trying to make it simple again can be far from simple.

    I hope that makes sense.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  3. #178
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    What is wrong with this test case...?
    PHP Code:
    class RoleBasedPermissionsTest extends UnitTestCase 
        function 
    RoleBasedPermissionsTest() { 
            
    $this->UnitTestCase();
        } 
        function 
    setUp() { 
            
    $authoriser = &new Authoriser();
            
    $authoriser->addPrincipal('fred'); 
            
    $authoriser->assign('fred''pleb'); 
            
    $authoriser->permit('pleb''do_stuff');
        } 
        function 
    tearDown() { 
            
    $authoriser = &new Authoriser();
            
    $authoriser->dropPrincipal('fred'); 
            
    $authoriser->dropRole('pleb'); 
        } 
        function 
    testNonUserHasNothingAllowed() {
            
    $authoriser = &new Authoriser();
            
    $permissions = &$authoriser->getPermissions('nobody');
            
    $this->assertFalse($permissions->can('do_stuff')); 
        } 
        function 
    testLegitimateUserHasActionAllowed() { 
            
    $authoriser = &new Authoriser();
            
    $permissions = &$authoriser->getPermissions('fred'); 
            
    $this->assertTrue($permissions->can('do_stuff')); 
        } 
        function 
    testUserCannotDoNonAction() { 
            
    $authoriser = &new Authoriser();
            
    $permissions = &$authoriser->getPermissions('fred'); 
            
    $this->assertFalse($permissions->can('do_unknown')); 
        } 

    I have removed the storage flexibility for now (it can be put in later if needed) and assumed that the editing methods will fill out needed data automatically. This is the simplest starting point I can come up with.

    yours, Marcus
    Looks good. You seem to have simplified it in a reasonable way. Now let me explore it.

    FIrst, I'm wondering how the actual authorization would happen in a real application. Would you actually specify the name of the principal? (I'm not sure I like the term, but I'm using it anyway.) Or would it be left to the authorization object to do that implicitly? Like this:
    PHP Code:
    $authoriser = &new Authoriser();
    $permissions = &$authoriser->getPermissions(); 
    $this->assertFalse($permissions->can('do_stuff')); 
    This code is simpler if we drop the $permissions object:
    PHP Code:
    $authoriser = &new Authoriser();
    $this->assertFalse($authoriser->can('do_stuff')); 
    And even simpler with a static method:
    PHP Code:
    $this->assertFalse(Authoriser:can('do_stuff')); 
    I'm not saying it's necessarily better, but there's no doubt it's simpler, and there's no reason why it shouldn't work.

    Another question which I've asked before: Should authorization and administration (=changing authorizations) be done by the same class? I think separating them completely, and allowing totally different designs, might be a good idea.

    Another simplification: If you use constants to represent the actions (DO_STUFF instead of 'do_stuff'), you don't really need to check for non-actions.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  4. #179
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm going to try putting in a UML class diagram. Never tried this before, but here goes.



    This is a design suggestion that builds on my previous comments. The diagram shows what I think of as the essential classes for this system, except I haven't specified any storage for the administration classes.

    The Authorizer is just a script, primitive but fast. It could even be a plain function. It generates and runs whatever SQL is necessary to check whether the currently logged-in user has the specified permission and returns TRUE or FALSE.

    The other two classes are the domain model. The operations are just about obvious from the structure. To get the kind of API that has been suggested, you need an extra facade class, In lastcraft's test class, the Authoriser does that.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  5. #180
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    In the best traditions of debate I feel entitled to disagree with all your points .

    Quote Originally Posted by dagfinn
    Or would it be left to the authorization object to do that implicitly?
    I think removing complexity is a good thing, but just hiding it just seems to make things more complex.

    If the Authoriser can find the name of the principal (can we just change this to LoginId?) then it has gained background configuration, which is way more complex than passing it in. It is a whole extra communication channel. I think the Authorisation would follow the Authentication immediately in practice anyway...
    PHP Code:
    $permissions $authoriser->getPermissions(
            
    $authenticator->logIn( ... )); 
    Quote Originally Posted by dagfinn
    This code is simpler if we drop the $permissions object:
    This adds state to the Authenticator. It means that we go from one service and one value to one entity. Two very simple classes to one very complex one . Looks painful when you try to write the test case as well because the setup stuff increases dramatically.

    Quote Originally Posted by dagfinn
    And even simpler with a static method:
    I see static methods as syntactic sugar once you have the main interface sorted out. They can really destroy APIs because of their inflexibility (no polymorphism, no inheritance). They also add state again, effectively creating a singleton. I feel "boxed in" by them.

    I have spent too much of my programmer life stripping out statics. I would almost go so far to say they were evil.

    Quote Originally Posted by dagfinn
    Another question which I've asked before: Should authorization and administration (=changing authorizations) be done by the same class? I think separating them completely, and allowing totally different designs, might be a good idea.
    I think that this is the way it will ultimately go. It also means that less code has to be loaded in the performance critical case (login). I needed to separate them earlier to make things transactional anyway (the edit object). I am pretty sure it will go this way, but was unclear about the way to achieve it, so I left them joined for now as part of the simplification.

    One complication though is the storage. You have to make sure that both the authoriser and administration system use the same one. I have gone off the idea of a hidden behind the scenes configuration class (jumping into the container solution too early). Making the administrator from a factory on the authoriser seemed to me the minimal connecting linkage.

    Quote Originally Posted by dagfinn
    Another simplification: If you use constants to represent the actions (DO_STUFF instead of 'do_stuff'), you don't really need to check for non-actions.
    You are creating a "little language" by this, so I wouldn't force that way of doing things. If what you are saying is that they might use integers instead of strings in the methods, then I agree. We can stick to a generic "mixed" type by only using "===" to test them and avoiding specfic type checks. We should allow both.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  6. #181
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by Zoef
    Better title might be... "Discussion on making a simple problem complex beyond the understanding of 99% of the php community by some gurus that can't agree on anything."
    I have since found out that in the nineties a similar attempt was made on one of the comp.oo newsgroups. They had a simpler problem of designing an alarm clock. The debate raged for months dragging in more and more luminaries. I don't know if it reached a conclusion, but that was at the start of the patterns movement. I have seen no less than four references to that thread (including the whole chapter of a book).

    Like you I don't know where we are going, but the journey is getting interesting.

    Also what you are seeing is what happens with real development teams. It looks like we are not making progress, but eventually stuff gets hammered out. It is two steps forward and one step back, but gradually things crystalize. This thread actually feels like "work" to me.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  7. #182
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No offence Marcus, but

    Looks painful when you try to write the test case as well
    It is only a test case though, isn't it ? Once everything is sorted out, and working as it should do, that's that.

    It's out of the way, no ? I kind of favour the static method myself as well, but only because it looks a lot clearer as to what is happening

    But I can understand your reluctance to use it Your test case Interface btw, is fine by me, even though I would never venture to use test cases at the moment

  8. #183
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by Widow Maker
    No offence Marcus, but
    It's OK, I am not that sensitive... It was an aside.

    Quote Originally Posted by Widow Maker
    It is only a test case though, isn't it ? Once everything is sorted out, and working as it should do, that's that.
    I used to agree, but these days I am not so sure. I am building a strong personal circumstantial case for treating test case code with great respect. It's code that exercises the interface fully and so problems here indicate to me a problem interface. I even refactor it for clarity now (on demand only).

    Also, code that has to be in setUp() has to be in the application too. setUp() clutter is client code clutter.

    yours, Marcus

    p.s. Please have a go sometime with unit tests. They are a real life changer .
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  9. #184
    SitePoint Zealot
    Join Date
    Feb 2003
    Location
    Virginia
    Posts
    143
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sounds like Mock Objects might be what you guys need. : )

  10. #185
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Marcus, I would really like to do test cases, though I can't justify the learning curve nor the actual purpose (and any benifits) unit testing may have.

    My scripting hasn't reached the point where I've to put together applications that are indepth enough to justify it all as I see it

    Maybe one day I'll get better knowledge wise on software layering, and UML ? Then I can justify the cause of unit testing to myself

  11. #186
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    In the best traditions of debate I feel entitled to disagree with all your points .
    It seems you agreed with one of them. I guess you didn't try hard enough .
    Quote Originally Posted by lastcraft
    If the Authoriser can find the name of the principal (can we just change this to LoginId?) then it has gained background configuration, which is way more complex than passing it in. It is a whole extra communication channel. I think the Authorisation would follow the Authentication immediately in practice anyway...
    PHP Code:
    $permissions $authoriser->getPermissions(
            
    $authenticator->logIn( ... )); 
    So what do you do when you want to check whether the current user (loginid) has the right to see the Edit button or not?

    It seems to me authentication is part of pre-processing which is going to be the same over all or most of the application. Checking permissions is much more fine-grained, per page (whatever that means) or finer. So I don't see them happening together all the time.

    And slice it any way you like, your authenticator needs to remember the login somehow. So there has to be some global data that's available to the authenticator. As long as that's the case, it should be a piece of cake for the authorizer to use the same global data. So why should "state" be a problem?

    Anyway, I think this makes it clear that the test case is insufficient as a specification. We need to agree on how and when the different classes are used in the application code.
    Quote Originally Posted by lastcraft
    I have spent too much of my programmer life stripping out statics. I would almost go so far to say they were evil.
    I've been around this group long enough to know you would say that. I haven't had traumatic experiences with them. Maybe I've just used them less. Or maybe I just laugh in the face of evil. I'm entertaining the vision of this particular operation being repeated 10 grillion times in the application code, so I want just that one thing as simple as possible.
    Quote Originally Posted by lastcraft
    One complication though is the storage. You have to make sure that both the authoriser and administration system use the same one. I have gone off the idea of a hidden behind the scenes configuration class (jumping into the container solution too early). Making the administrator from a factory on the authoriser seemed to me the minimal connecting linkage.
    What's wrong with a good old-fashioned configuration variable? Do you want to use different kinds of storage in different places in the code?
    Quote Originally Posted by lastcraft
    You are creating a "little language" by this, so I wouldn't force that way of doing things. If what you are saying is that they might use integers instead of strings in the methods, then I agree. We can stick to a generic "mixed" type by only using "===" to test them and avoiding specfic type checks. We should allow both.
    I don't think I understand what you're saying. What I'm proposing is make a permission in effect an enumeration by restricting it to a set of constants (PHP 5 class constants would be better). Whether these have integer values or not is not important to the principle of the thing.

    The idea is to avoid bugs by restricting permissions to a hard-coded set of values.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  12. #187
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by dagfinn
    So what do you do when you want to check whether the current user (loginid) has the right to see the Edit button or not?
    You ask the permissions object.

    Quote Originally Posted by dagfinn
    Checking permissions is much more fine-grained, per page (whatever that means) or finer. So I don't see them happening together all the time.

    And slice it any way you like, your authenticator needs to remember the login somehow.
    No it doesn't. Once you have a permissions set you no longer need any reference to the original login. This is a big simplification and a big win.

    Quote Originally Posted by dagfinn
    Anyway, I think this makes it clear that the test case is insufficient as a specification. We need to agree on how and when the different classes are used in the application code.
    I am afraid I don't see what's missing .

    Quote Originally Posted by dagfinn
    I've been around this group long enough to know you would say that.


    Quote Originally Posted by dagfinn
    I'm entertaining the vision of this particular operation being repeated 10 grillion times in the application code, so I want just that one thing as simple as possible.
    Second order explanation:
    1) I don't mind statics in my application code, because I have control of it there. I can simply refactor if I get it wrong. It's a big issue in a library component. I say we avoid them and let the application writer do the static wrap. They will probably want to wrap the authentication as well in the same method.
    2) I don't think it will occour quite that many times. Likely the app. developer or us would wrap their version in a subclass (fixing storage and other options).

    Quote Originally Posted by dagfinn
    What's wrong with a good old-fashioned configuration variable? Do you want to use different kinds of storage in different places in the code?
    Just that the application developer probably already has a configuration class and their own config. file. Either our library forces another config. file on the developer or we must accept in a passed in configuration interface. This will likely force the developer to add an adapter.

    Another option is to have something like...
    PHP Code:
    AuthoriserOptions::setStorage('MySQL'); 
    Basically a registry. I started down this road before realising a factory dependency was sufficient.

    I am open to other options, but a configuration file is more complicated. The current test case could be implemented with MySql in about 20 lines of code.

    Quote Originally Posted by dagfinn
    The idea is to avoid bugs by restricting permissions to a hard-coded set of values.
    But we don't know what these values are, only the application writer knows that.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  13. #188
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow, this is getting interesting...
    Quote Originally Posted by lastcraft
    You ask the permissions object.
    And what do you do with the permissions object between the time you create it (during login) and the time you ask it? Keep it in a global variable?
    Quote Originally Posted by lastcraft
    No it doesn't. Once you have a permissions set you no longer need any reference to the original login. This is a big simplification and a big win.
    I must have missed something serious here. It seems elementary to me, but you're not in the same galaxy. If you don't need to keep the original login, how do you know you have a logged-in user when you get the next HTTP request? There has to be some information in the session that records the fact that the user is logged in. It has to be some global information, and it might as well be enough to enable us to get the permissions.
    Quote Originally Posted by lastcraft
    Second order explanation:
    1) I don't mind statics in my application code, because I have control of it there. I can simply refactor if I get it wrong. It's a big issue in a library component. I say we avoid them and let the application writer do the static wrap. They will probably want to wrap the authentication as well in the same method.
    I see your point. But couldn't you just as well implement both and let the application developer choose which one to use, and have them change to the other one if it's unsatisfactory?
    Quote Originally Posted by lastcraft
    Basically a registry. I started down this road before realising a factory dependency was sufficient.
    But what does your factory thing do in this case that a simple constant won't do? Does it do anything beyond changing two occurences of the storage type to one occurence? Isn't that the kind of thing we have variables and constants for?
    Quote Originally Posted by lastcraft
    But we don't know what these values are, only the application writer knows that.
    You're right. So the application writer would define the constants, then.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  14. #189
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by dagfinn
    And what do you do with the permissions object between the time you create it (during login) and the time you ask it? Keep it in a global variable?
    Up to the application developer, but I would personally pass it around somehow. Probably it would sit in a session object. This stuff only applies to the presentation tier anyway so it shouldn't have to travel too far.

    Quote Originally Posted by dagfinn
    There has to be some information in the session that records the fact that the user is logged in.
    Yes, but session management is not our concern. The application writer would likely put the permission set into a session. This is why it's helpful that it is a value object - you don't have to unserialise an entity.

    Quote Originally Posted by dagfinn
    But couldn't you just as well implement both and let the application developer choose which one to use, and have them change to the other one if it's unsatisfactory?
    We could implement both (shall we?), in which case the static is syntactic sugar.

    Quote Originally Posted by dagfinn
    But what does your factory thing do in this case that a simple constant won't do?
    Just my natural resistance to global anything . There is one catch though. What if someone is integrating two apps. in one script, one using Postgres and the other MySql? OK...unlikely.

    It will cause mocking problems with a constant, but I think I can get around this.

    Quote Originally Posted by dagfinn
    You're right. So the application writer would define the constants, then.
    Yep. As long as we don't distinguish between strings and integers the app. people can do it both ways.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  15. #190
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm sensing that we are getting closer to some code. Maybe an implementation of the proposed test case would shed some light on the subject.

    JT

  16. #191
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    Yes, but session management is not our concern. The application writer would likely put the permission set into a session. This is why it's helpful that it is a value object - you don't have to unserialise an entity.
    OK. Now I understand what you're trying to do, but I question your premise. You say "this is too complex" and then you say "let the application writer take care of it". It seems to me you're unloading complexity on the application writer. I think we should be doing the opposite--making life easier for the application writer.

    If I'm the application writer and I'm required to build a layer on top of the library component to make it simple for me to use, then I'll probably decide to build my own instead.

    I would prefer to drop the whole assumption that this is a library component. It's over our heads. It adds indeterminacy and complexity. Better to make a complete working system, including test code that resembles a real application. And then, on the next iteration, find out what's needed to make a library component.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  17. #192
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Let me show you some code to make my point. Here's my implementation of the Authoriser class:

    PHP Code:
    define('DO_STUFF',1);
    class 
    Authoriser {
        function 
    isAllowed($permission) { //In PHP 5, I would have 'static function'
            
    $userAccount $_SESSION['currentUserAccount'];
            
    $sql "SELECT permission FROM Permissions p, Roles r, UserRoles ur, UserAccounts u ".
                
    "WHERE p.role_id = r.id AND r.id = ur.role_id AND ur.account_id = u.id ".
                
    "AND u.name = '$userAccount' AND permission = $permission";
                
    $result mysql_query($sql);
                return 
    mysql_num_rows($result) ? TRUE FALSE;
        }

    Ignore the details, like the database structure, for the moment. My point is this: this code is so simple, there is no need to build in flexibility. If you need another behavior, just re-implement the whole thing.

    That's what I was referring to in my previous post: I would rather implement my own specialized Authoriser that would satisfy my needs exactly than to build a simplification layer on top of generic, complex library software.

    These comments apply to the authorization part, not the administration part. That's different, more complex and with completely different requirements.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  18. #193
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    On the other hand, just to argue with myself a little bit, the permissions object alternative does avoid accessing the database every time. That may or may not be important and worthwhile. Anyway, here's another way to do it:

    PHP Code:
    define('DO_STUFF',1);
    class 
    Permissions {
        var 
    $permissions = array();
        function 
    Permissions($permissionArray) {
            
    $this->permissions $permissionArray;
        }

        function 
    isAllowed($permission) {
            return 
    array_key_exists($permission,$this->permissions);
        }
    }

    class 
    Authoriser {
        function 
    getPermissions($userAccount) {
            
    $sql "SELECT permission FROM Permissions p, Roles r, UserRoles ur, UserAccounts u ".
                
    "WHERE p.role_id = r.id AND r.id = ur.role_id AND ur.account_id = u.id ".
                
    "AND u.name = '$userAccount'";
                
    $result mysql_query($sql);
                
    $permissionArray = array();
                while (
    $row mysql_fetch_array($result)) {
                    
    $permissionArray[$row[0]] = TRUE;
                }
                
    $_SESSION['permissions'] = new Permissions($permissionArray);
                return 
    $_SESSION['permissions']; 
        }

        function 
    isAllowed($permission) {
                return 
    $_SESSION['permissions']->isAllowed($permission);
        }

    And here's the test code:
    PHP Code:
        function testNonUserHasNothingAllowed() {
            
    $permissions Authoriser::getPermissions('nobody');
            
    $this->assertFalse($permissions->isAllowed(DO_STUFF));
            
    $this->assertFalse(Authoriser::isAllowed(DO_STUFF));
        }
        function 
    testLegitimateUserHasActionAllowed() {
            
    $permissions Authoriser::getPermissions('fred');
            
    $this->assertTrue($permissions->isAllowed(DO_STUFF));
            
    $this->assertTrue(Authoriser::isAllowed(DO_STUFF));
        } 
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  19. #194
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by dagfinn
    you say "let the application writer take care of it". It seems to me you're unloading complexity on the application writer.
    No. I am saying that teh app. writer will already have a system for dealing with it. If we step into that teritory then we will be incompatible with some applications from a core module. Now we may want to supplement our core module with some extended typical cases, but that is not necessary right now. We have yet to fully complete a single iteration.

    Quote Originally Posted by dagfinn
    If I'm the application writer and I'm required to build a layer on top of the library component to make it simple for me to use, then I'll probably decide to build my own instead.
    If our system cuts across your system or cannot be understood then you will have to anyway. If our component is simple to understand and extend then it will be an aid to building the app. system. You will actually get more reuse from a simple module. It is the paradox of OO that less is more (actually programming in general - look at Unix). Do one thing and do it well.

    Quote Originally Posted by dagfinn
    Better to make a complete working system, including test code that resembles a real application. And then, on the next iteration, find out what's needed to make a library component.
    We don't have time. Anyway I have built enough applications by now, I really don't need yet more practice in this area . Besides we have had nearly 200 posts and were almost getting to a specification. If you blow the whole thing open now we will be back to square one. Do you want that?

    Let's do an iteration. If you want to add supplementary services then you can layer them on the core in the next version. That way we both have what we want.

    yours, Marcus

    p.s. Your code does not work. If we add more test cases we will get test interference. If the app. writer adds more test cases he will get test interference that he doesn't understand. An untestable system definitely won't get reused.
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  20. #195
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just arrived, but

    Once you have a permissions set you no longer need any reference to the original login.
    This point is very true, from what I understand and agree with Marcus. At the point of log in, and it's validated, you'd query the database based on user ID, to locate all permissions for a given person yes ?

    Then put these in a SESSION for example, for page to page reference as I see it. Having to query the database every page load just to see if someone has a permission is wasteful

    Maybe a Singleton would be ideal point of use for this ? On all the other points, still to read through - again

  21. #196
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    We don't have time. Anyway I have built enough applications by now, I really don't need yet more practice in this area . Besides we have had nearly 200 posts and were almost getting to a specification. If you blow the whole thing open now we will be back to square one. Do you want that?
    No, that's not what I'm asking for. I'm suggesting that we simplify the task by scaling down the requirements; by not requiring a kind of re-usability that requires thinking about hypothetical future use. Maybe I'm wrong, but I believe that might save us from yet another round of trying to implement, finding it too complex and having to go back and simplify again.

    And I'm asking for more realistic and complete requirements; or, at least, that we think about it together. That's what I've been getting from you, and it's good progress as far as I'm concerned.

    Maybe you know better than me (and possibly all the rest of us), given that you "don't need more practice", Really, I don't mean that sarcastically; I'm totally open to that possibility. I'm just not taking your word for it. And if you do know how to do it, I need you to explain it to me. And you pretty much have, but I haven't finished thinking about it.
    Quote Originally Posted by lastcraft
    p.s. Your code does not work. If we add more test cases we will get test interference. If the app. writer adds more test cases he will get test interference that he doesn't understand. An untestable system definitely won't get reused.
    My code works in the sense that I am running the test cases and the tests pass. Which part of the code? The test cases are almost identical to two of yours; you can change it to instantiate the Authoriser, it will still work. I'm afraid I need you to explain this, too. What test interference are you talking about?
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  22. #197
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by dagfinn
    Maybe you know better than me (and possibly all the rest of us), given that you "don't need more practice",
    I am going to regret that comment for a long time, I can tell...

    Quote Originally Posted by dagfinn
    And if you do know how to do it, I need you to explain it to me. And you pretty much have, but I haven't finished thinking about it.
    OK, sincere and humble apologies . I had just come in to work and panicked at the thought of building an application as well . I am in a calmer home environment now. Breathe...

    Quote Originally Posted by dagfinn
    I'm afraid I need you to explain this, too. What test interference are you talking about?
    I am having severe guilt trips about my rather rash post .

    The problem I have is session management being hidden behind the Authoriser::isAllowed(). If Authoriser::getPermissions() is not called then Authoriser::isAllowed() carries the result of the last test, or even the last run of the script. It's got side effects.

    The requirement to call Authoriser::getPermissions() even if there is no user to login could cause this to happen...
    PHP Code:
    if ($user_id $authenticator->logIn($attempt)) {
        
    Authoriser::getPermissions($user_id);
    }
    if (
    Authoriser::isAllowed('secret') {
        ...

    But yes the tests work. The current test case is not sufficient for stateful behaviour though.

    Anyway, sorry for being so abrupt. I'll hopefully engage my manners before replying next time.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  23. #198
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    PHP Code:
    if ($user_id $authenticator->logIn($attempt)) {
        
    Authoriser::getPermissions($user_id);
    }
    if (
    Authoriser::isAllowed('secret') {
        ...

    That structure is starting to look like something that was proposed around post #100.

    JT

  24. #199
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    OK, sincere and humble apologies . I had just come in to work and panicked at the thought of building an application as well . I am in a calmer home environment now. Breathe...
    That's OK, no problem Your panic is understandable. And given how differently you and I think, and the intensity of the exchange, it was probably an accident waiting to happen.
    Quote Originally Posted by lastcraft
    The problem I have is session management being hidden behind the Authoriser::isAllowed(). If Authoriser::getPermissions() is not called then Authoriser::isAllowed() carries the result of the last test, or even the last run of the script. It's got side effects.
    You're right, I get it now. (I woke up this morning thinking "of course, why didn't I think of that".) But solving that kind of thing is what tearDown() is for, I believe?

    But let's not get bogged down in these details. I was trying to explore the overall effect of some design decisions. I'm still fascinated by the radical simplicity of my first attempt, but I'm open to other ways of doing it.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  25. #200
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Looking at the older part of this thread, I see I'm questioning some of the decisions that were made early. I understand how that might be annoying. I wasn't actively following the thread at that time, and although I have read all of the posts, I missed some of the finer points until now.

    But even after seeing how it came to be, I'm still questioning the factory dependency. Let me try to make it clear.
    Quote Originally Posted by lastcraft
    Just my natural resistance to global anything .
    I despise globals, too, but I don't see how introducing the factory dependency helps avoid them.

    Here's an example from the thread's deep dark past,
    PHP Code:
    $authoriser = &new Authoriser($this->_configuration);
    $edit = &$authorisor->createEdit(); 
    My point is this: To create the Edit object which is in sync with the Authoriser, you have to keep $authoriser alive. This variable will need exactly the same scope (global or otherwise) as a variable holding the value of $this->_configuration. So how does it help you avoid globals?
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •