chore: bump version to 2.23.2 and enhance team account creation (#440)

* chore: bump version to 2.23.2 and enhance team account creation

- Updated application version from 2.23.1 to 2.23.2 in package.json.
- Enhanced team account creation to support slugs for non-Latin names, including validation and UI updates.
- Updated localization files to reflect new slug requirements and error messages.
- Refactored related schemas and server actions to accommodate slug handling in team account creation and updates.

* refactor: remove old trigger and function for adding current user to new account

- Dropped the trigger "add_current_user_to_new_account" and the associated function from the database schema.
- Updated permissions for the function public.create_team_account to ensure proper access control.
This commit is contained in:
Giancarlo Buomprisco
2026-01-08 14:18:13 +01:00
committed by GitHub
parent e1bfbc8106
commit 0636f8cf11
21 changed files with 2042 additions and 1619 deletions

View File

@@ -1,20 +1,20 @@
'use server';
import 'server-only';
import { redirect } from 'next/navigation';
import { enhanceAction } from '@kit/next/actions';
import { getLogger } from '@kit/shared/logger';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { CreateTeamSchema } from '../../schema/create-team.schema';
import { createAccountCreationPolicyEvaluator } from '../policies';
import { createCreateTeamAccountService } from '../services/create-team-account.service';
export const createTeamAccountAction = enhanceAction(
async ({ name }, user) => {
async ({ name, slug }, user) => {
const logger = await getLogger();
const client = getSupabaseServerClient();
const service = createCreateTeamAccountService(client);
const service = createCreateTeamAccountService();
const ctx = {
name: 'team-accounts.create',
@@ -52,12 +52,19 @@ export const createTeamAccountAction = enhanceAction(
}
}
// Service throws on error, so no need to check for error
const { data } = await service.createNewOrganizationAccount({
const { data, error } = await service.createNewOrganizationAccount({
name,
userId: user.id,
slug,
});
if (error === 'duplicate_slug') {
return {
error: true,
message: 'teams:duplicateSlugError',
};
}
logger.info(ctx, `Team account created`);
const accountHomePath = '/home/' + data.slug;

View File

@@ -12,7 +12,9 @@ export const updateTeamAccountName = enhanceAction(
async (params) => {
const client = getSupabaseServerClient();
const logger = await getLogger();
const { name, path, slug } = params;
const { name, path, slug, newSlug } = params;
const slugToUpdate = newSlug ?? slug;
const ctx = {
name: 'team-accounts.update',
@@ -25,7 +27,7 @@ export const updateTeamAccountName = enhanceAction(
.from('accounts')
.update({
name,
slug,
slug: slugToUpdate,
})
.match({
slug,
@@ -34,17 +36,25 @@ export const updateTeamAccountName = enhanceAction(
.single();
if (error) {
// Handle duplicate slug error
if (error.code === '23505') {
return {
success: false,
error: 'teams:duplicateSlugError',
};
}
logger.error({ ...ctx, error }, `Failed to update team name`);
throw error;
}
const newSlug = data.slug;
const updatedSlug = data.slug;
logger.info(ctx, `Team name updated`);
if (newSlug) {
const nextPath = path.replace('[account]', newSlug);
if (updatedSlug && updatedSlug !== slug) {
const nextPath = path.replace('[account]', updatedSlug);
redirect(nextPath);
}

View File

@@ -1,45 +1,57 @@
import 'server-only';
import { SupabaseClient } from '@supabase/supabase-js';
import { getLogger } from '@kit/shared/logger';
import { Database } from '@kit/supabase/database';
import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client';
export function createCreateTeamAccountService(
client: SupabaseClient<Database>,
) {
return new CreateTeamAccountService(client);
export function createCreateTeamAccountService() {
return new CreateTeamAccountService();
}
class CreateTeamAccountService {
private readonly namespace = 'accounts.create-team-account';
constructor(private readonly client: SupabaseClient<Database>) {}
async createNewOrganizationAccount(params: { name: string; userId: string }) {
async createNewOrganizationAccount(params: {
name: string;
userId: string;
slug?: string;
}) {
const client = getSupabaseServerAdminClient();
const logger = await getLogger();
const ctx = { ...params, namespace: this.namespace };
logger.info(ctx, `Creating new team account...`);
const { error, data } = await this.client.rpc('create_team_account', {
// Call the RPC function which handles:
// 1. Checking if team accounts are enabled
// 2. Creating the account with name, slug, and primary_owner_user_id
// 3. Creating membership for the owner (atomic transaction)
const { error, data } = await client.rpc('create_team_account', {
account_name: params.name,
user_id: params.userId,
account_slug: params.slug,
});
if (error) {
logger.error(
{
error,
...ctx,
},
`Error creating team account`,
);
// Handle duplicate slug error
if (error.code === '23505' && error.message.includes('slug')) {
logger.warn(
{ ...ctx, slug: params.slug },
`Duplicate slug detected, rejecting team creation`,
);
return {
data: null,
error: 'duplicate_slug' as const,
};
}
logger.error({ error, ...ctx }, `Error creating team account`);
throw new Error('Error creating team account');
}
logger.info(ctx, `Team account created successfully`);
return { data, error };
return { data, error: null };
}
}