Skip to content

Commit

Permalink
Merge pull request #4171 from systeminit/wendy/eng-2604-redirect-to-p…
Browse files Browse the repository at this point in the history
…roduction-workspace-in-auth-portal

feat(auth) - prod workspace stuff for SaaS
  • Loading branch information
wendybujalski authored Jul 17, 2024
2 parents 3e1c032 + 0a62780 commit 80e6054
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 11 deletions.
1 change: 1 addition & 0 deletions app/auth-portal/src/pages/ProfilePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ const saveHandler = async () => {
const completeProfileReq = await authStore.COMPLETE_PROFILE({});
if (completeProfileReq.result.success) {
if (authStore.user?.emailVerified) {
tracker.trackEvent("workspace_launcher_widget_click");
window.location.href = `${API_HTTP_URL}/workspaces/${workspacesStore.defaultWorkspace.id}/go`;
} else {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
Expand Down
20 changes: 20 additions & 0 deletions app/auth-portal/src/pages/WorkspaceDetailsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@

<VormInput
v-if="createWorkspaceType === 'url'"
ref="urlInputRef"
v-model="draftWorkspace.instanceUrl"
label="URL"
autocomplete="url"
Expand Down Expand Up @@ -227,6 +228,8 @@ const props = defineProps({
workspaceId: { type: String as PropType<WorkspaceId>, required: true },
});
const urlInputRef = ref<InstanceType<typeof VormInput>>();
const { validationState, validationMethods } = useValidatedInputGroup();
const members = computed(() => workspacesStore.selectedWorkspaceMembers);
Expand Down Expand Up @@ -295,6 +298,23 @@ const createWorkspace = async () => {
draftWorkspace.instanceUrl = "https://app.systeminit.com";
} else if (createWorkspaceType.value === "local") {
draftWorkspace.instanceUrl = "localhost:8080";
} else {
if (draftWorkspace.instanceUrl.includes("app.systeminit")) {
// Can't create a Remote URL workspace with our URL!
urlInputRef.value?.setError(
'You cannot use an "app.systeminit" URL for a Remote URL Workspace. Use "Managed By System Initiative" instead.',
);
return;
} else if (
draftWorkspace.instanceUrl.includes("localhost") ||
draftWorkspace.instanceUrl.includes("127.0.0.1")
) {
// Can't create a Remote URL workspace with localhost!
urlInputRef.value?.setError(
'You cannot use a "localhost" URL for a Remote URL Workspace. Use "Local Dev Instance" instead.',
);
return;
}
}
if (validationMethods.hasError()) return;
Expand Down
4 changes: 3 additions & 1 deletion app/web/src/store/workspaces.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ type WorkspaceExportSummary = {
createdAt: IsoDateString;
};

type InstanceEnvType = "LOCAL" | "PRIVATE" | "SI";

type AuthApiWorkspace = {
creatorUserId: string;
displayName: string;
id: WorkspacePk;
pk: WorkspacePk; // not actually in the response, but we backfill
// instanceEnvType: "LOCAL" // not used yet...
instanceEnvType: InstanceEnvType;
instanceUrl: string;
role: "OWNER" | "EDITOR";
token: string;
Expand Down
13 changes: 12 additions & 1 deletion bin/auth-api/src/routes/workspace.routes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { nanoid } from "nanoid";
import { z } from 'zod';
import { InstanceEnvType } from "@prisma/client";
import { ApiError } from "../lib/api-error";
import { getCache, setCache } from "../lib/cache";
import { getUserById, refreshUserAuth0Profile } from "../services/users.service";
Expand Down Expand Up @@ -81,7 +82,17 @@ router.post("/workspaces/new", async (ctx) => {
displayName: z.string(),
}));

const workspaceDetails = await createWorkspace(ctx.state.authUser, reqBody.instanceUrl, reqBody.displayName);
let workspaceEnvType;
if (reqBody.instanceUrl === "https://app.systeminit.com") {
workspaceEnvType = InstanceEnvType.SI;
} else if (reqBody.instanceUrl === "localhost:8080") {
workspaceEnvType = InstanceEnvType.LOCAL;
} else {
workspaceEnvType = InstanceEnvType.PRIVATE;
}

const workspaceDetails = await
createWorkspace(ctx.state.authUser, workspaceEnvType, reqBody.instanceUrl, reqBody.displayName);

ctx.body = {
workspaces: await getUserWorkspaces(ctx.state.authUser.id),
Expand Down
6 changes: 3 additions & 3 deletions bin/auth-api/src/services/users.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _ from 'lodash';
import { ulid } from "ulidx";
import * as Auth0 from 'auth0';
import { Prisma, PrismaClient } from '@prisma/client';
import { InstanceEnvType, Prisma, PrismaClient } from '@prisma/client';

import { createWorkspace } from "./workspaces.service";
import { LATEST_TOS_VERSION_ID } from './tos.service';
Expand Down Expand Up @@ -115,8 +115,8 @@ export async function createOrUpdateUserFromAuth0Details(auth0UserData: Auth0.Us
lastName: user.lastName,
});

// create a default dev workspace
await createWorkspace(user);
// create a default saas workspace
await createWorkspace(user, InstanceEnvType.SI, "https://app.systeminit.com", `${user.nickname}'s Production Workspace`);
}

return user;
Expand Down
7 changes: 4 additions & 3 deletions bin/auth-api/src/services/workspaces.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ export async function getWorkspaceById(id: WorkspaceId) {

export async function createWorkspace(
creatorUser: User,
instanceUrl = "http://localhost:8080",
displayName = `${creatorUser.nickname}'s dev workspace`,
workspaceEnvType: InstanceEnvType,
instanceUrl: string,
displayName: string,
) {
const newWorkspace = await prisma.workspace.create({
data: {
id: ulid(),
token: ulid(),
instanceEnvType: InstanceEnvType.LOCAL,
instanceEnvType: workspaceEnvType,
instanceUrl,
displayName,
creatorUserId: creatorUser.id,
Expand Down
3 changes: 2 additions & 1 deletion bin/auth-api/test/auth-routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import t from 'tap';
import { expect } from 'chai';
import _ from 'lodash';

import { InstanceEnvType } from '@prisma/client';
import { request } from './helpers/supertest-agents';
import { testSuiteAfter, testSuiteBefore } from './helpers/test-suite-hooks';
import { mockAuth0TokenExchange } from './helpers/auth0-mocks';
Expand Down Expand Up @@ -94,7 +95,7 @@ t.test('Auth routes', async () => {
if (!user) {
t.bailout("User Fetch has failed");
}
const workspace = await createWorkspace(user!);
const workspace = await createWorkspace(user!, InstanceEnvType.SI, "https://app.systeminit.com", `${user!.nickname}'s Testing Workspace`);
const sdfToken = createSdfAuthToken(authData.userId, workspace.id);
await request.get('/whoami')
.set('cookie', `si-auth=${sdfToken}`)
Expand Down
6 changes: 4 additions & 2 deletions bin/auth-api/test/helpers/dummy-factory.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Prisma, PrismaClient, User } from '@prisma/client';
import {
InstanceEnvType, Prisma, PrismaClient, User,
} from '@prisma/client';
import { ulid } from 'ulidx';
import _ from 'lodash';
import { saveTosAgreement, LATEST_TOS_VERSION_ID } from '../../src/services/tos.service';
Expand Down Expand Up @@ -50,7 +52,7 @@ export async function createDummyUser(options?: {
await saveTosAgreement(user, LATEST_TOS_VERSION_ID, '1.2.3.4');
}

const workspace = await createWorkspace(user);
const workspace = await createWorkspace(user, InstanceEnvType.SI, "https://app.systeminit.com", `${user.nickname}'s Testing Workspace`);

return { user, workspace };
}

0 comments on commit 80e6054

Please sign in to comment.