Compare commits

...

1 Commits

Author SHA1 Message Date
Henry
d3687cfb10 fix: API key authentication and REST handler errors 2026-03-18 22:46:30 +00:00
4 changed files with 18 additions and 14 deletions

View File

@@ -11,10 +11,10 @@ https://kan.bn/api/v1
## Authentication
Most endpoints require authentication using your API key. You can create one in the [settings page](https://kan.bn/settings) of your account. Include this key in the `x-api-key` header of each request.
Most endpoints require authentication using your API key. You can create one in the [settings page](https://kan.bn/settings) of your account. Include this key as a Bearer token in the `Authorization` header of each request.
```
'x-api-key': kan_123456789
'Authorization': 'Bearer kan_123456789'
```
## Response codes

View File

@@ -19,6 +19,7 @@ import { encryptToken } from "../utils/encryption";
export const integrationRouter = createTRPCRouter({
saveGitHubToken: protectedProcedure
.input(z.object({ token: z.string() }))
.output(z.object({ success: z.boolean() }))
.mutation(async ({ ctx, input }) => {
const user = ctx.user;
@@ -43,7 +44,9 @@ export const integrationRouter = createTRPCRouter({
return { success: true };
}),
disconnectGitHub: protectedProcedure.mutation(async ({ ctx }) => {
disconnectGitHub: protectedProcedure
.output(z.object({ success: z.boolean() }))
.mutation(async ({ ctx }) => {
const user = ctx.user;
if (!user)
@@ -56,7 +59,9 @@ export const integrationRouter = createTRPCRouter({
return { success: true };
}),
getGitHubStatus: protectedProcedure.query(async ({ ctx }) => {
getGitHubStatus: protectedProcedure
.output(z.object({ connected: z.boolean() }))
.query(async ({ ctx }) => {
const user = ctx.user;
if (!user)

View File

@@ -137,9 +137,7 @@ const loggingMiddleware = t.middleware(async ({ path, type, next, ctx }) => {
return result;
});
export const publicProcedure = t.procedure.use(loggingMiddleware).meta({
openapi: { method: "GET", path: "/public" },
});
export const publicProcedure = t.procedure.use(loggingMiddleware);
const enforceUserIsAuthed = t.middleware(async ({ ctx, next }) => {
if (!ctx.user) {
@@ -163,13 +161,7 @@ const enforceUserIsAdmin = t.middleware(async ({ ctx, next }) => {
export const protectedProcedure = t.procedure
.use(loggingMiddleware)
.use(enforceUserIsAuthed)
.meta({
openapi: {
method: "GET",
path: "/protected",
},
});
.use(enforceUserIsAuthed);
export const adminProtectedProcedure = t.procedure
.use(loggingMiddleware)

View File

@@ -165,6 +165,13 @@ export function createPlugins(db: dbClient) {
: []),
apiKey({
enableSessionForAPIKeys: true,
customAPIKeyGetter: (ctx) => {
const authorization = ctx.headers?.get("authorization");
if (authorization?.startsWith("Bearer ")) {
return authorization.slice(7);
}
return ctx.headers?.get("x-api-key") ?? undefined;
},
rateLimit: {
enabled: true,
timeWindow: 1000 * 60, // 1 minute