Skip to content

Commit

Permalink
[keyserver][native] Fix invite links setup
Browse files Browse the repository at this point in the history
Summary:
Our invite link url is `https://comm.app/invite/:secret`.

In our prod setup, we forward all the traffic from `comm.app` to `localhost:3000/commlanding`, which means that our invite link gets replaced by `localhost:3000/commlanding/invite/:secret` and that means that we should handle this route in landing router. It doesn't hurt to also support it in web router - `/invite/:secret` gets replaced later by `/handle/invite/:secret`, so it doesn't cause any issue, but has a benefit that in some other configs would still work.

In `inviteResponder` for web, we were assuming that the route is handled by web router. This is no longer the case, and we have to explicitly forward to web url.

The final issue was that, our invite links for iOS and Android were configured for `web.comm.app` domain instead of `comm.app`. This requires updating `inviteResponder` for iOS (as there's a link url), and `Comm.entitlements`. In order to avoid redirecting all the traffic from `comm.app` to the mobile app, we have to introduce some filtering: for iOS, we modify AASA file to only handle `/invite` route. For Android, we set `pathPrefix` in Manifest.

https://linear.app/comm/issue/ENG-4089/invite-links-dont-work-on-prod

Test Plan:
Some changes can't be tested yet, as we have to update `.well-known` files on server for the deep links on native to be updated.
The part with `landing` was tested by checking if accessing `/commlanding/invite/:secret` results in web app `/handle/invite/:secret` route being accessed.

Reviewers: bartek, kamil, inka

Reviewed By: kamil

Subscribers: ashoat

Differential Revision: https://phab.comm.dev/D8255
  • Loading branch information
palys-swm committed Jun 26, 2023
1 parent bd5f5b2 commit b062e65
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 12 deletions.
4 changes: 2 additions & 2 deletions keyserver/.well-known/apple-app-site-association
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
"appIDs": [ "H98Y8MH53M.app.comm" ],
"components": [
{
"/": "*"
"/": "/invite/*"
}
]
},
{
"appID": "H98Y8MH53M.app.comm",
"paths": [ "*" ]
"paths": [ "/invite/*" ]
}
]
}
Expand Down
8 changes: 3 additions & 5 deletions keyserver/src/keyserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ import {
downloadHandler(uploadDownloadResponder),
);

router.get('/invite/:secret', inviteResponder);

// $FlowFixMe express-ws has side effects that can't be typed
router.ws('/ws', onConnection);
router.get('/worker/:worker', webWorkerResponder);
Expand All @@ -127,15 +129,11 @@ import {
// and prevent commAppRouter and landingRouter from working correctly. So we
// make sure that squadCalRouter goes last

// This endpoint should be handled by the mobile app. If the server
// receives this request, it means that the app is not installed and we
// should redirect the user to a place from which the app can be
// downloaded. It's important to define it before any other router so that
// it won't get handled by e.g. `/` rule.
server.get('/invite/:secret', inviteResponder);

if (landingBaseRoutePath) {
const landingRouter = express.Router();
landingRouter.get('/invite/:secret', inviteResponder);
landingRouter.use('/images', express.static('images'));
landingRouter.use('/fonts', express.static('fonts'));
landingRouter.use(
Expand Down
13 changes: 10 additions & 3 deletions keyserver/src/responders/website-responders.js
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,8 @@ async function websiteResponder(

const inviteSecretRegex = /^[a-z0-9]+$/i;

// On native, if this responder is called, it means that the app isn't
// installed.
async function inviteResponder(req: $Request, res: $Response): Promise<void> {
const { secret } = req.params;
const userAgent = req.get('User-Agent');
Expand All @@ -624,8 +626,10 @@ async function inviteResponder(req: $Request, res: $Response): Promise<void> {
res.end();
return;
} else if (detectionResult.os !== 'iOS') {
const baseRoutePath = getCommAppURLFacts()?.baseRoutePath;
const redirectUrl = `${baseRoutePath ?? '/'}handle/invite/${secret}`;
const urlFacts = getCommAppURLFacts();
const baseDomain = urlFacts?.baseDomain ?? '';
const basePath = urlFacts?.basePath ?? '/';
const redirectUrl = `${baseDomain}${basePath}handle/invite/${secret}`;
res.writeHead(301, {
Location: redirectUrl,
});
Expand Down Expand Up @@ -780,7 +784,10 @@ async function inviteResponder(req: $Request, res: $Response): Promise<void> {
<div class="separator"></div>
<section class="buttons">
<a class="button" href="${stores.appStoreUrl}">Download Comm</a>
<a class="button secondary" href="/invite/${secret}">
<a
class="button secondary"
href="https://comm.app/invite/${secret}"
>
Invite Link
</a>
</section>
Expand Down
4 changes: 3 additions & 1 deletion native/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@

<data
android:scheme="https"
android:host="web.comm.app" />
android:host="comm.app"
android:pathPrefix="/invite"
/>
</intent-filter>
</activity>
<activity
Expand Down
2 changes: 1 addition & 1 deletion native/ios/Comm/Comm.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:web.comm.app</string>
<string>applinks:comm.app</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
Expand Down

0 comments on commit b062e65

Please sign in to comment.