Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve zuora/salesforce identity id backfill #213

Merged
merged 4 commits into from
Nov 15, 2018
Merged

Conversation

QuarpT
Copy link
Contributor

@QuarpT QuarpT commented Nov 14, 2018

Work done:

  • If an identity user has an unvalidated email and they have no password then we can use this identity id in the backfill
  • statusFields optional in identity response - not all users have status fields

Why are we doing this:

Increase the number of users backfilled with existing accounts.

@coveralls
Copy link

coveralls commented Nov 14, 2018

Pull Request Test Coverage Report for Build 600

  • 21 of 26 (80.77%) changed or added relevant lines in 5 files are covered.
  • 2 unchanged lines in 2 files lost coverage.
  • Overall coverage increased (+0.3%) to 71.112%

Changes Missing Coverage Covered Lines Changed/Added Lines %
handlers/identity-backfill/src/main/scala/com/gu/identity/GetByIdentityId.scala 7 8 87.5%
handlers/identity-backfill/src/main/scala/com/gu/identityBackfill/Handler.scala 2 6 33.33%
Files with Coverage Reduction New Missed Lines %
lib/restHttp/src/main/scala/com/gu/util/resthttp/RestRequestMaker.scala 1 69.49%
handlers/identity-backfill/src/main/scala/com/gu/identityBackfill/Handler.scala 1 79.55%
Totals Coverage Status
Change from base Build 560: 0.3%
Covered Lines: 1669
Relevant Lines: 2347

💛 - Coveralls

@@ -13,14 +13,17 @@ object GetByEmail {

sealed trait IdentityAccount
case class IdentityAccountWithValidatedEmail(identityId: IdentityId) extends IdentityAccount
case object IdentityAccountWithUnvalidatedEmail extends IdentityAccount
case class IdentityAccountWithUnvalidatedEmail(identityId: IdentityId) extends IdentityAccount
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the identity id exists on all possibilities, just move it up a level and make both of these into a case object (effectively becomes a boolean with a better name)

Copy link
Contributor Author

@QuarpT QuarpT Nov 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean by 'move identity id up a level'
I think a single case class

case class IdentityAccount(id: IdentityId, userEmailValidated: Boolean)

would be sufficient

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah you're right.... boolean makes more sense than keeping the specially named trait


object RawWireModel {

case class StatusFields(userEmailValidated: Boolean)
implicit val statusFieldsReads: Reads[StatusFields] = Json.reads[StatusFields]

case class User(id: String, statusFields: StatusFields)
case class User(id: String, statusFields: Option[StatusFields]) {
val isUserEmailValidated: Boolean = statusFields.exists(_.userEmailValidated)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a big difference, but I tried to move towards keeping the wire and domain models clean, and put all the conversion code in the separate wireToDomainModel function. This does apply to varying degress in the older lambdas though!

""".stripMargin
val actual = GetByIdentityId.wrapper.toNewResponse(Json.parse(identityResponse))
actual should be(ClientSuccess(IdentityUser(IdentityId("1234"), hasPassword = false)))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great, nice clear tests!

case ClientSuccess(IdentityAccountWithUnvalidatedEmail) => ReturnWithResponse(ApiGatewayResponse.notFound("identity email not validated"))
case other: ClientFailure => ReturnWithResponse(ApiGatewayResponse.internalServerError(other.toString))
}).withLogging("GetByEmail")
maybeExistingIdentityId <- findExistingIdentityId(getByEmail, getByIdentityId, emailAddress)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion to make it simpler/easier to test:

currently getByEmail and getByIdentityId are passed into PreReqCheck and then directly onto findExistingIdentityId. This gives PreReqCheck extra parameters it doesn't need so harder to test.
My suggestion would be to partially apply findExistingIdentityId in the wiring stage i.e. Handler on line 72, and then pass it into PreReqCheck as something like EmailAddress => ApiGatewayOp[Option[IdentityId]]
This means they can be tested separately which should help and it avoids PreReqCheck becoming all knowing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can do

@johnduffell
Copy link
Member

looks great, the main comments would be moving up the identity id field a level and simplifying the parameters of PreReqCheck and testing the new function separately. These are important because they are keeping the structure of the program simple as the code changes.

@@ -150,4 +131,45 @@ class PreReqCheckTest extends FlatSpec with Matchers {
PreReqCheck.acceptableReaderType(ClientSuccess(readerTypes)).toDisjunction.leftMap(_.statusCode) should be(scalaz.-\/("404"))
}

"findExistingIdentityId" should "continue processing with identity id for existing validated account" in {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep much better with the tests split up, thanks

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my comment about the new function is there's no need to bundle these new tests in the same file as the existing ones. It would be more decoupled to put findExistingIdentityId in its own file and same goes for the tests.

Copy link
Member

@johnduffell johnduffell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a small comment about physically splitting out the long test as wel as the new function if you have time, but the dependencies and types look good, thanks

@QuarpT QuarpT merged commit f8cd1c8 into master Nov 15, 2018
@QuarpT QuarpT deleted the improve-backfill branch November 15, 2018 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants