Remove team account related services and actions

Removed services and actions related to team account deletion as well as updated paths within other dependent files, better reflecting their new locations. Also, added a new service titled 'AccountBillingService' for handling billing-related operations and restructured the form layout and handled translation in 'team-account-danger-zone' component.
This commit is contained in:
giancarlo
2024-03-28 15:27:56 +08:00
parent 3ac4d3b00d
commit 041efb89fb
77 changed files with 1998 additions and 1553 deletions

View File

@@ -0,0 +1,58 @@
'use server';
import { redirect } from 'next/navigation';
import { z } from 'zod';
import { Logger } from '@kit/shared/logger';
import { requireAuth } from '@kit/supabase/require-auth';
import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client';
import { CreateTeamSchema } from '../../schema/create-team.schema';
import { CreateTeamAccountService } from '../services/create-team-account.service';
const TEAM_ACCOUNTS_HOME_PATH = z
.string({
required_error: 'variable TEAM_ACCOUNTS_HOME_PATH is required',
})
.min(1)
.parse(process.env.TEAM_ACCOUNTS_HOME_PATH);
export async function createOrganizationAccountAction(
params: z.infer<typeof CreateTeamSchema>,
) {
const { name: accountName } = CreateTeamSchema.parse(params);
const client = getSupabaseServerActionClient();
const service = new CreateTeamAccountService(client);
const session = await requireAuth(client);
if (session.error) {
redirect(session.redirectTo);
}
const userId = session.data.user.id;
const createAccountResponse = await service.createNewOrganizationAccount({
name: accountName,
userId,
});
if (createAccountResponse.error) {
Logger.error(
{
userId,
error: createAccountResponse.error,
name: 'accounts',
},
`Error creating team account`,
);
throw new Error('Error creating team account');
}
const accountHomePath =
TEAM_ACCOUNTS_HOME_PATH + '/' + createAccountResponse.data.slug;
redirect(accountHomePath);
}

View File

@@ -0,0 +1,60 @@
'use server';
import { redirect } from 'next/navigation';
import { SupabaseClient } from '@supabase/supabase-js';
import { Database } from '@kit/supabase/database';
import { requireAuth } from '@kit/supabase/require-auth';
import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client';
import { DeleteTeamAccountSchema } from '../../schema/delete-team-account.schema';
import { DeleteTeamAccountService } from '../services/delete-team-account.service';
export async function deleteTeamAccountAction(formData: FormData) {
const params = DeleteTeamAccountSchema.parse(
Object.fromEntries(formData.entries()),
);
const client = getSupabaseServerActionClient();
// Check if the user has the necessary permissions to delete the team account
await assertUserPermissionsToDeleteTeamAccount(client, params.accountId);
// Get the Supabase client and create a new service instance.
const service = new DeleteTeamAccountService();
// Delete the team account and all associated data.
await service.deleteTeamAccount(
getSupabaseServerActionClient({
admin: true,
}),
params,
);
return redirect('/home');
}
async function assertUserPermissionsToDeleteTeamAccount(
client: SupabaseClient<Database>,
accountId: string,
) {
const auth = await requireAuth(client);
if (auth.error ?? !auth.data.user.id) {
throw new Error('Authentication required');
}
const userId = auth.data.user.id;
const { data, error } = await client
.from('accounts')
.select('id')
.eq('primary_owner_user_id', userId)
.eq('is_personal_account', false)
.eq('id', accountId);
if (error ?? !data) {
throw new Error('Account not found');
}
}

View File

@@ -0,0 +1,16 @@
'use server';
import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client';
import { LeaveTeamAccountSchema } from '../../schema/leave-team-account.schema';
import { LeaveAccountService } from '../services/leave-account.service';
export async function leaveTeamAccountAction(formData: FormData) {
const body = Object.fromEntries(formData.entries());
const params = LeaveTeamAccountSchema.parse(body);
const service = new LeaveAccountService(getSupabaseServerActionClient());
await service.leaveTeamAccount(params);
return { success: true };
}

View File

@@ -0,0 +1,39 @@
'use server';
import { redirect } from 'next/navigation';
import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client';
export async function updateTeamAccountName(params: {
name: string;
slug: string;
path: string;
}) {
const client = getSupabaseServerComponentClient();
const { error, data } = await client
.from('accounts')
.update({
name: params.name,
slug: params.slug,
})
.match({
slug: params.slug,
})
.select('slug')
.single();
if (error) {
throw error;
}
const newSlug = data.slug;
if (newSlug) {
const path = params.path.replace('[account]', newSlug);
redirect(path);
}
return { success: true };
}

View File

@@ -0,0 +1,89 @@
'use server';
import { revalidatePath } from 'next/cache';
import { SupabaseClient } from '@supabase/supabase-js';
import { z } from 'zod';
import { Database } from '@kit/supabase/database';
import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client';
import { DeleteInvitationSchema } from '../../schema/delete-invitation.schema';
import { InviteMembersSchema } from '../../schema/invite-members.schema';
import { UpdateInvitationSchema } from '../../schema/update-invitation-schema';
import { AccountInvitationsService } from '../services/account-invitations.service';
/**
* Creates invitations for inviting members.
*/
export async function createInvitationsAction(params: {
account: string;
invitations: z.infer<typeof InviteMembersSchema>['invitations'];
}) {
const client = getSupabaseServerActionClient();
await assertSession(client);
const { invitations } = InviteMembersSchema.parse({
invitations: params.invitations,
});
const service = new AccountInvitationsService(client);
await service.sendInvitations({ invitations, account: params.account });
revalidatePath('/home/[account]/members', 'page');
return { success: true };
}
/**
* Deletes an invitation specified by the invitation ID.
*
* @param {Object} params - The parameters for the method.
* @param {string} params.invitationId - The ID of the invitation to be deleted.
*
* @return {Object} - The result of the delete operation.
*/
export async function deleteInvitationAction(
params: z.infer<typeof DeleteInvitationSchema>,
) {
const invitation = DeleteInvitationSchema.parse(params);
const client = getSupabaseServerActionClient();
const { data, error } = await client.auth.getUser();
if (error ?? !data.user) {
throw new Error(`Authentication required`);
}
const service = new AccountInvitationsService(client);
await service.deleteInvitation(invitation);
return { success: true };
}
export async function updateInvitationAction(
params: z.infer<typeof UpdateInvitationSchema>,
) {
const client = getSupabaseServerActionClient();
const invitation = UpdateInvitationSchema.parse(params);
await assertSession(client);
const service = new AccountInvitationsService(client);
await service.updateInvitation(invitation);
return { success: true };
}
async function assertSession(client: SupabaseClient<Database>) {
const { data, error } = await client.auth.getUser();
if (error ?? !data.user) {
throw new Error(`Authentication required`);
}
}

View File

@@ -0,0 +1,75 @@
'use server';
import { SupabaseClient } from '@supabase/supabase-js';
import { Database } from '@kit/supabase/database';
import { getSupabaseServerActionClient } from '@kit/supabase/server-actions-client';
import { AccountMembersService } from '../services/account-members.service';
export async function removeMemberFromAccountAction(params: {
accountId: string;
userId: string;
}) {
const client = getSupabaseServerActionClient();
const { data, error } = await client.auth.getUser();
if (error ?? !data.user) {
throw new Error(`Authentication required`);
}
const service = new AccountMembersService(client);
await service.removeMemberFromAccount({
accountId: params.accountId,
userId: params.userId,
});
return { success: true };
}
export async function updateMemberRoleAction(params: {
accountId: string;
userId: string;
role: Database['public']['Enums']['account_role'];
}) {
const client = getSupabaseServerActionClient();
await assertSession(client);
const service = new AccountMembersService(client);
await service.updateMemberRole({
accountId: params.accountId,
userId: params.userId,
role: params.role,
});
return { success: true };
}
export async function transferOwnershipAction(params: {
accountId: string;
userId: string;
}) {
const client = getSupabaseServerActionClient();
await assertSession(client);
const service = new AccountMembersService(client);
await service.transferOwnership({
accountId: params.accountId,
userId: params.userId,
});
return { success: true };
}
async function assertSession(client: SupabaseClient<Database>) {
const { data, error } = await client.auth.getUser();
if (error ?? !data.user) {
throw new Error(`Authentication required`);
}
}