Skip to content

Commit

Permalink
complete admin auth
Browse files Browse the repository at this point in the history
  • Loading branch information
Hoishin committed Jan 7, 2024
1 parent 8d6254f commit 643c019
Show file tree
Hide file tree
Showing 47 changed files with 1,194 additions and 434 deletions.
29 changes: 29 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,34 @@
"plugin:@typescript-eslint/stylistic-type-checked",
"plugin:react-hooks/recommended",
"prettier"
],

"rules": {
"@typescript-eslint/no-misused-promises": [
"error",
{ "checksVoidReturn": false }
],
"@typescript-eslint/no-unused-vars": "off"
},

"overrides": [
{
"files": ["./projects/admin/**/*.ts", "./projects/admin/**/*.tsx"],
"parserOptions": {
"project": "./projects/admin/tsconfig.json"
}
},
{
"files": ["./projects/client/**/*.ts", "./projects/client/**/*.tsx"],
"parserOptions": {
"project": "./projects/client/tsconfig.json"
}
},
{
"files": ["./projects/server/**/*.ts"],
"parserOptions": {
"project": "./projects/server/tsconfig.json"
}
}
]
}
23 changes: 23 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: CI

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: package.json
- run: npm ci
- run: npm run lint
- run: npm run check-format
- run: npm run build
- run: npm run test
53 changes: 50 additions & 3 deletions package-lock.json

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

19 changes: 17 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
{
"private": true,
"type": "module",
"scripts": {
"dev": "run-p dev:*",
"dev:admin": "npm run dev --workspace=admin",
"dev:client": "npm run dev --workspace=client",
"dev:server": "npm run dev --workspace=server",
"lint": "eslint --ext .ts,.tsx .",
"check-format": "prettier --check .",
"format": "prettier --write .",
"build": "npm run build --workspaces",
"test": "npm run test --workspaces --if-present"
},
"workspaces": [
"projects/server",
"projects/admin",
"projects/client",
"projects/admin"
"projects/server"
],
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^6.17.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-react-hooks": "^4.6.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.1.1",
"typescript": "~5.3.3"
},
"engines": {
"node": "^20.10.0"
}
}
7 changes: 5 additions & 2 deletions projects/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
"scripts": {
"dev": "run-p dev:*",
"dev:vite": "vite",
"dev:types": "tsc -b --watch --preserveWatchOutput"
"dev:types": "tsc -b --watch --preserveWatchOutput",
"build": "tsc -b && vite build"
},
"dependencies": {
"@trpc/client": "^10.45.0",
"react": "^18.2.0",
"react-admin": "^4.16.5",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-hook-form": "^7.49.2",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/react": "^18.2.46",
Expand Down
8 changes: 7 additions & 1 deletion projects/admin/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { Admin, Resource } from "react-admin";
import { dataProvider } from "./data-provider/data-provider";
import { UserEdit, UserList } from "./users";
import { LoginPage } from "./login";
import { authProvider } from "./auth-provider";

export const App = () => {
return (
<Admin dataProvider={dataProvider}>
<Admin
loginPage={LoginPage}
authProvider={authProvider}
dataProvider={dataProvider}
>
<Resource
name="users"
list={UserList}
Expand Down
69 changes: 69 additions & 0 deletions projects/admin/src/auth-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { z } from "zod";
import type { AuthProvider } from "react-admin";
import { trpc } from "./trpc";
import { TRPCClientError } from "@trpc/client";

const loginParamsSchema = z.object({
email: z.string().email(),
});

const trpcErrorSchema = z.object({
code: z.string(),
httpStatus: z.number().int(),
path: z.string(),
});

export const authProvider: AuthProvider = {
login: async (params) => {
const { email } = loginParamsSchema.parse(params);
const callbackUrl = new URL(window.location.origin);
callbackUrl.hash = "/auth-callback";
await trpc.authentication.initialize.mutate({

Check failure on line 21 in projects/admin/src/auth-provider.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe call of an `any` typed value

Check failure on line 21 in projects/admin/src/auth-provider.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe member access .initialize on an `any` value
email,
callbackUrl: callbackUrl.href,
});
},

handleCallback: async () => {
const searchParams = new URLSearchParams(window.location.search);
window.location.search = "";

const token = searchParams.get("token");
if (!token) {
return;
}

await trpc.authentication.verifyToken.mutate({ token });

Check failure on line 36 in projects/admin/src/auth-provider.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe call of an `any` typed value

Check failure on line 36 in projects/admin/src/auth-provider.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe member access .verifyToken on an `any` value
},

// eslint-disable-next-line @typescript-eslint/require-await
checkError: async (error) => {
if (!(error instanceof TRPCClientError)) {
return;
}
const errorData = trpcErrorSchema.parse(error.data);
if (errorData.code === "UNAUTHORIZED") {
throw new Error("not signed in");
}
return;
},

checkAuth: async () => {
const signedIn = await trpc.validateSession.query();

Check failure on line 52 in projects/admin/src/auth-provider.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe assignment of an `any` value

Check failure on line 52 in projects/admin/src/auth-provider.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe call of an `any` typed value

Check failure on line 52 in projects/admin/src/auth-provider.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe member access .query on an `any` value
if (!signedIn) {
throw new Error("not signed in");
}
},

logout: async () => {
try {
await trpc.authentication.signOut.mutate();

Check failure on line 60 in projects/admin/src/auth-provider.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe call of an `any` typed value

Check failure on line 60 in projects/admin/src/auth-provider.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe member access .signOut on an `any` value
} catch (error) {
console.error(error);
}
},

getPermissions: () => {
return Promise.resolve("admin");
},
};
1 change: 1 addition & 0 deletions projects/admin/src/data-provider/create.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/require-await */
import type { CreateParams, CreateResult } from "react-admin";

export const create = async (
Expand Down
17 changes: 10 additions & 7 deletions projects/admin/src/data-provider/delete-many.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import type { DeleteManyParams, DeleteManyResult } from "react-admin";
import { trpc } from "../trpc";
import { z } from "zod";

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

export const deleteMany = async (
resource: string,
params: DeleteManyParams,
): Promise<DeleteManyResult> => {
const { ids } = paramsSchema.parse(params);
switch (resource) {
case "users":
const result = await trpc.admin.users.deleteMany.mutate({
ids: params.ids,
});
return {
data: result,
};
case "users": {
const result = await trpc.admin.users.deleteMany.mutate({ ids });

Check failure on line 16 in projects/admin/src/data-provider/delete-many.ts

View workflow job for this annotation

GitHub Actions / test

Unsafe assignment of an `any` value
return { data: result };
}
default:
throw new Error(`unknown resource ${resource}`);
}
Expand Down
15 changes: 10 additions & 5 deletions projects/admin/src/data-provider/delete.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import type { DeleteParams, DeleteResult } from "react-admin";
import { trpc } from "../trpc";
import { z } from "zod";

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

export const deleteMethod = async (
resource: string,
params: DeleteParams,
): Promise<DeleteResult> => {
const { id } = paramsSchema.parse(params);
switch (resource) {
case "users":
const result = await trpc.admin.users.delete.mutate(params.id);
return {
data: result,
};
case "users": {
const result = await trpc.admin.users.delete.mutate({ id });
return { data: result };
}
default:
throw new Error(`unknown resource ${resource}`);
}
Expand Down
3 changes: 2 additions & 1 deletion projects/admin/src/data-provider/get-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const getList = async (
{ pagination, sort }: GetListParams,
): Promise<GetListResult> => {
switch (resource) {
case "users":
case "users": {
const res = await trpc.admin.users.list.query({
order: lowercase(sort.order),
orderBy: sort.field,
Expand All @@ -18,6 +18,7 @@ export const getList = async (
data: res.data,
total: res.count,
};
}
default:
throw new Error(`unknown resource ${resource}`);
}
Expand Down
1 change: 1 addition & 0 deletions projects/admin/src/data-provider/get-many-reference.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/require-await */
import type {
GetManyReferenceParams,
GetManyReferenceResult,
Expand Down
Loading

0 comments on commit 643c019

Please sign in to comment.