private String getSolver(final Principal user, final UserClaimRequest userClaimRequest, final RequestDto request) { final IssueInformationDto issueInformation = request.getIssueInformation(); final String solver = Optional.ofNullable(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber()).getSolver()) .orElseThrow(() -> new RuntimeException("Unable to get solver")); final String userPlatformUsername = getUserPlatformUsername(user, userClaimRequest.getPlatform()).orElseThrow(GITHUB_ACCOUNT_IS_NOT_LINKED); if (!solver.equalsIgnoreCase(userPlatformUsername)) { throw new RuntimeException("Claim executed by wrong user"); } return solver; }
public Optional<GithubIssue> findBy(final String platformId) { return GithubId.fromPlatformId(platformId) .map(githubId -> githubScraper.fetchGithubIssue(githubId.getOwner(), githubId.getRepo(), githubId.getNumber())); } }
private CreateGithubComment createComment(final Long requestId, final IssueInformationDto issueInformation, final ClaimDto claim) { final String solver = Optional.ofNullable(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber()).getSolver()) .orElseThrow(() -> new RuntimeException("No solver found for request " + requestId)); final String transactionHash = claim.getTransactionHash(); final CreateGithubComment comment = new CreateGithubComment(); comment.setBody(githubCommentFactory.createClosedComment(requestId, solver, transactionHash)); return comment; }
@Override public Health health() { try { final List<Health> healths = getIssues().keySet() .stream() .map(number -> getGithubScraper().fetchGithubIssue(getOwner(), getRepo(), number)) .map(this::check) .collect(Collectors.toList()); return Health.status(calculateOverallStatus(healths)).withDetail("healths", healths).build(); } catch (Exception e) { return Health.down().withDetail(DOWN_PROBLEM_KEY, "Exception thrown while fetching GitHub issue").build(); } }
@Test public void claimableResult_currentStatusFunded() { final String owner = "FundRequest"; final String repo = "area51"; final String number = "983"; final String solver = "davyvanroy"; when(githubScraper.fetchGithubIssue(owner, repo, number)).thenReturn(GithubIssue.builder() .solver(solver) .status("Closed") .build()); final ClaimableResultDto result = claimResolver.claimableResult(owner, repo, number, RequestStatus.FUNDED); assertThat(result.isClaimable()).isTrue(); assertThat(result.getPlatform()).isEqualTo(Platform.GITHUB); assertThat(result.getClaimableByPlatformUserName()).isEqualTo(solver); }
@Test public void claimableResult_currentStatusClaimable() { final String owner = "FundRequest"; final String repo = "area51"; final String number = "983"; final String solver = "davyvanroy"; when(githubScraper.fetchGithubIssue(owner, repo, number)).thenReturn(GithubIssue.builder() .solver(solver) .status("Closed") .build()); final ClaimableResultDto result = claimResolver.claimableResult(owner, repo, number, RequestStatus.CLAIMABLE); assertThat(result.isClaimable()).isTrue(); assertThat(result.getPlatform()).isEqualTo(Platform.GITHUB); assertThat(result.getClaimableByPlatformUserName()).isEqualTo(solver); }
@Test public void claimableResult_githubIssueNoSolver() { final String owner = "FundRequest"; final String repo = "area51"; final String number = "983"; when(githubScraper.fetchGithubIssue(owner, repo, number)).thenReturn(GithubIssue.builder() .status("Closed") .build()); final ClaimableResultDto result = claimResolver.claimableResult(owner, repo, number, RequestStatus.FUNDED); assertThat(result.isClaimable()).isFalse(); assertThat(result.getPlatform()).isEqualTo(Platform.GITHUB); assertThat(result.getClaimableByPlatformUserName()).isNull(); }
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void createGithubCommentOnRequestClaimable(final RequestClaimableEvent event) { if (addComment) { final RequestDto request = event.getRequestDto(); final IssueInformationDto issueInformation = request.getIssueInformation(); if (issueInformation.getPlatform() == Platform.GITHUB) { final String solver = Optional.ofNullable(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber()).getSolver()) .orElseThrow(() -> new RuntimeException("No solver found for request " + request.getId())); final CreateGithubComment comment = new CreateGithubComment(); comment.setBody(githubCommentFactory.createResolvedComment(request.getId(), solver)); githubGateway.createCommentOnIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber(), comment); } } } }
@Test public void claimableResult_githubIssueNotClosed() { final String owner = "FundRequest"; final String repo = "area51"; final String number = "983"; final String solver = "davyvanroy"; when(githubScraper.fetchGithubIssue(owner, repo, number)).thenReturn(GithubIssue.builder() .status("Open") .solver(solver) .build()); final ClaimableResultDto result = claimResolver.claimableResult(owner, repo, number, RequestStatus.FUNDED); assertThat(result.isClaimable()).isFalse(); assertThat(result.getPlatform()).isEqualTo(Platform.GITHUB); assertThat(result.getClaimableByPlatformUserName()).isNull(); }
@Test public void canClaim() { final Principal principal = PrincipalMother.davyvanroy(); final RequestDto requestDto = RequestDtoMother.fundRequestArea51(); final IssueInformationDto issueInformation = requestDto.getIssueInformation(); when(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(GithubIssue.builder() .solver("davyvanroy") .status("Closed") .build()); when(keycloakRepository.getUserIdentities(principal.getName())).thenReturn(Stream.of(UserIdentity.builder().provider(Provider.GITHUB).username("davyvanroy").build())); assertThat(claimResolver.canClaim(principal, requestDto)).isTrue(); }
@Test public void canClaim_issueNotClosed() { final Principal principal = PrincipalMother.davyvanroy(); final RequestDto requestDto = RequestDtoMother.fundRequestArea51(); final IssueInformationDto issueInformation = requestDto.getIssueInformation(); when(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(GithubIssue.builder() .status("Open") .build()); assertThat(claimResolver.canClaim(principal, requestDto)).isFalse(); }
@Test public void canClaim_differentUser() { final Principal principal = PrincipalMother.davyvanroy(); final RequestDto requestDto = RequestDtoMother.fundRequestArea51(); final IssueInformationDto issueInformation = requestDto.getIssueInformation(); when(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(GithubIssue.builder() .solver("dfgj") .status("Closed") .build()); when(keycloakRepository.getUserIdentities(principal.getName())).thenReturn(Stream.of(UserIdentity.builder().provider(Provider.GITHUB).username("davyvanroy").build())); assertThat(claimResolver.canClaim(principal, requestDto)).isFalse(); }
public Boolean canClaim(final Principal user, final RequestDto request) { final String owner = request.getIssueInformation().getOwner(); final String repo = request.getIssueInformation().getRepo(); final String number = request.getIssueInformation().getNumber(); final GithubIssue githubIssue = githubScraper.fetchGithubIssue(owner, repo, number); return isIssueClosed(githubIssue) && isClaimalbeByLoggedInUser(user, request, githubIssue.getSolver()); }
@Test public void postsGithubComment() { final RequestClaimableEvent event = new RequestClaimableEvent(RequestDtoMother.freeCodeCampNoUserStories(), LocalDateTime.now()); final String expectedMessage = "ytufg"; final RequestDto request = event.getRequestDto(); final IssueInformationDto issueInformation = request.getIssueInformation(); final String solver = "gdhfjghiuyutfyd"; final ArgumentCaptor<CreateGithubComment> createGithubCommentArgumentCaptor = ArgumentCaptor.forClass(CreateGithubComment.class); when(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(GithubIssue.builder() .solver(solver) .build()); when(githubCommentFactory.createResolvedComment(request.getId(), solver)).thenReturn(expectedMessage); handler.createGithubCommentOnRequestClaimable(event); verify(githubGateway).createCommentOnIssue(eq(issueInformation.getOwner()), eq(issueInformation.getRepo()), eq(issueInformation.getNumber()), createGithubCommentArgumentCaptor.capture()); assertThat(createGithubCommentArgumentCaptor.getValue().getBody()).isEqualTo(expectedMessage); }
@Test public void postsGithubComment_noSolverFound() { final RequestClaimableEvent event = new RequestClaimableEvent(RequestDtoMother.freeCodeCampNoUserStories(), LocalDateTime.now()); final RequestDto request = event.getRequestDto(); final IssueInformationDto issueInformation = request.getIssueInformation(); when(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(GithubIssue.builder().build()); try { handler.createGithubCommentOnRequestClaimable(event); fail("RuntimeException expected"); } catch (RuntimeException e) { assertThat(e.getMessage()).isEqualTo("No solver found for request " + request.getId()); } } }
public ClaimableResultDto claimableResult(final String owner, final String repo, final String number, final RequestStatus requestStatus) { final GithubIssue githubIssue = githubScraper.fetchGithubIssue(owner, repo, number); if (isIssueClosed(githubIssue) && githubIssue.getSolver() != null && (requestStatus == FUNDED || requestStatus == CLAIMABLE)) { return ClaimableResultDto.builder() .claimable(true) .platform(Platform.GITHUB) .claimableByPlatformUserName(githubIssue.getSolver()) .build(); } return ClaimableResultDto.builder().claimable(false).platform(Platform.GITHUB).build(); }
@Test public void claim() { final RequestDto request = RequestDtoMother.freeCodeCampNoUserStories(); final UserClaimRequest userClaimRequest = createClaimRequest(request); final IssueInformationDto issueInformation = request.getIssueInformation(); final SignClaimCommand signClaimCommand = createSignClaimCommand(userClaimRequest, "davyvanroy"); final ClaimSignature claimSignature = createClaimSignature(signClaimCommand); when(keycloakRepository.getUserIdentities("davyvanroy")).thenReturn(Stream.of(UserIdentity.builder() .provider(Provider.GITHUB) .username("davyvanroy") .build())); when(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(GithubIssue.builder() .solver("davyvanroy") .status("Closed") .build()); when(azraelClient.getSignature(signClaimCommand)).thenReturn(claimSignature); SignedClaim result = claimResolver.getSignedClaim(() -> "davyvanroy", userClaimRequest, request); assertThat(result.getPlatform().toString()).isEqualTo(claimSignature.getPlatform()); assertThat(result.getPlatformId()).isEqualTo(claimSignature.getPlatformId()); assertThat(result.getSolver()).isEqualTo(claimSignature.getSolver()); assertThat(result.getSolverAddress()).isEqualTo(claimSignature.getAddress()); assertThat(result.getR()).isEqualTo(claimSignature.getR()); assertThat(result.getS()).isEqualTo(claimSignature.getS()); assertThat(result.getV()).isEqualTo(claimSignature.getV()); }
@Test public void postsGithubComment_noSolverFound() { final RequestClaimedEvent event = RequestClaimedEvent.builder() .blockchainEventId(1324354L) .requestDto(RequestDtoMother.freeCodeCampNoUserStories()) .claimDto(mock(ClaimDto.class)) .solver(SOLVER) .timestamp(LocalDateTime.now()) .build(); final RequestDto request = event.getRequestDto(); final IssueInformationDto issueInformation = request.getIssueInformation(); when(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(GithubIssue.builder().build()); try { handler.createGithubCommentOnRequestClaimed(event); fail("RuntimeException expected"); } catch (RuntimeException e) { assertThat(e.getMessage()).isEqualTo("No solver found for request " + request.getId()); } }
@Test public void postsGithubComment_lessThan2CommentsPresent() { final RequestClaimedEvent event = RequestClaimedEvent.builder() .blockchainEventId(1324354L) .requestDto(RequestDtoMother.freeCodeCampNoUserStories()) .claimDto(mock(ClaimDto.class)) .solver(SOLVER) .timestamp(LocalDateTime.now()) .build(); final RequestDto request = event.getRequestDto(); final IssueInformationDto issueInformation = request.getIssueInformation(); final ClaimDto claim = event.getClaimDto(); final ArgumentCaptor<CreateGithubComment> createGithubCommentArgumentCaptor = ArgumentCaptor.forClass(CreateGithubComment.class); final List<GithubIssueCommentsResult> existingComments = Arrays.asList(createCommentFromGithubUserMock(0)); when(githubGateway.getCommentsForIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(existingComments); when(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(GithubIssue.builder().solver(SOLVER).build()); when(githubCommentFactory.createClosedComment(request.getId(), SOLVER, claim.getTransactionHash())).thenReturn(EXPECTED_MESSAGE); handler.createGithubCommentOnRequestClaimed(event); final InOrder inOrder = inOrder(githubGateway); inOrder.verify(githubGateway).evictCommentsForIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber()); inOrder.verify(githubGateway).getCommentsForIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber()); inOrder.verify(githubGateway).createCommentOnIssue(eq(issueInformation.getOwner()), eq(issueInformation.getRepo()), eq(issueInformation.getNumber()), createGithubCommentArgumentCaptor.capture()); assertThat(createGithubCommentArgumentCaptor.getValue().getBody()).isEqualTo(EXPECTED_MESSAGE); }
@Test public void postsGithubComment_2CommentsPresent() { final RequestClaimedEvent event = RequestClaimedEvent.builder() .blockchainEventId(1324354L) .requestDto(RequestDtoMother.freeCodeCampNoUserStories()) .claimDto(mock(ClaimDto.class)) .solver(SOLVER) .timestamp(LocalDateTime.now()) .build(); final RequestDto request = event.getRequestDto(); final IssueInformationDto issueInformation = request.getIssueInformation(); final ClaimDto claim = event.getClaimDto(); final ArgumentCaptor<CreateGithubComment> createGithubCommentArgumentCaptor = ArgumentCaptor.forClass(CreateGithubComment.class); final GithubIssueCommentsResult firstComment = createCommentFromGithubUserMock(-2); final GithubIssueCommentsResult secondComment = createCommentFromGithubUserMock(-1); final List<GithubIssueCommentsResult> existingComments = Arrays.asList(firstComment, secondComment); when(githubGateway.getCommentsForIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(existingComments); when(githubScraper.fetchGithubIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber())).thenReturn(GithubIssue.builder().solver(SOLVER).build()); when(githubCommentFactory.createClosedComment(request.getId(), SOLVER, claim.getTransactionHash())).thenReturn(EXPECTED_MESSAGE); handler.createGithubCommentOnRequestClaimed(event); final InOrder inOrder = inOrder(githubGateway); inOrder.verify(githubGateway).evictCommentsForIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber()); inOrder.verify(githubGateway).getCommentsForIssue(issueInformation.getOwner(), issueInformation.getRepo(), issueInformation.getNumber()); inOrder.verify(githubGateway).editCommentOnIssue(eq(issueInformation.getOwner()), eq(issueInformation.getRepo()), eq(secondComment.getId()), createGithubCommentArgumentCaptor.capture()); assertThat(createGithubCommentArgumentCaptor.getValue().getBody()).isEqualTo(EXPECTED_MESSAGE); }