@anthusai/papyrus 1.0.0-next.8 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/amplify/auth/redirect-urls.js +54 -0
- package/amplify/auth/redirect-urls.ts +66 -0
- package/amplify/auth/resource.js +20 -5
- package/amplify/auth/resource.ts +27 -5
- package/amplify/data/resource.js +42 -80
- package/amplify/data/resource.ts +42 -80
- package/amplify/data/schema.js +45 -60
- package/amplify/data/schema.ts +47 -60
- package/amplify/functions/category-action/handler.ts +5 -3
- package/amplify/functions/console-chat-responder/py/execute_tactus_runner.py +0 -10
- package/amplify/functions/console-chat-responder/resource.js +0 -7
- package/amplify/functions/console-chat-responder/resource.ts +0 -8
- package/amplify/functions/console-chat-responder/src/main.rs +0 -9
- package/amplify/functions/content-actions/handler.py +143 -1
- package/amplify/functions/content-actions/requirements.txt +2 -1
- package/amplify/functions/content-actions/resource.js +6 -1
- package/amplify/functions/content-actions/resource.ts +9 -2
- package/amplify/functions/renditions/handler.py +120 -0
- package/amplify/functions/renditions/requirements.txt +4 -0
- package/amplify/functions/shared/python-bundle.js +42 -2
- package/amplify/functions/shared/python-bundle.ts +47 -2
- package/amplify/functions/shared/reference-curation-metadata.ts +29 -0
- package/amplify/inbound-email/ses-intake.js +86 -0
- package/amplify/inbound-email/ses-intake.ts +110 -0
- package/amplify/plugins/registry.js +19 -0
- package/amplify/plugins/registry.ts +23 -0
- package/amplify/plugins/signup/function/handler.py +200 -0
- package/amplify/plugins/signup/function/resource.js +27 -0
- package/amplify/plugins/signup/function/resource.ts +35 -0
- package/amplify/plugins/signup/papyrus.plugin.js +59 -0
- package/amplify/plugins/signup/papyrus.plugin.ts +74 -0
- package/amplify/plugins/signup/schema.js +40 -0
- package/amplify/plugins/signup/schema.ts +41 -0
- package/amplify/plugins/signup/waf.js +48 -0
- package/amplify/plugins/signup/waf.ts +51 -0
- package/amplify/plugins/types.js +1 -0
- package/amplify/plugins/types.ts +39 -0
- package/amplify/plugins/wire.js +24 -0
- package/amplify/plugins/wire.ts +26 -0
- package/amplify/publication/default-publication.js +18 -0
- package/amplify/publication/default-publication.ts +20 -0
- package/amplify/publication/invalidation-alarm.js +26 -0
- package/amplify/publication/invalidation-alarm.ts +30 -0
- package/amplify/publication/redirect-and-index.js +37 -0
- package/amplify/publication/renditions-function.js +74 -0
- package/amplify/publication/renditions-function.ts +112 -0
- package/amplify/publication/renditions-settings.js +51 -0
- package/amplify/publication/renditions-settings.ts +58 -0
- package/amplify/publication/reproject-on-deploy.js +73 -0
- package/amplify/publication/reproject-on-deploy.ts +78 -0
- package/amplify/publication/s3-projection-settings.js +67 -0
- package/amplify/publication/s3-projection-settings.ts +101 -0
- package/amplify/publication/s3-projection.js +151 -0
- package/amplify/publication/s3-projection.ts +201 -0
- package/amplify/resolver-waves.js +26 -0
- package/amplify/resolver-waves.ts +34 -0
- package/amplify/revalidate-invalidation-settings.js +30 -0
- package/amplify/revalidate-invalidation-settings.ts +35 -0
- package/amplify/revalidate-secret-policy.js +13 -0
- package/amplify/revalidate-secret-policy.ts +19 -0
- package/amplify/site-backend-config.js +65 -1
- package/amplify/site-backend-config.ts +153 -2
- package/amplify/site-backend-names.js +103 -0
- package/amplify/site-backend-names.ts +166 -0
- package/amplify/site-backend.js +143 -176
- package/amplify/site-backend.ts +181 -201
- package/amplify/storage-backups/construct.js +31 -0
- package/amplify/storage-backups/construct.ts +47 -0
- package/app/[year]/[month]/[day]/[articleSlug]/page.tsx +8 -1
- package/app/[year]/[month]/[day]/edition-route-page.tsx +2 -0
- package/app/[year]/[month]/[day]/page/[pageNumber]/page.tsx +6 -1
- package/app/[year]/[month]/[day]/page.tsx +1 -1
- package/app/[year]/[month]/[day]/section/[sectionKey]/page.tsx +6 -1
- package/app/api/archive/editions/route.ts +1 -1
- package/app/api/cyclotron/priming-proof/route.ts +11 -0
- package/app/api/media/[...path]/route.ts +5 -16
- package/app/api/revalidate/route.ts +15 -7
- package/app/archive/page.tsx +1 -1
- package/app/articles/[slug]/page.tsx +7 -5
- package/app/blog-rhythm.css +278 -0
- package/app/cyclotron/page.tsx +13 -0
- package/app/globals.css +2 -0
- package/app/layout.tsx +16 -0
- package/app/newsroom/[section]/[...selection]/page.tsx +9 -6
- package/app/newsroom/[section]/page.tsx +6 -3
- package/app/newsroom/layout.tsx +4 -9
- package/app/newsroom/settings/page.tsx +6 -0
- package/app/newsroom/work/page.tsx +10 -0
- package/app/page.tsx +22 -8
- package/app/robots.ts +2 -5
- package/app/tailwind.css +1 -0
- package/bin/papyrus-infra.mjs +3 -3
- package/components/amplify-client-provider.tsx +5 -22
- package/components/archive-shell.tsx +2 -22
- package/components/article-video.tsx +152 -5
- package/components/blog-page-background.tsx +23 -6
- package/components/news-desk-page.tsx +4 -15
- package/components/news-desk-taxonomy-client.ts +90 -3
- package/components/newspaper.tsx +6 -2
- package/components/newsroom-access-gate.tsx +2 -1
- package/components/newsroom-board-view.tsx +99 -0
- package/components/newsroom-client-shell.tsx +12 -0
- package/components/newsroom-curation-provider.tsx +17 -0
- package/components/newsroom-fonts/playfair-display-700.ttf +0 -0
- package/components/newsroom-fonts/playfair-display-900.ttf +0 -0
- package/components/newsroom-fonts/playfair-display-OFL.txt +93 -0
- package/components/newsroom-fonts/plus-jakarta-sans-400.ttf +0 -0
- package/components/newsroom-fonts/plus-jakarta-sans-600.ttf +0 -0
- package/components/newsroom-fonts/plus-jakarta-sans-OFL.txt +93 -0
- package/components/newsroom-newsprint-board.css +48 -0
- package/components/newsroom-ops-overview.tsx +28 -11
- package/components/newsroom-ops-shell.tsx +7 -1
- package/components/newsroom-organizer-shell.tsx +130 -0
- package/components/newsroom-organizer.css +63 -0
- package/components/newsroom-references-view.tsx +92 -8
- package/components/papyrus-console-shell.tsx +4 -2
- package/components/pictogram-figure.tsx +9 -2
- package/components/presentation-header.tsx +135 -0
- package/components/presentation-rhythm-hrule.tsx +17 -0
- package/components/priming-proof-page.tsx +92 -0
- package/components/publication-cyclotron-panel.tsx +57 -0
- package/components/reader-auth-control.tsx +8 -5
- package/components/reference-curation-controls.tsx +77 -0
- package/components/reference-cyclotron-status.tsx +109 -0
- package/components/reference-priming.tsx +18 -0
- package/components/reference-relevance-review.tsx +75 -0
- package/components/settings-page.tsx +2 -1
- package/components/signup-entries-panel.tsx +94 -0
- package/components/topic-steering-workspace.tsx +78 -6
- package/components/use-blog-header-obstacles.ts +81 -0
- package/components/use-brand-fonts-ready.ts +28 -0
- package/components/use-near-viewport.ts +30 -0
- package/components/use-rhythm-overlay.ts +29 -0
- package/infra/amplify-app-shell.js +219 -71
- package/infra/amplify-app-shell.ts +231 -77
- package/infra/build-specs.js +23 -8
- package/infra/build-specs.ts +27 -11
- package/infra/site-config.js +277 -34
- package/infra/site-config.ts +340 -43
- package/lib/amplify-outputs-path.ts +5 -1
- package/lib/amplify-server-runtime.ts +36 -1
- package/lib/approved-priming-proof-reports.ts +6 -0
- package/lib/blog-feature-solver.ts +459 -0
- package/lib/blog-rhythm.ts +134 -0
- package/lib/brand-fonts-watch.ts +43 -0
- package/lib/brand-fonts.ts +112 -0
- package/lib/cached-content-repository.ts +12 -0
- package/lib/category-repository.ts +43 -93
- package/lib/content-item-lifecycle.ts +55 -0
- package/lib/content-repository.ts +3 -0
- package/lib/content-types.ts +4 -0
- package/lib/curation-client.ts +61 -0
- package/lib/edition-routes.ts +31 -29
- package/lib/graphql-content-repository.ts +56 -22
- package/lib/media-route-response.ts +45 -0
- package/lib/newspaper-layout.ts +3 -2
- package/lib/newsroom-base-path.ts +12 -3
- package/lib/newsroom-board.ts +99 -0
- package/lib/newsroom-category-drilldown.ts +3 -2
- package/lib/newsroom-forum-routes.ts +6 -4
- package/lib/newsroom-index-filters.ts +14 -10
- package/lib/newsroom-nav.ts +3 -1
- package/lib/newsroom-organizer-nav.ts +37 -0
- package/lib/newsroom-section-routing.ts +20 -0
- package/lib/oauth-redirect-priority.ts +40 -0
- package/lib/papyrus-web-locations.ts +7 -6
- package/lib/plugin-settings.ts +11 -0
- package/lib/presentation-footer.ts +3 -2
- package/lib/pretext-layout.ts +12 -3
- package/lib/priming-proof-report.ts +89 -0
- package/lib/prospectus-site-identity.ts +303 -0
- package/lib/publication-cyclotron.ts +74 -0
- package/lib/rate-limit-retry.ts +55 -0
- package/lib/reader-base-path.ts +24 -0
- package/lib/reader-cache-lifetime.ts +5 -0
- package/lib/reader-static-params.ts +85 -4
- package/lib/reader-storage-url.ts +9 -12
- package/lib/reference-policy.ts +5 -0
- package/lib/relevance-decisions.ts +103 -0
- package/lib/relevance-status.ts +63 -0
- package/lib/renderer.ts +7 -0
- package/lib/revalidate-prewarm.ts +53 -0
- package/lib/revalidate-secret.ts +59 -0
- package/lib/robots-policy.ts +14 -0
- package/lib/root-route-redirect.ts +16 -0
- package/lib/semantic-graph.ts +7 -0
- package/lib/shared-credentials-provider.ts +61 -0
- package/lib/signup-csv.ts +24 -0
- package/lib/site-brand.ts +59 -0
- package/lib/staging-gated-path.ts +23 -0
- package/lib/staging-preview-object.ts +21 -5
- package/lib/test-editor-override.ts +4 -0
- package/lib/video-loading.ts +22 -0
- package/lib/video-script.ts +14 -0
- package/middleware.ts +11 -19
- package/package.json +64 -1
- package/renderers/pretext/article-page.tsx +39 -3
- package/renderers/pretext/presentation-shared.tsx +113 -0
- package/renderers/pretext/presentation-shell.tsx +15 -102
- package/renderers/pretext/rhythm-article-page.tsx +165 -0
- package/renderers/pretext/rhythm-blog-presentation.tsx +279 -0
- package/renderers/pretext/rhythm-shell-style.ts +35 -0
- package/routes.manifest.json +68 -12
- package/src/sync.mjs +30 -6
- package/src/with-papyrus.d.mts +9 -0
- package/src/with-papyrus.mjs +48 -3
- package/amplify/functions/graphql-jwt-authorizer/handler.ts +0 -193
- package/amplify/functions/graphql-jwt-authorizer/resource.js +0 -14
- package/amplify/functions/graphql-jwt-authorizer/resource.ts +0 -15
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export const DEFAULT_NEWSROOM_BASE_PATH = "/newsroom";
|
|
2
|
+
function parseRedirectUrl(value) {
|
|
3
|
+
try {
|
|
4
|
+
const parsed = new URL(value);
|
|
5
|
+
return { original: value, origin: parsed.origin, path: parsed.pathname.replace(/\/+$/, "") };
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Expands every origin in an OAuth redirect list to both the newsroom return
|
|
13
|
+
* path and the site root, newsroom first. Amplify signs in with the first
|
|
14
|
+
* entry that matches the current origin, so a list that names only
|
|
15
|
+
* `https://host/` would land a signed-in editor on the public reader.
|
|
16
|
+
*
|
|
17
|
+
* With `newsroomBasePath` of `""` (a CMS-only host that mounts the newsroom at
|
|
18
|
+
* `/`), the root already is the newsroom and nothing is added. Explicit
|
|
19
|
+
* entries are kept; unparseable entries pass through unchanged.
|
|
20
|
+
*/
|
|
21
|
+
export function expandNewsroomRedirectUrls(redirectUrls, newsroomBasePath = DEFAULT_NEWSROOM_BASE_PATH) {
|
|
22
|
+
const newsroomPath = newsroomBasePath.replace(/\/+$/, "");
|
|
23
|
+
const originOrder = [];
|
|
24
|
+
const explicitByOrigin = new Map();
|
|
25
|
+
const passthrough = [];
|
|
26
|
+
for (const value of redirectUrls) {
|
|
27
|
+
const parsed = parseRedirectUrl(value);
|
|
28
|
+
if (!parsed) {
|
|
29
|
+
passthrough.push(value);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (!explicitByOrigin.has(parsed.origin)) {
|
|
33
|
+
originOrder.push(parsed.origin);
|
|
34
|
+
explicitByOrigin.set(parsed.origin, []);
|
|
35
|
+
}
|
|
36
|
+
explicitByOrigin.get(parsed.origin)?.push(value);
|
|
37
|
+
}
|
|
38
|
+
const expanded = [];
|
|
39
|
+
for (const origin of originOrder) {
|
|
40
|
+
const explicit = explicitByOrigin.get(origin) ?? [];
|
|
41
|
+
if (newsroomPath === "") {
|
|
42
|
+
expanded.push(...explicit);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const newsroomEntries = explicit.filter((value) => parseRedirectUrl(value)?.path === newsroomPath);
|
|
46
|
+
const otherEntries = explicit.filter((value) => {
|
|
47
|
+
const path = parseRedirectUrl(value)?.path;
|
|
48
|
+
return path !== newsroomPath && path !== "";
|
|
49
|
+
});
|
|
50
|
+
expanded.push(...(newsroomEntries.length > 0 ? newsroomEntries : [`${origin}${newsroomPath}`]), `${origin}/`, ...otherEntries);
|
|
51
|
+
}
|
|
52
|
+
expanded.push(...passthrough);
|
|
53
|
+
return [...new Set(expanded)];
|
|
54
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export const DEFAULT_NEWSROOM_BASE_PATH = "/newsroom";
|
|
2
|
+
|
|
3
|
+
type ParsedRedirectUrl = { original: string; origin: string; path: string } | null;
|
|
4
|
+
|
|
5
|
+
function parseRedirectUrl(value: string): ParsedRedirectUrl {
|
|
6
|
+
try {
|
|
7
|
+
const parsed = new URL(value);
|
|
8
|
+
return { original: value, origin: parsed.origin, path: parsed.pathname.replace(/\/+$/, "") };
|
|
9
|
+
} catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Expands every origin in an OAuth redirect list to both the newsroom return
|
|
16
|
+
* path and the site root, newsroom first. Amplify signs in with the first
|
|
17
|
+
* entry that matches the current origin, so a list that names only
|
|
18
|
+
* `https://host/` would land a signed-in editor on the public reader.
|
|
19
|
+
*
|
|
20
|
+
* With `newsroomBasePath` of `""` (a CMS-only host that mounts the newsroom at
|
|
21
|
+
* `/`), the root already is the newsroom and nothing is added. Explicit
|
|
22
|
+
* entries are kept; unparseable entries pass through unchanged.
|
|
23
|
+
*/
|
|
24
|
+
export function expandNewsroomRedirectUrls(
|
|
25
|
+
redirectUrls: readonly string[],
|
|
26
|
+
newsroomBasePath: string = DEFAULT_NEWSROOM_BASE_PATH,
|
|
27
|
+
): string[] {
|
|
28
|
+
const newsroomPath = newsroomBasePath.replace(/\/+$/, "");
|
|
29
|
+
const originOrder: string[] = [];
|
|
30
|
+
const explicitByOrigin = new Map<string, string[]>();
|
|
31
|
+
const passthrough: string[] = [];
|
|
32
|
+
|
|
33
|
+
for (const value of redirectUrls) {
|
|
34
|
+
const parsed = parseRedirectUrl(value);
|
|
35
|
+
if (!parsed) {
|
|
36
|
+
passthrough.push(value);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (!explicitByOrigin.has(parsed.origin)) {
|
|
40
|
+
originOrder.push(parsed.origin);
|
|
41
|
+
explicitByOrigin.set(parsed.origin, []);
|
|
42
|
+
}
|
|
43
|
+
explicitByOrigin.get(parsed.origin)?.push(value);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const expanded: string[] = [];
|
|
47
|
+
for (const origin of originOrder) {
|
|
48
|
+
const explicit = explicitByOrigin.get(origin) ?? [];
|
|
49
|
+
if (newsroomPath === "") {
|
|
50
|
+
expanded.push(...explicit);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const newsroomEntries = explicit.filter((value) => parseRedirectUrl(value)?.path === newsroomPath);
|
|
54
|
+
const otherEntries = explicit.filter((value) => {
|
|
55
|
+
const path = parseRedirectUrl(value)?.path;
|
|
56
|
+
return path !== newsroomPath && path !== "";
|
|
57
|
+
});
|
|
58
|
+
expanded.push(
|
|
59
|
+
...(newsroomEntries.length > 0 ? newsroomEntries : [`${origin}${newsroomPath}`]),
|
|
60
|
+
`${origin}/`,
|
|
61
|
+
...otherEntries,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
expanded.push(...passthrough);
|
|
65
|
+
return [...new Set(expanded)];
|
|
66
|
+
}
|
package/amplify/auth/resource.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { defineAuth, secret } from "@aws-amplify/backend";
|
|
2
2
|
import { manageUserRole } from "../functions/manage-user-role/resource.js";
|
|
3
|
+
import { CfnUserPoolDomain } from "aws-cdk-lib/aws-cognito";
|
|
4
|
+
import { expandNewsroomRedirectUrls } from "./redirect-urls.js";
|
|
3
5
|
// Default OAuth redirect URLs for the p.apyr.us app. Other publications pass
|
|
4
6
|
// `auth.redirectUrls` to `defineSiteBackend` (or, for Papyrus's own backend,
|
|
5
7
|
// the PAPYRUS_OAUTH_REDIRECT_URLS branch env var, comma-separated).
|
|
8
|
+
// `defineSiteAuth` adds the newsroom and root variants of every origin listed.
|
|
6
9
|
// See docs/google-oauth-setup.md.
|
|
7
10
|
const DEFAULT_AUTH_REDIRECT_URLS = [
|
|
8
11
|
"http://localhost:3001/",
|
|
@@ -25,15 +28,13 @@ export function authConfigFromEnv() {
|
|
|
25
28
|
return {
|
|
26
29
|
redirectUrls: resolveAuthRedirectUrls(),
|
|
27
30
|
disableGoogleOAuth: process.env.PAPYRUS_DISABLE_GOOGLE_OAUTH === "1",
|
|
28
|
-
// Stable Cognito hosted-UI domain prefix for Google OAuth redirect URIs.
|
|
29
|
-
// See docs/google-oauth-setup.md.
|
|
30
31
|
cognitoDomainPrefix: (process.env.PAPYRUS_COGNITO_DOMAIN_PREFIX ?? "").trim(),
|
|
32
|
+
applyCognitoDomainPrefix: process.env.PAPYRUS_APPLY_COGNITO_DOMAIN_PREFIX === "true",
|
|
31
33
|
};
|
|
32
34
|
}
|
|
33
35
|
export function defineSiteAuth(config) {
|
|
34
|
-
const authRedirectUrls = config.redirectUrls ?? DEFAULT_AUTH_REDIRECT_URLS;
|
|
36
|
+
const authRedirectUrls = expandNewsroomRedirectUrls(config.redirectUrls ?? DEFAULT_AUTH_REDIRECT_URLS, config.newsroomBasePath);
|
|
35
37
|
const disableGoogleOAuth = config.disableGoogleOAuth === true;
|
|
36
|
-
const cognitoDomainPrefix = (config.cognitoDomainPrefix ?? "").trim();
|
|
37
38
|
return defineAuth({
|
|
38
39
|
loginWith: {
|
|
39
40
|
email: true,
|
|
@@ -49,7 +50,6 @@ export function defineSiteAuth(config) {
|
|
|
49
50
|
scopes: ["EMAIL", "PROFILE", "OPENID"],
|
|
50
51
|
callbackUrls: authRedirectUrls,
|
|
51
52
|
logoutUrls: authRedirectUrls,
|
|
52
|
-
...(cognitoDomainPrefix ? { domainPrefix: cognitoDomainPrefix } : {}),
|
|
53
53
|
},
|
|
54
54
|
}),
|
|
55
55
|
},
|
|
@@ -59,3 +59,18 @@ export function defineSiteAuth(config) {
|
|
|
59
59
|
],
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
|
+
// Amplify Gen2's auth factory overwrites `externalProviders.domainPrefix` with a
|
|
63
|
+
// hash of the backend id, so the prefix cannot be passed through `defineAuth`.
|
|
64
|
+
// This sets the user pool domain on the synthesized resource instead. Cognito
|
|
65
|
+
// cannot rename a pool domain in place: CloudFormation replaces the domain,
|
|
66
|
+
// which changes the hosted-UI URL and the Google redirect URI. Callers must
|
|
67
|
+
// only use it when the site opted in (see docs/google-oauth-setup.md).
|
|
68
|
+
export function applyCognitoDomainPrefix(authStack, cognitoDomainPrefix) {
|
|
69
|
+
const domainResources = authStack.node
|
|
70
|
+
.findAll()
|
|
71
|
+
.filter((construct) => construct instanceof CfnUserPoolDomain);
|
|
72
|
+
if (domainResources.length !== 1) {
|
|
73
|
+
throw new Error(`Expected exactly one Cognito user pool domain in the auth stack to apply cognitoDomainPrefix, found ${domainResources.length}`);
|
|
74
|
+
}
|
|
75
|
+
domainResources[0].domain = cognitoDomainPrefix;
|
|
76
|
+
}
|
package/amplify/auth/resource.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { defineAuth, secret } from "@aws-amplify/backend";
|
|
2
2
|
import { manageUserRole } from "../functions/manage-user-role/resource";
|
|
3
|
+
import { Stack } from "aws-cdk-lib";
|
|
4
|
+
import { CfnUserPoolDomain } from "aws-cdk-lib/aws-cognito";
|
|
3
5
|
import type { PapyrusAuthConfig } from "../site-backend-config";
|
|
6
|
+
import { expandNewsroomRedirectUrls } from "./redirect-urls";
|
|
4
7
|
|
|
5
8
|
// Default OAuth redirect URLs for the p.apyr.us app. Other publications pass
|
|
6
9
|
// `auth.redirectUrls` to `defineSiteBackend` (or, for Papyrus's own backend,
|
|
7
10
|
// the PAPYRUS_OAUTH_REDIRECT_URLS branch env var, comma-separated).
|
|
11
|
+
// `defineSiteAuth` adds the newsroom and root variants of every origin listed.
|
|
8
12
|
// See docs/google-oauth-setup.md.
|
|
9
13
|
const DEFAULT_AUTH_REDIRECT_URLS = [
|
|
10
14
|
"http://localhost:3001/",
|
|
@@ -28,16 +32,17 @@ export function authConfigFromEnv(): PapyrusAuthConfig {
|
|
|
28
32
|
return {
|
|
29
33
|
redirectUrls: resolveAuthRedirectUrls(),
|
|
30
34
|
disableGoogleOAuth: process.env.PAPYRUS_DISABLE_GOOGLE_OAUTH === "1",
|
|
31
|
-
// Stable Cognito hosted-UI domain prefix for Google OAuth redirect URIs.
|
|
32
|
-
// See docs/google-oauth-setup.md.
|
|
33
35
|
cognitoDomainPrefix: (process.env.PAPYRUS_COGNITO_DOMAIN_PREFIX ?? "").trim(),
|
|
36
|
+
applyCognitoDomainPrefix: process.env.PAPYRUS_APPLY_COGNITO_DOMAIN_PREFIX === "true",
|
|
34
37
|
};
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
export function defineSiteAuth(config: PapyrusAuthConfig) {
|
|
38
|
-
const authRedirectUrls =
|
|
41
|
+
const authRedirectUrls = expandNewsroomRedirectUrls(
|
|
42
|
+
config.redirectUrls ?? DEFAULT_AUTH_REDIRECT_URLS,
|
|
43
|
+
config.newsroomBasePath,
|
|
44
|
+
);
|
|
39
45
|
const disableGoogleOAuth = config.disableGoogleOAuth === true;
|
|
40
|
-
const cognitoDomainPrefix = (config.cognitoDomainPrefix ?? "").trim();
|
|
41
46
|
return defineAuth({
|
|
42
47
|
loginWith: {
|
|
43
48
|
email: true,
|
|
@@ -53,7 +58,6 @@ export function defineSiteAuth(config: PapyrusAuthConfig) {
|
|
|
53
58
|
scopes: ["EMAIL", "PROFILE", "OPENID"],
|
|
54
59
|
callbackUrls: authRedirectUrls,
|
|
55
60
|
logoutUrls: authRedirectUrls,
|
|
56
|
-
...(cognitoDomainPrefix ? { domainPrefix: cognitoDomainPrefix } : {}),
|
|
57
61
|
},
|
|
58
62
|
}),
|
|
59
63
|
},
|
|
@@ -63,3 +67,21 @@ export function defineSiteAuth(config: PapyrusAuthConfig) {
|
|
|
63
67
|
],
|
|
64
68
|
});
|
|
65
69
|
}
|
|
70
|
+
|
|
71
|
+
// Amplify Gen2's auth factory overwrites `externalProviders.domainPrefix` with a
|
|
72
|
+
// hash of the backend id, so the prefix cannot be passed through `defineAuth`.
|
|
73
|
+
// This sets the user pool domain on the synthesized resource instead. Cognito
|
|
74
|
+
// cannot rename a pool domain in place: CloudFormation replaces the domain,
|
|
75
|
+
// which changes the hosted-UI URL and the Google redirect URI. Callers must
|
|
76
|
+
// only use it when the site opted in (see docs/google-oauth-setup.md).
|
|
77
|
+
export function applyCognitoDomainPrefix(authStack: Stack, cognitoDomainPrefix: string): void {
|
|
78
|
+
const domainResources = authStack.node
|
|
79
|
+
.findAll()
|
|
80
|
+
.filter((construct): construct is CfnUserPoolDomain => construct instanceof CfnUserPoolDomain);
|
|
81
|
+
if (domainResources.length !== 1) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Expected exactly one Cognito user pool domain in the auth stack to apply cognitoDomainPrefix, found ${domainResources.length}`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
domainResources[0].domain = cognitoDomainPrefix;
|
|
87
|
+
}
|