Skip to content

Commit b8ed217

Browse files
Merge pull request #502 from kinde-oss/Fix/Folder-level-redirects
Fix/folder level redirects
2 parents 1addcac + 0aee554 commit b8ed217

File tree

4 files changed

+258
-5
lines changed

4 files changed

+258
-5
lines changed

astro.config.mjs

Lines changed: 199 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,205 @@ export default defineConfig({
6060
"/design/pages/set-language-for-pages/":
6161
"/design/content-customization/set-language-for-pages/",
6262
"/design/pages/internationalization/":
63-
"/design/content-customization/set-language-for-pages/"
63+
"/design/content-customization/set-language-for-pages/",
64+
65+
// Section-level redirects to prevent 404s when users truncate URLs
66+
"/authenticate/":
67+
"/authenticate/about-auth/about-authentication/",
68+
"/billing/":
69+
"/billing/about-billing/about-billing/",
70+
"/build/":
71+
"/build/applications/about-applications/",
72+
"/contribute/":
73+
"/contribute/",
74+
"/design/":
75+
"/design/brand/global-brand-defaults/",
76+
"/developer-tools/":
77+
"/developer-tools/about/our-sdks/",
78+
"/get-started/":
79+
"/get-started/apis-and-sdks/about-kinde-apis/",
80+
"/integrate/":
81+
"/integrate/connected-apps/add-connected-apps/",
82+
"/machine-to-machine-applications/":
83+
"/machine-to-machine-applications/about-m2m/authenticate-with-m2m/",
84+
"/manage-your-account/":
85+
"/manage-your-account/business-information/update-your-details/",
86+
"/manage-users/":
87+
"/manage-users/about/manage-users-across-organizations/",
88+
"/properties/":
89+
"/properties/about-properties/application-properties/",
90+
"/releases/":
91+
"/releases/about/about-feature-flags/",
92+
"/trust-center/":
93+
"/trust-center/agreements/terms-of-service/",
94+
"/workflows/":
95+
"/workflows/about-workflows/",
96+
97+
// Authenticate section subfolder redirects
98+
"/authenticate/about-auth/":
99+
"/authenticate/about-auth/about-authentication/",
100+
"/authenticate/auth-guides/":
101+
"/authenticate/auth-guides/enterprise-connections-identity/",
102+
"/authenticate/authentication-methods/":
103+
"/authenticate/authentication-methods/email-authentication/",
104+
"/authenticate/custom-configurations/":
105+
"/authenticate/custom-configurations/authentication-experience/",
106+
"/authenticate/enterprise-connections/":
107+
"/authenticate/enterprise-connections/about-enterprise-connections/",
108+
"/authenticate/manage-authentication/":
109+
"/authenticate/manage-authentication/authenticated-sessions-across-multiple-applications/",
110+
"/authenticate/multi-factor-auth/":
111+
"/authenticate/multi-factor-auth/about-multi-factor-authentication/",
112+
"/authenticate/social-sign-in/":
113+
"/authenticate/social-sign-in/add-social-sign-in/",
114+
115+
// Billing section subfolder redirects
116+
"/billing/about-billing/":
117+
"/billing/about-billing/about-billing/",
118+
"/billing/billing-user-experience/":
119+
"/billing/billing-user-experience/add-pricing-table/",
120+
"/billing/get-started/":
121+
"/billing/get-started/add-billing-role/",
122+
"/billing/manage-plans/":
123+
"/billing/manage-plans/about-plans/",
124+
"/billing/manage-subscribers/":
125+
"/billing/manage-subscribers/add-metered-usage/",
126+
"/billing/payment-management/":
127+
"/billing/payment-management/manage-stripe-connection/",
128+
"/billing/pricing/":
129+
"/billing/pricing/pricing-models/",
130+
131+
// Build section subfolder redirects
132+
"/build/applications/":
133+
"/build/applications/about-applications/",
134+
"/build/domains/":
135+
"/build/domains/pointing-your-domain/",
136+
"/build/env-variables/":
137+
"/build/env-variables/add-manage-env-variables/",
138+
"/build/environments/":
139+
"/build/environments/environments/",
140+
"/build/organizations/":
141+
"/build/organizations/add-and-manage-organizations/",
142+
"/build/set-up-options/":
143+
"/build/set-up-options/access-policies/",
144+
"/build/tokens/":
145+
"/build/tokens/about-access-tokens/",
146+
147+
// Design section subfolder redirects
148+
"/design/brand/":
149+
"/design/brand/global-brand-defaults/",
150+
"/design/content-customization/":
151+
"/design/content-customization/how-content-is-managed/",
152+
"/design/customize-with-code/":
153+
"/design/customize-with-code/connect-repo/",
154+
"/design/pages/":
155+
"/design/pages/page-layout/",
156+
157+
// Developer tools section subfolder redirects
158+
"/developer-tools/about/":
159+
"/developer-tools/about/our-sdks/",
160+
"/developer-tools/account-api/":
161+
"/developer-tools/account-api/about-account-api/",
162+
"/developer-tools/guides/":
163+
"/developer-tools/guides/code-sync-errors/",
164+
"/developer-tools/kinde-api/":
165+
"/developer-tools/kinde-api/about-m2m-scopes/",
166+
"/developer-tools/sdks/backend/":
167+
"/developer-tools/sdks/backend/apollo-graphql/",
168+
"/developer-tools/sdks/frontend/":
169+
"/developer-tools/sdks/frontend/javascript-sdk/",
170+
"/developer-tools/sdks/native/":
171+
"/developer-tools/sdks/native/android-sdk/",
172+
"/developer-tools/your-apis/":
173+
"/developer-tools/your-apis/access-to-your-api/",
174+
175+
// Get started section subfolder redirects
176+
"/get-started/apis-and-sdks/":
177+
"/get-started/apis-and-sdks/about-kinde-apis/",
178+
"/get-started/connect/":
179+
"/get-started/connect/callback-urls/",
180+
"/get-started/guides/":
181+
"/get-started/guides/byo-code/",
182+
"/get-started/learn-about-kinde/":
183+
"/get-started/learn-about-kinde/kinde-product-security/",
184+
"/get-started/switch-to-kinde/":
185+
"/get-started/switch-to-kinde/auth0-to-kinde/",
186+
"/get-started/team-and-account/":
187+
"/get-started/team-and-account/add-team-members/",
188+
189+
// Integrate section subfolder redirects
190+
"/integrate/connected-apps/":
191+
"/integrate/connected-apps/add-connected-apps/",
192+
"/integrate/third-party-tools/":
193+
"/integrate/third-party-tools/cloudflare-zero-trust/",
194+
"/integrate/webhooks/":
195+
"/integrate/webhooks/about-webhooks/",
196+
197+
// Machine-to-machine applications section subfolder redirects
198+
"/machine-to-machine-applications/m2m-application-setup/":
199+
"/machine-to-machine-applications/m2m-application-setup/add-feature-flags-to-m2m-applications/",
200+
"/machine-to-machine-applications/m2m-token-customization/":
201+
"/machine-to-machine-applications/m2m-token-customization/customize-m2m-tokens/",
202+
"/machine-to-machine-applications/m2m-workflow-automation/":
203+
"/machine-to-machine-applications/m2m-workflow-automation/m2m-workflow/",
204+
"/machine-to-machine-applications/organization-scoped-m2m-apps/":
205+
"/machine-to-machine-applications/organization-scoped-m2m-apps/enforce-org-m2m-access-in-your-api/",
206+
"/machine-to-machine-applications/troubleshooting-m2m/":
207+
"/machine-to-machine-applications/troubleshooting-m2m/troubleshoot-m2m-token-errors/",
208+
209+
// Manage your account section subfolder redirects
210+
"/manage-your-account/business-information/":
211+
"/manage-your-account/business-information/change-your-business-time-zone/",
212+
"/manage-your-account/profile-and-plan/":
213+
"/manage-your-account/profile-and-plan/change-kinde-plan/",
214+
"/manage-your-account/your-data/":
215+
"/manage-your-account/your-data/check-your-mau/",
216+
217+
// Manage users section subfolder redirects
218+
"/manage-users/access-control/":
219+
"/manage-users/access-control/accept-policies-signup/",
220+
"/manage-users/add-and-edit/":
221+
"/manage-users/add-and-edit/add-and-edit-users/",
222+
"/manage-users/roles-and-permissions/":
223+
"/manage-users/roles-and-permissions/apply-roles-and-permissions-to-users/",
224+
"/manage-users/view-activity/":
225+
"/manage-users/view-activity/hotjar/",
226+
227+
// Properties section subfolder redirects
228+
"/properties/work-with-properties/":
229+
"/properties/work-with-properties/manage-properties/",
230+
231+
// Releases section subfolder redirects
232+
"/releases/about/":
233+
"/releases/about/about-feature-flags/",
234+
"/releases/feature-flags/":
235+
"/releases/feature-flags/add-feature-flag/",
236+
"/releases/guides/":
237+
"/releases/guides/guide-to-app-store-approvals/",
238+
239+
// Trust center section subfolder redirects
240+
"/trust-center/agreements/":
241+
"/trust-center/agreements/end-user-licence-agreement/",
242+
"/trust-center/kinde-performance/":
243+
"/trust-center/kinde-performance/service-status/",
244+
"/trust-center/privacy-and-compliance/":
245+
"/trust-center/privacy-and-compliance/compliance/",
246+
"/trust-center/security/":
247+
"/trust-center/security/security-at-kinde/",
248+
249+
// Workflows section subfolder redirects
250+
"/workflows/bindings/":
251+
"/workflows/bindings/access-token-binding/",
252+
"/workflows/configuration/":
253+
"/workflows/configuration/bindings/",
254+
"/workflows/example-workflows/":
255+
"/workflows/example-workflows/existing-password-provided-workflow/",
256+
"/workflows/getting-started/":
257+
"/workflows/getting-started/connect-repo-for-workflows/",
258+
"/workflows/manage-workflows/":
259+
"/workflows/manage-workflows/create-workflow/",
260+
"/workflows/observability/":
261+
"/workflows/observability/workflow-build-logs/",
64262
},
65263
markdown: {
66264
rehypePlugins: [

scripts/validate-links.js

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,48 @@ const __filename = fileURLToPath(import.meta.url);
99
const __dirname = path.dirname(__filename);
1010

1111
const distFolder = path.join(__dirname, "../dist");
12+
const astroConfigPath = path.join(__dirname, "../astro.config.mjs");
13+
14+
// Function to extract redirect destinations from astro.config.mjs
15+
function getRedirectDestinations() {
16+
try {
17+
const configContent = fs.readFileSync(astroConfigPath, "utf-8");
18+
19+
// Extract the redirects object using regex
20+
const redirectsMatch = configContent.match(/redirects:\s*{([^}]+)}/s);
21+
if (!redirectsMatch) {
22+
console.log(chalk.yellow("No redirects found in astro.config.mjs"));
23+
return [];
24+
}
25+
26+
const redirectsSection = redirectsMatch[1];
27+
28+
// Extract all destination URLs (the values after the colons)
29+
const destinationMatches = redirectsSection.match(/:\s*"([^"]+)"/g);
30+
if (!destinationMatches) {
31+
console.log(chalk.yellow("No redirect destinations found in astro.config.mjs"));
32+
return [];
33+
}
34+
35+
// Clean up the matches to get just the URLs
36+
const destinations = destinationMatches.map(match => {
37+
// Remove the ': "' prefix and '"' suffix
38+
return match.replace(/:\s*"/, '').replace(/"$/, '');
39+
});
40+
41+
console.log(chalk.blue(`Found ${destinations.length} redirect destinations`));
42+
return destinations;
43+
44+
} catch (error) {
45+
console.error(chalk.red(`Error reading astro.config.mjs: ${error.message}`));
46+
return [];
47+
}
48+
}
49+
50+
// Function to check if a URL is a redirect destination
51+
function isRedirectDestination(url, redirectDestinations) {
52+
return redirectDestinations.includes(url);
53+
}
1254

1355
// Function to read all HTML files from a directory
1456
function readHtmlFiles(dir) {
@@ -63,7 +105,7 @@ function anchorExists(html, anchor) {
63105
}
64106

65107
// Function to validate links
66-
function validateLinks(htmlFiles) {
108+
function validateLinks(htmlFiles, redirectDestinations) {
67109
let invalidLinks = [];
68110

69111
htmlFiles.forEach((file) => {
@@ -74,6 +116,13 @@ function validateLinks(htmlFiles) {
74116
// Split by the first occurrence of `#` to allow fragments with slashes
75117
const [pathWithoutHash, ...hashParts] = link.split("#");
76118
const hash = hashParts.length ? hashParts.join("#") : null;
119+
120+
// Check if this is a redirect destination - if so, skip validation
121+
if (isRedirectDestination(pathWithoutHash, redirectDestinations)) {
122+
console.log(chalk.yellow(`Skipping redirect destination: ${pathWithoutHash}`));
123+
return;
124+
}
125+
77126
const resolvedPath = path.join(distFolder, pathWithoutHash);
78127
const normalizedPath = path.normalize(resolvedPath);
79128
const ext = path.extname(normalizedPath);
@@ -109,6 +158,9 @@ function validateLinks(htmlFiles) {
109158

110159
// Main function
111160
function main() {
161+
// Get redirect destinations from astro.config.mjs
162+
const redirectDestinations = getRedirectDestinations();
163+
112164
const htmlFiles = readHtmlFiles(distFolder);
113165
const allLinks = new Set();
114166

@@ -118,7 +170,7 @@ function main() {
118170
links.forEach((link) => allLinks.add(link));
119171
});
120172

121-
const invalidLinks = validateLinks(htmlFiles);
173+
const invalidLinks = validateLinks(htmlFiles, redirectDestinations);
122174

123175
if (invalidLinks.length > 0) {
124176
console.log(chalk.red("Invalid Links:"));

src/content/docs/authenticate/about-auth/identity-and-verification.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,15 @@ When you set up an enterprise connection or a social connection, you can select
9898

9999
If a social provider gives us a new first name, last name or picture for a user, Kinde updates these fields in the user profile to match those supplied to us.
100100

101-
This is on by default, but you can turn it off if you wish to keep a static profile. [About profile sync](/manage-users/about/#user-profiles-are-synced-to-kinde).
101+
This is on by default, but you can turn it off if you wish to keep a static profile. [About profile sync](/manage-users/about/).
102102

103103
If you have syncing off at an environment level but turned on at a social connection level we will honor the request for the social connection to sync.
104104

105105
### Enterprise connection syncing
106106

107107
If an enterprise provider gives us a new first name, last name, or picture for a user, Kinde updates these fields in the user profile to match those supplied to us.
108108

109-
This is on by default, but you can turn it off if you wish to keep a static profile. [About profile sync](/manage-users/about/#user-profiles-are-synced-to-kinde).
109+
This is on by default, but you can turn it off if you wish to keep a static profile. [About profile sync](/manage-users/about/).
110110

111111
If you have syncing off at an environment level but turned on at an enterprise connection level we will honor the request for the enterprise connection to sync.
112112

src/content/docs/authenticate/manage-authentication/session-management-per-organization.mdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ relatedArticles:
77
- 76e2d2d3-830a-43b0-8b7b-8d0b0316b776
88
- 5a248c6f-c1ae-480a-95c3-d3c69c81598d
99
- 4ed081b0-7853-49be-b5fd-22a84a86bdad
10+
app_context:
11+
- m: organization_details
12+
- s: sessions
1013
description: Guide to managing Kinde authenticated sessions at the organization level including session persistence and inactivity timeouts for enterprise customers.
1114
metadata:
1215
topics: [authenticate]

0 commit comments

Comments
 (0)