Class AdminPrivilegeService

java.lang.Object
com.broadleafcommerce.adminuser.user.service.AdminPrivilegeService

public class AdminPrivilegeService extends Object
A service that contains various utility and comparison functions related to AdminPermissionRef, AdminRoleRef, AdminRestriction, AdminRestrictedRole, and AdminRestrictedPermission. These functions are most useful for validation purposes to prevent flat permission, role, restriction, restricted role, and restricted permission escalation. This service also considers permissions inherited from an entity's roles and their ancestors.

The AdminUser entity supports the concept of restrictions, flat permissions, flat roles, restricted roles, and restricted permissions.

Restrictions are used to exclusively restrict entities to only the specific targets within each specified restriction type. See AdminUser.getRestrictions().

An entity with no (empty) restrictions is not restricted in any way and can be considered "least restrictive" automatically.

However, if an entity has one or more restrictions, it is exclusively restricted to only the specific targets within each specified restriction type. For example, assume we have "entityX" with restrictions [{VENDOR: [vendorA, vendorB]}, {STORE: [storeA, storeB]}]. It is exclusively restricted to vendors vendorA and vendorB, and stores storeA and storeB. It is not allowed to access storeC or vendorC, nor is it allowed to access targets of any other arbitrary restriction type.

In order for an entity's restrictions to be less restrictive than another entity, it must have access to restriction targets that the other entity does not.

If we have another "entityY" with restrictions [{VENDOR: [vendorA]}], it is exclusively restricted to vendor vendorA. It is not allowed to access vendorB or any other vendor besides vendorA, nor is it allowed to access any stores, nor is it allowed to access to targets of any other arbitrary restriction type. In this case, we would say that "entityX" is less restrictive than "entityY", as "entityX" is able to access items that "entityY" cannot. "entityY" is not less restrictive than "entityX", because "entityX" has access to all the restriction targets that "entityY" can.

A permission enables access to some resource(s). Without the appropriate permission, the entity cannot access those resource(s).

"Flat permissions" is the term used for all permissions that come from AdminUser.getPermissions() and any permissions inherited from AdminUser.getRoles()) or their ancestors. If the entity has restrictions, then these permissions are only granted in those restrictions (effectively becoming restricted permissions). If the entity has no restrictions, then those permissions are granted everywhere.

"Flat roles" is the term used for all roles that come from AdminUser.getRoles() and those inherited from their parent roles. Similarly, if the entity has restrictions, these roles are only granted in those restrictions (effectively becoming restricted roles). If the entity has no restrictions, then those roles are granted everywhere.

"Restricted permissions" are specific to particular restrictions. These are effectively added to whatever "flat permissions" the restriction already inherits, and thus are a way to give additional access within certain restrictions. See AdminUser.getRestrictedPermissions().

For example, assume we have a "userA" with restrictions on [vendorA, vendorC] with READ_PRODUCT "flat permission", and "restricted permission" of UPDATE_PRODUCT on [vendorC]. In this case, the user effectively has READ_PRODUCT permission on both vendorA and vendorC, and also UPDATE_PRODUCT permission on only vendorC.

"Restricted roles" are similar to "restricted permissions." Except the roles basically serve as a group of permissions, and each of those permission is specific to particular restrictions, just like "restricted permissions."

In order for an entity's permissions to be less restrictive than another entity, it must have permissions (whether they come from flat permissions, flat roles, restricted roles, or restricted permissions) in a context/restriction that the other entity does not.

Assume we have another "userB" with restrictions on [vendorA] with READ_PRODUCT "flat permission", and "restricted permission" of UPDATE_PRODUCT on [vendorA]. we would say that "userA" is less restrictive than "userB" because "userA" has READ_PRODUCT and UPDATE_PRODUCT on vendorC, which "userB" does not. Likewise, "userB" is also less restrictive than "userA" because "userB" has UPDATE_PRODUCT on vendorA, which "userA" does not.

Author:
Sunny Yu
See Also:
  • Constructor Details

  • Method Details

    • isLessRestrictiveByRestrictions

      public boolean isLessRestrictiveByRestrictions(@NonNull @NonNull AdminUser user1, @NonNull @NonNull AdminUser user2)
      Checks if user1's restrictions is less restrictive than user2's restrictions.

      See the class-level javadocs for the detailed explanations on what it means to be less restrictive.

      Parameters:
      user1 - the AdminUser to compare from
      user2 - the AdminUser to compare to
      Returns:
      true if user1's restrictions are less restrictive than user2's restrictions, else false
    • isLessRestrictiveByPrivileges

      public boolean isLessRestrictiveByPrivileges(@NonNull @NonNull AdminUser user1, @NonNull @NonNull AdminUser user2)
      Checks if user1 is less restrictive than user2 based on all of their flat permissions, flat roles, restrictions, restricted roles, and restricted permissions as a whole, which also includes those that are inherited from their roles and ancestry roles.

      See the class-level javadocs for the detailed explanations on what it means to be less restrictive.

      Parameters:
      user1 - the AdminUser to compare from
      user2 - the AdminUser to compare to
      Returns:
      true if user1 is less restrictive than user2, else false
    • restrictedRolesRestrictionsAreLessRestrictiveThanFlatRestrictions

      public boolean restrictedRolesRestrictionsAreLessRestrictiveThanFlatRestrictions(AdminUser user)
      Checks if AdminUser.getRestrictedRoles() specified restrictions are less restrictive than AdminUser.getRestrictions().
      Parameters:
      user - the AdminUser to check against
      Returns:
      true if user's specified restrictions for restricted roles are less restrictive than user's flat restrictions, else false
    • restrictedPermissionsRestrictionsAreLessRestrictiveThanFlatRestrictions

      public boolean restrictedPermissionsRestrictionsAreLessRestrictiveThanFlatRestrictions(AdminUser user)
      Checks if AdminUser.getRestrictedPermissions() specified restrictions are less restrictive than AdminUser.getRestrictions().
      Parameters:
      user - the AdminUser to check against
      Returns:
      true if user's specified restrictions for restricted permissions are less restrictive than user's flat restrictions, else false
    • restrictedPrivilegeRestrictionsAreLessRestrictiveThanFlatRestrictions

      protected boolean restrictedPrivilegeRestrictionsAreLessRestrictiveThanFlatRestrictions(Set<AdminRestriction> restrictions, Set<? extends AdminRestrictedPrivilege> restrictedPrivileges)
    • getConsolidatedRestrictionTypeAndTargetsByPermissionName

      protected Map<String,Map<String,Set<String>>> getConsolidatedRestrictionTypeAndTargetsByPermissionName(@NonNull @NonNull AdminPrivilegeService.PrivilegeHydrationResult privilegeHydrationResult)
      Gets a consolidated map of restricted permissions with the combination of flat permissions and restrictions, restricted roles, and restricted permissions. Flat permissions and restrictions are converted into a map of equivalent restricted permissions. Similarly, restricted roles are also converted into equivalent restricted permissions.

      For example, if an entity has READ_PRODUCT as flat permission (that came either from its direct flat permissions or from a flat role) with a flat vendor restriction on vendorA, it is then converted into a restricted permission as such: {READ_PRODUCT: {VENDOR: [vendorA]}}. This helps with the process of comparing entities' restrictiveness.

      Likewise, if an entity has a role that has READ_PRODUCT permission assigned, and has the role added as restricted role on vendorA, it is then converted into a restricted permission as well: {READ_PRODUCT: {VENDOR: [vendorA]}}. This also helps with the process of comparing entities' restrictiveness.

      Parameters:
      privilegeHydrationResult - AdminPrivilegeService.PrivilegeHydrationResult to consolidate the permissions, restrictions, restricted roles, and restricted permissions for a user
      Returns:
      a consolidated map of restricted permissions from flat permissions, restrictions, restricted roles, and restricted permissions
    • getHydratedPrivileges

      protected AdminPrivilegeService.PrivilegeHydrationResult getHydratedPrivileges(@NonNull @NonNull AdminUser user)
    • getRoleIds

      protected Set<String> getRoleIds(@NonNull @NonNull AdminUser user)
    • getRoleIds

      protected Set<String> getRoleIds(@NonNull @NonNull Set<AdminRestrictedRole> restrictedRoles)
    • getRoleWithAncestorsByRoleId

      protected Map<String,Collection<AdminRoleRef>> getRoleWithAncestorsByRoleId(@NonNull @NonNull Set<String> roleIds)
      Gets roles along with their ancestry roles mapped by given role id.
      Parameters:
      roleIds - role ids to get the roles and ancestry roles for
      Returns:
      a collection containing the given roles along with their ancestors mapped by given role id
    • getAllPermissionNames

      protected Set<String> getAllPermissionNames(@NonNull @NonNull Set<AdminPermissionRef> permissions)
      Get all permission names from a set of AdminPermissionRef.

      Permissions would be expanded if it starts with ALL_*, such as ALL_PRODUCT.

      Parameters:
      permissions - a set of permissions to get the all the permission names from
      Returns:
      a set of permission names
      See Also:
    • getAllFlatPermissions

      protected Set<AdminPermissionRef> getAllFlatPermissions(@NonNull @NonNull AdminUser user, @NonNull @NonNull Collection<AdminRoleRef> roles)
      Parameters:
      user - AdminUser to get the permissions for
      roles - Collection of roles to get all the permissions from. This is typically a collection of user's roles and their ancestry roles to prevent the need of querying all ancestry roles every time
      Returns:
      a set containing the flat permissions from the given user and roles
    • getAllFlatPermissions

      protected Set<AdminPermissionRef> getAllFlatPermissions(@NonNull @NonNull Collection<AdminRoleRef> roles)
      Parameters:
      roles - Collection of roles to get all the permissions from
      Returns:
      a set containing the flat permissions from the given roles
    • getMergedRestrictionTypeAndTargetsByPermissionName

      protected Map<String,Map<String,Set<String>>> getMergedRestrictionTypeAndTargetsByPermissionName(Map<String,Map<String,Set<String>>> restrictionTypeAndTargetsByPermissionName1, Map<String,Map<String,Set<String>>> restrictionTypeAndTargetsByPermissionName2)
      Gets a Map that is a combination of the two given restricted permissions maps.
      Parameters:
      restrictionTypeAndTargetsByPermissionName1 - first Map to combine with
      restrictionTypeAndTargetsByPermissionName2 - second Map to combine with
      Returns:
      a map that is a combination of the two given maps
    • isLessRestrictiveByRestrictions

      protected boolean isLessRestrictiveByRestrictions(@NonNull @NonNull Map<String,Set<String>> aRestrictionTargetsByType, @NonNull @NonNull Map<String,Set<String>> bRestrictionTargetsByType)
      Checks if aRestrictionTargetsByType is less restrictive than bRestrictionTargetsByType. Both have the structure of { restrictionType: [restrictionTargets] }.
      Parameters:
      aRestrictionTargetsByType - the Map of restriction targets by restriction type to compare from
      bRestrictionTargetsByType - the Map of restriction targets by restriction type to compare to
      Returns:
      true if aRestrictionTargetsByRestrictionType is less restrictive than bRestrictionTargetsByRestrictionType, else false.
    • isLessRestrictiveByRestrictedPermissions

      protected boolean isLessRestrictiveByRestrictedPermissions(@NonNull @NonNull Map<String,Map<String,Set<String>>> aRestrictionsByPermissionName, @NonNull @NonNull Map<String,Map<String,Set<String>>> bRestrictionsByPermissionName)
      Checks if aRestrictionsByPermissionName is less restrictive than bRestrictionsByPermissionName. Both have the structure of { permissionName: { restrictionType: [restrictionTargets] } }.
      Parameters:
      aRestrictionsByPermissionName - the Map of restrictions by permission name to compare from
      bRestrictionsByPermissionName - the Map of restrictions by permission name to compare to
      Returns:
      true if aRestrictionsByPermissionName is less restrictive than bRestrictionsByPermissionName, else false.
    • getRestrictionTargetsByRestrictionType

      protected Map<String,Set<String>> getRestrictionTargetsByRestrictionType(@NonNull @NonNull Set<AdminRestriction> restrictions)
      Converts the Set of AdminRestriction to a Map with the structure of: { restrictionType: [restrictionTargets] }.
      Parameters:
      restrictions - Set of AdminRestriction
      Returns:
      a map with restriction type as key and restriction targets as value converted from the given set of restrictions
    • getRestrictionTypeAndTargetsByPermissionName

      protected Map<String,Map<String,Set<String>>> getRestrictionTypeAndTargetsByPermissionName(Set<AdminRestriction> restrictions, Set<AdminPermissionRef> flatPermissions)
      Maps each AdminPermissionRef with all of AdminRestriction. Doing this to convert flat permissions and restrictions into the map structure of restricted permissions, which helps the comparisons of restrictiveness.

      However, when there's no flat permissions, the restrictions are not added.

      Note: The ALL_* permissions are expanded into CRUD_* permissions before mapping with a restriction.

      Parameters:
      restrictions - Set of AdminRestriction
      flatPermissions - Set of AdminPermissionRef
      Returns:
      a map of restricted permissions converted from restrictions and flat permissions
    • getRestrictionTypeAndTargetsByPermissionNameFromRestrictedRoles

      protected Map<String,Map<String,Set<String>>> getRestrictionTypeAndTargetsByPermissionNameFromRestrictedRoles(@NonNull @NonNull AdminPrivilegeService.PrivilegeHydrationResult privilegeHydrationResult)
      Maps each AdminPermissionRef from the AdminRestrictedRole with the corresponding restriction. Doing this to convert permissions assigned to the restricted role and restricted role restrictions into the map structure of restricted permissions, which helps the comparisons of restrictiveness.

      The ALL_* permissions are expanded into CRUD_* permissions with the same restrictions.

      Parameters:
      privilegeHydrationResult - AdminPrivilegeService.PrivilegeHydrationResult to get the restricted roles and their ancestors from
      Returns:
      a map of restriction type and targets mapped by permission name converted from the given set of restricted roles and ancestor roles from AdminPrivilegeService.PrivilegeHydrationResult
    • getRestrictionTypeAndTargetsByPermissionName

      protected Map<String,Map<String,Set<String>>> getRestrictionTypeAndTargetsByPermissionName(@NonNull @NonNull Set<AdminRestrictedPermission> restrictedPermissions)
      Converts the Set of AdminRestrictedPermission to a Map with the structure of: { permissionName: { restrictionType: [restrictionTargets] } }.

      The ALL_* permissions are expanded into CRUD_* permissions with the same restrictions. For example, if the set contains only {ALL_PRODUCT: {VENDOR: [vendor1, vendor2}}, it will be expanded into: [ {CREATE_PRODUCT: {VENDOR: [vendor1, vendor2}}, {READ_PRODUCT: {VENDOR: [vendor1, vendor2}}, {UPDATE_PRODUCT: {VENDOR: [vendor1, vendor2}}, {DELETE_PRODUCT: {VENDOR: [vendor1, vendor2}} ]

      Parameters:
      restrictedPermissions - Set of restricted permissions
      Returns:
      a map converted from the given set of restricted permissions
    • getCurrentlyAuthenticatedAdminUser

      public Optional<AdminUser> getCurrentlyAuthenticatedAdminUser()
      If the current authentication exists and is an admin user, reads the user from the data store and returns them in an Optional. Otherwise, returns empty.
      Returns:
      an Optional containing the currently authenticated AdminUser
      Throws:
      IllegalStateException - if the authentication had an admin user ID but the user wasn't found in the data store
    • getAdminUserService

      @NonNull protected AdminUserService<AdminUser> getAdminUserService()
    • getAdminRoleHydrationService

      @NonNull protected AdminRoleHydrationService getAdminRoleHydrationService()
    • getPolicyUtils

      @Nullable protected com.broadleafcommerce.data.tracking.core.policy.PolicyUtils getPolicyUtils()
    • getAuthProvider

      protected AuthProvider getAuthProvider()