diff --git a/packages/features/flags/features.repository.ts b/packages/features/flags/features.repository.ts index 8fc6b96126..1e6bd0626a 100644 --- a/packages/features/flags/features.repository.ts +++ b/packages/features/flags/features.repository.ts @@ -6,7 +6,18 @@ import type { AppFlags } from "./config"; import type { IFeaturesRepository } from "./features.repository.interface"; import { getFeatureFlag } from "./server/utils"; +/** + * Repository class for managing feature flags and feature access control. + * Implements the IFeaturesRepository interface to provide feature flag functionality + * for users, teams, and global application features. + */ export class FeaturesRepository implements IFeaturesRepository { + /** + * Checks if a feature is enabled globally in the application. + * @param slug - The feature flag identifier to check + * @returns Promise - True if the feature is enabled globally, false otherwise + * @throws Error if the feature flag check fails + */ async checkIfFeatureIsEnabledGlobally(slug: keyof AppFlags) { try { return await getFeatureFlag(db, slug); @@ -15,6 +26,15 @@ export class FeaturesRepository implements IFeaturesRepository { throw err; } } + + /** + * Checks if a specific user has access to a feature. + * Checks both direct user feature assignments and team-based feature access. + * @param userId - The ID of the user to check + * @param slug - The feature identifier to check + * @returns Promise - True if the user has access to the feature, false otherwise + * @throws Error if the feature access check fails + */ async checkIfUserHasFeature(userId: number, slug: string) { try { /** @@ -39,6 +59,15 @@ export class FeaturesRepository implements IFeaturesRepository { throw err; } } + + /** + * Private helper method to check if a user belongs to any team that has access to a feature. + * @param userId - The ID of the user to check + * @param slug - The feature identifier to check + * @returns Promise - True if the user belongs to a team with the feature, false otherwise + * @throws Error if the team feature check fails + * @private + */ private async checkIfUserBelongsToTeamWithFeature(userId: number, slug: string) { try { const user = await db.user.findUnique({ @@ -65,10 +94,34 @@ export class FeaturesRepository implements IFeaturesRepository { throw err; } } + + /** + * Checks if a team has access to a specific feature. + * Also checks if the team's parent organization has the feature. + * @param teamId - The ID of the team to check + * @param featureId - The feature identifier to check + * @returns Promise - True if the team has access to the feature, false otherwise + * @throws Error if the team feature check fails + */ async checkIfTeamHasFeature(teamId: number, featureId: keyof AppFlags) { try { - const teamFeature = await db.teamFeatures.findUnique({ - where: { teamId_featureId: { teamId, featureId } }, + const teamFeature = await db.teamFeatures.findFirst({ + where: { + OR: [ + { teamId, featureId }, + { + team: { + parent: { + features: { + some: { + featureId, + }, + }, + }, + }, + }, + ], + }, }); return !!teamFeature; } catch (err) {