diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c347726ed..67b81ccac 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -33,6 +33,7 @@ body: options: # The below comment is used to insert a new version with on-release.yml #NEXT_VERSION# + - 1.36.1 - 1.36.0 - 1.35.1 - 1.35.0 diff --git a/.github/workflows/deployment-docker-image.yml b/.github/workflows/deployment-docker-image.yml index 307930137..96cb3a9e5 100644 --- a/.github/workflows/deployment-docker-image.yml +++ b/.github/workflows/deployment-docker-image.yml @@ -57,7 +57,7 @@ jobs: if: env.SKIP_RELEASE == 'false' with: persist-credentials: false - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 if: env.SKIP_RELEASE == 'false' with: node-version: 22.19.0 diff --git a/.github/workflows/update-contributors.yml b/.github/workflows/update-contributors.yml index 86f7c95d5..95b52365b 100644 --- a/.github/workflows/update-contributors.yml +++ b/.github/workflows/update-contributors.yml @@ -32,7 +32,7 @@ jobs: GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }} - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: ${{ matrix.node-version }} diff --git a/apps/nextjs/next.config.ts b/apps/nextjs/next.config.ts index 5f21d74e4..be0798daa 100644 --- a/apps/nextjs/next.config.ts +++ b/apps/nextjs/next.config.ts @@ -42,9 +42,11 @@ const nextConfig: NextConfig = { headers: [ { key: "Content-Security-Policy", + // worker-src / media-src with blob: is necessary for video.js, see https://github.com/homarr-labs/homarr/issues/3912 and https://stackoverflow.com/questions/65792855/problem-with-video-js-and-content-security-policy-csp value: ` default-src 'self'; script-src * 'unsafe-inline' 'unsafe-eval'; + worker-src * blob:; base-uri 'self'; connect-src *; style-src * 'unsafe-inline'; @@ -53,7 +55,7 @@ const nextConfig: NextConfig = { form-action 'self'; img-src * data:; font-src * data:; - media-src * data:; + media-src * data: blob:; ` .replace(/\s{2,}/g, " ") .trim(), diff --git a/apps/nextjs/package.json b/apps/nextjs/package.json index c64203b6c..6f22469eb 100644 --- a/apps/nextjs/package.json +++ b/apps/nextjs/package.json @@ -61,17 +61,17 @@ "@tanstack/react-query": "^5.87.1", "@tanstack/react-query-devtools": "^5.87.1", "@tanstack/react-query-next-experimental": "^5.87.1", - "@trpc/client": "^11.5.0", - "@trpc/next": "^11.5.0", - "@trpc/react-query": "^11.5.0", - "@trpc/server": "^11.5.0", + "@trpc/client": "^11.5.1", + "@trpc/next": "^11.5.1", + "@trpc/react-query": "^11.5.1", + "@trpc/server": "^11.5.1", "@xterm/addon-canvas": "^0.7.0", "@xterm/addon-fit": "0.10.0", "@xterm/xterm": "^5.5.0", "chroma-js": "^3.1.2", "clsx": "^2.1.1", "dayjs": "^1.11.18", - "dotenv": "^17.2.1", + "dotenv": "^17.2.2", "flag-icons": "^7.5.0", "glob": "^11.0.3", "jotai": "^2.13.1", @@ -83,9 +83,9 @@ "react-dom": "19.1.1", "react-error-boundary": "^6.0.0", "react-simple-code-editor": "^0.14.1", - "sass": "^1.91.0", + "sass": "^1.92.1", "superjson": "2.2.2", - "swagger-ui-react": "^5.28.0", + "swagger-ui-react": "^5.28.1", "use-deep-compare-effect": "^1.8.1", "zod": "^4.1.5" }, @@ -94,13 +94,13 @@ "@homarr/prettier-config": "workspace:^0.1.0", "@homarr/tsconfig": "workspace:^0.1.0", "@types/chroma-js": "3.1.1", - "@types/node": "^22.18.0", + "@types/node": "^22.18.1", "@types/prismjs": "^1.26.5", "@types/react": "19.1.12", "@types/react-dom": "19.1.9", "@types/swagger-ui-react": "^5.18.0", "concurrently": "^9.2.1", - "eslint": "^9.34.0", + "eslint": "^9.35.0", "node-loader": "^2.1.0", "prettier": "^3.6.2", "typescript": "^5.9.2" diff --git a/apps/nextjs/src/app/[locale]/boards/[name]/settings/page.tsx b/apps/nextjs/src/app/[locale]/boards/[name]/settings/page.tsx index 31dfd48c3..a728e8949 100644 --- a/apps/nextjs/src/app/[locale]/boards/[name]/settings/page.tsx +++ b/apps/nextjs/src/app/[locale]/boards/[name]/settings/page.tsx @@ -61,6 +61,10 @@ const getBoardAndPermissionsAsync = async (params: Awaited) => notFound(); } + if (error instanceof TRPCError && error.code === "BAD_REQUEST") { + notFound(); + } + throw error; } }; diff --git a/apps/nextjs/src/app/[locale]/boards/_layout-creator.tsx b/apps/nextjs/src/app/[locale]/boards/_layout-creator.tsx index c04d6fe56..da1880963 100644 --- a/apps/nextjs/src/app/[locale]/boards/_layout-creator.tsx +++ b/apps/nextjs/src/app/[locale]/boards/_layout-creator.tsx @@ -45,6 +45,10 @@ export const createBoardLayout = ({ notFound(); } + if (error instanceof TRPCError && error.code === "BAD_REQUEST") { + notFound(); + } + throw error; }); const colorScheme = await getCurrentColorSchemeAsync(); diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/_components/secrets/integration-secret-icons.ts b/apps/nextjs/src/app/[locale]/manage/integrations/_components/secrets/integration-secret-icons.ts index 008d8b34f..0faccc11c 100644 --- a/apps/nextjs/src/app/[locale]/manage/integrations/_components/secrets/integration-secret-icons.ts +++ b/apps/nextjs/src/app/[locale]/manage/integrations/_components/secrets/integration-secret-icons.ts @@ -1,9 +1,11 @@ import { + IconCode, IconGrid3x3, IconKey, IconMessage, IconPassword, IconPasswordUser, + IconPlug, IconServer, IconUser, } from "@tabler/icons-react"; @@ -21,4 +23,7 @@ export const integrationSecretIcons = { topic: IconMessage, opnsenseApiKey: IconKey, opnsenseApiSecret: IconPassword, + githubAppId: IconCode, + githubInstallationId: IconPlug, + privateKey: IconKey, } satisfies Record; diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/_components/secrets/integration-secret-inputs.tsx b/apps/nextjs/src/app/[locale]/manage/integrations/_components/secrets/integration-secret-inputs.tsx index 45f5b3156..78e2d78c1 100644 --- a/apps/nextjs/src/app/[locale]/manage/integrations/_components/secrets/integration-secret-inputs.tsx +++ b/apps/nextjs/src/app/[locale]/manage/integrations/_components/secrets/integration-secret-inputs.tsx @@ -1,7 +1,7 @@ "use client"; import type { ChangeEventHandler, FocusEventHandler } from "react"; -import { PasswordInput, TextInput } from "@mantine/core"; +import { PasswordInput, Textarea, TextInput } from "@mantine/core"; import { integrationSecretKindObject } from "@homarr/definitions"; import type { IntegrationSecretKind } from "@homarr/definitions"; @@ -14,9 +14,9 @@ interface IntegrationSecretInputProps { label?: string; kind: IntegrationSecretKind; value?: string; - onChange: ChangeEventHandler; - onFocus?: FocusEventHandler; - onBlur?: FocusEventHandler; + onChange: ChangeEventHandler; + onFocus?: FocusEventHandler; + onBlur?: FocusEventHandler; error?: string; } @@ -31,6 +31,19 @@ export const IntegrationSecretInput = (props: IntegrationSecretInputProps) => { const PublicSecretInput = ({ kind, ...props }: IntegrationSecretInputProps) => { const t = useI18n(); const Icon = integrationSecretIcons[kind]; + const { multiline } = integrationSecretKindObject[kind]; + if (multiline) { + return ( +