Compare commits

..

4 Commits

Author SHA1 Message Date
Henry
80aa6aa2aa feat: remove key from user response 2026-03-16 13:41:16 +00:00
Henry
6852e83349 feat: use plain text editor for checklist items 2026-03-16 13:40:30 +00:00
Henry
8b6e46fe63 feat: add basic editor 2026-03-16 13:35:29 +00:00
Henry
4088f9abd5 feat: sanitize input for checklists 2026-03-16 13:35:03 +00:00
13 changed files with 59 additions and 63 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 as a Bearer token in the `Authorization` 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 in the `x-api-key` header of each request.
```
'Authorization': 'Bearer kan_123456789'
'x-api-key': kan_123456789
```
## Response codes

View File

@@ -280,7 +280,7 @@
"message": "Add details...",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 169]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 200]],
"translation": "Details hinzufügen..."
},
"lyqwgn": {
@@ -4336,8 +4336,8 @@
["src/views/boards/components/ImportBoardsForm.tsx", 243],
["src/views/boards/components/ImportBoardsForm.tsx", 395],
["src/views/card/components/AttachmentThumbnails.tsx", 74],
["src/views/card/components/ChecklistItemRow.tsx", 67],
["src/views/card/components/ChecklistItemRow.tsx", 95],
["src/views/card/components/ChecklistItemRow.tsx", 69],
["src/views/card/components/ChecklistItemRow.tsx", 97],
["src/views/card/components/ChecklistNameInput.tsx", 47],
["src/views/card/components/Checklists.tsx", 81],
["src/views/card/components/Comment.tsx", 93],
@@ -5634,7 +5634,7 @@
"message": "Unable to delete checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 94]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 96]],
"translation": "Checklistenelement konnte nicht gelöscht werden"
},
"2QGEbi": {
@@ -5718,7 +5718,7 @@
"message": "Unable to update checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 66]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 68]],
"translation": "Checklisten-Element konnte nicht aktualisiert werden"
},
"fYVH36": {

View File

@@ -471,7 +471,7 @@
"origin": [
[
"src/views/card/components/ChecklistItemRow.tsx",
169
200
]
],
"translation": "Add details..."
@@ -7332,11 +7332,11 @@
],
[
"src/views/card/components/ChecklistItemRow.tsx",
67
69
],
[
"src/views/card/components/ChecklistItemRow.tsx",
95
97
],
[
"src/views/card/components/ChecklistNameInput.tsx",
@@ -9571,7 +9571,7 @@
"origin": [
[
"src/views/card/components/ChecklistItemRow.tsx",
94
96
]
],
"translation": "Unable to delete checklist item"
@@ -9707,7 +9707,7 @@
"origin": [
[
"src/views/card/components/ChecklistItemRow.tsx",
66
68
]
],
"translation": "Unable to update checklist item"

View File

@@ -280,7 +280,7 @@
"message": "Add details...",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 169]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 200]],
"translation": "Añadir detalles..."
},
"lyqwgn": {
@@ -4336,8 +4336,8 @@
["src/views/boards/components/ImportBoardsForm.tsx", 243],
["src/views/boards/components/ImportBoardsForm.tsx", 395],
["src/views/card/components/AttachmentThumbnails.tsx", 74],
["src/views/card/components/ChecklistItemRow.tsx", 67],
["src/views/card/components/ChecklistItemRow.tsx", 95],
["src/views/card/components/ChecklistItemRow.tsx", 69],
["src/views/card/components/ChecklistItemRow.tsx", 97],
["src/views/card/components/ChecklistNameInput.tsx", 47],
["src/views/card/components/Checklists.tsx", 81],
["src/views/card/components/Comment.tsx", 93],
@@ -5634,7 +5634,7 @@
"message": "Unable to delete checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 94]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 96]],
"translation": "No se pudo eliminar el elemento de la lista de verificación"
},
"2QGEbi": {
@@ -5718,7 +5718,7 @@
"message": "Unable to update checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 66]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 68]],
"translation": "No se pudo actualizar el elemento de la lista de verificación"
},
"fYVH36": {

View File

@@ -280,7 +280,7 @@
"message": "Add details...",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 169]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 200]],
"translation": "Ajouter des détails..."
},
"lyqwgn": {
@@ -4336,8 +4336,8 @@
["src/views/boards/components/ImportBoardsForm.tsx", 243],
["src/views/boards/components/ImportBoardsForm.tsx", 395],
["src/views/card/components/AttachmentThumbnails.tsx", 74],
["src/views/card/components/ChecklistItemRow.tsx", 67],
["src/views/card/components/ChecklistItemRow.tsx", 95],
["src/views/card/components/ChecklistItemRow.tsx", 69],
["src/views/card/components/ChecklistItemRow.tsx", 97],
["src/views/card/components/ChecklistNameInput.tsx", 47],
["src/views/card/components/Checklists.tsx", 81],
["src/views/card/components/Comment.tsx", 93],
@@ -5634,7 +5634,7 @@
"message": "Unable to delete checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 94]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 96]],
"translation": "Impossible de supprimer l'élément de liste de contrôle"
},
"2QGEbi": {
@@ -5718,7 +5718,7 @@
"message": "Unable to update checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 66]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 68]],
"translation": "Impossible de mettre à jour l'élément de la checklist"
},
"fYVH36": {

View File

@@ -280,7 +280,7 @@
"message": "Add details...",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 169]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 200]],
"translation": "Aggiungi dettagli..."
},
"lyqwgn": {
@@ -4336,8 +4336,8 @@
["src/views/boards/components/ImportBoardsForm.tsx", 243],
["src/views/boards/components/ImportBoardsForm.tsx", 395],
["src/views/card/components/AttachmentThumbnails.tsx", 74],
["src/views/card/components/ChecklistItemRow.tsx", 67],
["src/views/card/components/ChecklistItemRow.tsx", 95],
["src/views/card/components/ChecklistItemRow.tsx", 69],
["src/views/card/components/ChecklistItemRow.tsx", 97],
["src/views/card/components/ChecklistNameInput.tsx", 47],
["src/views/card/components/Checklists.tsx", 81],
["src/views/card/components/Comment.tsx", 93],
@@ -5634,7 +5634,7 @@
"message": "Unable to delete checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 94]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 96]],
"translation": "Impossibile eliminare l'elemento della checklist"
},
"2QGEbi": {
@@ -5718,7 +5718,7 @@
"message": "Unable to update checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 66]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 68]],
"translation": "Impossibile aggiornare l'elemento della checklist"
},
"fYVH36": {

View File

@@ -280,7 +280,7 @@
"message": "Add details...",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 169]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 200]],
"translation": "Voeg details toe..."
},
"lyqwgn": {
@@ -4336,8 +4336,8 @@
["src/views/boards/components/ImportBoardsForm.tsx", 243],
["src/views/boards/components/ImportBoardsForm.tsx", 395],
["src/views/card/components/AttachmentThumbnails.tsx", 74],
["src/views/card/components/ChecklistItemRow.tsx", 67],
["src/views/card/components/ChecklistItemRow.tsx", 95],
["src/views/card/components/ChecklistItemRow.tsx", 69],
["src/views/card/components/ChecklistItemRow.tsx", 97],
["src/views/card/components/ChecklistNameInput.tsx", 47],
["src/views/card/components/Checklists.tsx", 81],
["src/views/card/components/Comment.tsx", 93],
@@ -5634,7 +5634,7 @@
"message": "Unable to delete checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 94]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 96]],
"translation": "Kan checklistitem niet verwijderen"
},
"2QGEbi": {
@@ -5718,7 +5718,7 @@
"message": "Unable to update checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 66]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 68]],
"translation": "Kan checklistitem niet bijwerken"
},
"fYVH36": {

View File

@@ -280,7 +280,7 @@
"message": "Add details...",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 169]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 200]],
"translation": "Dodaj szczegóły..."
},
"lyqwgn": {
@@ -4336,8 +4336,8 @@
["src/views/boards/components/ImportBoardsForm.tsx", 243],
["src/views/boards/components/ImportBoardsForm.tsx", 395],
["src/views/card/components/AttachmentThumbnails.tsx", 74],
["src/views/card/components/ChecklistItemRow.tsx", 67],
["src/views/card/components/ChecklistItemRow.tsx", 95],
["src/views/card/components/ChecklistItemRow.tsx", 69],
["src/views/card/components/ChecklistItemRow.tsx", 97],
["src/views/card/components/ChecklistNameInput.tsx", 47],
["src/views/card/components/Checklists.tsx", 81],
["src/views/card/components/Comment.tsx", 93],
@@ -5634,7 +5634,7 @@
"message": "Unable to delete checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 94]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 96]],
"translation": "Nie można usunąć elementu listy kontrolnej"
},
"2QGEbi": {
@@ -5718,7 +5718,7 @@
"message": "Unable to update checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 66]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 68]],
"translation": "Nie można zaktualizować elementu listy kontrolnej"
},
"fYVH36": {

View File

@@ -280,7 +280,7 @@
"message": "Add details...",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 169]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 200]],
"translation": "Adicionar detalhes..."
},
"lyqwgn": {
@@ -4336,8 +4336,8 @@
["src/views/boards/components/ImportBoardsForm.tsx", 243],
["src/views/boards/components/ImportBoardsForm.tsx", 395],
["src/views/card/components/AttachmentThumbnails.tsx", 74],
["src/views/card/components/ChecklistItemRow.tsx", 67],
["src/views/card/components/ChecklistItemRow.tsx", 95],
["src/views/card/components/ChecklistItemRow.tsx", 69],
["src/views/card/components/ChecklistItemRow.tsx", 97],
["src/views/card/components/ChecklistNameInput.tsx", 47],
["src/views/card/components/Checklists.tsx", 81],
["src/views/card/components/Comment.tsx", 93],
@@ -5634,7 +5634,7 @@
"message": "Unable to delete checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 94]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 96]],
"translation": "Não foi possível excluir item da checklist"
},
"2QGEbi": {
@@ -5718,7 +5718,7 @@
"message": "Unable to update checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 66]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 68]],
"translation": "Não foi possível atualizar o item da checklist"
},
"fYVH36": {

View File

@@ -280,7 +280,7 @@
"message": "Add details...",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 169]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 200]],
"translation": "Добавить детали..."
},
"lyqwgn": {
@@ -4336,8 +4336,8 @@
["src/views/boards/components/ImportBoardsForm.tsx", 243],
["src/views/boards/components/ImportBoardsForm.tsx", 395],
["src/views/card/components/AttachmentThumbnails.tsx", 74],
["src/views/card/components/ChecklistItemRow.tsx", 67],
["src/views/card/components/ChecklistItemRow.tsx", 95],
["src/views/card/components/ChecklistItemRow.tsx", 69],
["src/views/card/components/ChecklistItemRow.tsx", 97],
["src/views/card/components/ChecklistNameInput.tsx", 47],
["src/views/card/components/Checklists.tsx", 81],
["src/views/card/components/Comment.tsx", 93],
@@ -5634,7 +5634,7 @@
"message": "Unable to delete checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 94]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 96]],
"translation": "Не удалось удалить элемент контрольного списка"
},
"2QGEbi": {
@@ -5718,7 +5718,7 @@
"message": "Unable to update checklist item",
"placeholders": {},
"comments": [],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 66]],
"origin": [["src/views/card/components/ChecklistItemRow.tsx", 68]],
"translation": "Не удалось обновить элемент контрольного списка"
},
"fYVH36": {

View File

@@ -19,7 +19,6 @@ 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;
@@ -44,9 +43,7 @@ export const integrationRouter = createTRPCRouter({
return { success: true };
}),
disconnectGitHub: protectedProcedure
.output(z.object({ success: z.boolean() }))
.mutation(async ({ ctx }) => {
disconnectGitHub: protectedProcedure.mutation(async ({ ctx }) => {
const user = ctx.user;
if (!user)
@@ -59,9 +56,7 @@ export const integrationRouter = createTRPCRouter({
return { success: true };
}),
getGitHubStatus: protectedProcedure
.output(z.object({ connected: z.boolean() }))
.query(async ({ ctx }) => {
getGitHubStatus: protectedProcedure.query(async ({ ctx }) => {
const user = ctx.user;
if (!user)

View File

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

View File

@@ -165,13 +165,6 @@ 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