From 57d476ac8f1a36112bad1ae5680afa3cee67d9b6 Mon Sep 17 00:00:00 2001 From: Madison Date: Thu, 3 Jul 2025 12:42:28 -0500 Subject: [PATCH 1/5] Remove admin section from API sidebar. (#735) --- .../components/layouts/api/api-sidebar.tsx | 106 ++++++++++-------- 1 file changed, 62 insertions(+), 44 deletions(-) diff --git a/docs/src/components/layouts/api/api-sidebar.tsx b/docs/src/components/layouts/api/api-sidebar.tsx index 7014a23a0..239904c4c 100644 --- a/docs/src/components/layouts/api/api-sidebar.tsx +++ b/docs/src/components/layouts/api/api-sidebar.tsx @@ -242,56 +242,74 @@ export function ApiSidebarContent({ pages = [] }: { pages?: PageData[] }) { Overview - {Object.entries(organizedPages).map(([sectionKey, section]) => ( -
- {section.title} + {Object.entries(organizedPages) + .filter(([sectionKey]) => sectionKey !== 'admin') // Hide admin section from sidebar + .sort(([aKey], [bKey]) => { + // Define the desired order of sections + const sectionOrder = ['client', 'server', 'webhooks']; + const aIndex = sectionOrder.indexOf(aKey); + const bIndex = sectionOrder.indexOf(bKey); + // If both sections are in our defined order, sort by that order + if (aIndex !== -1 && bIndex !== -1) { + return aIndex - bIndex; + } + // If only one is in our defined order, prioritize it + if (aIndex !== -1) return -1; + if (bIndex !== -1) return 1; + // If neither is in our defined order, sort alphabetically + //eslint-disable-next-line + return aKey.localeCompare(bKey); + }) + .map(([sectionKey, section]) => ( +
+ {section.title} - {/* Section-level pages */} - {section.pages.length > 0 && section.pages.map((page: PageData) => ( - - {page.data.title || formatTitle(page.slugs[page.slugs.length - 1])} - - ))} + {/* Section-level pages */} + {section.pages.length > 0 && section.pages.map((page: PageData) => ( + + {page.data.title || formatTitle(page.slugs[page.slugs.length - 1])} + + ))} - {/* Grouped pages */} - {Object.entries(section.groups).map(([groupKey, group]: [string, OrganizedGroup]) => ( - - {group.pages.map((page: PageData) => { - const method = getHttpMethod(page); - const title = page.data.title || formatTitle(page.slugs[page.slugs.length - 1]); + {/* Grouped pages */} + {Object.entries(section.groups).map(([groupKey, group]: [string, OrganizedGroup]) => ( + + {group.pages.map((page: PageData) => { + const method = getHttpMethod(page); + const title = page.data.title || formatTitle(page.slugs[page.slugs.length - 1]); + + // Special handling for webhooks (EVENT badge instead of HTTP method) + if (sectionKey === 'webhooks') { + return ( + +
+ + EVENT + + {title} +
+
+ ); + } - // Special handling for webhooks (EVENT badge instead of HTTP method) - if (sectionKey === 'webhooks') { return ( - -
- - EVENT - - {title} -
+ + {title} ); - } - - return ( - - {title} - - ); - })} -
- ))} -
- ))} + })} + + ))} +
+ ))} From 8b3a94928ab051fe289422675567d07c567c6f24 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Thu, 3 Jul 2025 13:59:46 -0700 Subject: [PATCH 2/5] No longer remove dots from normalized emails --- apps/backend/src/lib/emails.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/backend/src/lib/emails.tsx b/apps/backend/src/lib/emails.tsx index 7c54691eb..ca79a750d 100644 --- a/apps/backend/src/lib/emails.tsx +++ b/apps/backend/src/lib/emails.tsx @@ -373,8 +373,6 @@ export function normalizeEmail(email: string): string { throw new TypeError('normalize-email expects a string'); } - const removeDotsDomains = ['gmail.com', 'googlemail.com', 'live.com']; - const emailLower = email.trim().toLowerCase(); const emailParts = emailLower.split(/@/); @@ -384,10 +382,6 @@ export function normalizeEmail(email: string): string { let [username, domain] = emailParts; - if (removeDotsDomains.includes(domain)) { - username = username.replace(/\.+/g, ''); - } - return `${username}@${domain}`; } From 668ab68ebb417b47e5a3813d294bda9ae50fa9f8 Mon Sep 17 00:00:00 2001 From: Zai Shi Date: Thu, 3 Jul 2025 14:12:14 -0700 Subject: [PATCH 3/5] Update Docker build workflow to use ubicloud --- .github/workflows/docker-server-build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-server-build.yaml b/.github/workflows/docker-server-build.yaml index 7e477eae1..09d2a5ec8 100644 --- a/.github/workflows/docker-server-build.yaml +++ b/.github/workflows/docker-server-build.yaml @@ -13,7 +13,7 @@ concurrency: jobs: build-server: name: Docker Build and Push Server - runs-on: ubuntu-latest + runs-on: ubicloud-standard-8 steps: - name: Checkout uses: actions/checkout@v4 From d58dda3ed83232bcb527ac617199f33f97fc04c6 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Thu, 3 Jul 2025 14:35:56 -0700 Subject: [PATCH 4/5] Revert "No longer remove dots from normalized emails" This reverts commit 8b3a94928ab051fe289422675567d07c567c6f24. --- apps/backend/src/lib/emails.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/backend/src/lib/emails.tsx b/apps/backend/src/lib/emails.tsx index ca79a750d..7c54691eb 100644 --- a/apps/backend/src/lib/emails.tsx +++ b/apps/backend/src/lib/emails.tsx @@ -373,6 +373,8 @@ export function normalizeEmail(email: string): string { throw new TypeError('normalize-email expects a string'); } + const removeDotsDomains = ['gmail.com', 'googlemail.com', 'live.com']; + const emailLower = email.trim().toLowerCase(); const emailParts = emailLower.split(/@/); @@ -382,6 +384,10 @@ export function normalizeEmail(email: string): string { let [username, domain] = emailParts; + if (removeDotsDomains.includes(domain)) { + username = username.replace(/\.+/g, ''); + } + return `${username}@${domain}`; } From fe3bd7a201d5d1b164cac9feefdc5a990ece81be Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Thu, 3 Jul 2025 15:43:36 -0700 Subject: [PATCH 5/5] Re-add CLI auth docs --- docs/public/stack-auth-cli-template.py | 56 ++++++++++++++++++++ docs/templates/others/cli-authentication.mdx | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 docs/public/stack-auth-cli-template.py diff --git a/docs/public/stack-auth-cli-template.py b/docs/public/stack-auth-cli-template.py new file mode 100644 index 000000000..126d19b35 --- /dev/null +++ b/docs/public/stack-auth-cli-template.py @@ -0,0 +1,56 @@ +import time +import requests +import webbrowser +import urllib.parse + +def prompt_cli_login( + *, + base_url: str = "https://api.stack-auth.com", + app_url: str, + project_id: str, + publishable_client_key: str, +): + if not app_url: + raise Exception("app_url is required and must be set to the URL of the app you're authenticating with") + if not project_id: + raise Exception("project_id is required") + if not publishable_client_key: + raise Exception("publishable_client_key is required") + + def post(endpoint, json): + return requests.request( + 'POST', + f'{base_url}{endpoint}', + headers={ + 'Content-Type': 'application/json', + 'x-stack-project-id': project_id, + 'x-stack-access-type': 'client', + 'x-stack-publishable-client-key': publishable_client_key, + }, + json=json, + ) + + # Step 1: Initiate the CLI auth process + init = post('/api/v1/auth/cli', { + 'expires_in_millis': 10 * 60 * 1000, + }) + if init.status_code != 200: + raise Exception(f"Failed to initiate CLI auth: {init.status_code} {init.text}") + polling_code = init.json()['polling_code'] + login_code = init.json()['login_code'] + + # Step 2: Open the browser for the user to authenticate + url = f'{app_url}/handler/cli-auth-confirm?login_code={urllib.parse.quote(login_code)}' + print(f"Opening browser to authenticate. If it doesn't open automatically, please visit:\n{url}") + webbrowser.open(url) + + # Step 3: Retrieve the token + while True: + status = post('/api/v1/auth/cli/poll', { + 'polling_code': polling_code, + }) + if status.status_code != 200 and status.status_code != 201: + raise Exception(f"Failed to get CLI auth status: {status.status_code} {status.text}") + if status.json()['status'] == 'success': + return status.json()['refresh_token'] + time.sleep(2) diff --git a/docs/templates/others/cli-authentication.mdx b/docs/templates/others/cli-authentication.mdx index a671df140..e95632713 100644 --- a/docs/templates/others/cli-authentication.mdx +++ b/docs/templates/others/cli-authentication.mdx @@ -5,7 +5,7 @@ description: How to authenticate a command line application using Stack Auth If you're building a command line application that runs in a terminal, you can use Stack Auth to let your users log in to their accounts. -To do so, we provide a Python template that you can use as a starting point. [Download it here](https://github.com/stack-auth/stack-auth/tree/main/docs/examples/stack_auth_cli_template.py) and copy it into your project, for example: +To do so, we provide a Python template that you can use as a starting point. [Download it here](https://github.com/stack-auth/stack-auth/tree/main/docs/public/stack_auth_cli_template.py) and copy it into your project, for example: ```py └─ my-python-app