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

com.stackmob.lucid.ProvisioningServerSpecs.scala Maven / Gradle / Ivy

The newest version!
package com.stackmob.lucid

/**
 * Copyright 2012-2013 StackMob
 *
 * 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.
 */

import java.net.{HttpURLConnection, URI}
import java.util.Properties
import org.scalacheck.Gen
import org.scalacheck.Prop._
import org.specs2._
import scalaz._
import Scalaz._

class ProvisioningServerSpecs
  extends Specification
  with ScalaCheck { override def is = stopOnFail ^ sequential                                                           ^
  "Provisioning Server Tests:".title                                                                                    ^
  "Provisioning should => POST /provision/stackmob"                                                                     ^
    "Return 201 created if the provision was successful"                                                                ! provision().created ^
    "Return 401 not authorized if authorization fails"                                                                  ! provision().notAuthorized ^
    "Return 409 conflict if a plan exists for the given id"                                                             ! provision().conflict ^
                                                                                                                        endp^
  "Deprovisioning should => DELETE /provision/stackmob/:id"                                                             ^
    "Return 204 no content if the deprovision was successful"                                                           ! deprovision().noContent ^
    "Return 401 not authorized if authorization fails"                                                                  ! deprovision().notAuthorized ^
    "Return 404 not found if no plan exists for the given id"                                                           ! deprovision().notFound ^
                                                                                                                        endp^
  "Changing a plan should => PUT /provision/stackmob/:id"                                                               ^
    "Return 204 no content if the plan was changed"                                                                     ! change().noContent ^
    "Return 401 not authorized if authorization fails"                                                                  ! change().notAuthorized ^
    "Return 404 not found if no plan exists for the given id"                                                           ! change().notFound ^
                                                                                                                        endp^
  "Single sign on should => POST /:sso-path"                                                                            ^
    "Return 302 redirect if the single sign on was successful"                                                          ! sso().redirect ^
    "Return 403 forbidden if authentication fails"                                                                      ! sso().forbiddenAuth ^
    "Return 403 forbidden if the timestamp is older than five minutes"                                                  ! sso().forbiddenTimestamp ^
    "Return 404 not found if no plan exists for the given id"                                                           ! sso().notFound ^
                                                                                                                        endp^
  "Reprovisioning should => POST /provision/stackmob"                                                                   ^
    "Return 201 created if the provision was successful"                                                                ! reprovision().created ^
                                                                                                                        end

  // use scalacheck to randomize requests, but we don't want duplicate requests
  implicit val params = set(minTestsOk -> 1)

  case class sso() extends ProvisioningContext {

    def redirect = apply {
      forAllNoShrink(genProvisionRequestViaProps) { (request) =>
        val timestamp = System.currentTimeMillis
        val token = createToken(request.id, request.email, salt, timestamp)
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        (client must resultInProvisionResponse(request)) and
          (client must resultInSSOResponse(SSORequest(request.id, token, request.email, ssoPath, timestamp)))
      }
    }

    def forbiddenAuth = apply {
      forAllNoShrink(genSSORequestViaProps) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        client must resultInSSOError(request.copy(email = "[email protected]"), HttpURLConnection.HTTP_FORBIDDEN)
      }
    }

    def forbiddenTimestamp = apply {
      forAllNoShrink(genSSORequestViaProps) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        client must resultInSSOError(
          request.copy(token = createToken(request.id, request.email, salt, 1), timestamp = 1),
          HttpURLConnection.HTTP_FORBIDDEN
        )
      }
    }

    def notFound = apply {
      forAllNoShrink(genSSORequestViaProps) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        client must resultInSSOError(request, HttpURLConnection.HTTP_NOT_FOUND)
      }
    }

  }

  case class provision() extends ProvisioningContext {

    def created = apply {
      forAllNoShrink(genProvisionRequestViaProps) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        client must resultInProvisionResponse(request)
      }
    }

    def notAuthorized = apply {
      forAllNoShrink(genProvisionRequestViaProps) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = "incorrect")
        client must resultInProvisionError(request, HttpURLConnection.HTTP_UNAUTHORIZED)
      }
    }

    def conflict = apply {
      forAllNoShrink(genProvisionRequestViaProps) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        (client must resultInProvisionResponse(request)) and
          (client must resultInProvisionError(request, HttpURLConnection.HTTP_CONFLICT))
      }
    }

  }

  case class reprovision() extends ProvisioningContext {

    def created() = apply {
      forAllNoShrink(genProvisionRequestViaProps) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        ((client must resultInProvisionResponse(request)) and
          (client must resultInDeprovisionResponse(DeprovisionRequest(request.id))) and
          (client must resultInProvisionResponse(request)))
      }
    }

  }

  case class deprovision() extends ProvisioningContext {

    def noContent = apply {
      forAllNoShrink(genProvisionRequestViaProps) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        ((client must resultInProvisionResponse(request)) and
          (client must resultInDeprovisionResponse(DeprovisionRequest(request.id))))
      }
    }

    def notAuthorized = apply {
      forAllNoShrink(genDeprovisionRequest) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = "incorrect")
        client must resultInDeprovisionError(request, HttpURLConnection.HTTP_UNAUTHORIZED)
      }
    }

    def notFound = apply {
      forAllNoShrink(genDeprovisionRequest) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        client must resultInDeprovisionError(request, HttpURLConnection.HTTP_NOT_FOUND)
      }
    }

  }

  case class change() extends ProvisioningContext {

    def noContent = apply {
      forAllNoShrink(genProvisionRequestViaProps) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        (client must resultInProvisionResponse(request)) and
          (client must resultInChangePlanResponse(ChangePlanRequest(request.id, request.plan)))
      }
    }

    def notAuthorized = apply {
      forAllNoShrink(genChangePlanRequest) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = "incorrect")
        client must resultInChangePlanError(request, HttpURLConnection.HTTP_UNAUTHORIZED)
      }
    }

    def notFound = apply {
      forAllNoShrink(genChangePlanRequest) { (request) =>
        val client = new ProvisioningClient(host = provisionPath.getHost, pathPrefix = provisionPath.getPath,
          protocol = protocol, port = port, moduleId = moduleId, password = password)
        client must resultInChangePlanError(request, HttpURLConnection.HTTP_NOT_FOUND)
      }
    }

  }

  trait ProvisioningContext extends CommonContext {

    lazy val genProvisionRequestViaProps: Gen[ProvisionRequest] = {
      for {
        id <- genNonEmptyAlphaStr
        plan <- Gen.oneOf(plans)
        email <- genEmail
      } yield {
        ProvisionRequest(id, plan, email)
      }
    }

    lazy val genSSORequestViaProps: Gen[SSORequest] = {
      for {
        id <- genNonEmptyAlphaStr
        email <- genEmail
      } yield {
        val timestamp = System.currentTimeMillis
        SSORequest(id, createToken(id, email, salt, timestamp), email, ssoPath, timestamp)
      }
    }

    private lazy val props = {
      val p = new Properties
      val props = LucidRunner.propertyFile | getClass.getClassLoader.getResource("lucid.properties")
      p.load(props.openStream())
      p
    }

    lazy val protocol = props.getProperty("protocol")
    lazy val provisionPath = new URI("%s://%s".format(protocol, props.getProperty("provisionPath")))
    lazy val port = props.getProperty("port").toInt
    lazy val plans = props.getProperty("plans").split(",").toList
    lazy val moduleId = props.getProperty("moduleId")
    lazy val password = props.getProperty("password")
    lazy val ssoPath = new URI(props.getProperty("ssoPath"))
    lazy val salt = props.getProperty("salt")

  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy