diff --git a/apps/nextjs/src/components/board/items/item-content.tsx b/apps/nextjs/src/components/board/items/item-content.tsx index 7ee901ac8d..709d521825 100644 --- a/apps/nextjs/src/components/board/items/item-content.tsx +++ b/apps/nextjs/src/components/board/items/item-content.tsx @@ -5,8 +5,6 @@ import combineClasses from "clsx"; import { NoIntegrationSelectedError } from "node_modules/@homarr/widgets/src/errors"; import { ErrorBoundary } from "react-error-boundary"; -import { useSession } from "@homarr/auth/client"; -import { isWidgetRestricted } from "@homarr/auth/shared"; import { useRequiredBoard } from "@homarr/boards/context"; import { useEditMode } from "@homarr/boards/edit-mode"; import { useSettings } from "@homarr/settings"; @@ -17,7 +15,6 @@ import type { SectionItem } from "~/app/[locale]/boards/_types"; import classes from "../sections/item.module.css"; import { useItemActions } from "./item-actions"; import { BoardItemMenu } from "./item-menu"; -import { RestrictedWidgetContent } from "./restricted"; interface BoardItemContentProps { item: SectionItem; @@ -62,7 +59,6 @@ interface InnerContentProps { const InnerContent = ({ item, ...dimensions }: InnerContentProps) => { const settings = useSettings(); const board = useRequiredBoard(); - const { data: session } = useSession(); const [isEditMode] = useEditMode(); const Comp = loadWidgetDynamic(item.kind); const { definition } = widgetImports[item.kind]; @@ -74,16 +70,6 @@ const InnerContent = ({ item, ...dimensions }: InnerContentProps) => { const widgetSupportsIntegrations = "supportedIntegrations" in definition && definition.supportedIntegrations.length >= 1; - if ( - isWidgetRestricted({ - definition, - user: session?.user ?? null, - check: (level) => level === "all", - }) - ) { - return ; - } - return ( {({ reset }) => ( diff --git a/apps/nextjs/src/components/board/items/item-menu.tsx b/apps/nextjs/src/components/board/items/item-menu.tsx index 7712796798..e7072fea43 100644 --- a/apps/nextjs/src/components/board/items/item-menu.tsx +++ b/apps/nextjs/src/components/board/items/item-menu.tsx @@ -3,8 +3,6 @@ import { ActionIcon, Menu } from "@mantine/core"; import { IconCopy, IconDotsVertical, IconLayoutKanban, IconPencil, IconTrash } from "@tabler/icons-react"; import { clientApi } from "@homarr/api/client"; -import { useSession } from "@homarr/auth/client"; -import { isWidgetRestricted } from "@homarr/auth/shared"; import { useEditMode } from "@homarr/boards/edit-mode"; import { useConfirmModal, useModalAction } from "@homarr/modals"; import { useSettings } from "@homarr/settings"; @@ -39,7 +37,6 @@ export const BoardItemMenu = ({ const currentDefinition = useMemo(() => widgetImports[item.kind].definition, [item.kind]); const { gridstack } = useSectionContext().refs; const settings = useSettings(); - const { data: session } = useSession(); // Reset error boundary on next render if item has been edited useEffect(() => { @@ -94,16 +91,6 @@ export const BoardItemMenu = ({ }); }; - if ( - isWidgetRestricted({ - definition: currentDefinition, - user: session?.user ?? null, - check: (level) => level !== "none", - }) - ) { - return null; - } - return ( diff --git a/apps/nextjs/src/components/board/items/item-select-modal.tsx b/apps/nextjs/src/components/board/items/item-select-modal.tsx index c93a594974..a2fce1264f 100644 --- a/apps/nextjs/src/components/board/items/item-select-modal.tsx +++ b/apps/nextjs/src/components/board/items/item-select-modal.tsx @@ -2,8 +2,6 @@ import { useMemo, useState } from "react"; import { Button, Card, Center, Grid, Input, Stack, Text } from "@mantine/core"; import { IconSearch } from "@tabler/icons-react"; -import { useSession } from "@homarr/auth/client"; -import { isWidgetRestricted } from "@homarr/auth/shared"; import { objectEntries } from "@homarr/common"; import type { WidgetKind } from "@homarr/definitions"; import { createModal } from "@homarr/modals"; @@ -17,18 +15,10 @@ export const ItemSelectModal = createModal(({ actions }) => { const [search, setSearch] = useState(""); const t = useI18n(); const { createItem } = useItemActions(); - const { data: session } = useSession(); const items = useMemo( () => objectEntries(widgetImports) - .filter(([, value]) => { - return !isWidgetRestricted({ - definition: value.definition, - user: session?.user ?? null, - check: (level) => level !== "none", - }); - }) .map(([kind, value]) => ({ kind, icon: value.definition.icon, @@ -36,7 +26,7 @@ export const ItemSelectModal = createModal(({ actions }) => { description: t(`widget.${kind}.description`), })) .sort((itemA, itemB) => itemA.name.localeCompare(itemB.name)), - [t, session?.user], + [t], ); const filteredItems = useMemo( diff --git a/apps/nextjs/src/components/board/items/restricted.tsx b/apps/nextjs/src/components/board/items/restricted.tsx deleted file mode 100644 index 494e90015d..0000000000 --- a/apps/nextjs/src/components/board/items/restricted.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Center, Group, Stack, Text } from "@mantine/core"; -import { IconShield } from "@tabler/icons-react"; - -import type { WidgetKind } from "@homarr/definitions"; -import { useScopedI18n } from "@homarr/translation/client"; - -interface RestrictedWidgetProps { - kind: WidgetKind; -} - -export const RestrictedWidgetContent = ({ kind }: RestrictedWidgetProps) => { - const tCurrentWidget = useScopedI18n(`widget.${kind}`); - const tCommonWidget = useScopedI18n("widget.common"); - - return ( -
- - - - - {tCommonWidget("restricted.title")} - - - {tCommonWidget("restricted.description", { name: tCurrentWidget("name") })} - -
- ); -}; diff --git a/packages/api/src/router/board.ts b/packages/api/src/router/board.ts index 4d5233b176..80e58393d2 100644 --- a/packages/api/src/router/board.ts +++ b/packages/api/src/router/board.ts @@ -2,7 +2,7 @@ import { TRPCError } from "@trpc/server"; import superjson from "superjson"; import { z } from "zod"; -import { constructBoardPermissions, isWidgetRestricted } from "@homarr/auth/shared"; +import { constructBoardPermissions } from "@homarr/auth/shared"; import type { DeviceType } from "@homarr/common/server"; import type { Database, InferInsertModel, InferSelectModel, SQL } from "@homarr/db"; import { and, asc, createId, eq, handleTransactionsAsync, inArray, isNull, like, not, or, sql } from "@homarr/db"; @@ -40,7 +40,6 @@ import { oldmarrConfigSchema } from "@homarr/old-schema"; import type { BoardItemAdvancedOptions } from "@homarr/validation"; import { sectionSchema, sharedItemSchema, validation, zodUnionFromArray } from "@homarr/validation"; -import { widgetImports } from "../../../widgets/src"; import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure, publicProcedure } from "../trpc"; import { throwIfActionForbiddenAsync } from "./board/board-access"; import { generateResponsiveGridFor } from "./board/grid-algorithm"; @@ -324,13 +323,6 @@ export const boardRouter = createTRPCRouter({ } const { sections: boardSections, items: boardItems, layouts: boardLayouts, ...boardProps } = board; - const allowedBoardItems = boardItems.filter((item) => { - return !isWidgetRestricted({ - definition: widgetImports[item.kind].definition, - user: ctx.session.user, - check: (level) => level !== "none", - }); - }); const newBoardId = createId(); @@ -378,8 +370,8 @@ export const boardRouter = createTRPCRouter({ ), ); - const itemMap = new Map(allowedBoardItems.map((item) => [item.id, createId()])); - const itemsToInsert: InferInsertModel[] = allowedBoardItems.map( + const itemMap = new Map(boardItems.map((item) => [item.id, createId()])); + const itemsToInsert: InferInsertModel[] = boardItems.map( ({ integrations: _, layouts: _layouts, ...item }) => ({ ...item, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -388,7 +380,7 @@ export const boardRouter = createTRPCRouter({ }), ); - const itemLayoutsToInsert: InferInsertModel[] = allowedBoardItems.flatMap((item) => + const itemLayoutsToInsert: InferInsertModel[] = boardItems.flatMap((item) => item.layouts.map( (layoutSection): InferInsertModel => ({ ...layoutSection, @@ -421,7 +413,7 @@ export const boardRouter = createTRPCRouter({ ) .then((result) => result.map((row) => row.id)); - const itemIntegrationsToInsert = allowedBoardItems.flatMap((item) => + const itemIntegrationsToInsert = boardItems.flatMap((item) => item.integrations // Restrict integrations to only those the user has access to .filter(({ integrationId }) => integrationIdsWithAccess.includes(integrationId) || hasAccessForAll) @@ -751,141 +743,106 @@ export const boardRouter = createTRPCRouter({ const dbBoard = await getFullBoardWithWhereAsync(ctx.db, eq(boards.id, input.id), ctx.session.user.id); - const addedSections = filterAddedItems(input.sections, dbBoard.sections); - const sectionsToInsert = addedSections.map( - (section): InferInsertModel => ({ - id: section.id, - kind: section.kind, - yOffset: section.kind !== "dynamic" ? section.yOffset : null, - xOffset: section.kind === "dynamic" ? null : 0, - options: section.kind === "dynamic" ? superjson.stringify(section.options) : emptySuperJSON, - name: "name" in section ? section.name : null, - boardId: dbBoard.id, - }), - ); - - const sectionLayoutsToInsert = addedSections - .filter((section) => section.kind === "dynamic") - .flatMap((section) => - section.layouts.map( - (sectionLayout): InferInsertModel => ({ - layoutId: sectionLayout.layoutId, - sectionId: section.id, - parentSectionId: sectionLayout.parentSectionId, - height: sectionLayout.height, - width: sectionLayout.width, - xOffset: sectionLayout.xOffset, - yOffset: sectionLayout.yOffset, - }), - ), - ); - - const addedItems = filterAddedItems(input.items, dbBoard.items).filter((item) => { - return !isWidgetRestricted({ - definition: widgetImports[item.kind].definition, - user: ctx.session.user, - check: (level) => level !== "none", - }); - }); - const itemsToInsert = addedItems.map( - (item): InferInsertModel => ({ - id: item.id, - kind: item.kind, - options: superjson.stringify(item.options), - advancedOptions: superjson.stringify(item.advancedOptions), - boardId: dbBoard.id, - }), - ); - - const itemLayoutsToInsert = addedItems.flatMap((item) => - item.layouts.map( - (layoutSection): InferInsertModel => ({ - layoutId: layoutSection.layoutId, - sectionId: layoutSection.sectionId, - itemId: item.id, - height: layoutSection.height, - width: layoutSection.width, - xOffset: layoutSection.xOffset, - yOffset: layoutSection.yOffset, - }), - ), - ); - - const inputIntegrationRelations = input.items.flatMap(({ integrationIds, id: itemId }) => - integrationIds.map((integrationId) => ({ - integrationId, - itemId, - })), - ); - const dbIntegrationRelations = dbBoard.items.flatMap(({ integrationIds, id: itemId }) => - integrationIds.map((integrationId) => ({ - integrationId, - itemId, - })), - ); - const addedIntegrationRelations = inputIntegrationRelations.filter( - (inputRelation) => - !dbIntegrationRelations.some( - (dbRelation) => - dbRelation.itemId === inputRelation.itemId && dbRelation.integrationId === inputRelation.integrationId, - ), - ); - const integrationItemsToInsert = addedIntegrationRelations.map((relation) => ({ - itemId: relation.itemId, - integrationId: relation.integrationId, - })); - - const updatedItems = filterUpdatedItems(input.items, dbBoard.items).filter((item) => { - return !isWidgetRestricted({ - definition: widgetImports[item.kind].definition, - user: ctx.session.user, - check: (level) => level !== "none", - }); - }); - const updatedSections = filterUpdatedItems(input.sections, dbBoard.sections); - - const removedIntegrationRelations = dbIntegrationRelations.filter( - (dbRelation) => - !inputIntegrationRelations.some( - (inputRelation) => - dbRelation.itemId === inputRelation.itemId && dbRelation.integrationId === inputRelation.integrationId, - ), - ); - - const removedItems = filterRemovedItems(input.items, dbBoard.items).filter((item) => { - return !isWidgetRestricted({ - definition: widgetImports[item.kind].definition, - user: ctx.session.user, - check: (level) => level !== "none", - }); - }); - const itemIdsToRemove = removedItems.map((item) => item.id); - - const removedSections = filterRemovedItems(input.sections, dbBoard.sections); - const sectionIdsToRemove = removedSections.map((section) => section.id); - await handleTransactionsAsync(ctx.db, { async handleAsync(db, schema) { await db.transaction(async (transaction) => { - if (sectionsToInsert.length > 0) { - await transaction.insert(schema.sections).values(sectionsToInsert); - } + const addedSections = filterAddedItems(input.sections, dbBoard.sections); + + if (addedSections.length > 0) { + await transaction.insert(schema.sections).values( + addedSections.map((section) => ({ + id: section.id, + kind: section.kind, + yOffset: section.kind !== "dynamic" ? section.yOffset : null, + xOffset: section.kind === "dynamic" ? null : 0, + options: section.kind === "dynamic" ? superjson.stringify(section.options) : emptySuperJSON, + name: "name" in section ? section.name : null, + boardId: dbBoard.id, + })), + ); - if (sectionLayoutsToInsert.length > 0) { - await transaction.insert(schema.sectionLayouts).values(sectionLayoutsToInsert); + if (addedSections.some((section) => section.kind === "dynamic")) { + await transaction.insert(schema.sectionLayouts).values( + addedSections + .filter((section) => section.kind === "dynamic") + .flatMap((section) => + section.layouts.map( + (sectionLayout): InferInsertModel => ({ + layoutId: sectionLayout.layoutId, + sectionId: section.id, + parentSectionId: sectionLayout.parentSectionId, + height: sectionLayout.height, + width: sectionLayout.width, + xOffset: sectionLayout.xOffset, + yOffset: sectionLayout.yOffset, + }), + ), + ), + ); + } } - if (itemsToInsert.length > 0) { - await transaction.insert(schema.items).values(itemsToInsert); - } - if (itemLayoutsToInsert.length > 0) { - await transaction.insert(schema.itemLayouts).values(itemLayoutsToInsert); + const addedItems = filterAddedItems(input.items, dbBoard.items); + + if (addedItems.length > 0) { + await transaction.insert(schema.items).values( + addedItems.map((item) => ({ + id: item.id, + kind: item.kind, + options: superjson.stringify(item.options), + advancedOptions: superjson.stringify(item.advancedOptions), + boardId: dbBoard.id, + })), + ); + await transaction.insert(schema.itemLayouts).values( + addedItems.flatMap((item) => + item.layouts.map( + (layoutSection): InferInsertModel => ({ + layoutId: layoutSection.layoutId, + sectionId: layoutSection.sectionId, + itemId: item.id, + height: layoutSection.height, + width: layoutSection.width, + xOffset: layoutSection.xOffset, + yOffset: layoutSection.yOffset, + }), + ), + ), + ); } - if (integrationItemsToInsert.length > 0) { - await transaction.insert(schema.integrationItems).values(integrationItemsToInsert); + const inputIntegrationRelations = input.items.flatMap(({ integrationIds, id: itemId }) => + integrationIds.map((integrationId) => ({ + integrationId, + itemId, + })), + ); + const dbIntegrationRelations = dbBoard.items.flatMap(({ integrationIds, id: itemId }) => + integrationIds.map((integrationId) => ({ + integrationId, + itemId, + })), + ); + const addedIntegrationRelations = inputIntegrationRelations.filter( + (inputRelation) => + !dbIntegrationRelations.some( + (dbRelation) => + dbRelation.itemId === inputRelation.itemId && + dbRelation.integrationId === inputRelation.integrationId, + ), + ); + + if (addedIntegrationRelations.length > 0) { + await transaction.insert(schema.integrationItems).values( + addedIntegrationRelations.map((relation) => ({ + itemId: relation.itemId, + integrationId: relation.integrationId, + })), + ); } + const updatedItems = filterUpdatedItems(input.items, dbBoard.items); + for (const item of updatedItems) { await transaction .update(schema.items) @@ -915,6 +872,8 @@ export const boardRouter = createTRPCRouter({ } } + const updatedSections = filterUpdatedItems(input.sections, dbBoard.sections); + for (const section of updatedSections) { const prev = dbBoard.sections.find((dbSection) => dbSection.id === section.id); await transaction @@ -948,6 +907,15 @@ export const boardRouter = createTRPCRouter({ } } + const removedIntegrationRelations = dbIntegrationRelations.filter( + (dbRelation) => + !inputIntegrationRelations.some( + (inputRelation) => + dbRelation.itemId === inputRelation.itemId && + dbRelation.integrationId === inputRelation.integrationId, + ), + ); + for (const relation of removedIntegrationRelations) { await transaction .delete(schema.integrationItems) @@ -959,37 +927,135 @@ export const boardRouter = createTRPCRouter({ ); } - if (itemIdsToRemove.length > 0) { - await transaction.delete(schema.items).where(inArray(schema.items.id, itemIdsToRemove)); + const removedItems = filterRemovedItems(input.items, dbBoard.items); + + const itemIds = removedItems.map((item) => item.id); + if (itemIds.length > 0) { + await transaction.delete(schema.items).where(inArray(schema.items.id, itemIds)); } - if (sectionIdsToRemove.length > 0) { - await transaction.delete(schema.sections).where(inArray(schema.sections.id, sectionIdsToRemove)); + const removedSections = filterRemovedItems(input.sections, dbBoard.sections); + const sectionIds = removedSections.map((section) => section.id); + + if (sectionIds.length > 0) { + await transaction.delete(schema.sections).where(inArray(schema.sections.id, sectionIds)); } }); }, handleSync(db) { db.transaction((transaction) => { - if (sectionsToInsert.length > 0) { - transaction.insert(sections).values(sectionsToInsert).run(); - } + const addedSections = filterAddedItems(input.sections, dbBoard.sections); - if (sectionLayoutsToInsert.length > 0) { - transaction.insert(sectionLayouts).values(sectionLayoutsToInsert).run(); - } + if (addedSections.length > 0) { + transaction + .insert(sections) + .values( + addedSections.map((section) => ({ + id: section.id, + kind: section.kind, + yOffset: section.kind !== "dynamic" ? section.yOffset : null, + xOffset: section.kind === "dynamic" ? null : 0, + options: section.kind === "dynamic" ? superjson.stringify(section.options) : emptySuperJSON, + name: "name" in section ? section.name : null, + boardId: dbBoard.id, + })), + ) + .run(); - if (itemsToInsert.length > 0) { - transaction.insert(items).values(itemsToInsert).run(); + if (addedSections.some((section) => section.kind === "dynamic")) { + transaction + .insert(sectionLayouts) + .values( + addedSections + .filter((section) => section.kind === "dynamic") + .flatMap((section) => + section.layouts.map( + (sectionLayout): InferInsertModel => ({ + layoutId: sectionLayout.layoutId, + sectionId: section.id, + parentSectionId: sectionLayout.parentSectionId, + height: sectionLayout.height, + width: sectionLayout.width, + xOffset: sectionLayout.xOffset, + yOffset: sectionLayout.yOffset, + }), + ), + ), + ) + .run(); + } } - if (itemLayoutsToInsert.length > 0) { - transaction.insert(itemLayouts).values(itemLayoutsToInsert).run(); + const addedItems = filterAddedItems(input.items, dbBoard.items); + + if (addedItems.length > 0) { + transaction + .insert(items) + .values( + addedItems.map((item) => ({ + id: item.id, + kind: item.kind, + options: superjson.stringify(item.options), + advancedOptions: superjson.stringify(item.advancedOptions), + boardId: dbBoard.id, + })), + ) + .run(); + transaction + .insert(itemLayouts) + .values( + addedItems.flatMap((item) => + item.layouts.map( + (layoutSection): InferInsertModel => ({ + layoutId: layoutSection.layoutId, + sectionId: layoutSection.sectionId, + itemId: item.id, + height: layoutSection.height, + width: layoutSection.width, + xOffset: layoutSection.xOffset, + yOffset: layoutSection.yOffset, + }), + ), + ), + ) + .run(); } - if (integrationItemsToInsert.length > 0) { - transaction.insert(integrationItems).values(integrationItemsToInsert).run(); + const inputIntegrationRelations = input.items.flatMap(({ integrationIds, id: itemId }) => + integrationIds.map((integrationId) => ({ + integrationId, + itemId, + })), + ); + const dbIntegrationRelations = dbBoard.items.flatMap(({ integrationIds, id: itemId }) => + integrationIds.map((integrationId) => ({ + integrationId, + itemId, + })), + ); + const addedIntegrationRelations = inputIntegrationRelations.filter( + (inputRelation) => + !dbIntegrationRelations.some( + (dbRelation) => + dbRelation.itemId === inputRelation.itemId && + dbRelation.integrationId === inputRelation.integrationId, + ), + ); + + if (addedIntegrationRelations.length > 0) { + transaction + .insert(integrationItems) + .values( + addedIntegrationRelations.map((relation) => ({ + itemId: relation.itemId, + integrationId: relation.integrationId, + })), + ) + .run(); } + const updatedItems = filterUpdatedItems(input.items, dbBoard.items); + for (const item of updatedItems) { transaction .update(items) @@ -1016,6 +1082,8 @@ export const boardRouter = createTRPCRouter({ } } + const updatedSections = filterUpdatedItems(input.sections, dbBoard.sections); + for (const section of updatedSections) { const prev = dbBoard.sections.find((dbSection) => dbSection.id === section.id); transaction @@ -1048,6 +1116,15 @@ export const boardRouter = createTRPCRouter({ } } + const removedIntegrationRelations = dbIntegrationRelations.filter( + (dbRelation) => + !inputIntegrationRelations.some( + (inputRelation) => + dbRelation.itemId === inputRelation.itemId && + dbRelation.integrationId === inputRelation.integrationId, + ), + ); + for (const relation of removedIntegrationRelations) { transaction .delete(integrationItems) @@ -1060,12 +1137,18 @@ export const boardRouter = createTRPCRouter({ .run(); } - if (itemIdsToRemove.length > 0) { - transaction.delete(items).where(inArray(items.id, itemIdsToRemove)).run(); + const removedItems = filterRemovedItems(input.items, dbBoard.items); + + const itemIds = removedItems.map((item) => item.id); + if (itemIds.length > 0) { + transaction.delete(items).where(inArray(items.id, itemIds)).run(); } - if (sectionIdsToRemove.length > 0) { - transaction.delete(sections).where(inArray(sections.id, sectionIdsToRemove)).run(); + const removedSections = filterRemovedItems(input.sections, dbBoard.sections); + const sectionIds = removedSections.map((section) => section.id); + + if (sectionIds.length > 0) { + transaction.delete(sections).where(inArray(sections.id, sectionIds)).run(); } }); }, @@ -1235,7 +1318,7 @@ export const boardRouter = createTRPCRouter({ .mutation(async ({ input, ctx }) => { const content = await input.file.text(); const oldmarr = oldmarrConfigSchema.parse(JSON.parse(content)); - await importOldmarrAsync(ctx.db, oldmarr, input.configuration, ctx.session); + await importOldmarrAsync(ctx.db, oldmarr, input.configuration); }), }); diff --git a/packages/api/src/router/import/import-router.ts b/packages/api/src/router/import/import-router.ts index f46cd40095..4ffc5ca1ab 100644 --- a/packages/api/src/router/import/import-router.ts +++ b/packages/api/src/router/import/import-router.ts @@ -37,7 +37,7 @@ export const importRouter = createTRPCRouter({ .requiresStep("import") .input(importInitialOldmarrInputSchema) .mutation(async ({ ctx, input }) => { - await importInitialOldmarrAsync(ctx.db, input, ctx.session); + await importInitialOldmarrAsync(ctx.db, input); await nextOnboardingStepAsync(ctx.db, undefined); }), }); diff --git a/packages/auth/permissions/index.ts b/packages/auth/permissions/index.ts index 83b13629a6..dd5b9e462c 100644 --- a/packages/auth/permissions/index.ts +++ b/packages/auth/permissions/index.ts @@ -1,3 +1,2 @@ export * from "./board-permissions"; export * from "./integration-permissions"; -export * from "./widget-restriction"; diff --git a/packages/auth/permissions/widget-restriction.ts b/packages/auth/permissions/widget-restriction.ts deleted file mode 100644 index 1959ffd0ed..0000000000 --- a/packages/auth/permissions/widget-restriction.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Session } from "next-auth"; - -import type { WidgetDefinition } from "../../widgets/src"; -import type { RestrictionLevel } from "../../widgets/src/definition"; - -export const isWidgetRestricted = (props: { - definition: TDefinition; - user: Session["user"] | null; - check: (level: RestrictionLevel) => boolean; -}) => { - if (!("restrict" in props.definition)) return false; - if (props.definition.restrict === undefined) return false; - return props.check(props.definition.restrict({ user: props.user ?? null })); -}; diff --git a/packages/old-import/package.json b/packages/old-import/package.json index f4995d385d..e86656bbe8 100644 --- a/packages/old-import/package.json +++ b/packages/old-import/package.json @@ -26,7 +26,6 @@ }, "prettier": "@homarr/prettier-config", "dependencies": { - "@homarr/auth": "workspace:^0.1.0", "@homarr/common": "workspace:^0.1.0", "@homarr/db": "workspace:^0.1.0", "@homarr/definitions": "workspace:^0.1.0", diff --git a/packages/old-import/src/import/collections/board-collection.ts b/packages/old-import/src/import/collections/board-collection.ts index 2fd2a51423..961dd8219f 100644 --- a/packages/old-import/src/import/collections/board-collection.ts +++ b/packages/old-import/src/import/collections/board-collection.ts @@ -1,12 +1,9 @@ -import type { Session } from "@homarr/auth"; -import { isWidgetRestricted } from "@homarr/auth/shared"; import { createId } from "@homarr/db"; import { createDbInsertCollectionForTransaction } from "@homarr/db/collection"; import { logger } from "@homarr/log"; import type { BoardSize, OldmarrConfig } from "@homarr/old-schema"; import { boardSizes, getBoardSizeName } from "@homarr/old-schema"; -import { widgetImports } from "../../../../widgets/src"; import { fixSectionIssues } from "../../fix-section-issues"; import { OldHomarrImportError } from "../../import-error"; import { mapBoard } from "../../mappers/map-board"; @@ -21,7 +18,6 @@ import type { InitialOldmarrImportSettings } from "../../settings"; export const createBoardInsertCollection = ( { preparedApps, preparedBoards }: Omit, "preparedIntegrations">, settings: InitialOldmarrImportSettings, - session: Session | null, ) => { const insertCollection = createDbInsertCollectionForTransaction([ "apps", @@ -117,18 +113,10 @@ export const createBoardInsertCollection = ( layoutMapping, mappedBoard.id, ); - preparedItems - .filter((item) => { - return !isWidgetRestricted({ - definition: widgetImports[item.kind].definition, - user: session?.user ?? null, - check: (level) => level !== "none", - }); - }) - .forEach(({ layouts, ...item }) => { - insertCollection.items.push(item); - insertCollection.itemLayouts.push(...layouts); - }); + preparedItems.forEach(({ layouts, ...item }) => { + insertCollection.items.push(item); + insertCollection.itemLayouts.push(...layouts); + }); logger.debug(`Added items to board insert collection count=${insertCollection.items.length}`); }); diff --git a/packages/old-import/src/import/import-initial-oldmarr.ts b/packages/old-import/src/import/import-initial-oldmarr.ts index de35a993ba..fdf1a79da0 100644 --- a/packages/old-import/src/import/import-initial-oldmarr.ts +++ b/packages/old-import/src/import/import-initial-oldmarr.ts @@ -1,6 +1,5 @@ import type { z } from "zod"; -import type { Session } from "@homarr/auth"; import { Stopwatch } from "@homarr/common"; import { handleTransactionsAsync } from "@homarr/db"; import type { Database } from "@homarr/db"; @@ -17,7 +16,6 @@ import { ensureValidTokenOrThrow } from "./validate-token"; export const importInitialOldmarrAsync = async ( db: Database, input: z.infer, - session: Session | null, ) => { const stopwatch = new Stopwatch(); const { checksum, configs, users: importUsers } = await analyseOldmarrImportAsync(input.file); @@ -31,7 +29,7 @@ export const importInitialOldmarrAsync = async ( logger.info("Preparing import data in insert collections for database"); - const boardInsertCollection = createBoardInsertCollection({ preparedApps, preparedBoards }, input.settings, session); + const boardInsertCollection = createBoardInsertCollection({ preparedApps, preparedBoards }, input.settings); const userInsertCollection = createUserInsertCollection(importUsers, input.token); const integrationInsertCollection = createIntegrationInsertCollection(preparedIntegrations, input.token); diff --git a/packages/old-import/src/import/import-single-oldmarr.ts b/packages/old-import/src/import/import-single-oldmarr.ts index 2ca42870f4..2ca6ed4c11 100644 --- a/packages/old-import/src/import/import-single-oldmarr.ts +++ b/packages/old-import/src/import/import-single-oldmarr.ts @@ -1,4 +1,3 @@ -import type { Session } from "@homarr/auth"; import { handleTransactionsAsync, inArray } from "@homarr/db"; import type { Database } from "@homarr/db"; import { apps } from "@homarr/db/schema"; @@ -13,7 +12,6 @@ export const importSingleOldmarrConfigAsync = async ( db: Database, config: OldmarrConfig, settings: OldmarrImportConfiguration, - session: Session | null, ) => { const { preparedApps, preparedBoards } = prepareSingleImport(config, settings); const existingApps = await db.query.apps.findMany({ @@ -31,7 +29,7 @@ export const importSingleOldmarrConfigAsync = async ( return app; }); - const boardInsertCollection = createBoardInsertCollection({ preparedApps, preparedBoards }, settings, session); + const boardInsertCollection = createBoardInsertCollection({ preparedApps, preparedBoards }, settings); await handleTransactionsAsync(db, { async handleAsync(db) { diff --git a/packages/old-import/src/index.ts b/packages/old-import/src/index.ts index c36d9e70b2..d3153a1897 100644 --- a/packages/old-import/src/index.ts +++ b/packages/old-import/src/index.ts @@ -1,4 +1,3 @@ -import type { Session } from "@homarr/auth"; import type { Database } from "@homarr/db"; import type { OldmarrConfig } from "@homarr/old-schema"; @@ -9,7 +8,6 @@ export const importOldmarrAsync = async ( db: Database, old: OldmarrConfig, configuration: OldmarrImportConfiguration, - session: Session | null, ) => { - await importSingleOldmarrConfigAsync(db, old, configuration, session); + await importSingleOldmarrConfigAsync(db, old, configuration); }; diff --git a/packages/translation/src/lang/en.json b/packages/translation/src/lang/en.json index b7bb3a9f90..966700f5e4 100644 --- a/packages/translation/src/lang/en.json +++ b/packages/translation/src/lang/en.json @@ -1724,11 +1724,7 @@ "noIntegration": "No integration selected", "noData": "No integration data available" }, - "option": {}, - "restricted": { - "title": "Restricted", - "description": "You don't have access to the {name} widget." - } + "option": {} }, "video": { "name": "Video Stream", diff --git a/packages/widgets/src/definition.ts b/packages/widgets/src/definition.ts index 453ca8c590..85e2de5ad9 100644 --- a/packages/widgets/src/definition.ts +++ b/packages/widgets/src/definition.ts @@ -1,7 +1,6 @@ import type { LoaderComponent } from "next/dynamic"; import type { DefaultErrorData } from "@trpc/server/unstable-core-do-not-import"; -import type { Session } from "@homarr/auth"; import type { IntegrationKind, WidgetKind } from "@homarr/definitions"; import type { ServerSettings } from "@homarr/server-settings"; import type { SettingsContextProps } from "@homarr/settings"; @@ -44,23 +43,8 @@ export interface WidgetDefinition { } > >; - /** - * Callback that returns wheter or not the widget should be available to the user. - * The widget will not be available in the widget picker and saving with a new one of this kind will not be possible. - * - * @param props contain user information - * @returns restriction type - */ - restrict?: (props: { user: Session["user"] | null }) => RestrictionLevel; } -/** - * none: The widget is fully available to the user. - * select: The widget is available to the user but not in the widget picker. - * all: The widget is not available to the user. As replacement a message will be shown at the widgets position. - */ -export type RestrictionLevel = "none" | "select" | "all"; - export interface WidgetProps { options: inferOptionsFromCreator>; integrationIds: string[]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7bca48cf5e..0bc14e6f21 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1512,9 +1512,6 @@ importers: packages/old-import: dependencies: - '@homarr/auth': - specifier: workspace:^0.1.0 - version: link:../auth '@homarr/common': specifier: workspace:^0.1.0 version: link:../common