Skip to content

Commit

Permalink
prime-1.17.0
Browse files Browse the repository at this point in the history
  • Loading branch information
vihangpatil authored Oct 12, 2018
2 parents 7c982fd + 82452ba commit 4814e87
Show file tree
Hide file tree
Showing 168 changed files with 2,816 additions and 1,557 deletions.
5 changes: 2 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,8 @@ jobs:

### JOBS FOR on-PR-merge-to-dev PIPELINE
build-code:

docker:
- image: circleci/openjdk:11-jdk-sid
machine:
enabled: true

steps:
- checkout
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ secrets/*
.swagger_gen_dir

ocs_descriptor.pb
metrics_descriptor.pb
metrics_descriptor.pb

.Mac
*.DS_Store
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,22 @@ Mono Repository for core protocols and services around a OCS/BSS for packet data

* [The big picture (diagram) of current work-flow](https://github.com/ostelco/ostelco-docs/blob/master/the-current-work-flow.md)
* [General Documentation](./docs/README.md)
* [analytics](./analytics/README.md)
* [admin-api](./admin-api/README.md)
* [auth-server](./auth-server/README.md)
* [bq-metrics-extractor](./bq-metrics-extractor/README.md)
* [client-api](./client-api/README.md)
* [dataflow-pipelines](./dataflow-pipelines/README.md)
* [diameter-stack](./diameter-stack/README.md)
* [diameter-test](./diameter-test/README.md)
* [exporter](./exporter/README.md)
* [ocs-api](./ocs-api/README.md)
* [neo4j-store](./neo4j-store/README.md)
* [ocs-grpc-api](./ocs-grpc-api/README.md)
* [ocsgw](./ocsgw/README.md)
* [ostelco-lib](./ostelco-lib/README.md)
* [payment-processor](./payment-processor/README.md)
* [prime-client-api](./prime-client-api/README.md)
* [prime](./prime/README.md)
* [infra](./prime/infra/README.md)
* [pseudonym-server](./pseudonym-server/README.md)
* [seagull](./seagull/README.md)
* [neo4j-admin-tools](./tools/neo4j-admin-tools/README.md)
2 changes: 1 addition & 1 deletion acceptance-tests/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.71"
id "application"
id "com.github.johnrengelman.shadow" version "4.0.0"
id "com.github.johnrengelman.shadow" version "4.0.1"
}

dependencies {
Expand Down
24 changes: 23 additions & 1 deletion acceptance-tests/src/main/kotlin/org/ostelco/at/jersey/Tests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,28 @@ class SourceTest {
}
}

@Test
fun `jersey test - GET list sources no profile `() {

val email = "purchase-${randomInt()}@test.com"

try {

val sources: PaymentSourceList = get {
path = "/paymentSources"
subscriberId = email
}

assert(sources.isEmpty()) { "Expected no payment source for profile $email" }

assertNotNull(StripePayment.getCustomerIdForEmail(email)) { "Customer Id should have been created" }

} finally {
StripePayment.deleteCustomer(email = email)
}
}


@Test
fun `jersey test - PUT source set default`() {

Expand Down Expand Up @@ -358,7 +380,7 @@ class SourceTest {
}

@Test
fun `okhttp test - DELETE source`() {
fun `jersey test - DELETE source`() {

val email = "purchase-${randomInt()}@test.com"

Expand Down
21 changes: 21 additions & 0 deletions acceptance-tests/src/main/kotlin/org/ostelco/at/okhttp/Tests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,27 @@ class SourceTest {
}
}

@Test
fun `okhttp test - GET list sources no profile`() {

val email = "purchase-${randomInt()}@test.com"
try {

val client = clientForSubject(subject = email)

Thread.sleep(200)

val sources = client.listSources()

assert(sources.isEmpty()) { "Expected no payment source for profile $email" }

assertNotNull(StripePayment.getCustomerIdForEmail(email)) { "Customer Id should have been created" }

} finally {
StripePayment.deleteCustomer(email = email)
}
}

@Test
fun `okhttp test - PUT source set default`() {

Expand Down
5 changes: 4 additions & 1 deletion admin-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ plugins {

dependencies {
implementation project(":prime-modules")
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion"

implementation "javax.xml.bind:jaxb-api:$jaxbVersion"
implementation "javax.activation:activation:$javaxActivationVersion"

testImplementation project(":jersey")
testImplementation "io.dropwizard:dropwizard-testing:$dropwizardVersion"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ class AdminModule : PrimeModule {
jerseySever.register(SegmentResource())
jerseySever.register(ProductResource())
jerseySever.register(ProductClassResource())
jerseySever.register(YamlMessageBodyReader::class.java)
jerseySever.register(ImporterResource(ImportAdapter()))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package org.ostelco.prime.admin.api

import org.ostelco.prime.admin.importer.AddToSegments
import org.ostelco.prime.admin.importer.ChangeSegments
import org.ostelco.prime.admin.importer.CreateOffer
import org.ostelco.prime.admin.importer.CreateSegments
import org.ostelco.prime.admin.importer.ImportProcessor
import org.ostelco.prime.admin.importer.RemoveFromSegments
import org.ostelco.prime.admin.importer.UpdateSegments
import org.ostelco.prime.getLogger
import org.ostelco.prime.jsonmapper.asJson
import javax.ws.rs.Consumes
import javax.ws.rs.DELETE
import javax.ws.rs.POST
import javax.ws.rs.PUT
import javax.ws.rs.Path
import javax.ws.rs.core.Response


/**
* Resource used to handle the import related REST calls.
*/
@Path("/import")
class ImporterResource(private val processor: ImportProcessor) {

private val logger by getLogger()

/**
* Create new [Offer].
* Link to new or existing [Product].
* Link to new or existing [Segment].
*/
@POST
@Path("/offer")
@Consumes("text/vnd.yaml")
fun createOffer(createOffer: CreateOffer): Response {
logger.info("POST for /import/offer")
return processor.createOffer(createOffer).fold(
{ apiError -> Response.status(apiError.status).entity(asJson(apiError)) },
{ Response.status(Response.Status.CREATED) }
).build()
}

/**
* Create new [Segment].
*/
@POST
@Path("/segments")
@Consumes("text/vnd.yaml")
fun createSegment(createSegments: CreateSegments): Response {
logger.info("POST for /import/segments")

return processor.createSegments(createSegments).fold(
{ apiError -> Response.status(apiError.status).entity(asJson(apiError)) },
{ Response.status(Response.Status.CREATED) }
).build()
}

/**
* Update [Segment] - Replace all [Subscriber]s under this [Segment].
*/
@PUT
@Path("/segments")
@Consumes("text/vnd.yaml")
fun importSegment(updateSegments: UpdateSegments): Response {
logger.info("PUT for /import/segments")

return processor.updateSegments(updateSegments).fold(
{ apiError -> Response.status(apiError.status).entity(asJson(apiError)) },
{ Response.status(Response.Status.OK) }
).build()
}

/**
* Add [Subscriber]s to [Segment]
*/
@POST
@Path("/segments/subscribers")
@Consumes("text/vnd.yaml")
fun importSegment(addToSegments: AddToSegments): Response {
logger.info("POST for /import/segments/subscribers")

return processor.addToSegments(addToSegments).fold(
{ apiError -> Response.status(apiError.status).entity(asJson(apiError)) },
{ Response.status(Response.Status.OK) }
).build()
}

/**
* Remove [Subscriber]s from [Segment]
*/
@DELETE
@Path("/segments/subscribers")
@Consumes("text/vnd.yaml")
fun importSegment(removeFromSegments: RemoveFromSegments): Response {
logger.info("DELETE for /import/segments/subscribers")

return processor.removeFromSegments(removeFromSegments).fold(
{ apiError -> Response.status(apiError.status).entity(asJson(apiError)) },
{ Response.status(Response.Status.OK) }
).build()
}

/**
* Move [Subscriber]s from one [Segment] to another.
*/
@PUT
@Path("/segments/subscribers")
@Consumes("text/vnd.yaml")
fun importSegment(changeSegments: ChangeSegments): Response {
logger.info("PUT for /import/segments/subscribers")

return processor.changeSegments(changeSegments).fold(
{ apiError -> Response.status(apiError.status).entity(asJson(apiError)) },
{ Response.status(Response.Status.OK) }
).build()
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,63 @@

package org.ostelco.prime.admin.importer

import arrow.core.Either
import org.ostelco.prime.apierror.ApiError
import org.ostelco.prime.apierror.ApiErrorCode
import org.ostelco.prime.apierror.BadRequestError
import org.ostelco.prime.model.Offer
import org.ostelco.prime.model.Segment
import org.ostelco.prime.module.getResource
import org.ostelco.prime.storage.AdminDataSource

interface ImportProcessor {
fun import(importDeclaration: ImportDeclaration): Either<ApiError, Unit>
fun createOffer(createOffer: CreateOffer): Either<ApiError, Unit>
fun createSegments(createSegments: CreateSegments): Either<ApiError, Unit>
fun updateSegments(updateSegments: UpdateSegments): Either<ApiError, Unit>
fun addToSegments(addToSegments: AddToSegments): Either<ApiError, Unit>
fun removeFromSegments(removeFromSegments: RemoveFromSegments): Either<ApiError, Unit>
fun changeSegments(changeSegments: ChangeSegments): Either<ApiError, Unit>
}

class ImportAdapter : ImportProcessor {

private val adminDataStore by lazy { getResource<AdminDataSource>() }

override fun import(importDeclaration: ImportDeclaration): Either<ApiError, Unit> {
override fun createOffer(createOffer: CreateOffer): Either<ApiError, Unit> {
return adminDataStore.atomicCreateOffer(
offer = createOffer.createOffer.let {
Offer(id = it.id, segments = it.existingSegments, products = it.existingProducts)
},
products = createOffer.createOffer.createProducts,
segments = createOffer.createOffer.createSegments)
.mapLeft { BadRequestError(it.message, ApiErrorCode.FAILED_TO_IMPORT_OFFER) }
}

return adminDataStore.atomicImport(
offer = importDeclaration.offer,
products = importDeclaration.products,
segments = importDeclaration.segments)
override fun createSegments(createSegments: CreateSegments): Either<ApiError, Unit> {
return adminDataStore.atomicCreateSegments(createSegments = createSegments.createSegments)
.mapLeft { BadRequestError(it.message, ApiErrorCode.FAILED_TO_IMPORT_OFFER) }
}
}

override fun updateSegments(updateSegments: UpdateSegments): Either<ApiError, Unit> {
return adminDataStore.atomicUpdateSegments(
updateSegments = updateSegments.updateSegments.map { Segment(id = it.id, subscribers = it.subscribers) }
).mapLeft { BadRequestError(it.message, ApiErrorCode.FAILED_TO_IMPORT_OFFER) }
}

override fun addToSegments(addToSegments: AddToSegments): Either<ApiError, Unit> {
return adminDataStore.atomicAddToSegments(
addToSegments = addToSegments.addToSegments.map { Segment(id = it.id, subscribers = it.subscribers) }
).mapLeft { BadRequestError(it.message, ApiErrorCode.FAILED_TO_IMPORT_OFFER) }
}

override fun removeFromSegments(removeFromSegments: RemoveFromSegments): Either<ApiError, Unit> {
return adminDataStore.atomicRemoveFromSegments(
removeFromSegments = removeFromSegments.removeFromSegments.map { Segment(id = it.id, subscribers = it.subscribers) }
).mapLeft { BadRequestError(it.message, ApiErrorCode.FAILED_TO_IMPORT_OFFER) }
}

override fun changeSegments(changeSegments: ChangeSegments): Either<ApiError, Unit> {
return adminDataStore.atomicChangeSegments(changeSegments = changeSegments.changeSegments)
.mapLeft { BadRequestError(it.message, ApiErrorCode.FAILED_TO_IMPORT_OFFER) }
}
}
Loading

0 comments on commit 4814e87

Please sign in to comment.