def get_permitted_environments_for_user(
    user: "FFAdminUser",
    project: Project,
    permission_key: str,
    tag_ids: List[int] = None,  # type: ignore[assignment]
    prefetch_metadata: bool = False,
) -> QuerySet[Environment]:
    """
    Get all environments that the user has the given permissions for.

    Rules:
        - User has the required permissions directly (UserEnvironmentPermission)
        - User is in a UserPermissionGroup that has required permissions (UserPermissionGroupEnvironmentPermissions)
        - User is an admin for the project the environment belongs to
        - User is an admin for the organisation the environment belongs to
        - User has a role attached with the required permissions(if rbac is enabled)
        - User is in a UserPermissionGroup that has a role attached with the required permissions(if rbac is enabled)
    NOTE:
        - If `tag_ids` is None, tags filter will not be applied
        - If `tag_ids` is an empty list, only environments with no tags will be returned
        - If `tag_ids` is a list of tag IDs, only environments with one of those tags will
        be returned
    """

    if is_user_project_admin(user, project):
        queryset = project.environments.all()
        if prefetch_metadata:
            return queryset.prefetch_related("metadata")
        return queryset

    environment_ids_from_base_filter = get_object_id_from_base_permission_filter(
        user,
        Environment,  # type: ignore[arg-type]
        permission_key,
        tag_ids=tag_ids,
    )
    queryset = Environment.objects.filter(
        id__in=environment_ids_from_base_filter, project=project
    )

    if prefetch_metadata:
        queryset = queryset.prefetch_related("metadata")

    # Description is defered due to Oracle support where a
    # query can't have a where clause if description is in
    # the select parameters. This leads to an N+1 query for
    # lists of environments when description is included, as
    # each environment object re-queries the DB seperately.
    return queryset.defer("description")

    Get all environments that the user has the given permissions for.

    Rules:
        - User has the required permissions directly (UserEnvironmentPermission)
        - User is in a UserPermissionGroup that has required permissions (UserPermissionGroupEnvironmentPermissions)
        - User is an admin for the project the environment belongs to
        - User is an admin for the organisation the environment belongs to
        - User has a role attached with the required permissions(if rbac is enabled)
        - User is in a UserPermissionGroup that has a role attached with the required permissions(if rbac is enabled)
    NOTE:
        - If `tag_ids` is None, tags filter will not be applied
        - If `tag_ids` is an empty list, only environments with no tags will be returned
        - If `tag_ids` is a list of tag IDs, only environments with one of those tags will
        be returned
    
api/permissions/permission_service.py