diff --git a/.github/workflows/web-deploy-payments.yml b/.github/workflows/web-deploy-payments.yml new file mode 100644 index 0000000000..c428d88bc2 --- /dev/null +++ b/.github/workflows/web-deploy-payments.yml @@ -0,0 +1,43 @@ +name: "Deploy (payments)" + +on: + push: + # Run workflow on pushes to the deploy/payments + branches: [deploy/payments] + +jobs: + deploy: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: web + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup node and enable yarn caching + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "yarn" + cache-dependency-path: "docs/yarn.lock" + + - name: Install dependencies + run: yarn install + + - name: Build payments + run: yarn build:payments + + - name: Publish payments + uses: cloudflare/pages-action@1 + with: + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + projectName: ente + branch: deploy/payments + directory: web/apps/payments/out + wranglerVersion: "3" diff --git a/.github/workflows/web-nightly.yml b/.github/workflows/web-nightly.yml index a800a4b736..89d5ecaa5c 100644 --- a/.github/workflows/web-nightly.yml +++ b/.github/workflows/web-nightly.yml @@ -78,6 +78,19 @@ jobs: directory: web/apps/cast/out wranglerVersion: "3" + - name: Build payments + run: yarn build:payments + + - name: Publish payments + uses: cloudflare/pages-action@1 + with: + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + projectName: ente + branch: n-payments + directory: web/apps/payments/out + wranglerVersion: "3" + - name: Build photos run: yarn build:photos env: diff --git a/.github/workflows/web-preview.yml b/.github/workflows/web-preview.yml index 4e86d9a816..2ad73b7a1f 100644 --- a/.github/workflows/web-preview.yml +++ b/.github/workflows/web-preview.yml @@ -12,6 +12,7 @@ on: - "accounts" - "auth" - "cast" + - "payments" - "photos" jobs: diff --git a/server/compose.yaml b/server/compose.yaml index 6972fc364c..a7d5a2c39e 100644 --- a/server/compose.yaml +++ b/server/compose.yaml @@ -17,6 +17,7 @@ services: - custom-logs:/var/logs - ./museum.yaml:/museum.yaml:ro - ./scripts/compose/credentials.yaml:/credentials.yaml:ro + - ./data:/data:ro networks: - internal diff --git a/web/apps/payments/README.md b/web/apps/payments/README.md index 568437afde..e01a8b1f92 100644 --- a/web/apps/payments/README.md +++ b/web/apps/payments/README.md @@ -3,28 +3,55 @@ Stripe's API for payments. ## Development -If you're running this to test out the payment flows end-to-end, please do a -`yarn build`, that will place the output within the `out` folder. +There are three pieces that need to be connected to have a working local setup: -Then use any tool to serve this over HTTP. For example, `python3 -m http.server -3001` will serve this directory over port `3001`. +- A client app +- This web app +- Museum -Aside that, these are the necessary configuration changes. +### Client app -### Local configuration +For the client, let us consider the Photos web app (similar configuration can be +done in the mobile client too). -Create an `.env` in this directory to point to the local museum instance, and to -define the necessary Stripe keys that can be fetched from [Stripe's developer +Add the following to `web/apps/photos/.env.local`: + +```env +NEXT_PUBLIC_ENTE_ENDPOINT = http://localhost:8080 +NEXT_PUBLIC_ENTE_PAYMENTS_ENDPOINT = http://localhost:3001 +``` +Then start it locally + +```sh +yarn dev:photos +``` + +This tells it to connect to the museum and payments app running on localhost. + +> For connecting from the mobile app, you'll need to run museum on a local IP +> instead localhost. If so, just replace "http://localhost:8080" with (say) +> "http://192.168.1.2:8080" wherever mentioned. + +### Payments app + +For this (payments) web app, configure it to connect to the local museum, and +use a set of (development) Stripe keys which can be found in [Stripe's developer dashboard](https://dashboard.stripe.com). -Assuming that your local museum instance is running on `192.168.1.2:8080`, your -`.env` should look as follows. +Add the following to +`web/apps/payments/.env.local` -``` -NEXT_PUBLIC_ENTE_ENDPOINT = http://192.168.1.2:8080 +```env +NEXT_PUBLIC_ENTE_ENDPOINT = http://localhost:8080 NEXT_PUBLIC_STRIPE_US_PUBLISHABLE_KEY = stripe_publishable_key ``` +Then start it locally + +```sh +yarn dev:payments +``` + ### Museum 1. Install the [stripe-cli](https://docs.stripe.com/stripe-cli) and capture the @@ -33,18 +60,32 @@ NEXT_PUBLIC_STRIPE_US_PUBLISHABLE_KEY = stripe_publishable_key 2. Define this secret within your `musuem.yaml` 3. Update the `whitelisted-redirect-urls` so that it supports redirecting to - this locally running project. + the locally running payments app. -Assuming that your local payments app is running on `192.168.1.2:3001`, your -`museum.yaml` should look as follows. +Assuming that your local payments app is running on `localhost:3001`, your +`server/museum.yaml` should look as follows. ```yaml stripe: us: key: stripe_dev_key webhook-secret: stripe_dev_webhook_secret - whitelisted-redirect-urls: ["http://192.168.1.2:3001/frameRedirect"] + whitelisted-redirect-urls: ["http://localhost:3000/gallery", "http://192.168.1.2:3001/frameRedirect"] path: success: ?status=success&session_id={CHECKOUT_SESSION_ID} cancel: ?status=fail&reason=canceled ``` + +Make sure you have test plans available for museum to use, by placing them in +(say) `server/data/billing/us-testing.json`. + +Finally, start museum, for example: + +``` +docker compose up +``` + +Now if you try to purchase a plan from your locally running photos web client, +it should redirect to the locally running payments app, and from there to +Stripe. Once the test purchase completes it should redirect back to the local +web client. diff --git a/web/apps/payments/public/fonts/UFL.txt b/web/apps/payments/public/fonts/UFL.txt deleted file mode 100644 index 6e722c88da..0000000000 --- a/web/apps/payments/public/fonts/UFL.txt +++ /dev/null @@ -1,96 +0,0 @@ -------------------------------- -UBUNTU FONT LICENCE Version 1.0 -------------------------------- - -PREAMBLE -This licence allows the licensed fonts to be used, studied, modified and -redistributed freely. The fonts, including any derivative works, can be -bundled, embedded, and redistributed provided the terms of this licence -are met. The fonts and derivatives, however, cannot be released under -any other licence. The requirement for fonts to remain under this -licence does not require any document created using the fonts or their -derivatives to be published under this licence, as long as the primary -purpose of the document is not to be a vehicle for the distribution of -the fonts. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this licence and clearly marked as such. This may -include source files, build scripts and documentation. - -"Original Version" refers to the collection of Font Software components -as received under this licence. - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to -a new environment. - -"Copyright Holder(s)" refers to all individuals and companies who have a -copyright ownership of the Font Software. - -"Substantially Changed" refers to Modified Versions which can be easily -identified as dissimilar to the Font Software by users of the Font -Software comparing the Original Version with the Modified Version. - -To "Propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification and with or without charging -a redistribution fee), making available to the public, and in some -countries other activities as well. - -PERMISSION & CONDITIONS -This licence does not grant any rights under trademark law and all such -rights are reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of the Font Software, to propagate the Font Software, subject to -the below conditions: - -1) Each copy of the Font Software must contain the above copyright -notice and this licence. These can be included either as stand-alone -text files, human-readable headers or in the appropriate machine- -readable metadata fields within text or binary files as long as those -fields can be easily viewed by the user. - -2) The font name complies with the following: -(a) The Original Version must retain its name, unmodified. -(b) Modified Versions which are Substantially Changed must be renamed to -avoid use of the name of the Original Version or similar names entirely. -(c) Modified Versions which are not Substantially Changed must be -renamed to both (i) retain the name of the Original Version and (ii) add -additional naming elements to distinguish the Modified Version from the -Original Version. The name of such Modified Versions must be the name of -the Original Version, with "derivative X" where X represents the name of -the new work, appended to that name. - -3) The name(s) of the Copyright Holder(s) and any contributor to the -Font Software shall not be used to promote, endorse or advertise any -Modified Version, except (i) as required by this licence, (ii) to -acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with -their explicit written permission. - -4) The Font Software, modified or unmodified, in part or in whole, must -be distributed entirely under this licence, and must not be distributed -under any other licence. The requirement for fonts to remain under this -licence does not affect any document created using the Font Software, -except any version of the Font Software extracted from a document -created using the Font Software may only be distributed under this -licence. - -TERMINATION -This licence becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF -COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER -DEALINGS IN THE FONT SOFTWARE. diff --git a/web/apps/payments/public/fonts/ubuntu-v15-latin-700.woff b/web/apps/payments/public/fonts/ubuntu-v15-latin-700.woff deleted file mode 100644 index 8f770546ac..0000000000 Binary files a/web/apps/payments/public/fonts/ubuntu-v15-latin-700.woff and /dev/null differ diff --git a/web/apps/payments/public/fonts/ubuntu-v15-latin-700.woff2 b/web/apps/payments/public/fonts/ubuntu-v15-latin-700.woff2 deleted file mode 100644 index e10142f55e..0000000000 Binary files a/web/apps/payments/public/fonts/ubuntu-v15-latin-700.woff2 and /dev/null differ diff --git a/web/apps/payments/public/fonts/ubuntu-v15-latin-regular.woff b/web/apps/payments/public/fonts/ubuntu-v15-latin-regular.woff deleted file mode 100644 index 2fc163ffb0..0000000000 Binary files a/web/apps/payments/public/fonts/ubuntu-v15-latin-regular.woff and /dev/null differ diff --git a/web/apps/payments/public/fonts/ubuntu-v15-latin-regular.woff2 b/web/apps/payments/public/fonts/ubuntu-v15-latin-regular.woff2 deleted file mode 100644 index a590b8a9e5..0000000000 Binary files a/web/apps/payments/public/fonts/ubuntu-v15-latin-regular.woff2 and /dev/null differ diff --git a/web/apps/payments/src/components/EnteSpinner.tsx b/web/apps/payments/src/components/EnteSpinner.tsx index c40057045e..277857e0ef 100644 --- a/web/apps/payments/src/components/EnteSpinner.tsx +++ b/web/apps/payments/src/components/EnteSpinner.tsx @@ -1,10 +1,10 @@ +import * as React from "react"; import { Spinner } from "react-bootstrap"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export default function EnteSpinner(props: any) { +export const EnteSpinner: React.FC = () => { return ( - + Loading... ); -} +}; diff --git a/web/apps/payments/src/pages/404.tsx b/web/apps/payments/src/pages/404.tsx index 17911a7fc6..4e1bd8f260 100644 --- a/web/apps/payments/src/pages/404.tsx +++ b/web/apps/payments/src/pages/404.tsx @@ -1,5 +1,5 @@ import { Container } from "components/Container"; -import constants from "utils/strings/constants"; +import constants from "utils/strings"; export default function Home() { return {constants.NOT_FOUND}; diff --git a/web/apps/payments/src/pages/_app.tsx b/web/apps/payments/src/pages/_app.tsx index 17db6086b2..bc7be4839e 100644 --- a/web/apps/payments/src/pages/_app.tsx +++ b/web/apps/payments/src/pages/_app.tsx @@ -1,7 +1,7 @@ import "bootstrap/dist/css/bootstrap.min.css"; import type { AppProps } from "next/app"; import Head from "next/head"; -import constants from "utils/strings/constants"; +import constants from "utils/strings"; import "../styles/globals.css"; function MyApp({ Component, pageProps }: AppProps) { @@ -14,4 +14,5 @@ function MyApp({ Component, pageProps }: AppProps) { ); } + export default MyApp; diff --git a/web/apps/payments/src/pages/desktop-redirect.tsx b/web/apps/payments/src/pages/desktop-redirect.tsx index b945ee20a2..2bccc7a0a3 100644 --- a/web/apps/payments/src/pages/desktop-redirect.tsx +++ b/web/apps/payments/src/pages/desktop-redirect.tsx @@ -1,5 +1,5 @@ import { Container } from "components/Container"; -import EnteSpinner from "components/EnteSpinner"; +import { EnteSpinner } from "components/EnteSpinner"; import * as React from "react"; export default function DesktopRedirect() { @@ -12,7 +12,7 @@ export default function DesktopRedirect() { return ( - + ); } diff --git a/web/apps/payments/src/pages/index.tsx b/web/apps/payments/src/pages/index.tsx index b4aad2a0e2..69288efa78 100644 --- a/web/apps/payments/src/pages/index.tsx +++ b/web/apps/payments/src/pages/index.tsx @@ -1,13 +1,14 @@ import { Container } from "components/Container"; -import EnteSpinner from "components/EnteSpinner"; +import { EnteSpinner } from "components/EnteSpinner"; import * as React from "react"; import { parseAndHandleRequest } from "services/billingService"; import { CUSTOM_ERROR } from "utils/error"; -import constants from "utils/strings/constants"; +import constants from "utils/strings"; export default function Home() { const [errorMessageView, setErrorMessageView] = React.useState(false); const [loading, setLoading] = React.useState(false); + React.useEffect(() => { async function main() { try { @@ -34,7 +35,7 @@ export default function Home() { {errorMessageView ? (
{constants.SOMETHING_WENT_WRONG}
) : ( - loading && + loading && )} ); diff --git a/web/apps/payments/src/services/billingService.ts b/web/apps/payments/src/services/billingService.ts index c7a6a17e94..9224129d3d 100644 --- a/web/apps/payments/src/services/billingService.ts +++ b/web/apps/payments/src/services/billingService.ts @@ -8,7 +8,7 @@ import { loadStripe } from "@stripe/stripe-js"; import { CUSTOM_ERROR } from "utils/error"; -import { logError } from "utils/sentry"; +import { logError } from "utils/log"; import HTTPService from "./HTTPService"; const getStripePublishableKey = (stripeAccount: StripeAccountCountry) => { diff --git a/web/apps/payments/src/styles/globals.css b/web/apps/payments/src/styles/globals.css index c3d1ceab66..d0d1ccf237 100644 --- a/web/apps/payments/src/styles/globals.css +++ b/web/apps/payments/src/styles/globals.css @@ -1,39 +1,16 @@ -/* ubuntu-regular - latin */ -@font-face { - font-family: "Ubuntu"; - font-style: normal; - font-weight: 400; - src: - local(""), - url("/fonts/ubuntu-v15-latin-regular.woff2") format("woff2"), - /* Chrome 26+, Opera 23+, Firefox 39+ */ - url("/fonts/ubuntu-v15-latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ -} - -/* ubuntu-700 - latin */ -@font-face { - font-family: "Ubuntu"; - font-style: normal; - font-weight: 700; - src: - local(""), - url("/fonts/ubuntu-v15-latin-700.woff2") format("woff2"), - /* Chrome 26+, Opera 23+, Firefox 39+ */ - url("/fonts/ubuntu-v15-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ -} html, body { padding: 0; margin: 0; - font-family: Arial, Helvetica, sans-serif; + font-family: system-ui, sans-serif; height: 100%; flex: 1; display: flex; flex-direction: column; background-color: #191919 !important; color: #aaa !important; - font-family: Ubuntu, Arial, sans-serif !important; } + :is(h1, h2, h3, h4, h5, h6) { color: #d7d7d7; } @@ -43,11 +20,3 @@ body { display: flex; flex-direction: column; } - -.ente-container { - display: flex; - flex: 1; - flex-direction: column; - justify-content: center; - align-items: center; -} diff --git a/web/apps/payments/src/utils/common.ts b/web/apps/payments/src/utils/common.ts deleted file mode 100644 index 7796b13036..0000000000 --- a/web/apps/payments/src/utils/common.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function runningInBrowser() { - return typeof window !== "undefined"; -} diff --git a/web/apps/payments/src/utils/error/index.ts b/web/apps/payments/src/utils/error.ts similarity index 100% rename from web/apps/payments/src/utils/error/index.ts rename to web/apps/payments/src/utils/error.ts diff --git a/web/apps/payments/src/utils/sentry/index.ts b/web/apps/payments/src/utils/log.ts similarity index 100% rename from web/apps/payments/src/utils/sentry/index.ts rename to web/apps/payments/src/utils/log.ts diff --git a/web/apps/payments/src/utils/strings/constants.tsx b/web/apps/payments/src/utils/strings.ts similarity index 99% rename from web/apps/payments/src/utils/strings/constants.tsx rename to web/apps/payments/src/utils/strings.ts index e08c6d558d..44ba64b8fe 100644 --- a/web/apps/payments/src/utils/strings/constants.tsx +++ b/web/apps/payments/src/utils/strings.ts @@ -3,4 +3,5 @@ const englishConstants = { SOMETHING_WENT_WRONG: "Oops, something went wrong.", NOT_FOUND: "404 | This page could not be found.", }; + export default englishConstants; diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index c62606b309..fe941f79ca 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -486,7 +486,9 @@ export default function App(props: EnteAppProps) { )} - + {isI18nReady && ( + + )} diff --git a/web/docs/deploy.md b/web/docs/deploy.md index c17de8ffa3..2c3cfcd97a 100644 --- a/web/docs/deploy.md +++ b/web/docs/deploy.md @@ -36,10 +36,12 @@ deployments, and the action that triggers them: | [auth.ente.io](https://auth.ente.io) | Production | Push to `deploy/auth` | | [accounts.ente.io](https://accounts.ente.io) | Production | Push to `deploy/accounts` | | [cast.ente.io](https://cast.ente.io) | Production | Push to `deploy/cast` | +| [payments.ente.io](https://payments.ente.io) | Production | Push to `deploy/payments` | | [help.ente.io](https://help.ente.io) | Production | Push to `main` + changes in `docs/` | | [accounts.ente.sh](https://accounts.ente.sh) | Preview | Nightly deploy of `main` | | [auth.ente.sh](https://auth.ente.sh) | Preview | Nightly deploy of `main` | | [cast.ente.sh](https://cast.ente.sh) | Preview | Nightly deploy of `main` | +| [payments.ente.sh](https://payments.ente.sh) | Preview | Nightly deploy of `main` | | [photos.ente.sh](https://photos.ente.sh) | Preview | Nightly deploy of `main` | | [preview.ente.sh](https://preview.ente.sh) | Preview | Manually triggered | @@ -52,8 +54,8 @@ Apart from this, there are also some other deployments: `albums.ente.io`, it redirects to the `/shared-albums` page (Enhancement: serve it as a separate app with a smaller bundle size). -- `payments.ente.io` and `family.ente.io` are currently in a separate - repositories (Enhancement: bring them in here). +- `family.ente.io` is currently in a separate repositories (Enhancement: bring + them in here). ### Preview deployments