diff options
author | Philippe Perrin <philippe.perrin@sonarsource.com> | 2019-10-10 13:50:45 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-10-11 20:21:07 +0200 |
commit | 6868ebd60bcc61d9ec5c079d9da55c836ba5c154 (patch) | |
tree | c46b21ef2cc0c3fc9b98dc56f217a9eee1aca428 /server | |
parent | 51a03704505d995f389524a1f30fbfbcd778327e (diff) | |
download | sonarqube-6868ebd60bcc61d9ec5c079d9da55c836ba5c154.tar.gz sonarqube-6868ebd60bcc61d9ec5c079d9da55c836ba5c154.zip |
SONAR-12284 Remove incorrect call to /api/components/show to verify access
Diffstat (limited to 'server')
8 files changed, 77 insertions, 5 deletions
diff --git a/server/sonar-web/src/main/js/api/nav.ts b/server/sonar-web/src/main/js/api/nav.ts index 273730e539e..9d1fdcec5e6 100644 --- a/server/sonar-web/src/main/js/api/nav.ts +++ b/server/sonar-web/src/main/js/api/nav.ts @@ -24,9 +24,11 @@ export function getGlobalNavigation(): Promise<T.AppState> { return getJSON('/api/navigation/global'); } +type NavComponent = T.Omit<T.Component, 'alm' | 'qualifier' | 'leakPeriodDate' | 'path' | 'tags'>; + export function getComponentNavigation( data: { component: string } & T.BranchParameters -): Promise<any> { +): Promise<NavComponent> { return getJSON('/api/navigation/component', data).catch(throwGlobalError); } diff --git a/server/sonar-web/src/main/js/app/types.d.ts b/server/sonar-web/src/main/js/app/types.d.ts index 703d7b8db5b..18ed0575aa5 100644 --- a/server/sonar-web/src/main/js/app/types.d.ts +++ b/server/sonar-web/src/main/js/app/types.d.ts @@ -152,6 +152,7 @@ declare namespace T { interface ComponentConfiguration { canApplyPermissionTemplate?: boolean; + canBrowseProject?: boolean; canUpdateProjectVisibilityToPrivate?: boolean; extensions?: Extension[]; showBackgroundTasks?: boolean; diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx index ac49f162fe7..150a2fff503 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx @@ -59,7 +59,9 @@ export default class ProjectRowActions extends React.PureComponent<Props, State> getComponentNavigation({ component: this.props.project.key }).then( ({ configuration }) => { if (this.mounted) { - const hasAccess = Boolean(configuration && configuration.showPermissions); + const hasAccess = Boolean( + configuration && configuration.showPermissions && configuration.canBrowseProject + ); this.setState({ hasAccess, loading: false }); } }, diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRowActions-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRowActions-test.tsx index 3f40b0ee688..13f41ccf25e 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRowActions-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRowActions-test.tsx @@ -28,6 +28,10 @@ jest.mock('../../../api/nav', () => ({ getComponentNavigation: jest.fn().mockResolvedValue({}) })); +beforeEach(() => { + jest.clearAllMocks(); +}); + it('renders correctly', () => { const wrapper = shallowRender(); expect(wrapper).toMatchSnapshot(); @@ -35,9 +39,9 @@ it('renders correctly', () => { describe('restore access', () => { beforeAll(() => { - jest.resetAllMocks(); (getComponentNavigation as jest.Mock).mockResolvedValue({ configuration: { + canBrowseProject: false, showPermissions: false } }); @@ -65,13 +69,26 @@ describe('restore access', () => { expect(wrapper.find('.js-restore-access').exists()).toBe(false); expect(wrapper.find('RestoreAccessModal').exists()).toBe(false); }); + + it('also shows the restore access when browse permission is missing', async () => { + (getComponentNavigation as jest.Mock).mockResolvedValueOnce({ + configuration: { canBrowseProject: false, showPermissions: true } + }); + + const wrapper = shallowRender(); + wrapper.instance().handleDropdownOpen(); + await waitAndUpdate(wrapper); + + expect(getComponentNavigation).toBeCalledWith({ component: 'foo' }); + expect(wrapper.find('.js-restore-access').exists()).toBe(true); + }); }); describe('permissions', () => { beforeAll(() => { - jest.resetAllMocks(); (getComponentNavigation as jest.Mock).mockResolvedValue({ configuration: { + canBrowseProject: true, showPermissions: true } }); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java index efa0e7ef96d..05017046620 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/ui/ws/ComponentAction.java @@ -307,6 +307,7 @@ public class ComponentAction implements NavigationWsAction { boolean isQualityProfileAdmin = userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, component.getOrganizationUuid()); boolean isQualityGateAdmin = userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_GATES, component.getOrganizationUuid()); boolean isOrganizationAdmin = userSession.hasPermission(OrganizationPermission.ADMINISTER, component.getOrganizationUuid()); + boolean canBrowseProject = userSession.hasComponentPermission(USER, component); json.prop("showSettings", isProjectAdmin && componentTypeHasProperty(component, PROPERTY_CONFIGURABLE)); json.prop("showQualityProfiles", isProject && (isProjectAdmin || isQualityProfileAdmin)); @@ -318,6 +319,7 @@ public class ComponentAction implements NavigationWsAction { json.prop("showUpdateKey", isProjectAdmin && componentTypeHasProperty(component, PROPERTY_UPDATABLE_KEY)); json.prop("showBackgroundTasks", showBackgroundTasks); json.prop("canApplyPermissionTemplate", isOrganizationAdmin); + json.prop("canBrowseProject", canBrowseProject); json.prop("canUpdateProjectVisibilityToPrivate", isProjectAdmin && billingValidations.canUpdateProjectVisibilityToPrivate(new BillingValidations.Organization(organization.getKey(), organization.getUuid(), organization.getName()))); } diff --git a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/ui/ws/component-example.json b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/ui/ws/component-example.json index b6968301a3c..fa258b64d3e 100644 --- a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/ui/ws/component-example.json +++ b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/ui/ws/component-example.json @@ -44,6 +44,7 @@ "showHistory": true, "showUpdateKey": true, "showBackgroundTasks": true, + "canBrowseProject": true, "extensions": [ { "key": "my_plugin/admin_page", diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java index 78791469832..6dd5b4ae903 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java @@ -409,6 +409,49 @@ public class ComponentActionTest { } @Test + public void return_configuration_for_private_projects() { + ComponentDto project = insertOrganizationAndProject(); + UserSessionRule userSessionRule = userSession.logIn(); + init(); + + userSessionRule.addProjectPermission(UserRole.ADMIN, project); + assertJson(execute(project.getDbKey())).isSimilarTo("{\n" + + " \"configuration\": {\n" + + " \"showSettings\": false,\n" + + " \"showQualityProfiles\": true,\n" + + " \"showQualityGates\": true,\n" + + " \"showManualMeasures\": true,\n" + + " \"showLinks\": true,\n" + + " \"showPermissions\": false,\n" + + " \"showHistory\": false,\n" + + " \"showUpdateKey\": false,\n" + + " \"showBackgroundTasks\": true,\n" + + " \"canApplyPermissionTemplate\": false,\n" + + " \"canBrowseProject\": false,\n" + + " \"canUpdateProjectVisibilityToPrivate\": false\n" + + " }\n" + + "}"); + + userSessionRule.addProjectPermission(UserRole.USER, project); + assertJson(execute(project.getDbKey())).isSimilarTo("{\n" + + " \"configuration\": {\n" + + " \"showSettings\": false,\n" + + " \"showQualityProfiles\": true,\n" + + " \"showQualityGates\": true,\n" + + " \"showManualMeasures\": true,\n" + + " \"showLinks\": true,\n" + + " \"showPermissions\": false,\n" + + " \"showHistory\": false,\n" + + " \"showUpdateKey\": false,\n" + + " \"showBackgroundTasks\": true,\n" + + " \"canApplyPermissionTemplate\": false,\n" + + " \"canBrowseProject\": true,\n" + + " \"canUpdateProjectVisibilityToPrivate\": false\n" + + " }\n" + + "}"); + } + + @Test public void return_bread_crumbs_on_several_levels() { ComponentDto project = insertOrganizationAndProject(); ComponentDto module = componentDbTester.insertComponent(newModuleDto("bcde", project).setDbKey("palap").setName("Palap")); @@ -681,7 +724,7 @@ public class ComponentActionTest { private void executeAndVerify(String componentKey, String expectedJson) { verify(execute(componentKey), expectedJson); - } +} private void addQualityProfiles(ComponentDto project, QualityProfile... qps) { MetricDto metric = newMetricDto().setKey(QUALITY_PROFILES_KEY); diff --git a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_with_all_properties.json b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_with_all_properties.json index 3384808676b..58ab0611f4c 100644 --- a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_with_all_properties.json +++ b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_with_all_properties.json @@ -8,6 +8,10 @@ "showPermissions": true, "showHistory": true, "showUpdateKey": true, + "showBackgroundTasks": true, + "canApplyPermissionTemplate": false, + "canBrowseProject": true, + "canUpdateProjectVisibilityToPrivate": false, "extensions": [] } } |