private def checkPackageReadPermission()

in core/controller/src/main/scala/org/apache/openwhisk/core/entitlement/PackageCollection.scala [84:144]


  private def checkPackageReadPermission(namespaces: Set[String], isOwner: Boolean, doc: DocId)(
    implicit ec: ExecutionContext,
    transid: TransactionId): Future[Boolean] = {

    val right = Privilege.READ

    WhiskPackage.get(entityStore, doc) flatMap {
      case wp if wp.binding.isEmpty =>
        val allowed = wp.publish || isOwner
        logging.debug(this, s"entitlement check on package, '$right' allowed?: $allowed")
        Future.successful(allowed)
      case wp =>
        if (isOwner) {
          val binding = wp.binding.get
          val pkgOwner = namespaces.contains(binding.namespace.asString)
          val pkgDocid = binding.docid
          logging.debug(this, s"checking subject has privilege '$right' for bound package '$pkgDocid'")
          if (doc == pkgDocid) {
            logging.error(this, s"unexpected package binding refers to itself: $doc")
            Future.failed(
              RejectRequest(
                UnprocessableEntity,
                Messages.packageBindingCircularReference(binding.fullyQualifiedName.toString)))
          } else {
            checkPackageReadPermission(namespaces, pkgOwner, pkgDocid)
          }
        } else {
          logging.debug(this, s"entitlement check on package binding, '$right' allowed?: false")
          Future.successful(false)
        }
    } recoverWith {
      case t: NoDocumentException =>
        logging.debug(this, s"the package does not exist (owner? $isOwner)")
        // if owner, reject with not found, otherwise fail the future to reject with
        // unauthorized (this prevents information leaks about packages in other namespaces)
        if (isOwner) {
          Future.failed(RejectRequest(NotFound))
        } else {
          Future.successful(false)
        }
      case t: DocumentTypeMismatchException =>
        logging.debug(this, s"the requested binding is not a package (owner? $isOwner)")
        // if owner, reject with not found, otherwise fail the future to reject with
        // unauthorized (this prevents information leaks about packages in other namespaces)
        if (isOwner) {
          Future.failed(RejectRequest(Conflict, Messages.conformanceMessage))
        } else {
          Future.successful(false)
        }
      case t: RejectRequest =>
        logging.error(this, s"entitlement check on package failed: $t")
        Future.failed(t)
      case t =>
        logging.error(this, s"entitlement check on package failed: ${t.getMessage}")
        if (isOwner) {
          Future.failed(RejectRequest(InternalServerError, Messages.corruptedEntity))
        } else {
          Future.successful(false)
        }
    }
  }