diff --git a/.github/workflows/deployment-docker-image.yml b/.github/workflows/deployment-docker-image.yml index 80e99e68a..c96cf1a1b 100644 --- a/.github/workflows/deployment-docker-image.yml +++ b/.github/workflows/deployment-docker-image.yml @@ -104,7 +104,7 @@ jobs: NEXT_VERSION: ${{ needs.release.outputs.version }} DEPLOY_LATEST: ${{ github.ref_name == 'main' }} DEPLOY_BETA: ${{ github.ref_name == 'beta' }} - PUSH_IMAGE: ${{ github.event_name != 'workflow_dispatch' || github.events.inputs.push-image == 'true' }} + PUSH_IMAGE: ${{ github.event_name != 'workflow_dispatch' || github.events.inputs.push-image == true }} steps: - uses: actions/checkout@v4 - name: Discord notification diff --git a/Dockerfile b/Dockerfile index 6b0ea4e63..3e6f04281 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ FROM base AS runner WORKDIR /app # gettext is required for envsubst -RUN apk add --no-cache redis nginx bash gettext +RUN apk add --no-cache redis nginx bash gettext su-exec RUN mkdir /appdata VOLUME /appdata RUN mkdir /secrets @@ -43,14 +43,12 @@ RUN echo $'#!/bin/bash\ncd /app/apps/cli && node ./cli.cjs "$@"' > /usr/bin/homa RUN chmod +x /usr/bin/homarr # Don't run production as root -RUN chown -R nextjs:nodejs /appdata RUN chown -R nextjs:nodejs /secrets RUN mkdir -p /var/cache/nginx && chown -R nextjs:nodejs /var/cache/nginx && \ mkdir -p /var/log/nginx && chown -R nextjs:nodejs /var/log/nginx && \ mkdir -p /var/lib/nginx && chown -R nextjs:nodejs /var/lib/nginx && \ touch /run/nginx/nginx.pid && chown -R nextjs:nodejs /run/nginx/nginx.pid && \ mkdir -p /etc/nginx/templates /etc/nginx/ssl/certs && chown -R nextjs:nodejs /etc/nginx -USER nextjs COPY --from=builder /app/apps/nextjs/next.config.mjs . COPY --from=builder /app/apps/nextjs/package.json . @@ -67,6 +65,8 @@ COPY --from=builder --chown=nextjs:nodejs /app/apps/nextjs/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/apps/nextjs/.next/static ./apps/nextjs/.next/static COPY --from=builder --chown=nextjs:nodejs /app/apps/nextjs/public ./apps/nextjs/public COPY --chown=nextjs:nodejs scripts/run.sh ./run.sh +COPY scripts/entrypoint.sh ./entrypoint.sh +RUN chmod +x ./entrypoint.sh COPY --chown=nextjs:nodejs scripts/generateRandomSecureKey.js ./generateRandomSecureKey.js COPY --chown=nextjs:nodejs packages/redis/redis.conf /app/redis.conf COPY --chown=nextjs:nodejs nginx.conf /etc/nginx/templates/nginx.conf @@ -77,4 +77,5 @@ ENV DB_DIALECT='sqlite' ENV DB_DRIVER='better-sqlite3' ENV AUTH_PROVIDERS='credentials' +ENTRYPOINT [ "/app/entrypoint.sh" ] CMD ["sh", "run.sh"] diff --git a/apps/nextjs/src/components/layout/header/user.tsx b/apps/nextjs/src/components/layout/header/user.tsx index 0821420b7..f4aabb767 100644 --- a/apps/nextjs/src/components/layout/header/user.tsx +++ b/apps/nextjs/src/components/layout/header/user.tsx @@ -7,13 +7,13 @@ import { CurrentUserAvatar } from "~/components/user-avatar"; import { UserAvatarMenu } from "~/components/user-avatar-menu"; export const UserButton = async () => { - const data = await api.updateChecker.getAvailableUpdates(); const session = await auth(); const isAdmin = session?.user.permissions.includes("admin"); + const data = isAdmin ? await api.updateChecker.getAvailableUpdates() : undefined; return ( - + - + diff --git a/apps/nextjs/src/versions/package-reader.ts b/apps/nextjs/src/versions/package-reader.ts index 25976619e..a7da5b029 100644 --- a/apps/nextjs/src/versions/package-reader.ts +++ b/apps/nextjs/src/versions/package-reader.ts @@ -1,7 +1,7 @@ import fsPromises from "fs/promises"; import { glob } from "glob"; -import packageJson from "~/../package.json"; +import packageJson from "../../../../package.json"; const getPackageVersion = () => packageJson.version; const getDependenciesAsync = async (): Promise => { diff --git a/packages/api/src/router/integration/integration-router.ts b/packages/api/src/router/integration/integration-router.ts index 54963407e..72378a7e9 100644 --- a/packages/api/src/router/integration/integration-router.ts +++ b/packages/api/src/router/integration/integration-router.ts @@ -14,15 +14,16 @@ import { } from "@homarr/db/schema/sqlite"; import type { IntegrationSecretKind } from "@homarr/definitions"; import { + getIntegrationKindsByCategory, getPermissionsWithParents, integrationDefs, integrationKinds, integrationSecretKindObject, - isIntegrationWithSearchSupport, } from "@homarr/definitions"; -import { integrationCreatorFromSecrets } from "@homarr/integrations"; +import { integrationCreator } from "@homarr/integrations"; import { validation, z } from "@homarr/validation"; +import { createOneIntegrationMiddleware } from "../../middlewares/integration"; import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure, publicProcedure } from "../../trpc"; import { throwIfActionForbiddenAsync } from "./integration-access"; import { testConnectionAsync } from "./integration-test-connection"; @@ -90,7 +91,7 @@ export const integrationRouter = createTRPCRouter({ where: inArray( integrations.kind, objectEntries(integrationDefs) - .filter(([_, integration]) => integration.supportsSearch) + .filter(([_, integration]) => [...integration.category].includes("search")) .map(([kind, _]) => kind), ), }); @@ -383,31 +384,11 @@ export const integrationRouter = createTRPCRouter({ }); }), searchInIntegration: protectedProcedure + .unstable_concat(createOneIntegrationMiddleware("query", ...getIntegrationKindsByCategory("search"))) .input(z.object({ integrationId: z.string(), query: z.string() })) .query(async ({ ctx, input }) => { - const integration = await ctx.db.query.integrations.findFirst({ - where: eq(integrations.id, input.integrationId), - with: { - secrets: true, - }, - }); - - if (!integration) { - throw new TRPCError({ - code: "NOT_FOUND", - message: "The requested integration does not exist", - }); - } - - if (!isIntegrationWithSearchSupport(integration)) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "The requested integration does not support searching", - }); - } - - const integrationInstance = integrationCreatorFromSecrets(integration); - return await integrationInstance.searchAsync(input.query); + const integrationInstance = integrationCreator(ctx.integration); + return await integrationInstance.searchAsync(encodeURI(input.query)); }), }); diff --git a/packages/auth/package.json b/packages/auth/package.json index 3eb20648a..1dfb76018 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -33,7 +33,7 @@ "@t3-oss/env-nextjs": "^0.11.1", "bcrypt": "^5.1.1", "cookies": "^0.9.1", - "ldapts": "7.2.2", + "ldapts": "7.3.0", "next": "^14.2.20", "next-auth": "5.0.0-beta.25", "react": "^19.0.0", diff --git a/packages/definitions/src/docs/homarr-docs-sitemap.ts b/packages/definitions/src/docs/homarr-docs-sitemap.ts index 2210941e3..31aa7c4c6 100644 --- a/packages/definitions/src/docs/homarr-docs-sitemap.ts +++ b/packages/definitions/src/docs/homarr-docs-sitemap.ts @@ -8,6 +8,7 @@ export type HomarrDocumentationPath = | "/blog/2023/11/10/authentication" | "/blog/2023/12/22/updated-documentation" | "/blog/2024/09/23/version-1.0" + | "/blog/2024/12/17/open-beta-1.0" | "/blog/archive" | "/blog/authors" | "/blog/authors/ajnart" @@ -33,6 +34,7 @@ export type HomarrDocumentationPath = | "/blog/tags/update" | "/blog/tags/version" | "/blog/translations" + | "/search" | "/docs/tags" | "/docs/tags/active-directory" | "/docs/tags/ad-guard" @@ -44,7 +46,6 @@ export type HomarrDocumentationPath = | "/docs/tags/apps" | "/docs/tags/banner" | "/docs/tags/blocking" - | "/docs/tags/board" | "/docs/tags/boards" | "/docs/tags/bookmark" | "/docs/tags/bookmarks" @@ -56,10 +57,12 @@ export type HomarrDocumentationPath = | "/docs/tags/connections" | "/docs/tags/customization" | "/docs/tags/data-sources" + | "/docs/tags/database" | "/docs/tags/developer" | "/docs/tags/development" | "/docs/tags/dns" | "/docs/tags/docker" + | "/docs/tags/donation" | "/docs/tags/edit-mode" | "/docs/tags/env" | "/docs/tags/environment-variables" @@ -71,6 +74,8 @@ export type HomarrDocumentationPath = | "/docs/tags/hardware" | "/docs/tags/health" | "/docs/tags/help" + | "/docs/tags/icon-picker" + | "/docs/tags/icon-repositories" | "/docs/tags/icons" | "/docs/tags/iframe" | "/docs/tags/images" @@ -84,17 +89,18 @@ export type HomarrDocumentationPath = | "/docs/tags/links" | "/docs/tags/lists" | "/docs/tags/management" + | "/docs/tags/media" | "/docs/tags/monitoring" | "/docs/tags/news" | "/docs/tags/notebook" | "/docs/tags/notes" | "/docs/tags/oidc" + | "/docs/tags/open-collective" | "/docs/tags/open-media-vault" | "/docs/tags/overseerr" | "/docs/tags/permissions" | "/docs/tags/pi-hole" | "/docs/tags/ping" - | "/docs/tags/preferences" | "/docs/tags/programming" | "/docs/tags/proxmox" | "/docs/tags/proxy" @@ -112,39 +118,37 @@ export type HomarrDocumentationPath = | "/docs/tags/table" | "/docs/tags/technical-documentation" | "/docs/tags/text" - | "/docs/tags/theming" + | "/docs/tags/torrent" | "/docs/tags/traefik" | "/docs/tags/translations" | "/docs/tags/unraid" - | "/docs/tags/user" + | "/docs/tags/uploads" + | "/docs/tags/usenet" | "/docs/tags/users" | "/docs/tags/variables" | "/docs/tags/widgets" | "/docs/advanced/command-line" | "/docs/advanced/command-line/password-recovery" - | "/docs/advanced/configuration/environment-variables" - | "/docs/advanced/configuration/keyboard-shortcuts" - | "/docs/advanced/configuration/proxies-and-certificates" - | "/docs/advanced/customizations/board-customization" - | "/docs/advanced/customizations/dark-mode" - | "/docs/advanced/customizations/icons" - | "/docs/advanced/customizations/user-preferences" - | "/docs/advanced/sso" + | "/docs/advanced/development/getting-started" + | "/docs/advanced/environment-variables" + | "/docs/advanced/icons" + | "/docs/advanced/keyboard-shortcuts" + | "/docs/advanced/proxy" + | "/docs/advanced/single-sign-on" | "/docs/category/advanced" - | "/docs/category/developer-guide" + | "/docs/category/community" + | "/docs/category/developer-guides" | "/docs/category/getting-started" | "/docs/category/installation" | "/docs/category/installation-1" | "/docs/category/integrations" | "/docs/category/management" - | "/docs/category/more" | "/docs/category/widgets" | "/docs/community/donate" | "/docs/community/faq" | "/docs/community/get-in-touch" | "/docs/community/license" | "/docs/community/translations" - | "/docs/development/getting-started" | "/docs/getting-started" | "/docs/getting-started/after-the-installation" | "/docs/getting-started/glossary" @@ -152,7 +156,6 @@ export type HomarrDocumentationPath = | "/docs/getting-started/installation/easy-panel" | "/docs/getting-started/installation/helm" | "/docs/getting-started/installation/home-assistant" - | "/docs/getting-started/installation/kubernetes" | "/docs/getting-started/installation/portainer" | "/docs/getting-started/installation/qnap" | "/docs/getting-started/installation/saltbox" @@ -172,15 +175,15 @@ export type HomarrDocumentationPath = | "/docs/management/apps" | "/docs/management/boards" | "/docs/management/integrations" + | "/docs/management/media" | "/docs/management/search-engines" | "/docs/management/settings" | "/docs/management/users" | "/docs/widgets/bookmarks" - | "/docs/widgets/calendar-widget" - | "/docs/widgets/clock-widget" - | "/docs/widgets/dashdot-widget" + | "/docs/widgets/calendar" + | "/docs/widgets/clock" | "/docs/widgets/dns-hole" - | "/docs/widgets/download-speed-widget" + | "/docs/widgets/downloads" | "/docs/widgets/health-monitoring" | "/docs/widgets/home-assistant" | "/docs/widgets/iframe" @@ -188,10 +191,8 @@ export type HomarrDocumentationPath = | "/docs/widgets/media-requests" | "/docs/widgets/media-server" | "/docs/widgets/notebook" - | "/docs/widgets/rss-widget" - | "/docs/widgets/torrent-widget" - | "/docs/widgets/usenet-widget" + | "/docs/widgets/rss" | "/docs/widgets/video" - | "/docs/widgets/weather-widget" + | "/docs/widgets/weather" | "" | "/sitemap.xml"; diff --git a/packages/definitions/src/group.ts b/packages/definitions/src/group.ts index 40c278b95..bf388c288 100644 --- a/packages/definitions/src/group.ts +++ b/packages/definitions/src/group.ts @@ -1,2 +1,2 @@ export const everyoneGroup = "everyone"; -export const credentialsAdminGroup = "admin"; +export const credentialsAdminGroup = "credentials-admin"; diff --git a/packages/definitions/src/integration.ts b/packages/definitions/src/integration.ts index 0856fa830..1ace6b955 100644 --- a/packages/definitions/src/integration.ts +++ b/packages/definitions/src/integration.ts @@ -14,7 +14,6 @@ interface integrationDefinition { iconUrl: string; secretKinds: AtLeastOneOf; // at least one secret kind set is required category: AtLeastOneOf; - supportsSearch: boolean; } export const integrationDefs = { @@ -23,140 +22,120 @@ export const integrationDefs = { secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/sabnzbd.png", category: ["downloadClient", "usenet"], - supportsSearch: false, }, nzbGet: { name: "NZBGet", secretKinds: [["username", "password"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/nzbget.png", category: ["downloadClient", "usenet"], - supportsSearch: false, }, deluge: { name: "Deluge", secretKinds: [["password"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/deluge.png", category: ["downloadClient", "torrent"], - supportsSearch: false, }, transmission: { name: "Transmission", secretKinds: [["username", "password"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/transmission.png", category: ["downloadClient", "torrent"], - supportsSearch: false, }, qBittorrent: { name: "qBittorrent", secretKinds: [["username", "password"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/qbittorrent.png", category: ["downloadClient", "torrent"], - supportsSearch: false, }, sonarr: { name: "Sonarr", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/sonarr.png", category: ["calendar"], - supportsSearch: false, }, radarr: { name: "Radarr", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/radarr.png", category: ["calendar"], - supportsSearch: false, }, lidarr: { name: "Lidarr", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/lidarr.png", category: ["calendar"], - supportsSearch: false, }, readarr: { name: "Readarr", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/readarr.png", category: ["calendar"], - supportsSearch: false, }, prowlarr: { name: "Prowlarr", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/prowlarr.png", category: ["indexerManager"], - supportsSearch: false, }, jellyfin: { name: "Jellyfin", secretKinds: [["username", "password"], ["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/jellyfin.png", category: ["mediaService"], - supportsSearch: false, }, plex: { name: "Plex", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/plex.png", category: ["mediaService"], - supportsSearch: false, }, jellyseerr: { name: "Jellyseerr", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/jellyseerr.png", - category: ["mediaSearch", "mediaRequest"], - supportsSearch: true, + category: ["mediaSearch", "mediaRequest", "search"], }, overseerr: { name: "Overseerr", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/overseerr.png", - category: ["mediaSearch", "mediaRequest"], - supportsSearch: true, + category: ["mediaSearch", "mediaRequest", "search"], }, piHole: { name: "Pi-hole", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/pi-hole.png", category: ["dnsHole"], - supportsSearch: false, }, adGuardHome: { name: "AdGuard Home", secretKinds: [["username", "password"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/adguard-home.png", category: ["dnsHole"], - supportsSearch: false, }, homeAssistant: { name: "Home Assistant", secretKinds: [["apiKey"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/home-assistant.png", category: ["smartHomeServer"], - supportsSearch: false, }, openmediavault: { name: "OpenMediaVault", secretKinds: [["username", "password"]], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/openmediavault.png", category: ["healthMonitoring"], - supportsSearch: false, }, dashDot: { name: "Dash.", secretKinds: [[]], category: ["healthMonitoring"], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/dashdot.png", - supportsSearch: false, }, tdarr: { name: "Tdarr", secretKinds: [[]], category: ["mediaTranscoding"], iconUrl: "https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/tdarr.png", - supportsSearch: false, }, } as const satisfies Record; @@ -195,22 +174,6 @@ export type IntegrationKindByCategory = { U : never; -/** - * Checks if search is supported by the integration - * Uses a typescript guard with is to allow only integrations with search support within if statement - * @param integration integration with kind - * @returns true if the integration supports search - */ -export const isIntegrationWithSearchSupport = (integration: { - kind: IntegrationKind; -}): integration is { kind: IntegrationWithSearchSupport } => { - return integrationDefs[integration.kind].supportsSearch; -}; - -type IntegrationWithSearchSupport = { - [Key in keyof typeof integrationDefs]: true extends (typeof integrationDefs)[Key]["supportsSearch"] ? Key : never; -}[keyof typeof integrationDefs]; - export type IntegrationSecretKind = keyof typeof integrationSecretKindObject; export type IntegrationKind = keyof typeof integrationDefs; export type IntegrationCategory = @@ -225,4 +188,5 @@ export type IntegrationCategory = | "smartHomeServer" | "indexerManager" | "healthMonitoring" + | "search" | "mediaTranscoding"; diff --git a/packages/integrations/src/base/integration.ts b/packages/integrations/src/base/integration.ts index c9c953443..413ec6096 100644 --- a/packages/integrations/src/base/integration.ts +++ b/packages/integrations/src/base/integration.ts @@ -29,6 +29,10 @@ export abstract class Integration { return secret.value; } + protected hasSecretValue(kind: IntegrationSecretKind) { + return this.integration.decryptedSecrets.some((secret) => secret.kind === kind); + } + protected url(path: `/${string}`, queryParams?: Record) { const baseUrl = removeTrailingSlash(this.integration.url); const url = new URL(`${baseUrl}${path}`); diff --git a/packages/integrations/src/jellyfin/jellyfin-integration.ts b/packages/integrations/src/jellyfin/jellyfin-integration.ts index 4a603d6c2..2383473cd 100644 --- a/packages/integrations/src/jellyfin/jellyfin-integration.ts +++ b/packages/integrations/src/jellyfin/jellyfin-integration.ts @@ -18,13 +18,13 @@ export class JellyfinIntegration extends Integration { }); public async testConnectionAsync(): Promise { - const api = this.getApi(); + const api = await this.getApiAsync(); const systemApi = getSystemApi(api); await systemApi.getPingSystem(); } public async getCurrentSessionsAsync(): Promise { - const api = this.getApi(); + const api = await this.getApiAsync(); const sessionApi = getSessionApi(api); const sessions = await sessionApi.getSessions(); @@ -59,8 +59,22 @@ export class JellyfinIntegration extends Integration { }); } - private getApi() { - const apiKey = this.getSecretValue("apiKey"); - return this.jellyfin.createApi(this.url("/").toString(), apiKey); + /** + * Constructs an ApiClient synchronously with an ApiKey or asynchronously + * with a username and password. + * @returns An instance of Api that has been authenticated + */ + private async getApiAsync() { + if (this.hasSecretValue("apiKey")) { + const apiKey = this.getSecretValue("apiKey"); + return this.jellyfin.createApi(this.url("/").toString(), apiKey); + } + + const apiClient = this.jellyfin.createApi(this.url("/").toString()); + // Authentication state is stored internally in the Api class, so now + // requests that require authentication can be made normally. + // see https://typescript-sdk.jellyfin.org/#usage + await apiClient.authenticateUserByName(this.getSecretValue("username"), this.getSecretValue("password")); + return apiClient; } } diff --git a/packages/old-import/src/import/collections/integration-collection.ts b/packages/old-import/src/import/collections/integration-collection.ts index dd21cd59f..1f67481dd 100644 --- a/packages/old-import/src/import/collections/integration-collection.ts +++ b/packages/old-import/src/import/collections/integration-collection.ts @@ -7,12 +7,17 @@ import { createDbInsertCollection } from "./common"; export const createIntegrationInsertCollection = ( preparedIntegrations: PreparedIntegration[], - encryptionToken: string | null, + encryptionToken: string | null | undefined, ) => { const insertCollection = createDbInsertCollection(["integrations", "integrationSecrets"]); + + if (preparedIntegrations.length === 0) { + return insertCollection; + } + logger.info(`Preparing integrations for insert collection count=${preparedIntegrations.length}`); - if (encryptionToken === null) { + if (encryptionToken === null || encryptionToken === undefined) { logger.debug("Skipping integration decryption due to missing token"); return insertCollection; } diff --git a/packages/old-import/src/import/collections/user-collection.ts b/packages/old-import/src/import/collections/user-collection.ts index 096a06591..e98307590 100644 --- a/packages/old-import/src/import/collections/user-collection.ts +++ b/packages/old-import/src/import/collections/user-collection.ts @@ -6,12 +6,19 @@ import { mapAndDecryptUsers } from "../../mappers/map-user"; import type { OldmarrImportUser } from "../../user-schema"; import { createDbInsertCollection } from "./common"; -export const createUserInsertCollection = (importUsers: OldmarrImportUser[], encryptionToken: string | null) => { +export const createUserInsertCollection = ( + importUsers: OldmarrImportUser[], + encryptionToken: string | null | undefined, +) => { const insertCollection = createDbInsertCollection(["users", "groups", "groupMembers", "groupPermissions"]); + if (importUsers.length === 0) { + return insertCollection; + } + logger.info(`Preparing users for insert collection count=${importUsers.length}`); - if (encryptionToken === null) { + if (encryptionToken === null || encryptionToken === undefined) { logger.debug("Skipping user decryption due to missing token"); return insertCollection; } diff --git a/packages/old-import/src/import/input.ts b/packages/old-import/src/import/input.ts index 13f28c774..3ea7119aa 100644 --- a/packages/old-import/src/import/input.ts +++ b/packages/old-import/src/import/input.ts @@ -20,5 +20,5 @@ export const importInitialOldmarrInputSchema = zfd.formData({ const map = boardSelectionMapSchema.parse(SuperJSON.parse(value)); return map; }), - token: zfd.text().nullable(), + token: zfd.text().nullable().optional(), }); diff --git a/packages/old-import/src/import/validate-token.ts b/packages/old-import/src/import/validate-token.ts index ac01cf20a..74e43e52e 100644 --- a/packages/old-import/src/import/validate-token.ts +++ b/packages/old-import/src/import/validate-token.ts @@ -1,6 +1,6 @@ import { decryptSecretWithKey } from "@homarr/common/server"; -export const ensureValidTokenOrThrow = (checksum: string | undefined, encryptionToken: string | null) => { +export const ensureValidTokenOrThrow = (checksum: string | undefined, encryptionToken: string | null | undefined) => { if (!encryptionToken || !checksum) return; const [first, second] = checksum.split("\n"); diff --git a/packages/old-import/src/move-widgets-and-apps-merge.ts b/packages/old-import/src/move-widgets-and-apps-merge.ts index 2111e5d9e..68abcb351 100644 --- a/packages/old-import/src/move-widgets-and-apps-merge.ts +++ b/packages/old-import/src/move-widgets-and-apps-merge.ts @@ -81,13 +81,26 @@ export const moveWidgetsAndAppsIfMerge = ( } if (configuration.sidebarBehaviour === "last-section") { - if (old.settings.customization.layout.enabledLeftSidebar) { + const areas = [...old.apps.map((app) => app.area), ...old.widgets.map((widget) => widget.area)]; + if ( + old.settings.customization.layout.enabledLeftSidebar || + areas.some((area) => area.type === "sidebar" && area.properties.location === "left") + ) { offset = moveWidgetsAndAppsInLeftSidebar(old, firstId, offset, configuration.screenSize); } - if (old.settings.customization.layout.enabledRightSidebar) { + if ( + old.settings.customization.layout.enabledRightSidebar || + areas.some((area) => area.type === "sidebar" && area.properties.location === "right") + ) { moveWidgetsAndAppsInRightSidebar(old, firstId, offset, configuration.screenSize); } + } else { + // Remove all widgets and apps in the sidebar + return { + apps: old.apps.filter((app) => app.area.type !== "sidebar"), + widgets: old.widgets.filter((app) => app.area.type !== "sidebar"), + }; } return { apps: old.apps, widgets: old.widgets }; diff --git a/packages/old-schema/src/app.ts b/packages/old-schema/src/app.ts index 79732af92..87bedef25 100644 --- a/packages/old-schema/src/app.ts +++ b/packages/old-schema/src/app.ts @@ -69,7 +69,7 @@ export const oldmarrAppSchema = z behaviour: appBehaviourSchema, network: appNetworkSchema, appearance: appAppearanceSchema, - integration: appIntegrationSchema.optional(), + integration: appIntegrationSchema.optional().nullable(), }) .and(tileBaseSchema); diff --git a/packages/translation/package.json b/packages/translation/package.json index 7defeef26..870ebfdcf 100644 --- a/packages/translation/package.json +++ b/packages/translation/package.json @@ -33,7 +33,7 @@ "deepmerge": "4.3.1", "mantine-react-table": "2.0.0-beta.7", "next": "^14.2.20", - "next-intl": "3.26.1", + "next-intl": "3.26.2", "react": "^19.0.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c364c6ddb..984302576 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -186,16 +186,16 @@ importers: version: 5.62.8(@tanstack/react-query@5.62.8(react@19.0.0))(next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0))(react@19.0.0) '@trpc/client': specifier: next - version: 11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2) + version: 11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2) '@trpc/next': specifier: next - version: 11.0.0-rc.660(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2))(@trpc/react-query@11.0.0-rc.660(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2))(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2) + version: 11.0.0-rc.666(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2))(@trpc/react-query@11.0.0-rc.666(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2))(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2) '@trpc/react-query': specifier: next - version: 11.0.0-rc.660(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2) + version: 11.0.0-rc.666(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2) '@trpc/server': specifier: next - version: 11.0.0-rc.660(typescript@5.7.2) + version: 11.0.0-rc.666(typescript@5.7.2) '@xterm/addon-canvas': specifier: ^0.7.0 version: 0.7.0(@xterm/xterm@5.5.0) @@ -538,13 +538,13 @@ importers: version: link:../validation '@trpc/client': specifier: next - version: 11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2) + version: 11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2) '@trpc/react-query': specifier: next - version: 11.0.0-rc.660(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2) + version: 11.0.0-rc.666(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2) '@trpc/server': specifier: next - version: 11.0.0-rc.660(typescript@5.7.2) + version: 11.0.0-rc.666(typescript@5.7.2) dockerode: specifier: ^4.0.2 version: 4.0.2 @@ -559,7 +559,7 @@ importers: version: 2.2.2 trpc-to-openapi: specifier: ^2.1.0 - version: 2.1.0(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(zod-openapi@2.19.0(zod@3.24.1))(zod@3.24.1) + version: 2.1.0(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(zod-openapi@2.19.0(zod@3.24.1))(zod@3.24.1) devDependencies: '@homarr/eslint-config': specifier: workspace:^0.2.0 @@ -616,8 +616,8 @@ importers: specifier: ^0.9.1 version: 0.9.1 ldapts: - specifier: 7.2.2 - version: 7.2.2 + specifier: 7.3.0 + version: 7.3.0 next: specifier: ^14.2.20 version: 14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0) @@ -1569,8 +1569,8 @@ importers: specifier: ^14.2.20 version: 14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0) next-intl: - specifier: 3.26.1 - version: 3.26.1(next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0))(react@19.0.0) + specifier: 3.26.2 + version: 3.26.2(next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0))(react@19.0.0) react: specifier: ^19.0.0 version: 19.0.0 @@ -3886,19 +3886,19 @@ packages: '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - '@trpc/client@11.0.0-rc.660': - resolution: {integrity: sha512-bNpkZEfyMGKHynYFxdLpY8nJ1n7E3JHKcd4Pe2cagmpkzOEF9tFT3kzNf+eLI8XMG8196lTRR0J0W2/1Q8/cug==} + '@trpc/client@11.0.0-rc.666': + resolution: {integrity: sha512-BP3H0bktY03m7haVT5QoPR4sn30DNJcvFHsA3Msj3uPRY8JLVE03MR4rVG6T7VbcglORKpyMlRxjpUgdRmJErA==} peerDependencies: - '@trpc/server': 11.0.0-rc.660+74625d5e4 + '@trpc/server': 11.0.0-rc.666+99556c074 typescript: '>=5.6.2' - '@trpc/next@11.0.0-rc.660': - resolution: {integrity: sha512-LQHdiVED8h+CJEAy/X9PDmY3fM8VPdZ+3bVkbmEiP4xoNnSKRTbSbknFyRzG9M2AogfIafF4zAZVwOvCxexyGw==} + '@trpc/next@11.0.0-rc.666': + resolution: {integrity: sha512-EiNMEY0nValoxMSvC+j68evlQqU/NoLrZXskvHnheoyaDLP8TxhTA2xUr+P4tkWPkjsRzh/Y5lxlyAb2PTA7aw==} peerDependencies: '@tanstack/react-query': ^5.59.15 - '@trpc/client': 11.0.0-rc.660+74625d5e4 - '@trpc/react-query': 11.0.0-rc.660+74625d5e4 - '@trpc/server': 11.0.0-rc.660+74625d5e4 + '@trpc/client': 11.0.0-rc.666+99556c074 + '@trpc/react-query': 11.0.0-rc.666+99556c074 + '@trpc/server': 11.0.0-rc.666+99556c074 next: '*' react: '>=16.8.0' react-dom: '>=16.8.0' @@ -3909,18 +3909,18 @@ packages: '@trpc/react-query': optional: true - '@trpc/react-query@11.0.0-rc.660': - resolution: {integrity: sha512-U2BHtYVt+8jt0a8Nrrk5cep8O1UZRxtTCBHtXie9kmJyQWWml43KfHxL5ssnFywaFrDZQz6Ec7kIoOxR/CQNfg==} + '@trpc/react-query@11.0.0-rc.666': + resolution: {integrity: sha512-BH0vU7g5w4IrN7xmWSKvLucZ9ZnpRwsDWCSJ0R09xdYwR7geHkna3PBbd8vQVFBSw7MpWEy6LGXVSCHSbUicLg==} peerDependencies: - '@tanstack/react-query': ^5.59.15 - '@trpc/client': 11.0.0-rc.660+74625d5e4 - '@trpc/server': 11.0.0-rc.660+74625d5e4 + '@tanstack/react-query': ^5.62.8 + '@trpc/client': 11.0.0-rc.666+99556c074 + '@trpc/server': 11.0.0-rc.666+99556c074 react: '>=18.2.0' react-dom: '>=18.2.0' typescript: '>=5.6.2' - '@trpc/server@11.0.0-rc.660': - resolution: {integrity: sha512-QUapcZCNOpHT7ng9LceGc9ImkboWd0Go9ryrduZpL+p4jdfaC6409AQ3x4XEW6Wu3yBmZAn4CywCsDrDhjDy/w==} + '@trpc/server@11.0.0-rc.666': + resolution: {integrity: sha512-k+jKrdH/owDRRXPR7oPKCQRTu0dOEnqdGh56863ym95sFY8qXE7BhOR8S4WqyZw1CiPZGjRkdFN0q/GsJhKsIA==} peerDependencies: typescript: '>=5.6.2' @@ -5076,6 +5076,15 @@ packages: supports-color: optional: true + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} @@ -6554,8 +6563,8 @@ packages: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} - ldapts@7.2.2: - resolution: {integrity: sha512-UotAq24/vJEz0m3w/jgwZm7JGNw8M6vexL/5KU5pe3aIZWBkT/HRhjsPw/buRqKSK5Y0vTu5Zv8iyPgQF7ozzg==} + ldapts@7.3.0: + resolution: {integrity: sha512-hj+cOy50uwu496x66IrqeY0WY35pMnkKrOgdYtZFu0uii4Xzw39Wng1hgzmGYWmzK9On4jYiiYyz1ZdVc857XA==} engines: {node: '>=18'} levn@0.4.1: @@ -6930,8 +6939,8 @@ packages: nodemailer: optional: true - next-intl@3.26.1: - resolution: {integrity: sha512-TE4cQgXNw4jzEtVPdiYQOCmhAu+Z2qoUppCMxPkJoz8XXe8TdqiNEPhD/GtXEsI80nV6NnVAq3hyTHH5+ex6Hw==} + next-intl@3.26.2: + resolution: {integrity: sha512-fPsL5/9Y/aYNHoOf904b+PhYkm1RfZKrNMAxUvURMqFuQTA0TQAIGnY0s03yPH7oRv9qCFcutaxr6DsHq0aCzQ==} peerDependencies: next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 @@ -8889,8 +8898,8 @@ packages: peerDependencies: react: '>=16.13' - use-intl@3.26.1: - resolution: {integrity: sha512-MZhtSBcMrDna3xs1T6O7CAXx4wRfm1eGyUYrDCCnW9qTOGZurCH5k/X6ChDl6EI4f+qYEtXQCRMkQUVOIhJWTQ==} + use-intl@3.26.2: + resolution: {integrity: sha512-H0BpBXLNFTkw6RvntLXSXr2+la4T/xilKSG5l8ND9Br9+i1hqHensWouNS288QZdiDTrfYUVswDtUIR6L39JHQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0 @@ -9096,6 +9105,10 @@ packages: resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==} engines: {node: '>=18'} + whatwg-url@14.1.0: + resolution: {integrity: sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==} + engines: {node: '>=18'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -11335,33 +11348,33 @@ snapshots: '@tootallnate/quickjs-emscripten@0.23.0': {} - '@trpc/client@11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2)': + '@trpc/client@11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2)': dependencies: - '@trpc/server': 11.0.0-rc.660(typescript@5.7.2) + '@trpc/server': 11.0.0-rc.666(typescript@5.7.2) typescript: 5.7.2 - '@trpc/next@11.0.0-rc.660(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2))(@trpc/react-query@11.0.0-rc.660(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2))(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2)': + '@trpc/next@11.0.0-rc.666(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2))(@trpc/react-query@11.0.0-rc.666(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2))(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2)': dependencies: - '@trpc/client': 11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2) - '@trpc/server': 11.0.0-rc.660(typescript@5.7.2) + '@trpc/client': 11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2) + '@trpc/server': 11.0.0-rc.666(typescript@5.7.2) next: 14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) typescript: 5.7.2 optionalDependencies: '@tanstack/react-query': 5.62.8(react@19.0.0) - '@trpc/react-query': 11.0.0-rc.660(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2) + '@trpc/react-query': 11.0.0-rc.666(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2) - '@trpc/react-query@11.0.0-rc.660(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2)': + '@trpc/react-query@11.0.0-rc.666(@tanstack/react-query@5.62.8(react@19.0.0))(@trpc/client@11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2))(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2)': dependencies: '@tanstack/react-query': 5.62.8(react@19.0.0) - '@trpc/client': 11.0.0-rc.660(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(typescript@5.7.2) - '@trpc/server': 11.0.0-rc.660(typescript@5.7.2) + '@trpc/client': 11.0.0-rc.666(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(typescript@5.7.2) + '@trpc/server': 11.0.0-rc.666(typescript@5.7.2) react: 19.0.0 react-dom: 19.0.0(react@19.0.0) typescript: 5.7.2 - '@trpc/server@11.0.0-rc.660(typescript@5.7.2)': + '@trpc/server@11.0.0-rc.666(typescript@5.7.2)': dependencies: typescript: 5.7.2 @@ -12714,6 +12727,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.0: + dependencies: + ms: 2.1.3 + decimal.js@10.4.3: {} decompress-response@6.0.0: @@ -14392,14 +14409,14 @@ snapshots: dependencies: readable-stream: 2.3.8 - ldapts@7.2.2: + ldapts@7.3.0: dependencies: '@types/asn1': 0.2.4 asn1: 0.2.6 - debug: 4.3.7 + debug: 4.4.0 strict-event-emitter-types: 2.0.0 uuid: 11.0.3 - whatwg-url: 14.0.0 + whatwg-url: 14.1.0 transitivePeerDependencies: - supports-color @@ -14746,13 +14763,13 @@ snapshots: next: 14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0) react: 19.0.0 - next-intl@3.26.1(next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0))(react@19.0.0): + next-intl@3.26.2(next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0))(react@19.0.0): dependencies: '@formatjs/intl-localematcher': 0.5.5 negotiator: 1.0.0 next: 14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0) react: 19.0.0 - use-intl: 3.26.1(react@19.0.0) + use-intl: 3.26.2(react@19.0.0) next@14.2.20(@babel/core@7.26.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.0): dependencies: @@ -16651,9 +16668,9 @@ snapshots: triple-beam@1.4.1: {} - trpc-to-openapi@2.1.0(@trpc/server@11.0.0-rc.660(typescript@5.7.2))(zod-openapi@2.19.0(zod@3.24.1))(zod@3.24.1): + trpc-to-openapi@2.1.0(@trpc/server@11.0.0-rc.666(typescript@5.7.2))(zod-openapi@2.19.0(zod@3.24.1))(zod@3.24.1): dependencies: - '@trpc/server': 11.0.0-rc.660(typescript@5.7.2) + '@trpc/server': 11.0.0-rc.666(typescript@5.7.2) co-body: 6.2.0 h3: 1.13.0 lodash.clonedeep: 4.5.0 @@ -16959,7 +16976,7 @@ snapshots: dequal: 2.0.3 react: 19.0.0 - use-intl@3.26.1(react@19.0.0): + use-intl@3.26.2(react@19.0.0): dependencies: '@formatjs/fast-memoize': 2.2.1 intl-messageformat: 10.7.1 @@ -17203,6 +17220,11 @@ snapshots: tr46: 5.0.0 webidl-conversions: 7.0.0 + whatwg-url@14.1.0: + dependencies: + tr46: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh new file mode 100644 index 000000000..59a5589df --- /dev/null +++ b/scripts/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +# Creating folders in volume +mkdir -p /appdata/db +mkdir -p /appdata/redis + +chown -R nextjs:nodejs /appdata + +su-exec 1001:1001 "$@" \ No newline at end of file diff --git a/scripts/run.sh b/scripts/run.sh index d22536ff2..2ba89cdff 100644 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -1,7 +1,3 @@ -# Creating folders in volume -mkdir -p /appdata/db -mkdir -p /appdata/redis - # Run migrations if [ $DB_MIGRATIONS_DISABLED = "true" ]; then echo "DB migrations are disabled, skipping"