2

I'm writing a program with the following conceptual mode.

A User can apply to become an employee, which places their account in a Pending state. They can then be Approved or Rejected. The only person who can put an account in the Pending state is the user themselves.

An Administrator can move users to and between the Approved and Rejected states (they are notified whenever a user enters the Pending state). They can also promote the account to become an Supervisor (I), Supervisor (II), or Administrator.

All Supervisors have the privileges of an Approved user in relation to their own account (e.g. schedule a vacation). They also have additional privileges (e.g. view any employee's phone number). No class of Supervisors necessarily has all the privileges of any other Supervisor class. A user can be more than one type of Supervisor at once.

Administrators have the privileges of Approved users in relation to their own account, as well as he privileges of all types of Supervisors.

However, I'm having trouble finding a good way to represent this. In particular, the bolded line means that it doesn't make sense to just use a single user_status enum.

Because I also want promotion to Supervisor/Administrator access from regular employee status to require re-authentication for the Administrator, it seems to make sense to distinguish (None)/Pending/Approved/Rejected (which are inherently mutually exclusive) from the Supervisor/Administrator statuses.

The best thing I've come up with so far is essentially something along the lines of the following:

public class Employee {
 // user id, name, etc.
 ArrayList<EmployeeRole> roles;
 EmployeeStatus status;
}
public enum EmployeeRole {
 Employee, SupervisorI, SupervisorII, ..., Administrator
}
public enum EmployeeStatus {
 None, Pending, Approved, Rejected
}

However, this doesn't represent the privilege model well (such that I'm not sure what a compatible design for that would even look like). Any suggestions for a better solution?

asked Oct 17, 2017 at 23:45

1 Answer 1

1

Perks

Here's my idea: you have a list of permissions/privileges (lets call them perks for short). A role contains one or more perks, but not ownership, which is to say a given perk in a role doesn't necessarily mean it is the only role with said perk.

Roles

User, Employee, Supervisor (I), Supervisor (II), Supervisor (III), Administrator are all just roles to your program. Take a deep breath and repeat. User, Employee, Supervisor (I), Supervisor (II), Supervisor (III), Administrator are all just roles to your program.

Now, in order to avoid complications in the future, you should associate a status to each role given to a user. The status can be Pending, Approved, Rejected. This implies two things:

  1. A user can have several pending requests potentially (if you decide that only one role can be pending at a time, that can be enforced by performing a simple check).
  2. Adding a new request is as straightforward as adding a role with status Pending to the user in question. Just don't forget to filter out roles that don't have status "Accepted" before you consider a user's permissions!

Flexibility

This has the added advantage that it is entirely flexible. You save the information in the data layer as such, and you can fine-tune behavior at the business level. If later, program behavior changes, you need only change the business logic for updating your data layer.

We can also use this system to enhance itself. For instance, we can create a perk that allows a user to add/remove roles to another user. So rather than checking if current user is an Administrator, you only check for the existence of this perk. In this case, you can present the proper GUI to allow said user to add/remove perks to another user.

We can take this further. We can create a Perk that allows a user to be able to immediately approve a role being added to a user. When a user attempts to add a new role to a user, you can check this for this perk, and if it exists, rather than set state PENDING, set it directly to APPROVED.

Notice that it would be a mistake to check for the roles of any given user. The roles exist only to group perks. The existence of the perks given by a user's roles are what tells you what a user can and cannot do. This is important as it means you never need to know if a user has Administrator role or not. Your program can function entirely with the use of roles abstracted away, with the minor exception of the data layer which loads the perks for a given user.

Why System Administrators will love you

Afterwards and only once the above works without problems, if you think the list of perks will be numerous, you should consider allowing a role to contain also other roles in addition to perks. For example, Administrator has all other roles, so should new perks get added to other roles, Administrator will have them too by default for instance). However, this isn't strictly necessary. Also, if you decide to take this route, you will have to do a quick check that you're not creating a cyclic dependency (Administrator cannot add role Supervisor (III) if Supervisor (III) already has role Administrator for instance).

Hope that helps!

answered Oct 18, 2017 at 7:38

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.