diff --git a/data/model/legacy.py b/data/model/legacy.py index 2feba5a82..dd6a10121 100644 --- a/data/model/legacy.py +++ b/data/model/legacy.py @@ -2291,10 +2291,12 @@ def load_token_data(code): def _get_build_base_query(): return (RepositoryBuild .select(RepositoryBuild, RepositoryBuildTrigger, BuildTriggerService, Repository, - Namespace) + Namespace, User) .join(Repository) .join(Namespace, on=(Repository.namespace_user == Namespace.id)) .switch(RepositoryBuild) + .join(User, JOIN_LEFT_OUTER) + .switch(RepositoryBuild) .join(RepositoryBuildTrigger, JOIN_LEFT_OUTER) .join(BuildTriggerService, JOIN_LEFT_OUTER) .order_by(RepositoryBuild.started.desc())) diff --git a/endpoints/api/build.py b/endpoints/api/build.py index a784c4f84..385e9288c 100644 --- a/endpoints/api/build.py +++ b/endpoints/api/build.py @@ -45,7 +45,7 @@ def user_view(user): 'is_robot': user.robot, } -def trigger_view(trigger, can_read=False, can_admin=False): +def trigger_view(trigger, can_read=False, can_admin=False, for_build=False): if trigger and trigger.uuid: build_trigger = BuildTriggerHandler.get_handler(trigger) build_source = build_trigger.config.get('build_source') @@ -55,17 +55,28 @@ def trigger_view(trigger, can_read=False, can_admin=False): if can_admin: can_read = True - return { - 'service': trigger.service.name, - 'build_source': build_source if can_read else None, - 'config': build_trigger.config if can_admin else {}, + is_connected_user = False + if (can_admin and get_authenticated_user() and + trigger.connected_user_id == get_authenticated_user().id): + is_connected_user = True + + trigger_data = { 'id': trigger.uuid, - 'connected_user': trigger.connected_user.username, + 'service': trigger.service.name, 'is_active': build_trigger.is_active(), - 'pull_robot': user_view(trigger.pull_robot) if trigger.pull_robot else None, + + 'build_source': build_source if can_read else None, 'repository_url': repo_url if can_read else None, + + 'config': build_trigger.config if can_admin else {}, + 'is_connected_user': is_connected_user, } + if not for_build and can_admin and trigger.pull_robot: + trigger_data['pull_robot'] = user_view(trigger.pull_robot) + + return trigger_data + return None @@ -111,7 +122,7 @@ def build_status_view(build_obj): 'tags': job_config.get('docker_tags', []), 'manual_user': job_config.get('manual_user', None), 'is_writer': can_write, - 'trigger': trigger_view(build_obj.trigger, can_read, can_admin), + 'trigger': trigger_view(build_obj.trigger, can_read, can_admin, for_build=True), 'trigger_metadata': job_config.get('trigger_metadata', None) if can_read else None, 'resource_key': build_obj.resource_key, 'pull_robot': user_view(build_obj.pull_robot) if build_obj.pull_robot else None, diff --git a/static/directives/repo-view/repo-panel-builds.html b/static/directives/repo-view/repo-panel-builds.html index d4f2b1db7..6db82a7cb 100644 --- a/static/directives/repo-view/repo-panel-builds.html +++ b/static/directives/repo-view/repo-panel-builds.html @@ -146,7 +146,7 @@ View Credentials + ng-class="trigger.is_connected_user ? '' : 'disabled'"> Run Trigger Now diff --git a/static/js/directives/repo-view/repo-panel-builds.js b/static/js/directives/repo-view/repo-panel-builds.js index d52d1de00..a1d8fdd31 100644 --- a/static/js/directives/repo-view/repo-panel-builds.js +++ b/static/js/directives/repo-view/repo-panel-builds.js @@ -197,9 +197,9 @@ angular.module('quay').directive('repoPanelBuilds', function () { }; $scope.askRunTrigger = function(trigger) { - if ($scope.user.username != trigger.connected_user) { - bootbox.alert('For security reasons, only user "' + trigger.connected_user + - '" can manually invoke this trigger'); + if (!trigger.is_connected_user) { + bootbox.alert('For security reasons, only the user that created this trigger can ' + + 'manually invoke this trigger'); return; } diff --git a/test/test_api_usage.py b/test/test_api_usage.py index 012375aa2..4dc012ae6 100644 --- a/test/test_api_usage.py +++ b/test/test_api_usage.py @@ -6,6 +6,8 @@ import json as py_json from urllib import urlencode from urlparse import urlparse, urlunparse, parse_qs +from playhouse.test_utils import assert_query_count + from endpoints.api import api_bp, api from endpoints.building import PreparedBuild from endpoints.webhooks import webhooks @@ -1544,16 +1546,18 @@ class TestRepoBuilds(ApiTestCase): def test_getrepo_nobuilds(self): self.login(ADMIN_ACCESS_USER) - json = self.getJsonResponse(RepositoryBuildList, - params=dict(repository=ADMIN_ACCESS_USER + '/simple')) + with assert_query_count(4): + json = self.getJsonResponse(RepositoryBuildList, + params=dict(repository=ADMIN_ACCESS_USER + '/simple')) assert len(json['builds']) == 0 def test_getrepobuilds(self): self.login(ADMIN_ACCESS_USER) - json = self.getJsonResponse(RepositoryBuildList, - params=dict(repository=ADMIN_ACCESS_USER + '/building')) + with assert_query_count(4): + json = self.getJsonResponse(RepositoryBuildList, + params=dict(repository=ADMIN_ACCESS_USER + '/building')) assert len(json['builds']) > 0 build = json['builds'][-1]