-
Notifications
You must be signed in to change notification settings - Fork 5
fix(platform): require organization name (#1951) #2101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ import { | |
|
|
||
| import { assertValidOrgSlug } from '../lib/shared/constants/org-slug'; | ||
| import { isReservedOrgSlug } from '../lib/shared/constants/reserved-org-slugs'; | ||
| import { organizationNameSchema } from '../lib/shared/schemas/organizations'; | ||
| import { sessionIdleWindowSeconds } from '../lib/shared/session-idle'; | ||
| import { getOrganizationDefaultLocale } from '../lib/shared/utils/get-organization-default-locale'; | ||
| import { isRecord, getString } from '../lib/utils/type-utils'; | ||
|
|
@@ -708,6 +709,22 @@ export const getAuthOptions = (ctx: GenericCtx<DataModel>) => { | |
| // through a `Record<string, unknown>` view so the field | ||
| // shape matches Better Auth's loose update payload type. | ||
| const orgPatch = data.organization as Record<string, unknown>; | ||
| // Org name is required: reject a rename that clears it (empty or | ||
| // whitespace-only). Mirrors the client-side `.min(1)` validation so | ||
| // an empty name can't slip past the auth boundary via a direct API | ||
| // call. Only enforced when `name` is part of the patch — a name-less | ||
| // update (e.g. locale-only) leaves the stored name untouched. | ||
| if (orgPatch.name !== undefined) { | ||
| const parsedName = organizationNameSchema().safeParse( | ||
| orgPatch.name, | ||
| ); | ||
| if (!parsedName.success) { | ||
| throw new APIError('BAD_REQUEST', { | ||
| message: 'Organization name is required.', | ||
| }); | ||
| } | ||
| orgPatch.name = parsedName.data; | ||
| } | ||
|
Comment on lines
+712
to
+727
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift Unify organization-name validation through one shared Zod schema. Line 711 introduces a second, manual validator for ♻️ Suggested direction+// shared (e.g. services/platform/lib/shared/schemas/organization.ts)
+export const organizationNameSchema = z.string().trim().min(1);
// services/platform/convex/auth.ts
-const rawName = orgPatch.name;
-if (rawName !== undefined) {
- if (typeof rawName !== 'string' || rawName.trim().length === 0) {
- throw new APIError('BAD_REQUEST', {
- message: 'Organization name is required.',
- });
- }
- orgPatch.name = rawName.trim();
-}
+if (orgPatch.name !== undefined) {
+ const parsed = organizationNameSchema.safeParse(orgPatch.name);
+ if (!parsed.success) {
+ throw new APIError('BAD_REQUEST', {
+ message: 'Organization name is required.',
+ });
+ }
+ orgPatch.name = parsed.data;
+}As per coding guidelines, "Validate at boundaries with Zod; shared schemas in services/platform/lib/shared/schemas/, imported on both client and server." 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| const rawSlug = orgPatch.slug; | ||
| if (typeof rawSlug !== 'string') return; | ||
| const normalizedSlug = rawSlug.toLowerCase(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Add an explicit whitespace-only edge-case test.
The new suite covers error (
'') and happy path ('New name'), but it misses the trim edge (' ') that this PR is specifically enforcing.As per coding guidelines: “Tests carry the change: unit (happy + one edge + one error).”
Suggested test addition
describe('OrganizationSettingsView name validation', () => { + it('treats whitespace-only org name as invalid', async () => { + render(<ValidationHarness orgName="Acme" />); + await waitFor(() => expect(holder.current?.isLoading).toBe(false)); + + const orgNameField = screen.getByRole('textbox', { + name: en.settings.organization.title, + }); + fireEvent.change(orgNameField, { target: { value: ' ' } }); + + await waitFor(() => + expect( + screen.getByText(en.settings.organization.nameRequired), + ).toBeInTheDocument(), + ); + expect(holder.current?.isValid).toBe(false); + }); + it('blocks an empty org name with an inline error and an invalid form', async () => {📝 Committable suggestion
🤖 Prompt for AI Agents
Source: Coding guidelines