Skip to content

Commit

Permalink
Fix workspace deletion in Poke (#7951)
Browse files Browse the repository at this point in the history
  • Loading branch information
flvndvd authored Oct 8, 2024
1 parent 344aaa5 commit 326cb4f
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 26 deletions.
60 changes: 59 additions & 1 deletion front/lib/api/workspace.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import type {
LightWorkspaceType,
MembershipRoleType,
Result,
RoleType,
SubscriptionType,
UserTypeWithWorkspaces,
WorkspaceDomain,
WorkspaceSegmentationType,
WorkspaceType,
} from "@dust-tt/types";
import { ACTIVE_ROLES } from "@dust-tt/types";
import { ACTIVE_ROLES, Err, Ok } from "@dust-tt/types";
import { Op } from "sequelize";

import type { PaginationParams } from "@app/lib/api/pagination";
import type { Authenticator } from "@app/lib/auth";
import { Subscription } from "@app/lib/models/plan";
import { Workspace, WorkspaceHasDomain } from "@app/lib/models/workspace";
import { getStripeSubscription } from "@app/lib/plans/stripe";
import { MembershipResource } from "@app/lib/resources/membership_resource";
import { UserResource } from "@app/lib/resources/user_resource";
import { renderLightWorkspaceType } from "@app/lib/workspace";
import { launchDeleteWorkspaceWorkflow } from "@app/poke/temporal/client";

export async function getWorkspaceInfos(
wId: string
Expand Down Expand Up @@ -282,3 +287,56 @@ export async function unsafeGetWorkspacesByModelId(
})
).map((w) => renderLightWorkspaceType({ workspace: w }));
}

export async function areAllSubscriptionsCanceled(
workspace: LightWorkspaceType
): Promise<boolean> {
const subscriptions = await Subscription.findAll({
where: {
workspaceId: workspace.id,
stripeSubscriptionId: {
[Op.not]: null,
},
},
});

// If the workspace had a subscription, it must be canceled.
if (subscriptions.length > 0) {
for (const sub of subscriptions) {
if (!sub.stripeSubscriptionId) {
continue;
}

const stripeSubscription = await getStripeSubscription(
sub.stripeSubscriptionId
);

if (!stripeSubscription) {
continue;
}

if (stripeSubscription.status !== "canceled") {
return false;
}
}
}

return true;
}

export async function deleteWorkspace(
owner: LightWorkspaceType
): Promise<Result<void, Error>> {
const allSubscriptionsCanceled = await areAllSubscriptionsCanceled(owner);
if (!allSubscriptionsCanceled) {
return new Err(
new Error(
"The workspace cannot be deleted because there are active subscriptions."
)
);
}

await launchDeleteWorkspaceWorkflow({ workspaceId: owner.sId });

return new Ok(undefined);
}
22 changes: 18 additions & 4 deletions front/pages/api/poke/workspaces/[wId]/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import * as t from "io-ts";
import * as reporter from "io-ts-reporters";
import type { NextApiRequest, NextApiResponse } from "next";

import { setInternalWorkspaceSegmentation } from "@app/lib/api/workspace";
import {
deleteWorkspace,
setInternalWorkspaceSegmentation,
} from "@app/lib/api/workspace";
import { withSessionAuthentication } from "@app/lib/api/wrappers";
import { Authenticator, getSession } from "@app/lib/auth";
import { apiError } from "@app/logger/withlogging";
import { launchDeleteWorkspaceWorkflow } from "@app/poke/temporal/client";

export const WorkspaceTypeSchema = t.type({
segmentation: t.union([t.literal("interesting"), t.null]),
Expand Down Expand Up @@ -71,9 +73,21 @@ async function handler(
return res.status(200).json({
workspace,
});
case "DELETE":
await launchDeleteWorkspaceWorkflow({ workspaceId: owner.sId });

case "DELETE": {
const deleteRes = await deleteWorkspace(owner);
if (deleteRes.isErr()) {
return apiError(req, res, {
status_code: 400,
api_error: {
type: "invalid_request_error",
message: deleteRes.error.message,
},
});
}

return res.status(200).json({ success: true });
}

default:
return apiError(req, res, {
Expand Down
25 changes: 4 additions & 21 deletions front/poke/temporal/activities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { hardDeleteApp } from "@app/lib/api/apps";
import config from "@app/lib/api/config";
import { hardDeleteDataSource } from "@app/lib/api/data_sources";
import { hardDeleteVault } from "@app/lib/api/vaults";
import { areAllSubscriptionsCanceled } from "@app/lib/api/workspace";
import { Authenticator } from "@app/lib/auth";
import { AgentBrowseAction } from "@app/lib/models/assistant/actions/browse";
import { AgentDataSourceConfiguration } from "@app/lib/models/assistant/actions/data_sources";
Expand Down Expand Up @@ -56,6 +57,7 @@ import { frontSequelize } from "@app/lib/resources/storage";
import { Provider } from "@app/lib/resources/storage/models/apps";
import { UserResource } from "@app/lib/resources/user_resource";
import { VaultResource } from "@app/lib/resources/vault_resource";
import { renderLightWorkspaceType } from "@app/lib/workspace";
import logger from "@app/logger/logger";

export async function scrubDataSourceActivity({
Expand Down Expand Up @@ -158,28 +160,9 @@ export async function isWorkflowDeletableActivity({
workspaceId: string;
}) {
const auth = await Authenticator.internalAdminForWorkspace(workspaceId);
const workspace = auth.workspace();
if (!workspace) {
return false;
}

// Workspace must have no data sources.
if (
(await DataSourceResource.listByWorkspace(auth, { limit: 1 })).length > 0
) {
return false;
}
const workspace = await auth.getNonNullableWorkspace();

// For now we don't support deleting workspaces who had a paid subscription at some point.
const subscriptions = await Subscription.findAll({
where: {
workspaceId: workspace.id,
stripeSubscriptionId: {
[Op.not]: null,
},
},
});
return subscriptions.length === 0;
return areAllSubscriptionsCanceled(renderLightWorkspaceType({ workspace }));
}

export async function deleteConversationsActivity({
Expand Down

0 comments on commit 326cb4f

Please sign in to comment.