Skip to content

Commit

Permalink
show user roles
Browse files Browse the repository at this point in the history
  • Loading branch information
Hoishin committed Jan 9, 2024
1 parent e882f43 commit 3e97f98
Show file tree
Hide file tree
Showing 16 changed files with 248 additions and 82 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion projects/admin/src/data-provider/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const create = async (
): Promise<CreateResult> => {
switch (resource) {
case "users":
throw new Error("not implemented");
throw new Error("not allowed");
default:
throw new Error(`unknown resource ${resource}`);
}
Expand Down
15 changes: 13 additions & 2 deletions projects/admin/src/data-provider/delete-many.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,21 @@ export const deleteMany = async (
params: DeleteManyParams,
): Promise<DeleteManyResult> => {
const { ids } = paramsSchema.parse(params);

switch (resource) {
case "users": {
const result = await trpc.admin.users.deleteMany.mutate({ ids });
return { data: result };
const deleted: string[] = [];
await Promise.all(
ids.map(async (id) => {
try {
const res = await trpc.admin.users.delete.mutate({ id });
deleted.push(res.id);
} catch (error) {
console.error(error);
}
}),
);
return { data: deleted };
}
default:
throw new Error(`unknown resource ${resource}`);
Expand Down
20 changes: 9 additions & 11 deletions projects/admin/src/data-provider/get-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@ import { lowercase } from "./data-provider.js";

export const getList = async (
resource: string,
{ pagination, sort }: GetListParams,
params: GetListParams,
): Promise<GetListResult> => {
const query = {
order: lowercase(params.sort.order),
orderBy: params.sort.field,
skip: (params.pagination.page - 1) * params.pagination.perPage,
take: params.pagination.perPage,
};
switch (resource) {
case "users": {
const res = await trpc.admin.users.list.query({
order: lowercase(sort.order),
orderBy: sort.field,
skip: (pagination.page - 1) * pagination.perPage,
take: pagination.perPage,
});
return {
data: res.data,
total: res.count,
};
const res = await trpc.admin.users.list.query(query);
return { data: res.data, total: res.count };
}
default:
throw new Error(`unknown resource ${resource}`);
Expand Down
15 changes: 10 additions & 5 deletions projects/admin/src/data-provider/get-many.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import type { GetManyParams, GetManyResult } from "react-admin";
import { trpc } from "../trpc";
import { z } from "zod";

const paramsSchema = z.object({
ids: z.array(z.string().uuid()),
});

export const getMany = async (
resource: string,
{ ids }: GetManyParams,
params: GetManyParams,
): Promise<GetManyResult> => {
console.log(params);
const { ids } = paramsSchema.parse(params);

switch (resource) {
case "users": {
const data = await Promise.all(
ids.map((id) => {
if (typeof id === "string") {
return trpc.admin.users.get.query({ id });
}
throw new Error(`invalid id ${id}`);
return trpc.admin.users.get.query({ id });
}),
);
return { data };
Expand Down
9 changes: 2 additions & 7 deletions projects/admin/src/data-provider/update-many.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import type { UpdateManyParams } from "react-admin";

// eslint-disable-next-line @typescript-eslint/require-await
export const updateMany = async (resource: string, _: UpdateManyParams) => {
switch (resource) {
case "users":
throw new Error("not implemented");
default:
throw new Error(`unknown resource ${resource}`);
}
export const updateMany = async (_: string, __: UpdateManyParams) => {
throw new Error("not implemented");
};
12 changes: 10 additions & 2 deletions projects/admin/src/users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@ import {
Edit,
SimpleForm,
TextInput,
ArrayField,
SingleFieldList,
} from "react-admin";

export const UserList = () => (
<List>
<Datagrid rowClick="edit">
<TextField source="id" />
<EmailField source="email" />
<DateField source="createdAt" />
<DateField source="updatedAt" />
<TextField source="username" />
<ArrayField source="userRoles">
<SingleFieldList linkType={false}>
<TextField source="role" />
</SingleFieldList>
</ArrayField>
<DateField source="lastLogin" />
</Datagrid>
</List>
);
Expand All @@ -24,6 +31,7 @@ export const UserEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="email" />
<TextField source="username" />
</SimpleForm>
</Edit>
);
1 change: 1 addition & 0 deletions projects/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"dev:server": "node --watch --watch-preserve-output --enable-source-maps bin.js",
"dev:build": "npm run build -- --watch",
"dev:types": "tsc -b --watch --preserveWatchOutput",
"dev:prisma": "prisma generate --watch",
"dev:db": "docker compose up",
"test": "vitest run"
},
Expand Down
31 changes: 31 additions & 0 deletions projects/server/prisma/migrations/20240108001454_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Warnings:
- Added the required column `endsAt` to the `Event` table without a default value. This is not possible if the table is not empty.
- Added the required column `startsAt` to the `Event` table without a default value. This is not possible if the table is not empty.
*/
-- CreateEnum
CREATE TYPE "MarathonType" AS ENUM ('ONLINE', 'ONSITE');

-- AlterTable
ALTER TABLE "Event" ADD COLUMN "endsAt" TIMESTAMP(3) NOT NULL,
ADD COLUMN "published" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "startsAt" TIMESTAMP(3) NOT NULL;

-- CreateTable
CREATE TABLE "EventMarathonType" (
"id" UUID NOT NULL,
"eventId" UUID NOT NULL,
"marathonType" "MarathonType" NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "EventMarathonType_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "EventMarathonType_eventId_marathonType_key" ON "EventMarathonType"("eventId", "marathonType");

-- AddForeignKey
ALTER TABLE "EventMarathonType" ADD CONSTRAINT "EventMarathonType_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "Event"("id") ON DELETE CASCADE ON UPDATE CASCADE;
12 changes: 12 additions & 0 deletions projects/server/prisma/migrations/20240109032853_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
Warnings:
- A unique constraint covering the columns `[username]` on the table `User` will be added. If there are existing duplicate values, this will fail.
- Added the required column `username` to the `User` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "User" ADD COLUMN "username" VARCHAR(255) NOT NULL;

-- CreateIndex
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
36 changes: 28 additions & 8 deletions projects/server/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
provider = "prisma-client-js"
}
Expand All @@ -11,8 +8,9 @@ datasource db {
}

model User {
id String @id @default(uuid()) @db.Uuid
email String @unique @db.VarChar(255)
id String @id @default(uuid()) @db.Uuid
email String @unique @db.VarChar(255)
username String? @unique @db.VarChar(255)
sessions Session[]
userRoles UserRole[]
Expand Down Expand Up @@ -70,15 +68,37 @@ model UserRole {
}

model Event {
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
id String @id @default(uuid()) @db.Uuid
name String @db.VarChar(255)
startsAt DateTime
endsAt DateTime
published Boolean @default(false)
gameSubmissions GameSubmission[]
gameSubmissions GameSubmission[]
eventMarathonTypes EventMarathonType[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

enum MarathonType {
ONLINE
ONSITE
}

model EventMarathonType {
id String @id @default(uuid()) @db.Uuid
eventId String @db.Uuid
marathonType MarathonType
event Event @relation(fields: [eventId], references: [id], onUpdate: Cascade, onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([eventId, marathonType])
}

model GameSubmission {
id String @id @default(uuid()) @db.Uuid
eventId String @db.Uuid
Expand Down
8 changes: 8 additions & 0 deletions projects/server/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@ const prisma = new PrismaClient();
await prisma.user.create({
data: {
email: "dev-admin@example.com",
username: "dev-admin",
userRoles: {
create: {
role: Role.ADMIN,
},
},
},
});

await prisma.user.create({
data: {
email: "dev-normal@example.com",
username: "dev-normal",
},
});
72 changes: 72 additions & 0 deletions projects/server/src/routes/admin/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { z } from "zod";
import { prisma } from "../../prisma.js";
import { adminProcedure, router } from "../../trpc.js";
import { listSchema } from "./utils.js";
import { MarathonType } from "@prisma/client";

export const eventsRouter = router({
list: adminProcedure.input(listSchema).query(async ({ input }) => {
const data = await prisma.event.findMany({
skip: input.skip,
take: input.take,
orderBy: {
name: input.orderBy === "name" ? input.order : undefined,
startsAt: input.orderBy === "startsAt" ? input.order : undefined,
endsAt: input.orderBy === "endsAt" ? input.order : undefined,
published: input.orderBy === "published" ? input.order : undefined,
},
});
const count = await prisma.event.count();
return { data, count };
}),
get: adminProcedure
.input(z.object({ id: z.string().uuid() }))
.query(async ({ input }) => {
const event = await prisma.event.findUnique({
where: {
id: input.id,
},
});
if (!event) {
throw new Error("event not found");
}
return event;
}),
update: adminProcedure
.input(
z.object({
id: z.string().uuid(),
data: z.object({
name: z.string(),
startsAt: z.string(),
endsAt: z.string(),
published: z.boolean(),
eventMarathonTypes: z.array(
z.enum([MarathonType.ONLINE, MarathonType.ONSITE]),
),
}),
}),
)
.mutation(async ({ input }) => {
const event = await prisma.event.update({
where: {
id: input.id,
},
data: {
name: input.data.name,
startsAt: input.data.startsAt,
endsAt: input.data.endsAt,
published: input.data.published,
},
});
return event;
}),
delete: adminProcedure
.input(z.object({ id: z.string().uuid() }))
.mutation(async ({ input }) => {
const result = await prisma.event.delete({
where: { id: input.id },
});
return result;
}),
});
Loading

0 comments on commit 3e97f98

Please sign in to comment.