diff --git a/Core/Core/Api/GraphQL/Client.GraphqlCleintOperations/Client.BranchOperations.cs b/Core/Core/Api/GraphQL/Client.GraphqlCleintOperations/Client.BranchOperations.cs index 386cccdfcd..2542ee0c8a 100644 --- a/Core/Core/Api/GraphQL/Client.GraphqlCleintOperations/Client.BranchOperations.cs +++ b/Core/Core/Api/GraphQL/Client.GraphqlCleintOperations/Client.BranchOperations.cs @@ -72,6 +72,71 @@ public async Task> StreamGetBranches( var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); return res.stream.branches.items; } +/// + /// Get branches from a given stream + /// + /// Id of the stream to get the branches from + /// Max number of branches to retrieve + /// Max number of commits to retrieve + /// + public Task PagedStreamGetBranches(string streamId, int branchesLimit = 10, int commitsLimit = 10, string? nextCursor = null) + { + return PagedStreamGetBranches(CancellationToken.None, streamId, branchesLimit, commitsLimit); + } + + /// + /// Get paginated branches from a given stream + /// + /// + /// Id of the stream to get the branches from + /// Max number of branches to retrieve + /// Max number of commits to retrieve + /// Cursor to get the next page of results + /// + /// + public async Task PagedStreamGetBranches( + CancellationToken cancellationToken, + string streamId, + int branchesLimit = 10, + int commitsLimit = 10, + string? nextCursor = null + ) + { + var request = new GraphQLRequest + { + Query = + $@"query Stream ($streamId: String!) {{ + stream(id: $streamId) {{ + branches(limit: {branchesLimit}, cursor: ""{nextCursor}"") {{ + cursor + items {{ + id + name + description + commits (limit: {commitsLimit}) {{ + totalCount + cursor + items {{ + id + referencedObject + sourceApplication + message + authorName + authorId + branchName + parents + createdAt + }} + }} + }} + }} + }} + }}", + Variables = new { streamId, nextCursor } + }; + var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); + return res.stream.branches; + } /// /// Creates a branch on a stream. diff --git a/DesktopUI2/DesktopUI2/ViewModels/StreamViewModel.cs b/DesktopUI2/DesktopUI2/ViewModels/StreamViewModel.cs index 7f3f451ea6..a00ee3baf6 100644 --- a/DesktopUI2/DesktopUI2/ViewModels/StreamViewModel.cs +++ b/DesktopUI2/DesktopUI2/ViewModels/StreamViewModel.cs @@ -220,6 +220,9 @@ public async Task GetStream() } } + /// The limit of branches to be displayed in the stream, Given a limit to prevent runaway Branch DOS attacks + private const int BranchLimit = 500; + internal async void GetBranchesAndRestoreState() { try @@ -246,7 +249,17 @@ internal async void GetBranchesAndRestoreState() AvailableFilters = new List(Bindings.GetSelectionFilters().Select(x => new FilterViewModel(x))); SelectedFilter = AvailableFilters[0]; - Branches = await Client.StreamGetBranches(Stream.id, 100, 0).ConfigureAwait(true); + // Get all branches created in the stream, not limited to the server limits + string nextCursor = null; + var branchCount = 0; + + do + { + var branchResponse = await Client.PagedStreamGetBranches(Stream.id, 100, 0, nextCursor).ConfigureAwait(false); + Branches.AddRange(branchResponse.items); + nextCursor = branchResponse.cursor; + branchCount += branchResponse.items.Count; + } while (!string.IsNullOrEmpty(nextCursor) && branchCount <= BranchLimit); var index = Branches.FindIndex(x => x.name == StreamState.BranchName); if (index != -1) @@ -408,7 +421,18 @@ private void UpdateStreamState() private async Task GetBranches() { var prevBranchName = SelectedBranch != null ? SelectedBranch.Branch.name : StreamState.BranchName; - Branches = await Client.StreamGetBranches(Stream.id, 100, 0).ConfigureAwait(true); + + // Get all branches created in the stream, not limited to the server limits + string nextCursor = null; + var branchCount = 0; + + do + { + var branchResponse = await Client.PagedStreamGetBranches(Stream.id, 100, 0, nextCursor).ConfigureAwait(false); + Branches.AddRange(branchResponse.items); + nextCursor = branchResponse.cursor; + branchCount += branchResponse.items.Count; + } while (!string.IsNullOrEmpty(nextCursor) && branchCount <= BranchLimit); var index = Branches.FindIndex(x => x.name == prevBranchName); if (index != -1)