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

be.objectify.deadbolt.scala.ConstraintLogic.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.{Singleton, Inject}

import be.objectify.deadbolt.scala.models.{PatternType, Subject}

import scala.concurrent.Future

@Singleton
class ConstraintLogic @Inject()(analyzer: StaticConstraintAnalyzer,
                                ecProvider: ExecutionContextProvider) {

  private val ec = ecProvider.get()

  def restrict[A, B](authRequest: AuthenticatedRequest[A],
                     handler: DeadboltHandler,
                     roleGroups: RoleGroups,
                     pass: AuthenticatedRequest[A] => Future[B],
                     fail: AuthenticatedRequest[A] => Future[B]): Future[B] = {
    def check(subject: Option[Subject], current: RoleGroup, remaining: RoleGroups): Boolean = {
      if (analyzer.hasAllRoles(subject, current)) true
      else if (remaining.isEmpty) false
      else check(subject, remaining.head, remaining.tail)
    }

    if (roleGroups.isEmpty) fail(authRequest)
    else {
      handler.getSubject(authRequest).flatMap((subjectOption: Option[Subject]) =>
        subjectOption match {
          case Some(subject) =>
            val withSubject = new AuthenticatedRequest(authRequest, subjectOption)
            if (check(subjectOption, roleGroups.head, roleGroups.tail)) pass(withSubject)
            else fail(withSubject)
          case _ => fail(authRequest)
        })(ec)
    }
  }

  def roleBasedPermissions[A, B](authRequest: AuthenticatedRequest[A],
                                 handler: DeadboltHandler,
                                 roleName: String,
                                 pass: AuthenticatedRequest[A] => Future[B],
                                 fail: AuthenticatedRequest[A] => Future[B]): Future[B] = {
    handler.getPermissionsForRole(roleName)
    .flatMap {
      case Nil => fail(authRequest)
      case permissions if permissions.isEmpty => fail(authRequest)
      case permissions => handler.getSubject(authRequest).flatMap {
        case None => fail(authRequest)
        case subjectOption@Some(subject) =>
          if (permissions.foldLeft(false)((state, p) => state || analyzer.checkRegexPattern(subjectOption, Option(p))))
            pass(new AuthenticatedRequest(authRequest, subjectOption))
          else fail(authRequest)
      }(ec)}(ec)
  }

  def dynamic[A, B](authRequest: AuthenticatedRequest[A],
                    handler: DeadboltHandler,
                    name: String,
                    meta: Option[Any] = None,
                    pass: AuthenticatedRequest[A] => Future[B],
                    fail: AuthenticatedRequest[A] => Future[B]): Future[B] =
    handler.getDynamicResourceHandler(authRequest).flatMap((drhOption: Option[DynamicResourceHandler]) => {
      drhOption match {
        case Some(dynamicHandler) =>
          handler.getSubject(authRequest).flatMap(subjectOption => {
            val maybeWithSubject = new AuthenticatedRequest(authRequest, subjectOption)
            dynamicHandler.isAllowed(name, meta, handler, maybeWithSubject).flatMap((allowed: Boolean) => if (allowed) {
              pass(maybeWithSubject)
            } else {
              fail(maybeWithSubject)
            })(ec)
          })(ec)
        case None =>
          throw new RuntimeException("A dynamic resource is specified but no dynamic resource handler is provided")
      }
    })(ec)

  def pattern[A, B](authRequest: AuthenticatedRequest[A],
                    handler: DeadboltHandler,
                    value: String,
                    patternType: PatternType,
                    meta: Option[Any] = None,
                    invert: Boolean,
                    pass: AuthenticatedRequest[A] => Future[B],
                    fail: AuthenticatedRequest[A] => Future[B]): Future[B] =
    handler.getSubject(authRequest).flatMap((subjectOption: Option[Subject]) => subjectOption match {
      case None => fail(authRequest)
      case Some(subject) =>
        val withSubject = new AuthenticatedRequest(authRequest, subjectOption)
        patternType match {
          case PatternType.EQUALITY =>
            val equal: Boolean = analyzer.checkPatternEquality(subjectOption, Option(value))
            if (if (invert) !equal else equal) pass(withSubject)
            else fail(withSubject)
          case PatternType.REGEX =>
            val patternMatch: Boolean = analyzer.checkRegexPattern(subjectOption, Option(value))
            if (if (invert) !patternMatch else patternMatch) pass(withSubject)
            else fail(withSubject)
          case PatternType.CUSTOM =>
            handler.getDynamicResourceHandler(authRequest).flatMap((drhOption: Option[DynamicResourceHandler]) => {
              drhOption match {
                case Some(dynamicHandler) =>
                  dynamicHandler.checkPermission(value, meta, handler, authRequest).flatMap((allowed: Boolean) => {
                    if (if (invert) !allowed else allowed) {
                      pass(withSubject)
                    } else {
                      fail(withSubject)
                    }
                  })(ec)
                case None =>
                  throw new RuntimeException("A custom pattern is specified but no dynamic resource handler is provided")
              }
            })(ec)
        }
    })(ec)

  def subjectPresent[A, B](authRequest: AuthenticatedRequest[A],
                           handler: DeadboltHandler,
                           present: AuthenticatedRequest[A] => Future[B],
                           notPresent: AuthenticatedRequest[A] => Future[B]): Future[B] = {
    val subject1: Future[Option[Subject]] = handler.getSubject(authRequest)
    subject1.flatMap((subjectOption: Option[Subject]) => subjectOption match {
      case Some(subject) => present(new AuthenticatedRequest(authRequest, subjectOption))
      case None => notPresent(new AuthenticatedRequest(authRequest, subjectOption))
    })(ec)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy