package se.bjurr.prnfb.service; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Ordering.usingToString; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static se.bjurr.prnfb.listener.PrnfbPullRequestAction.BUTTON_TRIGGER; import java.util.List; import java.util.UUID; import com.atlassian.bitbucket.pull.PullRequest; import com.atlassian.bitbucket.pull.PullRequestService; import com.atlassian.bitbucket.repository.Repository; import com.google.common.annotations.VisibleForTesting; import se.bjurr.prnfb.http.ClientKeyStore; import se.bjurr.prnfb.http.NotificationResponse; import se.bjurr.prnfb.listener.PrnfbPullRequestAction; import se.bjurr.prnfb.listener.PrnfbPullRequestEventListener; import se.bjurr.prnfb.service.VariablesContext.VariablesContextBuilder; import se.bjurr.prnfb.settings.PrnfbButton; import se.bjurr.prnfb.settings.PrnfbNotification; import se.bjurr.prnfb.settings.PrnfbSettingsData; public class ButtonsService { private final PrnfbPullRequestEventListener prnfbPullRequestEventListener; private final PrnfbRendererFactory prnfbRendererFactory; private final PullRequestService pullRequestService; private final SettingsService settingsService; private final UserCheckService userCheckService; public ButtonsService( PullRequestService pullRequestService, PrnfbPullRequestEventListener prnfbPullRequestEventListener, PrnfbRendererFactory prnfbRendererFactory, SettingsService settingsService, UserCheckService userCheckService) { this.pullRequestService = pullRequestService; this.prnfbPullRequestEventListener = prnfbPullRequestEventListener; this.prnfbRendererFactory = prnfbRendererFactory; this.settingsService = settingsService; this.userCheckService = userCheckService; } @VisibleForTesting List<PrnfbButton> doGetButtons( List<PrnfbNotification> notifications, ClientKeyStore clientKeyStore, final PullRequest pullRequest, boolean shouldAcceptAnyCertificate) { String projectKey = pullRequest.getToRef().getRepository().getProject().getKey(); String repositoryKey = pullRequest.getToRef().getRepository().getSlug(); List<PrnfbButton> allFoundButtons = newArrayList(); for (PrnfbButton candidate : settingsService.getButtons()) { PrnfbButton button = settingsService.getButton(candidate.getUuid()); VariablesContext variables = new VariablesContextBuilder() // .setButton(button) // .build(); PrnfbPullRequestAction pullRequestAction = BUTTON_TRIGGER; if (userCheckService.isAllowed(candidate.getUserLevel(), projectKey, repositoryKey) // && isTriggeredByAction( clientKeyStore, notifications, shouldAcceptAnyCertificate, pullRequestAction, pullRequest, variables) // && isVisibleOnPullRequest(candidate, pullRequest)) { allFoundButtons.add(candidate); } } allFoundButtons = usingToString().sortedCopy(allFoundButtons); return allFoundButtons; } @VisibleForTesting List<NotificationResponse> doHandlePressed( UUID buttonUuid, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, final PullRequest pullRequest, final String formData) { PrnfbButton button = settingsService.getButton(buttonUuid); VariablesContext variables = new VariablesContextBuilder() // .setButton(button) // .setFormData(formData) // .build(); List<NotificationResponse> successes = newArrayList(); for (PrnfbNotification prnfbNotification : settingsService.getNotifications()) { PrnfbPullRequestAction pullRequestAction = BUTTON_TRIGGER; PrnfbRenderer renderer = prnfbRendererFactory.create(pullRequest, pullRequestAction, prnfbNotification, variables); if (prnfbPullRequestEventListener.isNotificationTriggeredByAction( prnfbNotification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate)) { NotificationResponse response = prnfbPullRequestEventListener.notify( prnfbNotification, pullRequestAction, pullRequest, renderer, clientKeyStore, shouldAcceptAnyCertificate); if (response != null) { successes.add(response); } } } return successes; } public List<PrnfbButton> getButtons(Integer repositoryId, Long pullRequestId) { final PrnfbSettingsData settings = settingsService.getPrnfbSettingsData(); List<PrnfbNotification> notifications = settingsService.getNotifications(); ClientKeyStore clientKeyStore = new ClientKeyStore(settings); final PullRequest pullRequest = pullRequestService.getById(repositoryId, pullRequestId); boolean shouldAcceptAnyCertificate = settings.isShouldAcceptAnyCertificate(); return doGetButtons(notifications, clientKeyStore, pullRequest, shouldAcceptAnyCertificate); } public PrnfbRendererWrapper getRenderer( Integer repositoryId, Long pullRequestId, UUID buttonUuid) { final PrnfbSettingsData settings = settingsService.getPrnfbSettingsData(); ClientKeyStore clientKeyStore = new ClientKeyStore(settings); final PullRequest pullRequest = pullRequestService.getById(repositoryId, pullRequestId); boolean shouldAcceptAnyCertificate = settings.isShouldAcceptAnyCertificate(); PrnfbButton button = settingsService.getButton(buttonUuid); VariablesContext variables = new VariablesContextBuilder() // .setButton(button) // .build(); PrnfbPullRequestAction pullRequestAction = BUTTON_TRIGGER; PrnfbRendererWrapper renderer = prnfbRendererFactory.create( pullRequest, pullRequestAction, variables, clientKeyStore, shouldAcceptAnyCertificate); return renderer; } public List<NotificationResponse> handlePressed( Integer repositoryId, Long pullRequestId, UUID buttonUuid, String formData) { final PrnfbSettingsData prnfbSettingsData = settingsService.getPrnfbSettingsData(); ClientKeyStore clientKeyStore = new ClientKeyStore(prnfbSettingsData); boolean shouldAcceptAnyCertificate = prnfbSettingsData.isShouldAcceptAnyCertificate(); final PullRequest pullRequest = pullRequestService.getById(repositoryId, pullRequestId); return doHandlePressed( buttonUuid, clientKeyStore, shouldAcceptAnyCertificate, pullRequest, formData); } private boolean isTriggeredByAction( ClientKeyStore clientKeyStore, List<PrnfbNotification> notifications, boolean shouldAcceptAnyCertificate, PrnfbPullRequestAction pullRequestAction, PullRequest pullRequest, VariablesContext variables) { for (PrnfbNotification prnfbNotification : notifications) { PrnfbRenderer renderer = prnfbRendererFactory.create(pullRequest, pullRequestAction, prnfbNotification, variables); if (prnfbPullRequestEventListener.isNotificationTriggeredByAction( prnfbNotification, pullRequestAction, renderer, pullRequest, clientKeyStore, shouldAcceptAnyCertificate)) { return TRUE; } } return FALSE; } /** * Checks if the given button is visible on the pull request by either the from or to repository. */ private boolean isVisibleOnPullRequest(PrnfbButton button, PullRequest pullRequest) { return pullRequest.getFromRef() != null && isVisibleOnRepository(button, pullRequest.getFromRef().getRepository()) || pullRequest.getToRef() != null && isVisibleOnRepository(button, pullRequest.getToRef().getRepository()); } /** * Checks if the given button is visible in the given repository. * * @param button Button under test * @param repository Repository to check for * @return True if the button is either globally visible or matches with the given repository */ @VisibleForTesting boolean isVisibleOnRepository(PrnfbButton button, Repository repository) { boolean projectOk = false; boolean repoOk = false; do { if (button.getProjectKey().isPresent()) { projectOk |= button.getProjectKey().get().equals(repository.getProject().getKey()); } else { projectOk = true; } if (button.getRepositorySlug().isPresent()) { repoOk |= button.getRepositorySlug().get().equals(repository.getSlug()); } else { repoOk = true; } } while (!(projectOk && repoOk) && (repository = repository.getOrigin()) != null); return projectOk && repoOk; } }