Skip to content

Commit

Permalink
Ability to delete tenant
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Jan 31, 2024
1 parent 0b9bd91 commit 526c61d
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 16 deletions.
27 changes: 19 additions & 8 deletions api/src/routers/tenant.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import { z } from "zod";
import { authedProcedure, createTRPCRouter } from "../trpc";
import { authedProcedure, createTRPCRouter, tenantProcedure } from "../trpc";
import { encodeId } from "../utils";
import { db, tenantAccounts, tenants } from "../db";
import { db, devices, policies, tenantAccounts, tenants, users } from "../db";
import { eq } from "drizzle-orm";

export const tenantRouter = createTRPCRouter({
// get: procedure.input(z.object({ text: z.string() })).query(({ input }) => {
// return {
// greeting: `Hello ${input.text}`,
// };
// }),

create: authedProcedure
.input(z.object({ name: z.string().min(1) }))
.mutation(async ({ ctx, input }) => {
Expand All @@ -34,4 +29,20 @@ export const tenantRouter = createTRPCRouter({
id: encodeId("tenant", lastInsertId),
};
}),

delete: tenantProcedure.mutation(async ({ ctx }) => {
// TODO: Ensure no outstanding bills

await db.transaction(async (tx) => {
await db.delete(tenants).where(eq(tenants.id, ctx.tenantId));
await db
.delete(tenantAccounts)
.where(eq(tenantAccounts.tenantId, ctx.tenantId));
await db.delete(users).where(eq(users.tenantId, ctx.tenantId));
await db.delete(policies).where(eq(policies.tenantId, ctx.tenantId));
await db.delete(devices).where(eq(devices.tenantId, ctx.tenantId)); // TODO: Don't do this
});

// TODO: Schedule all devices for unenrolment
}),
});
88 changes: 88 additions & 0 deletions forge/src/routes/(dash)/[tenant]/settings/DeleteTenantButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { As } from "@kobalte/core";
import { useNavigate } from "@solidjs/router";
import { createSignal } from "solid-js";
import {
Button,
DialogContent,
DialogDescription,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
Input,
useController,
} from "~/components/ui";
import { trpc } from "~/lib";
import { useGlobalCtx } from "~/lib/globalCtx";

export function DeleteTenantButton() {
return (
<DialogRoot>
<DialogTrigger asChild>
<As component={Button} variant="destructive">
Delete
</As>
</DialogTrigger>

<DialogContent>
<DialogHeader>
<DialogTitle>Delete tenant?</DialogTitle>
<DialogDescription>
Are you sure you want to delete your tenant along with all{" "}
<b>users</b>, <b>devices</b>, <b>policies</b>, <b>applications</b>{" "}
and <b>groups</b>?
</DialogDescription>
</DialogHeader>

<Body />
</DialogContent>
</DialogRoot>
);
}

// `DialogContent` is only rendered when open. We split this out so the `activeTenantName` works.
function Body() {
const globalCtx = useGlobalCtx();
const controller = useController();
const navigate = useNavigate();

const [activeTenantName] = createSignal(globalCtx.activeTenant!.name); // We cache this so it doesn't change before the dialog closes
const [input, setInput] = createSignal<string>();
const deleteTenant = trpc.tenant.delete.useMutation(() => ({
onSuccess: async () => {
// Session also holds tenants
await globalCtx.refetchSession();

const nextTenant = globalCtx.session.tenants?.[0]?.id;
controller.setOpen(false);
if (nextTenant) {
globalCtx.setActiveTenant(nextTenant);
} else {
navigate(`/`);
}

// We ensure the form stays disabled until the animation is done.
await new Promise((r) => setTimeout(r, 1000));
},
}));

return (
<>
<p class="text-muted-foreground text-sm">
To confirm, type "{activeTenantName()}" in the box below
</p>
<Input
value={input()}
onInput={(e) => setInput(e.currentTarget.value)}
disabled={deleteTenant.isPending}
/>
<Button
variant="destructive"
disabled={deleteTenant.isPending || input() !== activeTenantName()}
onClick={() => deleteTenant.mutate()}
>
Delete "{activeTenantName()}"
</Button>
</>
);
}
18 changes: 10 additions & 8 deletions forge/src/routes/(dash)/[tenant]/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SelectTrigger,
SelectValue,
} from "~/components/ui";
import { DeleteTenantButton } from "./DeleteTenantButton";

export default function Page() {
return (
Expand All @@ -22,10 +23,7 @@ export default function Page() {

<Card class="w-[350px]">
<CardHeader>
<CardTitle>Create project</CardTitle>
<CardDescription>
Deploy your new project in one-click.
</CardDescription>
<CardTitle>Tenant Settings</CardTitle>
</CardHeader>
<CardContent>
<form>
Expand All @@ -50,12 +48,16 @@ export default function Page() {
</div>
</div>
</form>

<DeleteTenantButton />
</CardContent>
<CardFooter class="flex justify-between">
<Button variant="outline">Cancel</Button>
<Button>Deploy</Button>
</CardFooter>
</Card>
</div>
);
}

// TODO: Rename tenant

// TODO: Tenant user management
// TODO: Link with AzureAD
// TODO: Import devices from Intune/Jamf

0 comments on commit 526c61d

Please sign in to comment.