diff options
author | ssjenka <ssjenka@ops-slave-centos7-1.internal.sonarsource.com> | 2017-02-21 08:01:49 +0100 |
---|---|---|
committer | ssjenka <ssjenka@ops-slave-centos7-1.internal.sonarsource.com> | 2017-02-21 08:01:49 +0100 |
commit | 7ce73daef17c282256aebc4513bbf5718e0b351d (patch) | |
tree | 2a96f079c1ceab0d3ece1f429c28f0386052d4a8 | |
parent | 6c8d575311a638cd6ca565feff991db0f8c86bdb (diff) | |
parent | 5f09ded3a60950b1db7714f70f66850216acbff9 (diff) | |
download | sonarqube-7ce73daef17c282256aebc4513bbf5718e0b351d.tar.gz sonarqube-7ce73daef17c282256aebc4513bbf5718e0b351d.zip |
Automatic merge from branch-6.3
* origin/branch-6.3:
SONAR-8658 display "Apply Template" button for org admin
SONAR-8658 add field configuration.canApplyPermissionTemplate to response of api/navigation/component
change wording in organization form
return `isDefault` in /api/navigation/organization
SONAR-8658 fix applying of permission template
fix ui glitch on settings page on safari
8 files changed, 54 insertions, 21 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java index fa72601e834..dd8839b82d5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java @@ -61,6 +61,7 @@ import static org.sonar.api.web.UserRole.ADMIN; import static org.sonar.api.web.UserRole.USER; import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN; import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN; +import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; @@ -211,12 +212,12 @@ public class ComponentAction implements NavigationWsAction { } private void writeConfiguration(JsonWriter json, ComponentDto component) { - boolean isAdmin = userSession.hasComponentPermission(ADMIN, component); + boolean isProjectAdmin = userSession.hasComponentPermission(ADMIN, component); json.name("configuration").beginObject(); - writeConfigPageAccess(json, isAdmin, component); + writeConfigPageAccess(json, isProjectAdmin, component); - if (isAdmin) { + if (isProjectAdmin) { json.name("extensions").beginArray(); List<Page> configPages = pageRepository.getComponentPages(true, component.qualifier()); configPages.forEach(page -> writePage(json, page)); @@ -225,21 +226,23 @@ public class ComponentAction implements NavigationWsAction { json.endObject(); } - private void writeConfigPageAccess(JsonWriter json, boolean isAdmin, ComponentDto component) { + private void writeConfigPageAccess(JsonWriter json, boolean isProjectAdmin, ComponentDto component) { boolean isProject = Qualifiers.PROJECT.equals(component.qualifier()); - boolean showManualMeasures = isAdmin && !Qualifiers.DIRECTORY.equals(component.qualifier()); + boolean showManualMeasures = isProjectAdmin && !Qualifiers.DIRECTORY.equals(component.qualifier()); boolean isQualityProfileAdmin = userSession.hasOrganizationPermission(component.getOrganizationUuid(), QUALITY_PROFILE_ADMIN); boolean isQualityGateAdmin = userSession.hasOrganizationPermission(component.getOrganizationUuid(), QUALITY_GATE_ADMIN); + boolean isOrganizationAdmin = userSession.hasOrganizationPermission(component.getOrganizationUuid(), SYSTEM_ADMIN); - json.prop("showSettings", isAdmin && componentTypeHasProperty(component, PROPERTY_CONFIGURABLE)); - json.prop("showQualityProfiles", isProject && (isAdmin || isQualityProfileAdmin)); - json.prop("showQualityGates", isProject && (isAdmin || isQualityGateAdmin)); + json.prop("showSettings", isProjectAdmin && componentTypeHasProperty(component, PROPERTY_CONFIGURABLE)); + json.prop("showQualityProfiles", isProject && (isProjectAdmin || isQualityProfileAdmin)); + json.prop("showQualityGates", isProject && (isProjectAdmin || isQualityGateAdmin)); json.prop("showManualMeasures", showManualMeasures); - json.prop("showLinks", isAdmin && isProject); - json.prop("showPermissions", isAdmin && componentTypeHasProperty(component, PROPERTY_HAS_ROLE_POLICY)); - json.prop("showHistory", isAdmin && componentTypeHasProperty(component, PROPERTY_MODIFIABLE_HISTORY)); - json.prop("showUpdateKey", isAdmin && componentTypeHasProperty(component, PROPERTY_UPDATABLE_KEY)); - json.prop("showBackgroundTasks", isAdmin); + json.prop("showLinks", isProjectAdmin && isProject); + json.prop("showPermissions", isProjectAdmin && componentTypeHasProperty(component, PROPERTY_HAS_ROLE_POLICY)); + json.prop("showHistory", isProjectAdmin && componentTypeHasProperty(component, PROPERTY_MODIFIABLE_HISTORY)); + json.prop("showUpdateKey", isProjectAdmin && componentTypeHasProperty(component, PROPERTY_UPDATABLE_KEY)); + json.prop("showBackgroundTasks", isProjectAdmin); + json.prop("canApplyPermissionTemplate", isOrganizationAdmin); } private boolean componentTypeHasProperty(ComponentDto component, String resourceTypeProperty) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/OrganizationAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/OrganizationAction.java index 47cc9146e5c..2b66b7b9eb3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/OrganizationAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/OrganizationAction.java @@ -27,6 +27,7 @@ import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; +import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.user.UserSession; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; @@ -38,10 +39,12 @@ public class OrganizationAction implements NavigationWsAction { private static final String PARAM_ORGANIZATION = "organization"; private final DbClient dbClient; + private final DefaultOrganizationProvider defaultOrganizationProvider; private final UserSession userSession; - public OrganizationAction(DbClient dbClient, UserSession userSession) { + public OrganizationAction(DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider, UserSession userSession) { this.dbClient = dbClient; + this.defaultOrganizationProvider = defaultOrganizationProvider; this.userSession = userSession; } @@ -83,6 +86,7 @@ public class OrganizationAction implements NavigationWsAction { .prop("canAdmin", userSession.hasOrganizationPermission(organizationUuid, SYSTEM_ADMIN)) .prop("canProvisionProjects", userSession.hasOrganizationPermission(organizationUuid, GlobalPermissions.PROVISIONING)) .prop("canDelete", organization.isGuarded() ? userSession.isSystemAdministrator() : userSession.hasOrganizationPermission(organizationUuid, SYSTEM_ADMIN)) + .prop("isDefault", organization.getKey().equals(defaultOrganizationProvider.get().getKey())) .endObject(); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java index 38baa6485f7..0a293bc8974 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java @@ -35,6 +35,7 @@ import org.sonar.api.web.page.Page; import org.sonar.api.web.page.Page.Qualifier; import org.sonar.api.web.page.PageDefinition; import org.sonar.core.component.DefaultResourceTypes; +import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.platform.PluginRepository; import org.sonar.db.DbClient; import org.sonar.db.DbTester; @@ -380,6 +381,23 @@ public class ComponentActionTest { assertJson(result).ignoreFields("snapshotDate", "key", "qualityGate.key").isSimilarTo(ws.getDef().responseExampleAsString()); } + @Test + public void canApplyPermissionTemplate_is_true_if_logged_in_as_organization_administrator() { + init(createPages()); + OrganizationDto org = dbTester.organizations().insert(); + ComponentDto project = dbTester.components().insertProject(org); + + userSessionRule.logIn() + .addProjectUuidPermissions(UserRole.ADMIN, project.uuid()) + .addOrganizationPermission(org.getUuid(), GlobalPermissions.SYSTEM_ADMIN); + assertJson(execute(project.key())).isSimilarTo("{\"configuration\": {\"canApplyPermissionTemplate\": true}}"); + + userSessionRule.logIn() + .addProjectUuidPermissions(UserRole.ADMIN, project.uuid()); + + assertJson(execute(project.key())).isSimilarTo("{\"configuration\": {\"canApplyPermissionTemplate\": false}}"); + } + private void init(Page... pages) { PluginRepository pluginRepository = mock(PluginRepository.class); when(pluginRepository.hasPlugin(anyString())).thenReturn(true); diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/OrganizationActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/OrganizationActionTest.java index 47193174de5..46174db1ace 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/OrganizationActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/OrganizationActionTest.java @@ -28,6 +28,8 @@ import org.sonar.api.utils.System2; import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.organization.OrganizationDto; +import org.sonar.server.organization.DefaultOrganizationProvider; +import org.sonar.server.organization.TestDefaultOrganizationProvider; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.TestResponse; @@ -46,8 +48,9 @@ public class OrganizationActionTest { public ExpectedException expectedException = ExpectedException.none(); private DbClient dbClient = dbTester.getDbClient(); + private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester); - private WsActionTester underTest = new WsActionTester(new OrganizationAction(dbClient, userSession)); + private WsActionTester underTest = new WsActionTester(new OrganizationAction(dbClient, defaultOrganizationProvider, userSession)); @Test public void verify_definition() { diff --git a/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js b/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js index d85e3413036..9a0c10de08c 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js @@ -136,6 +136,7 @@ class CreateOrganizationForm extends React.Component { name="name" required={true} type="text" + minLength="2" maxLength="64" value={this.state.name} disabled={this.state.loading} @@ -151,6 +152,7 @@ class CreateOrganizationForm extends React.Component { <input id="organization-key" name="key" type="text" + minLength="2" maxLength="64" value={this.state.key} disabled={this.state.loading} diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js b/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js index 77f48eb680c..bc97d1c6ddf 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js @@ -23,7 +23,6 @@ import { translate } from '../../../../helpers/l10n'; import ApplyTemplateView from '../views/ApplyTemplateView'; import { loadHolders } from '../store/actions'; import { isPermissionsAppLoading } from '../../../../store/rootReducer'; -import { isUserAdmin } from '../../../../helpers/users'; class PageHeader extends React.Component { static propTypes = { @@ -44,12 +43,16 @@ class PageHeader extends React.Component { e.preventDefault(); e.target.blur(); const { project, loadHolders } = this.props; - new ApplyTemplateView({ project }) + const organization = project.organization ? { key: project.organization } : null; + new ApplyTemplateView({ project, organization }) .on('done', () => loadHolders(project.key)) .render(); } render () { + const configuration = this.props.project.configuration; + const canApplyPermissionTemplate = configuration != null && configuration.canApplyPermissionTemplate; + return ( <header className="page-header"> <h1 className="page-title"> @@ -60,7 +63,7 @@ class PageHeader extends React.Component { <i className="spinner"/> )} - {isUserAdmin(this.props.currentUser) && ( + {canApplyPermissionTemplate && ( <div className="page-actions"> <button className="js-apply-template" onClick={this.handleApplyTemplate}> Apply Template diff --git a/server/sonar-web/src/main/js/apps/settings/styles.css b/server/sonar-web/src/main/js/apps/settings/styles.css index 230724470cc..4a2926f69db 100644 --- a/server/sonar-web/src/main/js/apps/settings/styles.css +++ b/server/sonar-web/src/main/js/apps/settings/styles.css @@ -115,7 +115,7 @@ right: 0; height: 30px; display: block; - background: linear-gradient(to bottom, transparent, #fff); + background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgb(255, 255, 255)); content: ""; } diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 56479a79be1..108206c6bce 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2773,7 +2773,7 @@ organization.delete.description=Delete this organization from SonarQube. All pro organization.delete.question=Are you sure you want to delete this organization? organization.deleted=Organization has been deleted. organization.description=Description -organization.description.description=Description of the organization (256 characters max). +organization.description.description=Description of the organization. organization.edit=Edit Organization organization.key=Key organization.key.description=Key of the organization (2 to 32 characters). All chars must be lower-case letters (a to z), digits or dash (but dash can neither be trailing nor heading). When not specified, the key is computed from the name. @@ -2781,4 +2781,4 @@ organization.name=Name organization.name.description=Name of the organization (2 to 64 characters). organization.updated=Organization details have been updated. organization.url=Url -organization.url.description=Url of the homepage of the organization (256 characters max). +organization.url.description=Url of the homepage of the organization. |