diff --git a/apps/web/src/components/Input.tsx b/apps/web/src/components/Input.tsx
index d2712b2e..8a24d212 100644
--- a/apps/web/src/components/Input.tsx
+++ b/apps/web/src/components/Input.tsx
@@ -69,6 +69,7 @@ const Input = forwardRef
(
prefix && "rounded-l-none",
className && className,
)}
+ onKeyDown={onKeyDown}
{...props}
/>
{type === "password" && (
diff --git a/apps/web/src/components/LabelForm.tsx b/apps/web/src/components/LabelForm.tsx
index ef1a5496..5b2d8b41 100644
--- a/apps/web/src/components/LabelForm.tsx
+++ b/apps/web/src/components/LabelForm.tsx
@@ -1,5 +1,5 @@
import { Listbox, Transition } from "@headlessui/react";
-import { Fragment } from "react";
+import { Fragment, useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
import { HiChevronUpDown, HiXMark } from "react-icons/hi2";
@@ -103,6 +103,12 @@ export function LabelForm({
}
};
+ useEffect(() => {
+ const nameElement: HTMLElement | null =
+ document.querySelector("#label-name");
+ if (nameElement) nameElement.focus();
+ }, []);
+
return (
diff --git a/apps/web/src/pages/api/upload/image.ts b/apps/web/src/pages/api/upload/image.ts
index b824cc5d..2d903d4f 100644
--- a/apps/web/src/pages/api/upload/image.ts
+++ b/apps/web/src/pages/api/upload/image.ts
@@ -2,6 +2,10 @@ import type { NextApiRequest, NextApiResponse } from "next";
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { env } from "next-runtime-env";
+import { createNextApiContext } from "@kan/api/trpc";
+
+
+const allowedContentTypes = ["image/jpeg", "image/png"];
export default async function handler(
req: NextApiRequest,
@@ -12,14 +16,37 @@ export default async function handler(
}
try {
- const { filename, contentType } = req.body;
+ const { user } = await createNextApiContext(req);
+
+ if (!user) {
+ return res.status(401).json({ error: "Unauthorized" });
+ }
+
+ const { filename, contentType } = req.body as {
+ filename: string;
+ contentType: string;
+ };
+
+ // Specific to avatar uploads for now
+ const filenameRegex = /^[a-f0-9\-]+\/[a-zA-Z0-9_\-]+(\.jpg|\.jpeg|\.png)$/;
+
+ if (!filenameRegex.test(filename)) {
+ return res.status(400).json({ error: "Invalid filename" });
+ }
+
+ if (
+ typeof contentType !== "string" ||
+ !allowedContentTypes.includes(contentType)
+ ) {
+ return res.status(400).json({ error: "Invalid content type" });
+ }
const client = new S3Client({
- region: env.S3_REGION,
- endpoint: env.S3_ENDPOINT,
+ region: env.S3_REGION ?? "",
+ endpoint: env.S3_ENDPOINT ?? "",
credentials: {
- accessKeyId: env.S3_ACCESS_KEY_ID,
- secretAccessKey: env.S3_SECRET_ACCESS_KEY,
+ accessKeyId: env.S3_ACCESS_KEY_ID ?? "",
+ secretAccessKey: env.S3_SECRET_ACCESS_KEY ?? "",
},
});
diff --git a/apps/web/src/views/board/components/NewCardForm.tsx b/apps/web/src/views/board/components/NewCardForm.tsx
index ba76f42e..6d028e3a 100644
--- a/apps/web/src/views/board/components/NewCardForm.tsx
+++ b/apps/web/src/views/board/components/NewCardForm.tsx
@@ -226,6 +226,7 @@ export function NewCardForm({
New card
{
closeModal();
@@ -237,7 +238,17 @@ export function NewCardForm({
-
+ {
+ if (e.key === "Enter") {
+ e.preventDefault();
+ await handleSubmit(onSubmit)();
+ }
+ }}
+ />
setValue("description", e.target.value)}
value={watch("description")}
contentEditable
+ onKeyDown={async (e) => {
+ if (e.key === "Enter" && e.shiftKey) {
+ e.preventDefault();
+ await handleSubmit(onSubmit)();
+ }
+ }}
/>
diff --git a/apps/web/src/views/board/components/NewListForm.tsx b/apps/web/src/views/board/components/NewListForm.tsx
index ec642421..b6c64693 100644
--- a/apps/web/src/views/board/components/NewListForm.tsx
+++ b/apps/web/src/views/board/components/NewListForm.tsx
@@ -111,6 +111,7 @@ export function NewListForm({
New list
{
e.preventDefault();
@@ -121,7 +122,17 @@ export function NewListForm({
-
+
{
+ if (e.key === "Enter") {
+ e.preventDefault();
+ await handleSubmit(onSubmit)();
+ }
+ }}
+ />
diff --git a/apps/web/src/views/boards/components/ImportBoardsForm.tsx b/apps/web/src/views/boards/components/ImportBoardsForm.tsx
index a68c595a..d8aab5e1 100644
--- a/apps/web/src/views/boards/components/ImportBoardsForm.tsx
+++ b/apps/web/src/views/boards/components/ImportBoardsForm.tsx
@@ -251,6 +251,7 @@ export function ImportBoardsForm() {