@@ -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); | |||
} | |||
@@ -152,6 +152,7 @@ declare namespace T { | |||
interface ComponentConfiguration { | |||
canApplyPermissionTemplate?: boolean; | |||
canBrowseProject?: boolean; | |||
canUpdateProjectVisibilityToPrivate?: boolean; | |||
extensions?: Extension[]; | |||
showBackgroundTasks?: boolean; |
@@ -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 }); | |||
} | |||
}, |
@@ -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 | |||
} | |||
}); |
@@ -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()))); | |||
} |
@@ -44,6 +44,7 @@ | |||
"showHistory": true, | |||
"showUpdateKey": true, | |||
"showBackgroundTasks": true, | |||
"canBrowseProject": true, | |||
"extensions": [ | |||
{ | |||
"key": "my_plugin/admin_page", |
@@ -408,6 +408,49 @@ public class ComponentActionTest { | |||
executeAndVerify(project.getDbKey(), "return_configuration_for_quality_gate_admin.json"); | |||
} | |||
@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(); | |||
@@ -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); |
@@ -8,6 +8,10 @@ | |||
"showPermissions": true, | |||
"showHistory": true, | |||
"showUpdateKey": true, | |||
"showBackgroundTasks": true, | |||
"canApplyPermissionTemplate": false, | |||
"canBrowseProject": true, | |||
"canUpdateProjectVisibilityToPrivate": false, | |||
"extensions": [] | |||
} | |||
} |