Example

Data model

EmplBasic specifies basic employees’ information. In this example, an employee has a name, a surname, and a salary. An employee may have a supervisor and may in turn supervise other employees. Also, an employee may take one of two roles: “Worker” or “Supervisor”. In the terminology of ComponentUML, Employee is an entity; name, surname, salary, and role are attributes; supervisedBy and supervises are association-ends; and Role is an enumerated class. Notice that the association-end supervises has multiplicity 0..*, meaning that an employee may supervise zero or more employees, while the association-end supervisedBy has multiplicity 0..1 meaning that an employee may have at most one supervisor.
 
enum Role {
    WORKER
    SUPERVISOR
}

entity Employee {
    String name
    String surname
    Integer salary
    Role role

    Set(Employee) supervises oppositeTo supervisedBy
    Employee supervisedBy oppositeTo supervises
}

Security model

The security model specifies a basic FGAC policy for accessing the employees’ information considered in EmplBasic.dtm. In this example, permissions are assigned to users with the role Worker and users with role Supervisor. In addition, users with role Supervisor inherit all the permissions granted to users with role Worker.
In the terminology of SecureUML, Worker and Supervisor are roles, and the former is a superrole of the latter.

role WORKER {
    Employee {
        read(salary) constrainedBy [caller = self]
    }
}

role SUPERVISOR extends WORKER {
    Employee {
        read(salary)
        update(salary) constrainedBy [self.supervisedBy = caller]
    }
}

Invariants

We can refine the model EmplBasic by adding invariants. In particular, we can specify that:
  1. There is exactly one employee who has no supervisor.
  2. Nobody is its own supervisor.
  3. An employee has role Supervisor if and only if it has at least one supervisee.
  4. Every employee has one role.
These invariants can be formalized in OCL as follows:
  1. Employee.allInstances()->one(e| e.supervisedBy.oclIsUndefined())
  2. Employee.allInstances()->forAll(e|not(e.supervisedBy = e))
  3. Employee.allInstances()->forAll(e|(e.role = Supervisor implies e.supervises->notEmpty())
    and (e.supervises->notEmpty() implies e.role = Supervisor))
  4. Employee.allInstances()->forAll(e|not(e.role.oclIsUndefined())

Additional Constraints

You can add an additional contraint to the example. In this case we don't add anyone.

Analisys information

The extra information required is an action (i.e. create, read, update, delete),  a resource (i.e. Employee, Employee:name, Employee:surname, etc), select a role (i.e. Supervisor or Worker) and finally a type.  Types are always four: type I, type II, type III, and type IV. Those refer to, consider a role r and an action act, then:

  • Type I: If there is any scenario in which someone with role r will be allow to execute the action act.
  • Type II: If there is any scenario in which someone with role r will not be allow to execute the action act.
  • Type III: If there is any scenario in which nobody with role r will be allow to execute the action act.
  • Type IV: If, in any scenario, there is at least one object upon which nobody with role r will be allow to execute the action act.