I'm trying to figure out the best way to model/design and then implement a "user" feature in a system.


I am designing an on-line access request system, so our company can use a web-based method for users to request access to various software systems. Since the system is all about the "user", the user is the focal point of the system.

So, a User can request access to a system. Then, the User's Manager will approve/reject the request. After that, the System Owner will approve/reject the request. Then it's the System Admin who approves/rejects, and finally the Security Administrator approves/rejects and adds them to the appropriate Active Directory group so they have access to the target Active Directory-driven application (not this application).


I see all entities that represent a User as a core (set of) class(es) in the system. The User object is straight-forward - just pass their Windows login to Active Directory (AD) via an LDAP query and get their info and load it into an object. In an LDAP query, if there are other Users that report to them (a user's manager is stored in our AD), then this "user" is not only a User in this system but also a Manager. If this User is also in the database as a System Owner, they are also a System Owner.

So Far:

(Assume a Manager is someone with at least one direct report assigned to them in AD.)

I've considered a single User object, with properties such as IsManager or IsSystemOwner. However, should I construct an object hierarchy where (for example) a Manager class inherits from User? There are quirks with this, because a System Owner could inherit from User or Manager. Not all system owners are managers. However, Managers, System Owners, System Admins, and Security Admins are all Users, because they can be requesting access to some software system where there role in this system is only as a User. Here is an overview of "is a" for all of the user entities:

  • A User can request access to some other software system in this system.
  • A Manager is a User.
  • A System Owner is a User.
  • A System Admin is a User.
  • A Security Admin is a User (but unlikely to be, due to our organization).
  • A Manager may be a System Owner, but not always.
  • A System Owner may be a Manager, but not always.
  • A System Admin may be a Manager, but not always.
  • A System Admin may be a System Owner, but not likely.
  • A Security Admin may be a Manager, but not always.
  • A Security Admin may be a System Owner, but not likely.

Some additional info:

  • I don't anticipate Security Admins to be using the system as a User to request access, but it's always a possibility.
  • A Manager may create an access request on behalf of one of their employees (to revoke access to a fired employee, for example)
  • All employees in the Windows domain will have access to this site. I assume that I will have some Active Directory groups created for System Admins and Security Admins, as the users in these groups will not be dynamic, rather, users in one team are Sys Admins and users in another team are Security Admins.
  • The System Owner is subject to changed and will be stored in the database, along with the option to designate an alternate approver when on vacation, etc.
  • I may need a Manager to have an alternate approver, but I didn't plan on storing all users on the domain in the database!

This seems like it's so easy to model on paper, but getting it into good, flexible code is stumping me. All suggestions are welcome.

EDIT: Based on Karl's feedback, I have this prototype model. Does it look solid from an OOP perspective, based on my intended use?

Public Class MyCustomUserObject

    Public Property LoginID As String
    Public Property FirstName As String
    Public Property LastName As String
    Public Property EmailAddress As String

    Public Property Roles As List(Of Role)

    Public Function IsManager() As Boolean
        ' If List(Of Role) contains an object of type ManagerRole, then True, else False.
    End Function

    Public Function IsSystemOwner(systemName As String) As Boolean
        ' If List(Of Role) contains an object of type SystemOwnerRole with matching name
        ' in SystemOwnerRole.SoftwareSystems, then True, else False.
    End Function

    Public Function IsSystemAdministrator(systemName As String) As Boolean
        ' If List(Of Role) contains an object of type SystemAdministratorRole with matching name
        ' in SystemAdministratorRole.SoftwareSystems, then True, else False.
    End Function

    Public Function IsSecurityAdministrator() As Boolean
        Return My.User.IsInRole("My Active Directory group name for Security Admins")
    End Function

End Class

Public Class SoftwareSystem

    Public Property ID As String
    Public Property Name As String

End Class

Public MustInherit Class Role

    Public Property DesignatedApproverLoginID As String

End Class

Public Class ManagerRole
    Inherits Role

    Public Property Subordinates As List(Of AafUser)
    ' Or this, with a List of login IDs?
    ' Public Property Subordinates As List(Of String)

End Class

Public Class SystemOwnerRole
    Inherits Role

    Public Property SoftwareSystems As List(Of SoftwareSystem)

End Class

Public Class SystemAdministratorRole
    Inherits Role

    Public Property SoftwareSystems As List(Of SoftwareSystem)

End Class

Public Class SecurityAdministratorRole
    Inherits Role

    ' Explictly a Security Admin for all Software Systems.

End Class

3 Answers 3


My suggestion is rather than making different User classes for different roles, have a single User class that contains a list of Role objects. Role would be a base class, with Manager, SystemOwner, SecurityAdmin, and SystemAdmin being derived classes, with fields specific to their needs. Manager would have a list of subordinates, SystemOwner would have descriptions of the system, etc. Role could have common fields, like an alternate approver, for example.

That architecture opens a lot of possibilities. Someone can easily be the owner of multiple systems, for example. That also makes queries like "list all system owners" easier.

  • I've prototyped some classes and put them in my OP. Does it look about right to what you were thinking? I am thinking that a SecurityAdministratorRole might not be needed, since it's target system independent, and will not have a designated approver.
    – HardCode
    Commented May 11, 2012 at 19:25

I think the bit that you're missing is that Role is not an attribute of User. Role is an attribute of the relationship between two entities (either two users or a user and a system).

For example:

  • Bob might be the system owner of the Oracle database but have no ownership privileges with the SQL database.
  • Paul might be the manager of Bob but not the manager of Jason.

In the UML world, this sort of thing is called an association class. In the database world, it is called a descriptive attribute.

You will need

  1. A table of users, including user ID, name, and LAN ID
  2. A table of systems
  3. A table of user-user relationships. Each row should contain a FromUserID, ToUserID, and a RoleID (e.g. manager). You might also want a start and end date, since roles could change.
  4. A table of user-system relationships. Each row should contain UserID, SystemID, and a SystemRoleID (e.g. owner). Again, you might also want a start and end date.

You can still have a IsManagerOf method or IsOwnerOf method, of course, as a matter of convenience. But it terms of your data model, they don't belong to the user at all, they belong to the relationship that is attached to the user.


Your domain model is over-engineered for your use cases. For "Acess Management", you do not need to model or store who is in who's team in your database -- those information would be more current in your ldap systems.

I believe you are complicating by storing roles. The below diagrams may provide a simplistic model that may cover your use cases.

User object just needs an enterprise-wide-unique id, nothing more. Most hierarchy data may already be in enterprise ldap.

Class Diagram

Most of the heavy-weight business logic can be doe in service layer -- with ldap and your local db as your data sources.

Sequence diagram

The request object may go through various states, persisted/ queried for further processing, and data analytics etc.

State changes for request

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.