SitePoint Sponsor

User Tag List

Page 6 of 11 FirstFirst ... 2345678910 ... LastLast
Results 126 to 150 of 267
  1. #126
    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 seratonin
    I was wondering if you would perhaps propose a new design for us to evaluate.
    I probably need to know why you're asking for it. I understand you need something more specific, but what? What I posted two days ago was fairly specific I think. Not quite a design proposal though, more of a refactoring. I can give you some more details if you like. Or are you asking if I have something more up my sleeve? The answer is not really. I very loosely mentioned the possibility of Data Mappers, but my instinct is not telling me to go there, at least not yet.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  2. #127
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What I kind of wanted to do is revisit the idea of a Domain Model for this problem. Perhaps we can completely forget about the storage mechanism and the Data Model for a minute. What would a Domain Model look like for this problem? Well, let's suppose we want to just model the following entities: User, Role, Permission (forgive my naming for a moment)? What would each class look like? What data would each class have? What behavior would each class have? Well, the core RBAC spec describes this relationship:

    Code:
         *           *      *            *
    User <-----------> Role <------------> Permission
    We could have three classes: User, Permission, and Role.

    PHP Code:
    <?php
    // Domain Object: User
    class User {
        var 
    $id;
        var 
    $name;
        var 
    $roles;

        function 
    User() {}
        function 
    setId($id) {}
        function 
    getId() {}
        function 
    setName($name) {}
        function 
    getName() {}
        function 
    addRole(&$role) {}
        function 
    removeRole(&$role) {}
        function 
    hasRole(&$role) {}
        function &
    getRoles() {}
    }

    // Domain Object: Role
    class Role {
        var 
    $id;
        var 
    $name;
        var 
    $users;
        var 
    $permissions;

        function 
    Role() {}
        function 
    setId($id) {}
        function 
    getId() {}
        function 
    setName($name) {}
        function 
    getName() {}
        function 
    addUser(&$user) {}
        function 
    removeUser(&$user) {}
        function 
    hasUser(&$user) {}
        function &
    getUsers() {}
        function 
    addPermission(&$permission) {}
        function 
    removePermission(&$permission) {}
        function 
    hasPermission(&$permission) {}
        function &
    getPermissions() {}
    }

    // Domain Object: Permission
    class Permission {
        var 
    $id;
        var 
    $name;
        var 
    $roles;

        function 
    Permission() {}
        function 
    setId($id) {}
        function 
    getId() {}
        function 
    setName($name) {}
        function 
    getName() {}
        function 
    addRole(&$role) {}
        function 
    removeRole(&$role) {}
        function 
    hasRole(&$role) {}
        function &
    getRoles() {}
    }

    // Create a new user
    $user =& new User();
    $user->setName("John");

    // Update the data model
    $mapper =& new UserMapper();
    $mapper->insert($user);

    // Create a new role
    $role =& new Role();
    $role->setName("Administrator");

    // Update the data model
    $mapper =& new RoleMapper();
    $mapper->insert($role);

    // Create the many-to-many association between the two objects
    $user->addRole($role);
    $role->addUser($user); // <-- you don't really need to do this if you account for it in the User::addRole implementation $role->addUser($this)

    // Update the data model
    $mapper =& new UserMapper();
    $mapper->update($user);
    ?>
    Now, with a Domain Model like this you can definitely see there are several dependency relationships between the classes. You could employ lazy-loading for the dependent objects in each class. Also, the collections in each class could be identity maps.

    Okay, so what about the persistence. Well, you could use the Association Table Mapping pattern from PoEAA. So each class would have a Mapper/Finder class associated with it to manage it's persistence. However, since there are dependencies between the classes, the Mappers would have to call each other in order to manage the persistence of the dependent objects.

    I know it seems a little far-fetched, but I wanted to try to look at the problem from a different angle.

    JT
    Last edited by seratonin; Apr 17, 2004 at 16:53.

  3. #128
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not too keen on this idea actually, too many dependencies.

    Though I've no solution or better idea how to proceed Maybe Marcus will have some suggestions

  4. #129
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Widow Maker
    I'm not too keen on this idea actually, too many dependencies.

    Though I've no solution or better idea how to proceed Maybe Marcus will have some suggestions
    I agree about the dependencies, but that really is the model. And there are many instances that this type of relationship exists. This is why Fowler is motivated to devote an entire pattern to this type of "many-to-many" association.

    JT

  5. #130
    ********* 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 seratonin
    I agree about the dependencies, but that really is the model.
    I have my doubts about the many to many of roles and permissions. I think it is one to many. Also we don't need users, we can just have user IDs which avoid coding an object that we have no control over (hence why I only needed three tables above).

    However, it is really a data model rather than a behavioural one. If you want a really different angle, and one more realistic for an actual project, how about let's write some use cases?
    ---
    Fetching the permissions by user ID
    The authoriser fetches a permission set for a specific user ID. This permission set can be boolean tested for a particular allowed action (string). The permission set is read only.

    Sample code:
    PHP Code:
    $authoriser->getPermissions('user_id');
    if (
    $permissions->can('edit_own_post')) {
        ...

    Additional: Should be fast.
    ---

    ---
    Building a role
    A role can be added to. A role holds one or more permissions and is a named entity in the system. Additional permissions can be added to a role after it has been added.

    Sample code: ?
    ---
    ...and so on. Possible use cases are:

    1) Fetching permissions by user ID.
    2) Building a role and adding further permissions (grant).
    3) Dropping a role or just some of it's permissions.
    4) Attaching a role to a user ID.
    5) Stripping a role from a user ID or dropping a user ID altogether.

    At least I think that covers it. If those five can be fleshed out to the point of a code snippet, writing the actual implementation should be a doddle. I think we have settled on number 1 already (at least I haven't heard any dissent yet. It is just the administration that is thrashing, yes?

    yours, Marcus

    p.s. I have to say I find test cases a more concise form of communication than use cases when communicating with fellow developers. Ho hum.
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  6. #131
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    I have my doubts about the many to many of roles and permissions. I think it is one to many.
    Clearly the spec indicates that it is many-to-many and pretty much every other implementation I have ever come across (whether it is following the spec or not) also supports this relationship. HarryF has an example of this type of access control in his book and he uses a many-to-many mapping. Why exactly do you think it is one-to-many?

    Quote Originally Posted by lastcraft
    However, it is really a data model rather than a behavioural one. If you want a really different angle, and one more realistic for an actual project, how about let's write some use cases?
    I tend to disagree. All of the functions which are tied to dependent objects: addRole, removeRole, hasRole, getRoles, addUser, removeUser, hasUser, getUsers, addPermission, removePermission, hasPermission, and getPermissions all interact with the Finder/Mapper and lazy-load the objects from the Data Model. Any time you do an add or a remove you are modifying the structure of the Domain Model. This change-of-state causes an inconsistency with the Data Model which must be reconciled using the Data Mapper. Clearly thsi logic, although it does involve simple CRUD operations is considered domain logic. I will say that the Domain Model and the Data Model are isomorphic (or at least they could be depending on how you design the Data Model), but they are not the same thing. I refer you to the "Association Table Mapping" in PoEAA. Fowler has an Employee and a Skills class with a many-to-many relationship. I would think that this type of relationship is a very common thing in domain modelling. What do some of your Data Patterns books say on this?

    JT

  7. #132
    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
    Hi...
    1) Fetching permissions by user ID.
    2) Building a role and adding further permissions (grant).
    3) Dropping a role or just some of it's permissions.
    4) Attaching a role to a user ID.
    5) Stripping a role from a user ID or dropping a user ID altogether.
    In a real system you would likely have an administation user interface, wouldn't you? The administration interface should probably be able to list the various kinds of objects starting with the user accounts or whatever you want to call them.
    Quote Originally Posted by lastcraft
    p.s. I have to say I find test cases a more concise form of communication than use cases when communicating with fellow developers. Ho hum.
    I agree.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  8. #133
    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 seratonin
    Now, with a Domain Model like this you can definitely see there are several dependency relationships between the classes. You could employ lazy-loading for the dependent objects in each class. Also, the collections in each class could be identity maps.
    Yes, I think you would need lazy loading. The question is, how much complexity would be involved? I would want to keep it at a minimum. It might be interesting to try it and see.
    Quote Originally Posted by seratonin
    I know it seems a little far-fetched...
    Not really, considering the name of this thread.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  9. #134
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's a simplified lazy load strategy: think of the design as hierachical with the user account at the top, then roles, then permissions. Whenever you load the user account, you load the whole hierarchy for that user account--all the roles and permissions belonging to that account. No lazy load. Invoke the lazy load only when going the other way. When you want to get the roles having a permission or the user accounts having a role (probably rarely), you load them lazily. Something like this in its simplest form (using lazy initialization):

    PHP Code:
    class Permission...

    function 
    getRoles() {
        if (!isset(
    $this->roles)) {
         
    // get the RoleMapper and populate $this->roles
         
    return $this->roles;

    Now Role::getUsers() (I'm using seratonin's naming, call it something else than users if you like) might end up retrieving an exorbitant amount of data, but I'm not sure you'd need to worry about that until you actually wanted to use the method. And it's definitely not the first thing you want to do.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  10. #135
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My lazy loading strategy was almost exactly the same as yours. Here is what I was thinking:

    In the User class:
    PHP Code:

    function &getRoles() {
        if (!isset(
    $this->roles) {
            
    $this->loadRoles();
        }
        return 
    $this->roles;
    }

    function 
    hasRole(&$role) {
        if (!isset(
    $this->roles) {
            
    Rthis->loadRoles();
        }
        return 
    $this->roles->contains($role);
    }

    // You could also add a hasPermission function to the user class:
    function hasPermission(&$permission) {
        if (!isset(
    $this->roles)) {
            
    $this->loadRoles();
        }
        foreach (
    $this->roles as $role) {
            if (
    $role->hasPermission($permission)) {
                return 
    true;
            }
        }
        return 
    false;
    }

    function 
    loadRoles() {
        
    $finder =& new RoleFinder();
        
    $this->roles =& $finder->findAllByUserId($this->id);

    Similarily for all functions that, the roles, users, or permissions are checked and loaded iwth a common loadRoles, loadUsers, or loadPermissions function which uses the respective Finder/Mapper.

    JT

  11. #136
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    loaded iwth a common loadRoles, loadUsers, or loadPermissions function which uses the respective Finder/Mapper.
    If you find common ground over various classes, isn't there a better way to handle this functionality within the one class ?

    OO Composition would lend a hand no ? What if you had the individual classes extend to a parent class...

  12. #137
    SitePoint Zealot
    Join Date
    Jun 2003
    Location
    Elsewhere
    Posts
    107
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have another question: do any of you realize the full complexity of the problem you're trying to solve? I've been working on the permission problem for more than a year, and only now have I found a solution (Node/Group Based Access Control).

    I think you may have to decide whether you want to build a real solution, which can handle (almost) any situation, or build a tutorial solution, which only works in very simple cases, but teaches us something.

    If you're planning to build a 'real' solution, I think you'll all need to reconsider the problem, because the solutions I'm seeing in this thread seem far too simplistic to solve anything even remotely complex.

    - - -
    OT / Rant

    BTW: I would prefer the use of Group Based Access Control over Role Based Access Control. There isn't any real difference in the resulting database structure; only the visualization / conceptualization are different.

    Being a member of a group is a passive relation, since it doesn't imply any responsibility or required activity. Not so with roles. Let me try to explain with two sentences:

    "You are a member of the 'Registered Users' group."
    "Your role is to be a 'Registered User'."

    So what are a Registered User's tasks? I have no idea, and things get even more interesting when users are assigned to the role 'Banned'. The only sentence I can produce that describes a user's role without implying some responsibility is:

    "You are a Registered User."

    But this could just as well apply to membership of a group...

    The second reason I wouldn't ever use 'Roles' is because of the class structure it tends to produce. A user 'has a' role, so it's only natural to stick any and all roles into a User object. But we don't have these tendencies with groups, because groups don't belong to users.... user are members of groups.

    And adding role objects to a user object may make sense from the business domain's perspective, but I believe it's just wrong. We're dealing with a situation where we are requested to perform one specific action by a client. Before we can execute the requested action, we need to identify the client, and verify whether it is permitted to access the requested action. All we need in this scenario is the unique identifier of the client; we don't need a complete user object. We're all telling eachother never to trust user input. So let's be consistent and not ask a user object whether it is allowed to do something, but use a separate object that controls clients' access to actions.

    Anywho...

    that's just my two cents.

    Azmo

  13. #138
    SitePoint Zealot
    Join Date
    Feb 2003
    Location
    Virginia
    Posts
    143
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Marcus, that's about as far as I've seen anyone attempt to scope the problem. Kudos.

    PS: Are the rest of you building a rocket ship or a simple RBAC?

  14. #139
    SitePoint Enthusiast
    Join Date
    Apr 2004
    Location
    Berlin
    Posts
    25
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    as I understand this thead is just as much about RBAC as generally the design process itself. I just wanted to mention LiveUser here because I would be interested in getting some feedback since you all are now well versed in RBAC and authorization in general.

    Some comments:
    - LiveUser does both authentication and authorization but follows a container approach so you can mix and match different authentication and authorization containers
    - it actuall allows multiple authorization containers to be checked for one login
    - ownership of objects is stored outside of LiveUser (especially because this needs to be flexible and optional .. for some cases 1-1 many be anough for others 1-many is needed)

    LiveUser and RBAC
    - LiveUser doesnt have the concept of "object", however it has the concept of "areas" which let you group rights (so you could have one area "document" etc)
    - LiveUser's API expect you to pass it a right ID, however using the area concept you could implement a right finder to find find a given right id that matches a certain "operation" inside an "object" (so you would need to create a right inside the given area for every "operation" you want to allow for that "object" ..)
    - the concept of roles or groups to which rights have been attached

    I would appreciate your comments and maybe through studying LiveUser you can also get some ideas for your programming task at hand.

  15. #140
    SitePoint Enthusiast
    Join Date
    Apr 2004
    Location
    Berlin
    Posts
    25
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ups forgot to add a link:

    http://pear.php.net/package/LiveUser

  16. #141
    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 Resolution
    Are the rest of you building a rocket ship or a simple RBAC?
    A rocket is probably the simplest engine design imaginable, so RBAC would have to be more complex.
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  17. #142
    ********* 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 Azmo
    I think you may have to decide whether you want to build a real solution, which can handle (almost) any situation, or build a tutorial solution, which only works in very simple cases, but teaches us something.
    It's a tutorial. The topic being chosen pretty much at random (by me I think ).

    Quote Originally Posted by Azmo
    "You are a member of the 'Registered Users' group."
    "Your role is to be a 'Registered User'."
    You have a role in a system, especially if you allow multiple roles, so this isn't exactly correct, but it is interesting. What I do like about the group angle is that it separates the User more clearly. You have "membership" with groups and "assignments" with roles. The task of the RBAC is to provide a means to attach permissions to a user, not to say anything about the user itself.

    I think this also gets to the bottom of the problem I have with permissions being shared amongst roles. With groups, you would expect each group to be independent.

    Trouble is "group" implies the membership visibility is the other way. A user having a group does not make sense, but a user having a role does. I think I personally prefer "role" because that is the way the application sees it. I could change my mind pretty easily though.

    Quote Originally Posted by Azmo
    I have no idea, and things get even more interesting when users are assigned to the role 'Banned'.
    To me it doesn't make much sense adding the group "banned" either because of the effect taht will have on the way permissions are recovered. Strikes me, this is better done with authentication (if it blocks everything within an app) or with a layered authorisation.

    Quote Originally Posted by Azmo
    All we need in this scenario is the unique identifier of the client; we don't need a complete user object.
    Definitely.

    I am not discouraged by the apparent lack of progress in this thread. Evans describes this approach - write a solution, decide it's the wrong one, look at the problem again, write it faster and smaller next time - as "knowledge crunching". It is obvious that you have already been there and we are still catching up.

    Funny. It was meant to be a tutorial showing coding practices (patterns, etc). It's now an OO design tutorial instead.

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

  18. #143
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If I go the Domain Model route in my design (for illustration purposes), my intention is to design and implement the entire domain model (shouldn't be too difficult) and the associated mappers (will need Association Table Mapping pattern). Then I will probably build a unified API on top of the Domain model using the Serivice Layer pattern. The service layer will be thin and will transfer calls the the domain model and associated mappers.

    My data model will be a simple five table solution (2 connectives) and will require JOINs on the connective tables which seems to be a pretty standard implementation (I'm using MySQL). I will probably use either a built in DB api or PEAR as I do not want to do an entire DB abstraction layer.

    JT

  19. #144
    ********* 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 seratonin
    If I go the Domain Model route in my design (for illustration purposes), my intention is to design and implement the entire domain model (shouldn't be too difficult) and the associated mappers (will need Association Table Mapping pattern). Then I will probably build a unified API on top of the Domain model using the Serivice Layer pattern. The service layer will be thin and will transfer calls the the domain model and associated mappers.
    The tail will wag the donkey. You don't have a domain model, you have a data model. What behaviour does a role have for example? It is just passive. It is the service layer that will descibe the domain model because that will be the interface. If you spec that first, the data model will just drop out from normalising the targets of the queries.

    Quote Originally Posted by seratonin
    My data model will be a simple five table solution (2 connectives) and will require JOINs on the connective tables which seems to be a pretty standard implementation (I'm using MySQL). I will probably use either a built in DB api or PEAR as I do not want to do an entire DB abstraction layer.
    User should not be in the table at all (that is application), just a user_id in the next table, so that's four. The reason I think the second many-to-many is wrong is in how I see it being used.

    Say you plug the authorisation component into two in-house applications or web site sections. They would like to add their own roles, so one application adds "editor" and the second app adds "editor", but can't because that causes an error. Painful, but no disaster. Suppose the roles are different though. They start adding permissions. You either have to check every permission for existence (this will drive the development into the ground) or allow it to be added to that role. If one app decides to change the name of a permission, or to drop that permission, it will interfere with the other application without an obvious error.

    I was having a look around and the only big app I could find on my hard drive that used RBAC is Oracle. Guess what? it has groups too.

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

  20. #145
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi (and welcome to SP)...

    Quote Originally Posted by lsmith
    ...since you all are now well versed in RBAC and authorization in general.


    Quote Originally Posted by lsmith
    - LiveUser does both authentication and authorization but follows a container approach so you can mix and match different authentication and authorization containers
    I had some trouble with the docs . The setup seems to be heavily tied to the config file rather than in how the objects are assembled, but the usage example didn't show the syntax. I am afraid I could not follow it and had to start looking at the code.

    I was basically trying to find the interface for your "Perm" components. If we were writing a plug-in object for this container, what would be it's interface?

    Quote Originally Posted by lsmith
    - LiveUser's API expect you to pass it a right ID
    What is a "Right ID"?

    Quote Originally Posted by lsmith
    I would appreciate your comments and maybe through studying LiveUser you can also get some ideas for your programming task at hand.
    I don't want to derail the thread any further by getting into a specific API, but what problems were you trying to address with this framework?

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

  21. #146
    Non-Member
    Join Date
    Jan 2004
    Location
    Planet Earth
    Posts
    1,764
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ups forgot to add a link
    We are all aware of this package - that isn't the point of this thread though, is it?

    The whole point of this thread, and others that will spawn from it, it to learn. To share ideas, methods of OO design and scripting.

    To learn and share Using a pre-packaged class(es) in this case, kind of defeats the whole purpose yes ? Even if it's just to a case of looking at this PEAR package, and nothing more, you ain't going to learn from making mistakes.

    Anyways, if your happy using this PEAR package, thats great

  22. #147
    SitePoint Enthusiast
    Join Date
    Apr 2004
    Location
    Berlin
    Posts
    25
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sorry as I was trying to point out in my post my intention was not to derail this thread. Just to offer a place to have a look at another approach for all of you to prod for ideas. I forgot to say that feedback should best be send to me directly if its only relevant to LiveUser.

    Anyways for this reason I didnt reply to lastcraft in this thread.

  23. #148
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lastcraft
    The tail will wag the donkey. You don't have a domain model, you have a data model. What behaviour does a role have for example? It is just passive. It is the service layer that will descibe the domain model because that will be the interface. If you spec that first, the data model will just drop out from normalising the targets of the queries.
    I disagree. "A simple domain model looks much like the database design with mostly one domain object per database table (p. 117, PoEAA)". CRUD operations could be considered part the business logic as they can be independent of the data store. They exist in-memory as part of the domain object graph. Persistence can be completely separate. The Mappers and Finders are responsible for transparently loading and storing domain objects. Just because the domain model is extremely similar to the database design does not mean it is not a domain model, it merely means that it is isomorphic to the Data Model. The motivation for attempting a domain model here is to step back from the problem and tackle the graph of in-memory objects that represent the system, look at the dependencies, and the CRUD operations. Practically, it may not make sense to have a full domain model for this application as we have already seen. I am experimenting with different ideas.

    Regarding the Service Layer, it creates a use-case based interface for the Domain Model. It would be facade for all three domain objects Users, Roles, and Permissions. It would be thin and procedural in nature. The use cases would be primarily CRUD which is pretty boring (see p. 135, PoEAA).

    JT

  24. #149
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What we have here is two different areas of use. I hope we can agree on that. As Marcus said in the beginning:
    Quote Originally Posted by lastcraft
    The only operation an authorisation system ultimately has to accomplish is this...
    PHP Code:
    $permissions $authenticator->getPermissions($username$password);
    if (
    $permissions->can_edit()) {
        ...

    This is use case #1. It will be used practically anywhere, anytime. The rest of the use cases would be used only in separate, administration-related applications. So let's call the two authorization and administration.

    So my question is, do authorization and administration need to have common code at all? My impulse, without thinking too long about it, would be to let them be completely separate and let them communicate only through the database. The two are very different: authorization is extremely simple but requires high performance, administration is complex (relative to authorization) but performance is not that important. These factors point to the possibility of that completely different designs would be relevant for the two.

    Now let me object to myself: what about different kinds of storage? Once you start storing the data in different ways, wouldn't you need some kind of storage abstraction that could be used by both? The question keeps coming up. I've been saying design should reflect current requirements, not future ones. On the other hand, since this is not a real project, we can define "current requirements" as we please.

    So let me try to be more precise: any requirement that remains theoretical (= will not be implemented) for the duration of this exercise is worthless IMO. It will remain too fuzzy to allow us to achieve an excellent design.

    One possibility if we really are aiming for something "storage independent" is what Kent Beck calls Triangulation: we choose two different storage methods and drive the design from those. The more different the two are, the more general and abstract the design is likely be.

    That would allow us to discover whether the it's really useful to use the same generalization mechanism in the authorization and administration subsystems
    Dagfinn Reiersøl
    PHP in Action / Blog / Twitter
    "Making the impossible possible, the possible easy,
    and the easy elegant"
    -- Moshe Feldenkrais

  25. #150
    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
    I have my doubts about the many to many of roles and permissions. I think it is one to many.
    I just started reading Evans (Domain-Driven Design, on your excellent recommendation). Now I'm wondering if what you mean by what you're saying here is that it's a unidirectional association. You want to get the permissions for a role, but not the roles for a permission. (Like Evans' example, you want the president of a country but not vice versa.) If I've understood this correctly, treating the association as unidirectional allows us to simplify it. It means we can treat the association as one to many in the object model. But then can or should you denormalize and make it one to many in the database as well? I'm not clear about that yet.

    Anyway, the idea of unidirectional associations is the same I raised when I discussed lazy load. I just hadn't quite named it. Now I realize that if we consider both associations as unidirectional, it would be possible to avoid the lazy load altogether, even if we were using Mappers.
    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
  •