[web] Remove hardcoded URLs

Museum now supports configuring the URL that the clients should use for cast,
accounts (passkeys) and families portal.

If you're using the old method (which was only supported by the web app, unlike
the new method which is supported by both mobile and web, and also for cast) of
configuring the custom environment variables, then you should instead use the
corresponding setting in the museum configuration:

- NEXT_PUBLIC_ENTE_ACCOUNTS_URL => apps.account
- NEXT_PUBLIC_ENTE_FAMILY_URL => apps.family

Reference: [apps block in
local.yaml](fe2771f2e0/server/configurations/local.yaml (L75-L89))
This commit is contained in:
Manav Rathi 2025-01-01 14:03:53 +05:30
parent 65a92f1a77
commit 9910049d1d
No known key found for this signature in database
10 changed files with 53 additions and 87 deletions

View File

@ -5,5 +5,3 @@
#NEXT_PUBLIC_ENTE_ENDPOINT = http://localhost:8080
#NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT = http://localhost:3002
#NEXT_PUBLIC_ENTE_ACCOUNTS_URL = http://localhost:3001
#NEXT_PUBLIC_ENTE_PAYMENTS_URL = http://localhost:3001

View File

@ -20,9 +20,10 @@ Add the following to `web/apps/photos/.env.local`:
```env
NEXT_PUBLIC_ENTE_ENDPOINT = http://localhost:8080
NEXT_PUBLIC_ENTE_PAYMENTS_URL = http://localhost:3001
```
Modify "https://payments.ente.io" to "http://localhost:3001".
Then start it locally
```sh

View File

@ -34,21 +34,13 @@
#
# Note that even in development build, the app still connects to the production
# APIs by default (can be customized using the env vars below). This is usually
# a good default, for example a customer cloning this repository want to build
# and run the client from source but still use their actual Ente account.
# a good default, for example a customer cloning this repository would want to
# build and run the client from source but still use their actual Ente account.
# The Ente API endpoint
#
# NEXT_PUBLIC_ENTE_ENDPOINT = http://localhost:3000
# The URL of the accounts app
#
# NEXT_PUBLIC_ENTE_ACCOUNTS_URL = http://localhost:3001
# The URL of the payments app
#
# NEXT_PUBLIC_ENTE_PAYMENTS_URL = http://localhost:3001
# The URL for the shared albums deployment
#
# The shared albums are served from the photos app code, and "albums.ente.io" is
@ -69,16 +61,6 @@
#
# NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT = http://localhost:3002
# The URL of the family plans web app
#
# Currently the source code for the family plan related pages is in a separate
# repository (https://github.com/ente-io/families). The mobile app also uses
# these pages.
#
# Enhancement: Consider moving that into the app/ folder in this repository.
#
# NEXT_PUBLIC_ENTE_FAMILY_URL = http://localhost:3001
# The JSON which describes the expected results of our integration tests. See
# `upload.test.ts` for more details of the expected format.
#

View File

@ -18,14 +18,3 @@
# - `yarn dev:albums` (the sidecar app, in this case, albums)
#NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT = http://localhost:3002
# We also have various sidecar apps. These all run on a separate port, 3001,
# since usually when developing we usually need to run only one of them in
# addition to the main photos app. So you can uncomment this entire set.
#
# You'll also need to create a similar `.env.local` or `.env.development.local`
# in the app you're running (e.g. in apps/accounts), and put an
# `NEXT_PUBLIC_ENTE_ENDPOINT` in there.
#NEXT_PUBLIC_ENTE_ACCOUNTS_URL = http://localhost:3001
#NEXT_PUBLIC_ENTE_PAYMENTS_URL = http://localhost:3001

View File

@ -8,11 +8,12 @@
],
"scripts": {
"build": "yarn build:photos",
"build:accounts": "yarn workspace accounts next build",
"build:auth": "yarn workspace auth next build",
"build:cast": "yarn workspace cast next build",
"build:payments": "yarn workspace payments build",
"build:photos": "yarn workspace photos next build",
"build-prep": "packages/build-config/build-prep.sh",
"build:accounts": "yarn build-prep && yarn workspace accounts next build",
"build:auth": "yarn build-prep && yarn workspace auth next build",
"build:cast": "yarn build-prep && yarn workspace cast next build",
"build:payments": "yarn build-prep && yarn workspace payments build",
"build:photos": "yarn build-prep && yarn workspace photos next build",
"dev": "yarn dev:photos",
"dev:accounts": "yarn workspace accounts next dev -p 3001",
"dev:albums": "yarn workspace photos next dev -p 3002",

View File

@ -9,8 +9,7 @@ import {
publicRequestHeaders,
} from "@/base/http";
import log from "@/base/log";
import { accountsAppOrigin, apiURL } from "@/base/origins";
import { nullToUndefined } from "@/utils/transform";
import { apiURL } from "@/base/origins";
import { getRecoveryKey } from "@ente/shared/crypto/helpers";
import HTTPService from "@ente/shared/network/HTTPService";
import {
@ -30,14 +29,14 @@ import { unstashRedirect } from "./redirect";
* On successful verification, the accounts app will redirect back to our
* `/passkeys/finish` page.
*
* @param accountsURL Base URL for the accounts app (provided to us by remote in
* @param accountsURL The URL for the accounts app (provided to us by remote in
* the email or SRP verification response).
*
* @param passkeySessionID An identifier provided by museum for this passkey
* verification session.
*/
export const passkeyVerificationRedirectURL = (
accountsURL: string | undefined,
accountsURL: string,
passkeySessionID: string,
) => {
const clientPackage = clientPackageName;
@ -55,8 +54,7 @@ export const passkeyVerificationRedirectURL = (
redirect,
...recoverOption,
});
const baseURL = accountsURL ?? accountsAppOrigin();
return `${baseURL}/passkeys/verify?${params.toString()}`;
return `${accountsURL}/passkeys/verify?${params.toString()}`;
};
interface OpenPasskeyVerificationURLOptions {
@ -134,11 +132,11 @@ export const openAccountsManagePasskeysPage = async () => {
// Redirect to the Ente Accounts app where they can view and add and manage
// their passkeys.
const remoteParams = await getAccountsTokenAndURL();
const params = new URLSearchParams({ token: remoteParams.accountsToken });
const baseURL = remoteParams.accountsUrl ?? accountsAppOrigin();
const { accountsToken: token, accountsUrl: accountsURL } =
await getAccountsTokenAndURL();
const params = new URLSearchParams({ token });
window.open(`${baseURL}/passkeys?${params.toString()}`);
window.open(`${accountsURL}/passkeys?${params.toString()}`);
};
export const isPasskeyRecoveryEnabled = async () => {
@ -207,8 +205,10 @@ const getAccountsTokenAndURL = async () => {
ensureOk(res);
return z
.object({
// The origin that serves the accounts app.
accountsUrl: z.string(),
// A token that can be used to autheticate with the accounts app.
accountsToken: z.string(),
accountsUrl: z.string().nullish().transform(nullToUndefined),
})
.parse(await res.json());
};

View File

@ -21,7 +21,7 @@ export interface UserVerificationResponse {
* Base URL for the accounts app where we should redirect to for passkey
* verification.
*/
accountsUrl?: string | undefined;
accountsUrl: string;
passkeySessionID?: string | undefined;
/**
* If both passkeys and TOTP based two factors are enabled, then {@link
@ -164,7 +164,7 @@ export const EmailOrSRPAuthorizationResponse = z.object({
passkeySessionID: z.string().nullish().transform(nullToUndefined),
// Base URL for the accounts app where we should redirect to for passkey
// verification.
accountsUrl: z.string().nullish().transform(nullToUndefined),
accountsUrl: z.string(),
twoFactorSessionID: z.string().nullish().transform(nullToUndefined),
// TwoFactorSessionIDV2 is only set if user has both passkey and two factor
// enabled. This is to ensure older clients keep using passkey flow when

View File

@ -75,16 +75,6 @@ export const customAPIHost = async () => {
export const uploaderOrigin = async () =>
(await customAPIOrigin()) ?? "https://uploader.ente.io";
/**
* Return the origin that serves the accounts app.
*
* Defaults to our production instance, "https://accounts.ente.io", but can be
* overridden by setting the `NEXT_PUBLIC_ENTE_ACCOUNTS_URL` environment
* variable.
*/
export const accountsAppOrigin = () =>
process.env.NEXT_PUBLIC_ENTE_ACCOUNTS_URL ?? `https://accounts.ente.io`;
/**
* Return the origin that serves public albums.
*
@ -94,22 +84,3 @@ export const accountsAppOrigin = () =>
*/
export const albumsAppOrigin = () =>
process.env.NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT ?? "https://albums.ente.io";
/**
* Return the origin that serves the family dashboard which can be used to
* create or manage family plans..
*
* Defaults to our production instance, "https://family.ente.io", but can be
* overridden by setting the `NEXT_PUBLIC_ENTE_FAMILY_URL` environment variable.
*/
export const familyAppOrigin = () =>
process.env.NEXT_PUBLIC_ENTE_FAMILY_URL ?? "https://family.ente.io";
/**
* Return the origin that serves the payments app.
*
* Defaults to our production instance, "https://payments.ente.io", but can be
* overridden by setting the `NEXT_PUBLIC_ENTE_PAYMENTS_URL` environment variable.
*/
export const paymentsAppOrigin = () =>
process.env.NEXT_PUBLIC_ENTE_PAYMENTS_URL ?? "https://payments.ente.io";

View File

@ -0,0 +1,19 @@
#!/bin/sh
# Fail the build if the user is setting any of the legacy environment variables
# which have now been replaced with museum configuration. This is meant to help
# self hosters find the new setting instead of being caught unawares.
if test -n "$NEXT_PUBLIC_ENTE_ACCOUNTS_URL"
then
echo "The NEXT_PUBLIC_ENTE_ACCOUNTS_URL environment variable is not supported."
echo "Use apps.accounts in the museum configuration instead."
exit 1
fi
if test -n "$NEXT_PUBLIC_ENTE_FAMILY_URL"
then
echo "The NEXT_PUBLIC_ENTE_FAMILY_URL environment variable is not supported."
echo "Use apps.family in the museum configuration instead."
exit 1
fi

View File

@ -1,7 +1,7 @@
import { isDesktop } from "@/base/app";
import { authenticatedRequestHeaders, ensureOk } from "@/base/http";
import { getKV, setKV } from "@/base/kv";
import { apiURL, familyAppOrigin, paymentsAppOrigin } from "@/base/origins";
import { apiURL } from "@/base/origins";
import {
nullishToEmpty,
nullishToZero,
@ -367,6 +367,8 @@ export const cancelStripeSubscription = async () => {
return syncUserDetails();
};
const paymentsAppOrigin = "https://payments.ente.io";
/**
* Start the flow to purchase or update a subscription by redirecting the user
* to the payments app.
@ -381,7 +383,7 @@ export const redirectToPaymentsApp = async (
) => {
const paymentToken = await getPaymentToken();
const redirectURL = paymentCompletionRedirectURL();
window.location.href = `${paymentsAppOrigin()}?productID=${productID}&paymentToken=${paymentToken}&action=${action}&redirectURL=${redirectURL}`;
window.location.href = `${paymentsAppOrigin}?productID=${productID}&paymentToken=${paymentToken}&action=${action}&redirectURL=${redirectURL}`;
};
/**
@ -390,7 +392,7 @@ export const redirectToPaymentsApp = async (
*/
const paymentCompletionRedirectURL = () =>
isDesktop
? `${paymentsAppOrigin()}/desktop-redirect`
? `${paymentsAppOrigin}/desktop-redirect`
: `${window.location.origin}/gallery`;
/**
@ -511,8 +513,7 @@ export const getFamilyPortalRedirectURL = async () => {
userDetails && isPartOfFamily(userDetails) ? "true" : "false";
const redirectURL = `${window.location.origin}/gallery`;
const params = new URLSearchParams({ token, isFamilyCreated, redirectURL });
const baseURL = familiesURL ?? familyAppOrigin();
return `${baseURL}?${params.toString()}`;
return `${familiesURL}?${params.toString()}`;
};
/**
@ -526,8 +527,12 @@ const getFamiliesTokenAndURL = async () => {
ensureOk(res);
return z
.object({
// The origin that serves the family dashboard which can be used to
// create or manage family plans.
familyUrl: z.string(),
// A token that can be used to authenticate with the family
// dashboard.
familiesToken: z.string(),
familyUrl: z.string().nullish().transform(nullToUndefined),
})
.parse(await res.json());
};