mirror of
https://github.com/ajnart/homarr.git
synced 2026-01-29 18:59:20 +01:00
125 lines
4.2 KiB
TypeScript
125 lines
4.2 KiB
TypeScript
import type { Session } from "next-auth";
|
|
|
|
import type { Database } from "@homarr/db";
|
|
import { and, eq, inArray, or } from "@homarr/db";
|
|
import { boards, boardUserPermissions, groupMembers } from "@homarr/db/schema";
|
|
import type { IntegrationPermission } from "@homarr/definitions";
|
|
|
|
import { constructIntegrationPermissions } from "./integration-permissions";
|
|
|
|
interface Integration {
|
|
id: string;
|
|
items: {
|
|
item: {
|
|
section: {
|
|
boardId: string;
|
|
};
|
|
};
|
|
}[];
|
|
userPermissions: {
|
|
permission: IntegrationPermission;
|
|
}[];
|
|
groupPermissions: {
|
|
permission: IntegrationPermission;
|
|
}[];
|
|
}
|
|
|
|
export const hasQueryAccessToIntegrationsAsync = async (
|
|
db: Database,
|
|
integrations: Integration[],
|
|
session: Session | null,
|
|
) => {
|
|
// If the user has board-view-all and every integration has at least one item that is placed on a board he has access.
|
|
if (
|
|
session?.user.permissions.includes("board-view-all") &&
|
|
integrations.every((integration) => integration.items.length >= 1)
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
const integrationsWithUseAccess = integrations.filter(
|
|
(integration) => constructIntegrationPermissions(integration, session).hasUseAccess,
|
|
);
|
|
|
|
// If the user has use access to all integrations, he has access.
|
|
if (integrationsWithUseAccess.length === integrations.length) {
|
|
return true;
|
|
}
|
|
|
|
const integrationsWithoutUseAccessAndWithoutBoardViewAllAccess = integrations
|
|
.filter((integration) => !integrationsWithUseAccess.includes(integration))
|
|
.filter((integration) => !(session?.user.permissions.includes("board-view-all") && integration.items.length >= 1));
|
|
|
|
if (integrationsWithoutUseAccessAndWithoutBoardViewAllAccess.length === 0) {
|
|
return true;
|
|
}
|
|
|
|
const integrationsWithBoardIds = integrationsWithoutUseAccessAndWithoutBoardViewAllAccess.map((integration) => ({
|
|
id: integration.id,
|
|
anyOfBoardIds: integration.items.map(({ item }) => item.section.boardId),
|
|
}));
|
|
|
|
const permissionsOfCurrentUserWhenPresent = await db.query.boardUserPermissions.findMany({
|
|
where: eq(boardUserPermissions.userId, session?.user.id ?? ""),
|
|
});
|
|
|
|
// If for each integration the user has access to at least of of it's present boards, he has access.
|
|
if (
|
|
checkEveryIntegrationContainsSomeBoardIdIncludedInBoardsWithAccess(
|
|
integrationsWithBoardIds,
|
|
permissionsOfCurrentUserWhenPresent.map(({ boardId }) => boardId),
|
|
)
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
const permissionsOfCurrentUserGroupsWhenPresent = await db.query.groupMembers.findMany({
|
|
where: eq(groupMembers.userId, session?.user.id ?? ""),
|
|
with: {
|
|
group: {
|
|
with: {
|
|
boardPermissions: {},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
const boardIdsWithPermission = permissionsOfCurrentUserWhenPresent
|
|
.map((permission) => permission.boardId)
|
|
.concat(
|
|
permissionsOfCurrentUserGroupsWhenPresent
|
|
.map((groupMember) => groupMember.group.boardPermissions.map((permission) => permission.boardId))
|
|
.flat(),
|
|
);
|
|
|
|
// If for each integration the user has access to at least of of it's present boards, he has access.
|
|
if (
|
|
checkEveryIntegrationContainsSomeBoardIdIncludedInBoardsWithAccess(integrationsWithBoardIds, boardIdsWithPermission)
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
const relevantBoardIds = [...new Set(integrationsWithBoardIds.map(({ anyOfBoardIds }) => anyOfBoardIds).flat())];
|
|
const publicBoardsOrBoardsWhereCurrentUserIsOwner = await db.query.boards.findMany({
|
|
where: and(
|
|
or(eq(boards.isPublic, true), eq(boards.creatorId, session?.user.id ?? "")),
|
|
inArray(boards.id, relevantBoardIds),
|
|
),
|
|
});
|
|
|
|
const boardsWithAccess = boardIdsWithPermission.concat(
|
|
publicBoardsOrBoardsWhereCurrentUserIsOwner.map(({ id }) => id),
|
|
);
|
|
|
|
// If for each integration the user has access to at least of of it's present boards, he has access.
|
|
return checkEveryIntegrationContainsSomeBoardIdIncludedInBoardsWithAccess(integrationsWithBoardIds, boardsWithAccess);
|
|
};
|
|
|
|
const checkEveryIntegrationContainsSomeBoardIdIncludedInBoardsWithAccess = (
|
|
integration: { id: string; anyOfBoardIds: string[] }[],
|
|
boardIdsWithAccess: string[],
|
|
) => {
|
|
return integration.every(({ anyOfBoardIds }) =>
|
|
anyOfBoardIds.some((boardId) => boardIdsWithAccess.includes(boardId)),
|
|
);
|
|
};
|