All Downloads are FREE. Search and download functionalities are using the official Maven repository.

be.objectify.deadbolt.scala.StaticConstraintAnalyzer.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2012-2016 Steve Chaloner
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package be.objectify.deadbolt.scala

import javax.inject.{Inject, Singleton}

import be.objectify.deadbolt.scala.cache.PatternCache
import be.objectify.deadbolt.scala.models.Subject

/**
 * Static constraint analysis.
 *
 * @author Steve Chaloner ([email protected])
 */
@Singleton
class StaticConstraintAnalyzer @Inject()(patternCache: PatternCache) {

  /**
    * Convert the subject's roles to a list of role names.
    *
    * @param maybeSubject an option for the subject
    * @return None if the subject is None or the subject has no roles, otherwise Some list of strings in the same order as the roles
    */
  def getSubjectRoles(maybeSubject: Option[Subject]): Option[List[String]] =
    maybeSubject.map(subject => subject.roles)
    .filter(roles => roles.nonEmpty)
    .map(roles => for (role <- roles) yield role.name)

  /**
    * Check if the subject has a single role.
    *
    * @param maybeSubject an option for the subject
    * @param requiredRoleName the role name the subject is required to have
    * @return true iff the subject has that role
    */
  def hasRole(maybeSubject: Option[Subject],
              requiredRoleName: String): Boolean =
    hasAllRoles(maybeSubject, Array(requiredRoleName))

  /**
    * Check if the subject has several roles using AND.
    *
    * @param maybeSubject an option for the subject
    * @param requiredRoleNames all the roles the subject must hold
    * @return true iff the subject has all roles
    */
  def hasAllRoles(maybeSubject: Option[Subject],
                  requiredRoleNames: RoleGroup): Boolean = {
    def roleMatch(requiredRoleName: String,
                  subjectRoles: List[String]) = {
      val invert = requiredRoleName.startsWith("!")
      val role = if (invert) requiredRoleName.substring(1) else requiredRoleName
      if (invert) !subjectRoles.contains(role) else subjectRoles.contains(role)
    }
    getSubjectRoles(maybeSubject).filter(subjectRoles => subjectRoles.nonEmpty)
    .map(subjectRoles => for (requiredRole <- requiredRoleNames) yield roleMatch(requiredRole, subjectRoles))
    .exists(wasMatched => wasMatched.foldLeft(if (requiredRoleNames.isEmpty) false else true)(_ && _))
  }

  /**
    * Check if any of the subject's permissions match the supplied regular expression.
    *
    * @param maybeSubject an option for the subject
    * @param maybePattern an option for the regular expression
    * @return true iff the subject has permissions and at least one matches the regular expression
    */
  def checkRegexPattern(maybeSubject: Option[Subject],
                        maybePattern: Option[String]): Boolean = {
    val maybeResult: Option[Boolean] = for {
      permissions <- maybeSubject.map(subject => subject.permissions)
      pattern <- maybePattern.flatMap(p => patternCache(p))
    } yield permissions.map(permission => pattern.matcher(permission.value).matches()).foldLeft(false)(_ || _)
    maybeResult.getOrElse(false)
  }

  /**
    * Check if any of the subject's permissions equals the supplied pattern value.
    *
    * @param maybeSubject an option for the subject
    * @param maybePatternValue an option for the equality pattern
    * @return true iff the subject has permissions and at least one equals the pattern value
    */
  def checkPatternEquality(maybeSubject: Option[Subject],
                           maybePatternValue: Option[String]) = {
    val maybeResult: Option[Boolean] = for {
      permissions <- maybeSubject.map(subject => subject.permissions)
      patternValue <- maybePatternValue
    } yield permissions.map(permission => patternValue.equals(permission.value)).foldLeft(false)(_ || _)
    maybeResult.getOrElse(false)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy