Rename Organization to Project
We'll probably need a concept of organizations at some point in the future, but in practice the way we're using these in the codebase right now is as a project, so this renames it to that to avoid confusion.
This commit is contained in:
@@ -9,7 +9,7 @@ import { worldChampsRouter } from "./routers/worldChamps.router";
|
||||
import { datasetsRouter } from "./routers/datasets.router";
|
||||
import { datasetEntries } from "./routers/datasetEntries.router";
|
||||
import { externalApiRouter } from "./routers/externalApi.router";
|
||||
import { organizationsRouter } from "./routers/organizations.router";
|
||||
import { projectsRouter } from "./routers/projects.router";
|
||||
import { dashboardRouter } from "./routers/dashboard.router";
|
||||
|
||||
/**
|
||||
@@ -27,7 +27,7 @@ export const appRouter = createTRPCRouter({
|
||||
worldChamps: worldChampsRouter,
|
||||
datasets: datasetsRouter,
|
||||
datasetEntries: datasetEntries,
|
||||
organizations: organizationsRouter,
|
||||
projects: projectsRouter,
|
||||
dashboard: dashboardRouter,
|
||||
externalApi: externalApiRouter,
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ export const dashboardRouter = createTRPCRouter({
|
||||
z.object({
|
||||
// TODO: actually take startDate into account
|
||||
startDate: z.string().optional(),
|
||||
organizationId: z.string(),
|
||||
projectId: z.string(),
|
||||
}),
|
||||
)
|
||||
.query(async ({ input }) => {
|
||||
@@ -22,7 +22,7 @@ export const dashboardRouter = createTRPCRouter({
|
||||
"LoggedCall.id",
|
||||
"LoggedCallModelResponse.originalLoggedCallId",
|
||||
)
|
||||
.where("organizationId", "=", input.organizationId)
|
||||
.where("projectId", "=", input.projectId)
|
||||
.select(({ fn }) => [
|
||||
sql<Date>`date_trunc('day', "LoggedCallModelResponse"."startTime")`.as("period"),
|
||||
sql<number>`count("LoggedCall"."id")::int`.as("numQueries"),
|
||||
@@ -70,7 +70,7 @@ export const dashboardRouter = createTRPCRouter({
|
||||
"LoggedCall.id",
|
||||
"LoggedCallModelResponse.originalLoggedCallId",
|
||||
)
|
||||
.where("organizationId", "=", input.organizationId)
|
||||
.where("projectId", "=", input.projectId)
|
||||
.select(({ fn }) => [
|
||||
fn.sum(fn.coalesce("LoggedCallModelResponse.totalCost", sql<number>`0`)).as("totalCost"),
|
||||
fn.count("LoggedCall.id").as("numQueries"),
|
||||
@@ -79,7 +79,7 @@ export const dashboardRouter = createTRPCRouter({
|
||||
|
||||
const errors = await kysely
|
||||
.selectFrom("LoggedCall")
|
||||
.where("organizationId", "=", input.organizationId)
|
||||
.where("projectId", "=", input.projectId)
|
||||
.leftJoin(
|
||||
"LoggedCallModelResponse",
|
||||
"LoggedCall.id",
|
||||
|
||||
@@ -3,20 +3,20 @@ import { createTRPCRouter, protectedProcedure, publicProcedure } from "~/server/
|
||||
import { prisma } from "~/server/db";
|
||||
import {
|
||||
requireCanModifyDataset,
|
||||
requireCanModifyOrganization,
|
||||
requireCanModifyProject,
|
||||
requireCanViewDataset,
|
||||
requireCanViewOrganization,
|
||||
requireCanViewProject,
|
||||
} from "~/utils/accessControl";
|
||||
|
||||
export const datasetsRouter = createTRPCRouter({
|
||||
list: protectedProcedure
|
||||
.input(z.object({ organizationId: z.string() }))
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.query(async ({ input, ctx }) => {
|
||||
await requireCanViewOrganization(input.organizationId, ctx);
|
||||
await requireCanViewProject(input.projectId, ctx);
|
||||
|
||||
const datasets = await prisma.dataset.findMany({
|
||||
where: {
|
||||
organizationId: input.organizationId,
|
||||
projectId: input.projectId,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
@@ -36,26 +36,26 @@ export const datasetsRouter = createTRPCRouter({
|
||||
return await prisma.dataset.findFirstOrThrow({
|
||||
where: { id: input.id },
|
||||
include: {
|
||||
organization: true,
|
||||
project: true,
|
||||
},
|
||||
});
|
||||
}),
|
||||
|
||||
create: protectedProcedure
|
||||
.input(z.object({ organizationId: z.string() }))
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
await requireCanModifyOrganization(input.organizationId, ctx);
|
||||
await requireCanModifyProject(input.projectId, ctx);
|
||||
|
||||
const numDatasets = await prisma.dataset.count({
|
||||
where: {
|
||||
organizationId: input.organizationId,
|
||||
projectId: input.projectId,
|
||||
},
|
||||
});
|
||||
|
||||
return await prisma.dataset.create({
|
||||
data: {
|
||||
name: `Dataset ${numDatasets + 1}`,
|
||||
organizationId: input.organizationId,
|
||||
projectId: input.projectId,
|
||||
},
|
||||
});
|
||||
}),
|
||||
|
||||
@@ -8,9 +8,9 @@ import { generateNewCell } from "~/server/utils/generateNewCell";
|
||||
import {
|
||||
canModifyExperiment,
|
||||
requireCanModifyExperiment,
|
||||
requireCanModifyOrganization,
|
||||
requireCanModifyProject,
|
||||
requireCanViewExperiment,
|
||||
requireCanViewOrganization,
|
||||
requireCanViewProject,
|
||||
} from "~/utils/accessControl";
|
||||
import generateTypes from "~/modelProviders/generateTypes";
|
||||
import { promptConstructorVersion } from "~/promptConstructor/version";
|
||||
@@ -44,13 +44,13 @@ export const experimentsRouter = createTRPCRouter({
|
||||
};
|
||||
}),
|
||||
list: protectedProcedure
|
||||
.input(z.object({ organizationId: z.string() }))
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.query(async ({ input, ctx }) => {
|
||||
await requireCanViewOrganization(input.organizationId, ctx);
|
||||
await requireCanViewProject(input.projectId, ctx);
|
||||
|
||||
const experiments = await prisma.experiment.findMany({
|
||||
where: {
|
||||
organizationId: input.organizationId,
|
||||
projectId: input.projectId,
|
||||
},
|
||||
orderBy: {
|
||||
sortIndex: "desc",
|
||||
@@ -90,7 +90,7 @@ export const experimentsRouter = createTRPCRouter({
|
||||
const experiment = await prisma.experiment.findFirstOrThrow({
|
||||
where: { id: input.id },
|
||||
include: {
|
||||
organization: true,
|
||||
project: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -108,10 +108,10 @@ export const experimentsRouter = createTRPCRouter({
|
||||
}),
|
||||
|
||||
fork: protectedProcedure
|
||||
.input(z.object({ id: z.string(), organizationId: z.string() }))
|
||||
.input(z.object({ id: z.string(), projectId: z.string() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
await requireCanViewExperiment(input.id, ctx);
|
||||
await requireCanModifyOrganization(input.organizationId, ctx);
|
||||
await requireCanModifyProject(input.projectId, ctx);
|
||||
|
||||
const [
|
||||
existingExp,
|
||||
@@ -264,7 +264,7 @@ export const experimentsRouter = createTRPCRouter({
|
||||
id: newExperimentId,
|
||||
sortIndex: maxSortIndex + 1,
|
||||
label: `${existingExp.label} (forked)`,
|
||||
organizationId: input.organizationId,
|
||||
projectId: input.projectId,
|
||||
},
|
||||
}),
|
||||
prisma.promptVariant.createMany({
|
||||
@@ -294,9 +294,9 @@ export const experimentsRouter = createTRPCRouter({
|
||||
}),
|
||||
|
||||
create: protectedProcedure
|
||||
.input(z.object({ organizationId: z.string() }))
|
||||
.input(z.object({ projectId: z.string() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
await requireCanModifyOrganization(input.organizationId, ctx);
|
||||
await requireCanModifyProject(input.projectId, ctx);
|
||||
|
||||
const maxSortIndex =
|
||||
(
|
||||
@@ -304,7 +304,7 @@ export const experimentsRouter = createTRPCRouter({
|
||||
_max: {
|
||||
sortIndex: true,
|
||||
},
|
||||
where: { organizationId: input.organizationId },
|
||||
where: { projectId: input.projectId },
|
||||
})
|
||||
)._max?.sortIndex ?? 0;
|
||||
|
||||
@@ -312,7 +312,7 @@ export const experimentsRouter = createTRPCRouter({
|
||||
data: {
|
||||
sortIndex: maxSortIndex + 1,
|
||||
label: `Experiment ${maxSortIndex + 1}`,
|
||||
organizationId: input.organizationId,
|
||||
projectId: input.projectId,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ export const externalApiRouter = createTRPCRouter({
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
const reqPayload = await reqValidator.spa(input.reqPayload);
|
||||
const cacheKey = hashRequest(key.organizationId, reqPayload as JsonValue);
|
||||
const cacheKey = hashRequest(key.projectId, reqPayload as JsonValue);
|
||||
|
||||
const existingResponse = await prisma.loggedCallModelResponse.findFirst({
|
||||
where: {
|
||||
@@ -84,7 +84,7 @@ export const externalApiRouter = createTRPCRouter({
|
||||
|
||||
await prisma.loggedCall.create({
|
||||
data: {
|
||||
organizationId: key.organizationId,
|
||||
projectId: key.projectId,
|
||||
startTime: new Date(input.startTime),
|
||||
cacheHit: true,
|
||||
modelResponseId: existingResponse.id,
|
||||
@@ -135,7 +135,7 @@ export const externalApiRouter = createTRPCRouter({
|
||||
const reqPayload = await reqValidator.spa(input.reqPayload);
|
||||
const respPayload = await respValidator.spa(input.respPayload);
|
||||
|
||||
const requestHash = hashRequest(key.organizationId, reqPayload as JsonValue);
|
||||
const requestHash = hashRequest(key.projectId, reqPayload as JsonValue);
|
||||
|
||||
const newLoggedCallId = uuidv4();
|
||||
const newModelResponseId = uuidv4();
|
||||
@@ -146,7 +146,7 @@ export const externalApiRouter = createTRPCRouter({
|
||||
prisma.loggedCall.create({
|
||||
data: {
|
||||
id: newLoggedCallId,
|
||||
organizationId: key.organizationId,
|
||||
projectId: key.projectId,
|
||||
startTime: new Date(input.startTime),
|
||||
cacheHit: false,
|
||||
},
|
||||
|
||||
@@ -5,15 +5,15 @@ import { z } from "zod";
|
||||
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
||||
import { prisma } from "~/server/db";
|
||||
import { generateApiKey } from "~/server/utils/generateApiKey";
|
||||
import userOrg from "~/server/utils/userOrg";
|
||||
import userProject from "~/server/utils/userProject";
|
||||
import {
|
||||
requireCanModifyOrganization,
|
||||
requireCanViewOrganization,
|
||||
requireIsOrgAdmin,
|
||||
requireCanModifyProject,
|
||||
requireCanViewProject,
|
||||
requireIsProjectAdmin,
|
||||
requireNothing,
|
||||
} from "~/utils/accessControl";
|
||||
|
||||
export const organizationsRouter = createTRPCRouter({
|
||||
export const projectsRouter = createTRPCRouter({
|
||||
list: protectedProcedure.query(async ({ ctx }) => {
|
||||
const userId = ctx.session.user.id;
|
||||
requireNothing(ctx);
|
||||
@@ -22,9 +22,9 @@ export const organizationsRouter = createTRPCRouter({
|
||||
return null;
|
||||
}
|
||||
|
||||
const organizations = await prisma.organization.findMany({
|
||||
const projects = await prisma.project.findMany({
|
||||
where: {
|
||||
organizationUsers: {
|
||||
projectUsers: {
|
||||
some: { userId: ctx.session.user.id },
|
||||
},
|
||||
},
|
||||
@@ -33,30 +33,30 @@ export const organizationsRouter = createTRPCRouter({
|
||||
},
|
||||
});
|
||||
|
||||
if (!organizations.length) {
|
||||
if (!projects.length) {
|
||||
// TODO: We should move this to a separate endpoint that is called on sign up
|
||||
const personalOrg = await userOrg(userId);
|
||||
organizations.push(personalOrg);
|
||||
const personalProject = await userProject(userId);
|
||||
projects.push(personalProject);
|
||||
}
|
||||
|
||||
return organizations;
|
||||
return projects;
|
||||
}),
|
||||
get: protectedProcedure.input(z.object({ id: z.string() })).query(async ({ input, ctx }) => {
|
||||
await requireCanViewOrganization(input.id, ctx);
|
||||
const [org, userRole] = await prisma.$transaction([
|
||||
prisma.organization.findUnique({
|
||||
await requireCanViewProject(input.id, ctx);
|
||||
const [proj, userRole] = await prisma.$transaction([
|
||||
prisma.project.findUnique({
|
||||
where: {
|
||||
id: input.id,
|
||||
},
|
||||
include: {
|
||||
apiKeys: true,
|
||||
personalOrgUser: true,
|
||||
personalProjectUser: true,
|
||||
},
|
||||
}),
|
||||
prisma.organizationUser.findFirst({
|
||||
prisma.projectUser.findFirst({
|
||||
where: {
|
||||
userId: ctx.session.user.id,
|
||||
organizationId: input.id,
|
||||
projectId: input.id,
|
||||
role: {
|
||||
in: ["ADMIN", "MEMBER"],
|
||||
},
|
||||
@@ -64,20 +64,20 @@ export const organizationsRouter = createTRPCRouter({
|
||||
}),
|
||||
]);
|
||||
|
||||
if (!org) {
|
||||
if (!proj) {
|
||||
throw new TRPCError({ code: "NOT_FOUND" });
|
||||
}
|
||||
|
||||
return {
|
||||
...org,
|
||||
...proj,
|
||||
role: userRole?.role ?? null,
|
||||
};
|
||||
}),
|
||||
update: protectedProcedure
|
||||
.input(z.object({ id: z.string(), updates: z.object({ name: z.string() }) }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
await requireCanModifyOrganization(input.id, ctx);
|
||||
return await prisma.organization.update({
|
||||
await requireCanModifyProject(input.id, ctx);
|
||||
return await prisma.project.update({
|
||||
where: {
|
||||
id: input.id,
|
||||
},
|
||||
@@ -90,36 +90,36 @@ export const organizationsRouter = createTRPCRouter({
|
||||
.input(z.object({ name: z.string() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
requireNothing(ctx);
|
||||
const newOrgId = uuidv4();
|
||||
const [newOrg] = await prisma.$transaction([
|
||||
prisma.organization.create({
|
||||
const newProjectId = uuidv4();
|
||||
const [newProject] = await prisma.$transaction([
|
||||
prisma.project.create({
|
||||
data: {
|
||||
id: newOrgId,
|
||||
id: newProjectId,
|
||||
name: input.name,
|
||||
},
|
||||
}),
|
||||
prisma.organizationUser.create({
|
||||
prisma.projectUser.create({
|
||||
data: {
|
||||
userId: ctx.session.user.id,
|
||||
organizationId: newOrgId,
|
||||
projectId: newProjectId,
|
||||
role: "ADMIN",
|
||||
},
|
||||
}),
|
||||
prisma.apiKey.create({
|
||||
data: {
|
||||
name: "Default API Key",
|
||||
organizationId: newOrgId,
|
||||
projectId: newProjectId,
|
||||
apiKey: generateApiKey(),
|
||||
},
|
||||
}),
|
||||
]);
|
||||
return newOrg;
|
||||
return newProject;
|
||||
}),
|
||||
delete: protectedProcedure
|
||||
.input(z.object({ id: z.string() }))
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
await requireIsOrgAdmin(input.id, ctx);
|
||||
return await prisma.organization.delete({
|
||||
await requireIsProjectAdmin(input.id, ctx);
|
||||
return await prisma.project.delete({
|
||||
where: {
|
||||
id: input.id,
|
||||
},
|
||||
@@ -9,8 +9,8 @@ import {
|
||||
type OutputEvaluation,
|
||||
type Dataset,
|
||||
type DatasetEntry,
|
||||
type Organization,
|
||||
type OrganizationUser,
|
||||
type Project,
|
||||
type ProjectUser,
|
||||
type WorldChampEntrant,
|
||||
type LoggedCall,
|
||||
type LoggedCallModelResponse,
|
||||
@@ -43,8 +43,8 @@ interface DB {
|
||||
OutputEvaluation: OutputEvaluation;
|
||||
Dataset: Dataset;
|
||||
DatasetEntry: DatasetEntry;
|
||||
Organization: Organization;
|
||||
OrganizationUser: OrganizationUser;
|
||||
Project: Project;
|
||||
ProjectUser: ProjectUser;
|
||||
WorldChampEntrant: WorldChampEntrant;
|
||||
LoggedCall: LoggedCall;
|
||||
LoggedCallModelResponse: LoggedCallModelResponse;
|
||||
|
||||
@@ -4,21 +4,21 @@ import { generateApiKey } from "~/server/utils/generateApiKey";
|
||||
|
||||
console.log("backfilling api keys");
|
||||
|
||||
const organizations = await prisma.organization.findMany({
|
||||
const projects = await prisma.project.findMany({
|
||||
include: {
|
||||
apiKeys: true,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`found ${organizations.length} organizations`);
|
||||
console.log(`found ${projects.length} projects`);
|
||||
|
||||
const apiKeysToCreate: Prisma.ApiKeyCreateManyInput[] = [];
|
||||
|
||||
for (const org of organizations) {
|
||||
if (!org.apiKeys.length) {
|
||||
for (const proj of projects) {
|
||||
if (!proj.apiKeys.length) {
|
||||
apiKeysToCreate.push({
|
||||
name: "Default API Key",
|
||||
organizationId: org.id,
|
||||
projectId: proj.id,
|
||||
apiKey: generateApiKey(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ const projectId = "1234";
|
||||
// Find all calls in the last 24 hours
|
||||
const responses = await prisma.loggedCall.findMany({
|
||||
where: {
|
||||
organizationId: projectId,
|
||||
projectId: projectId,
|
||||
startTime: {
|
||||
gt: dayjs()
|
||||
.subtract(24 * 3600)
|
||||
@@ -24,7 +24,7 @@ const responses = await prisma.loggedCall.findMany({
|
||||
// Find all calls in the last 24 hours with promptId 'hello-world'
|
||||
const helloWorld = await prisma.loggedCall.findMany({
|
||||
where: {
|
||||
organizationId: projectId,
|
||||
projectId: projectId,
|
||||
startTime: {
|
||||
gt: dayjs()
|
||||
.subtract(24 * 3600)
|
||||
@@ -52,7 +52,7 @@ const totalSpent = await prisma.loggedCallModelResponse.aggregate({
|
||||
},
|
||||
where: {
|
||||
originalLoggedCall: {
|
||||
organizationId: projectId,
|
||||
projectId: projectId,
|
||||
},
|
||||
startTime: {
|
||||
gt: dayjs()
|
||||
|
||||
@@ -24,9 +24,9 @@ function sortKeys(obj: JsonValue): JsonValue {
|
||||
return sortedObj;
|
||||
}
|
||||
|
||||
export function hashRequest(organizationId: string, reqPayload: JsonValue): string {
|
||||
export function hashRequest(projectId: string, reqPayload: JsonValue): string {
|
||||
const obj = {
|
||||
organizationId,
|
||||
projectId,
|
||||
reqPayload,
|
||||
};
|
||||
return hashObject(obj);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { prisma } from "~/server/db";
|
||||
import { generateApiKey } from "./generateApiKey";
|
||||
|
||||
export default async function userOrg(userId: string) {
|
||||
return await prisma.organization.upsert({
|
||||
export default async function userProject(userId: string) {
|
||||
return await prisma.project.upsert({
|
||||
where: {
|
||||
personalOrgUserId: userId,
|
||||
personalProjectUserId: userId,
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
personalOrgUserId: userId,
|
||||
organizationUsers: {
|
||||
personalProjectUserId: userId,
|
||||
projectUsers: {
|
||||
create: {
|
||||
userId: userId,
|
||||
role: "ADMIN",
|
||||
Reference in New Issue
Block a user