Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api,cli,api-client,schema): Enhance permissions to allow filtering by environments through project roles #599

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

muntaxir4
Copy link
Contributor

@muntaxir4 muntaxir4 commented Dec 28, 2024

User description

Description

Allows roles to contain access to only specified environments for projects

Fixes #260

Future Improvements

Mention any improvements to be done in future related to any file/feature

Developer's checklist

  • My PR follows the style guidelines of this project
  • I have performed a self-check on my work

If changes are made in the code:

  • I have followed the coding guidelines
  • My changes in code generate no new warnings
  • My changes are breaking another fix/feature of the project
  • I have added test cases to show that my feature works
  • I have added relevant screenshots in my PR
  • There are no UI/UX issues

Documentation Update

  • This PR requires an update to the documentation at docs.keyshade.xyz
  • I have made the necessary updates to the documentation, or no documentation changes are required.

PR Type

Enhancement


Description

Enhanced workspace role permissions to support environment-specific access control:

  • Added new environment-specific permission system allowing roles to be restricted to specific environments within projects
  • Implemented getCollectiveEnvironmentAuthorities function to handle environment-level authority checks
  • Updated workspace role creation/update to support environment-specific access through new projectEnvironments structure
  • Modified database schema to support environment-to-role associations
  • Added comprehensive test coverage for new environment-specific role features
  • Updated API documentation to reflect new environment access control capabilities

Changes walkthrough 📝

Relevant files
Enhancement
authority-checker.service.ts
Update environment authority checking mechanism                   

apps/api/src/common/authority-checker.service.ts

  • Updated environment authority checking to use new
    getCollectiveEnvironmentAuthorities function
  • +3/-2     
    collective-authorities.ts
    Add environment-specific authority collection                       

    apps/api/src/common/collective-authorities.ts

  • Added new getCollectiveEnvironmentAuthorities function to handle
    environment-specific permissions
  • Function accumulates authorities across user roles with environment
    filtering
  • +73/-0   
    create-workspace-role.ts
    Update workspace role DTO for environment access                 

    apps/api/src/workspace-role/dto/create-workspace-role/create-workspace-role.ts

  • Replaced projectSlugs with new projectEnvironments structure
  • Added ProjectEnvironments class to handle environment-specific access
  • +19/-2   
    workspace-role.service.ts
    Implement environment-specific role management                     

    apps/api/src/workspace-role/service/workspace-role.service.ts

  • Updated create and update methods to handle environment-specific
    access
  • Modified project role associations to include environment connections
  • Enhanced transaction handling for role creation
  • +89/-29 
    schema.prisma
    Update schema for environment role associations                   

    apps/api/src/prisma/schema.prisma

  • Added environment relationship to ProjectWorkspaceRoleAssociation
    model
  • +4/-0     

    💡 PR-Agent usage: Comment /help "your question" on any pull request to receive relevant information

    Copy link
    Contributor

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    🎫 Ticket compliance analysis 🔶

    260 - Partially compliant

    Compliant requirements:

    • Update ProjectWorkspaceRoleAssociation entity to include environments
    • Create reverse relation from Environment to ProjectWorkspaceRoleAssociation
    • Add getCollectiveEnvironmentAuthorities util function
    • Update AuthorityCheckerService#checkAuthorityOverEnvironment
    • Update WorkspaceRoleService functions accordingly
    • Update required tests in workspace-role module

    Non-compliant requirements:

    • Update projectIds to be Map<String, Array> for project-environment mapping (implemented as array of objects instead)
    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Performance

    The getCollectiveEnvironmentAuthorities function makes multiple database queries that could be optimized by combining them into a single query with proper joins

    export const getCollectiveEnvironmentAuthorities = async (
      userId: User['id'],
      environemnt: EnvironmentWithProject,
      prisma: PrismaClient
    ): Promise<Set<Authority>> => {
      const authorities = new Set<Authority>()
    
      const projectRoleAssociations =
        await prisma.workspaceMemberRoleAssociation.findMany({
          where: {
            workspaceMember: {
              userId,
              workspaceId: environemnt.project.workspaceId
            }
          },
          select: {
            role: {
              select: {
                authorities: true
              }
            }
          }
        })
    
      if (projectRoleAssociations.length === 0) {
        return authorities
      }
    
      const environmentRoleAssociations =
        await prisma.projectWorkspaceRoleAssociation.findMany({
          where: {
            projectId: environemnt.project.id,
            environments: {
              some: {
                id: environemnt.id
              }
            }
          },
          select: {
            role: {
              select: {
                authorities: true
              }
            }
          }
        })
    
      projectRoleAssociations.forEach((roleAssociation) => {
        roleAssociation.role.authorities.forEach((authority) => {
          authorities.add(authority)
        })
      })
    
      environmentRoleAssociations.forEach((roleAssociation) => {
        roleAssociation.role.authorities.forEach((authority) => {
          authorities.add(authority)
        })
      })
    
      return authorities
    }
    Error Handling

    The update function lacks validation for environment slugs existence before attempting to connect them, which could lead to runtime errors

    if (dto.projectEnvironments) {
      await this.prisma.projectWorkspaceRoleAssociation.deleteMany({
        where: {
          roleId: workspaceRoleId
        }
      })
    
      const projectSlugToIdMap = await this.getProjectSlugToIdMap(
        dto.projectEnvironments.map((pe) => pe.projectSlug)
      )
    
      for (const pe of dto.projectEnvironments) {
        const projectId = projectSlugToIdMap.get(pe.projectSlug)
        if (projectId) {
          // Create or Update the project workspace role association with the environments accessible on the project
          await this.prisma.projectWorkspaceRoleAssociation.upsert({
            where: {
              roleId_projectId: {
                roleId: workspaceRoleId,
                projectId: projectId
              }
            },
            update: {
              environments: {
                set: [],
                connect: pe.environmentSlugs.map((slug) => ({ slug }))
              }
            },
            create: {
              roleId: workspaceRoleId,
              projectId: projectId,
              environments: {
                connect: pe.environmentSlugs.map((slug) => ({ slug }))
              }
            }
          })
        }
      }
    }

    Copy link
    Contributor

    codiumai-pr-agent-free bot commented Dec 28, 2024

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Score
    Possible issue
    Add validation to ensure referenced environment slugs exist before creating associations

    Add error handling to validate that all environment slugs provided in
    projectEnvironments exist for their respective projects before creating/updating
    role associations.

    apps/api/src/workspace-role/service/workspace-role.service.ts [268-270]

     environments: {
    -  connect: pe.environmentSlugs.map((slug) => ({ slug }))
    +  connect: await this.validateEnvironmentSlugs(projectId, pe.environmentSlugs)
     }
    • Apply this suggestion
    Suggestion importance[1-10]: 9

    Why: Missing validation could lead to runtime errors if non-existent environment slugs are provided. Adding validation is critical for data integrity.

    9
    Add error handling and rollback for database transactions to maintain data integrity

    Add transaction rollback handling in case of errors during role creation to maintain
    data consistency.

    apps/api/src/workspace-role/service/workspace-role.service.ts [161]

    -const workspaceRole = (await this.prisma.$transaction(op)).pop()
    +try {
    +  const workspaceRole = (await this.prisma.$transaction(op)).pop()
    +} catch (error) {
    +  this.logger.error('Failed to create workspace role:', error);
    +  throw new InternalServerErrorException('Failed to create workspace role');
    +}
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    Why: Adding proper error handling with transaction rollback ensures database consistency in case of failures during role creation.

    7
    General
    ✅ Fix parameter name typo to maintain code quality and prevent potential bugs

    Fix the typo in the parameter name 'environemnt' to 'environment' in the function
    signature and docstring to maintain code consistency and prevent potential issues.

    apps/api/src/common/collective-authorities.ts [108-112]

     export const getCollectiveEnvironmentAuthorities = async (
       userId: User['id'],
    -  environemnt: EnvironmentWithProject,
    +  environment: EnvironmentWithProject, 
       prisma: PrismaClient
     ): Promise<Set<Authority>> => {

    [Suggestion has been applied]

    Suggestion importance[1-10]: 8

    Why: The typo in parameter name 'environemnt' could cause confusion and potential bugs. Fixing it improves code quality and maintainability.

    8

    @muntaxir4 muntaxir4 changed the title feat(api): Enhance permissions to allow filtering by environments through project roles feat(api,cli,api-client,schema): Enhance permissions to allow filtering by environments through project roles Dec 28, 2024
    Copy link
    Member

    @rajdip-b rajdip-b left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    As per the last push made by me, i could see a ton of e2e tests fail on the API. You would need to update the environment access across the tests i believe

    const projectSlugToIdMap = await this.getProjectSlugToIdMap(
    dto.projectEnvironments
    .map((pe) => pe.projectSlug)
    .filter((slug) => slug)
    Copy link
    Member

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    I'm not entirely sure what the filter construct does

    Copy link
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    The cli implementation was causing undefined slug values.

    roleId: workspaceRoleId,
    projectId: projectId,
    environments: {
    connect: pe.environmentSlugs.map((slug) => ({ slug }))
    Copy link
    Member

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    For every environment slug belonging to a project, we need to make sure that the environment does indeed belong to a project.

    }
    },
    update: {
    environments: {
    Copy link
    Member

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Can you explain what this update does?

    Copy link
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Sets the previously connected environments to empty then adds the new ones.

    @muntaxir4
    Copy link
    Contributor Author

    As per the last push made by me, i could see a ton of e2e tests fail on the API. You would need to update the environment access across the tests i believe

    Could be. I try it later today

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    API: Enhance permissions to allow filtering by environments
    2 participants