-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[MBL-736] Upgrade PerimeterX #1839
Conversation
KsApi/GraphAPI.swift
Outdated
@@ -578,182 +578,6 @@ public enum GraphAPI { | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file gets re-gened every time KsAPI
is rebuilt, so can't avoid it being a change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we might consider putting this in our .gitignore to avoid confusion. We intentionally update this file as needed, when we support a new mutation for example. is there a reason we need to update this file on every build?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, yea it can get a little hairy if the intention is to leave out updating the graph schema.
The web folks are pretty good at honouring the API contract, which they have checks for.
The app will rarely fail a build because the schema doesn't match our side.
The two scenarios are:
- Breaking change - we have to update our app anyway.
- Non breaking change - we can assume the backward compatibility checks web folks have done are enough.
Problem with putting it in .gitignore
is we have to take it out every time we look for a GQL change.
Also we kind of want to know if the schema changes immediately. We can choose not to commit it - but then we'd be out of sync with the latest API's.
My thinking is - keep it the way it is - investigate the schema change, if it happens. If it's breaking especially. Otherwise trust the web folks to support our mobile side.
Codecov Report
@@ Coverage Diff @@
## main #1839 +/- ##
==========================================
- Coverage 84.54% 84.52% -0.02%
==========================================
Files 1274 1271 -3
Lines 115279 115144 -135
Branches 30698 30657 -41
==========================================
- Hits 97458 97323 -135
- Misses 16752 16755 +3
+ Partials 1069 1066 -3
... and 1 file with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
@@ -219,6 +219,12 @@ internal final class AppDelegate: UIResponder, UIApplicationDelegate { | |||
.messageBannerViewController?.showBanner(with: success ? .success : .error, message: message) | |||
} | |||
|
|||
self.viewModel.outputs.configurePerimeterX | |||
.observeValues { | |||
AppEnvironment.current.apiService.perimeterXClient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now where we call start
on PerimeterX, not in Service
. Thinking is more along the lines of their official instructions (Step 5). Although the SDK instructions explicitly say to "You should only call this function once" and appDidFinishLaunchingWithOptions
is called on every relaunch.
Some ambiguity there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The instructions also say "It's essential to call this function as early as possible in your application and before any URL request to your server" so this should be fine. I feel like they meant to say "only call this function once per app launch" 🤷🏻♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok makes sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused about what's going on here, so I don't want to approve and have my approval mean something. But in general, looks good! I left one comment on a section that feels incomplete to me, but feel free to ignore if I'm wrong.
…int statements for PerimeterX captcha state. Also removed the fatalError.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Followed the implementation steps in the docs and this all makes sense to me. App builds and tests pass. Did some general QA as well and everything seems fine 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took another pass at this and I think the handleError
being renamed to handleResponse
makes some of the comments unclear. I also don't know if the boolean means the same thing now as it did previously, and since I'm not sure how easy that's to test/catch, I wanted to bring it up so you could look into it, if you haven't already.
Given a URL Response and data, this method will allow for custom error handling logic. | ||
|
||
- parameter response: An `HTTPURLResponse` object with response data from a request. | ||
- parameter data: Data` associated with the request | ||
- parameter data: `Data` associated with the request | ||
- parameter response: An `URLResponse` object with response data from a request. | ||
|
||
- returns: A boolean indicating whether or not the error was handled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does handleResponse
actually do now? And what does the boolean mean? Since this is mostly done for us by PerimeterX, I think it'd be useful to have a more up-to-date comment here. Specifically, the returns
refers to "the error" when nothing in the function or parameter names indicates what that error is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well this is meant to be more of a wrapper around any error handling (ie. ErrorHandler
) for a URLRequest
. We use PerimeterX now but in the future if we changed to another captcha sheet provider or any URLRequest
with error handling - this is still a useful method of dependency injection.
Comment is left generic on purpose because it might not always be PerimeterX
we handle errors for.
KsApi/extensions/NSURLSession.swift
Outdated
@@ -35,7 +35,8 @@ internal extension URLSession { | |||
guard let response = response as? HTTPURLResponse else { fatalError() } | |||
|
|||
/// `error` is `nil` or `handleError` returns `false`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another outdated comment referring to handleError
- please update. Also, in this comment, can you expand on why we want to process the response when the SDK couldn't handle the response? I would've expected that to be a failure state and the true
to be a continue state, but I'll admit I don't think the documentation is very clear here. It's also very possible that true
indicates that the error is fully handled and we don't need to do anything else. Is this something you've been able to test (where the error is non-nil)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I'm going to delete the inline comment because I don' think we need it.
In fact - we generally don't write comments in line unless its' /// TODO:
or /// FIXME:
This was just something left in from the previous implementation that doesn't provide much clarity.
📲 What
Dependency is 2 major versions back (
1.16.3
->3.0.4
) so probably should be upgraded.🤔 Why
We were having login issues related to PerimeterX hopefully this upgrade solves those. We no longer manually launch the PX captcha sheet like in
1.16.3
(seegoToPerimeterXCaptcha
inAppDelegate
below).3.0.4
should take care of it automatically.This seemed like the issue causing our login button to not work.
🛠 How
Used the simpler PerimeterX upgrade documentation here and the work done on this older, closed pr.
Was able to reliably to show the captcha sheet on any REST call with these headers: (Solution Architect at PX provided this to us)
However, this isn't necessary to do on
xauth
or any other REST call, because PerimeterX has two modes monitor mode and enforce mode.We can enforce PerimeterX to fully validate each request from the Cloudflare worker.
Suggestion to @kickstarter/infrastructure was to add
xauth/access_token
topx_enforced_routes
to ensure that route shows captcha (at least on mobile).Either way - this boils down to an framework upgrade plain and simple. No extra customization required, let the Captcha sheet show if the SDK decides to.
There's some good cleanup happening as well, with the new SDK instructions which make this implementation much simpler:
Removed:
PerimeterXBlockResponseType
PerimeterXManagerType
PXManagerDelegate
KsAPINotification
PerimeterXClientTests
was also removed, reason being we usePerimeterXClient
class to wrap the actual SDK, there's no protocol in between to mock. We don't want to be testing the actual SDK.✅ Acceptance criteria
⏰ TODO