Skip to content

Commit

Permalink
SONAR-8857 make api/qualityprofiles/de|activate_rules organization aware
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Schwarz authored and bartfastiel committed Mar 23, 2017
1 parent ca9c09d commit bc02e17
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 67 deletions.
Expand Up @@ -30,9 +30,6 @@
import org.sonar.core.util.Uuids; import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient; import org.sonar.db.DbClient;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.qualityprofile.ActiveRuleChange; import org.sonar.server.qualityprofile.ActiveRuleChange;
import org.sonar.server.qualityprofile.RuleActivation; import org.sonar.server.qualityprofile.RuleActivation;
import org.sonar.server.qualityprofile.RuleActivator; import org.sonar.server.qualityprofile.RuleActivator;
Expand Down Expand Up @@ -108,7 +105,7 @@ public void handle(Request request, Response response) throws Exception {
String profileKey = request.mandatoryParam(PARAM_PROFILE_KEY); String profileKey = request.mandatoryParam(PARAM_PROFILE_KEY);
userSession.checkLoggedIn(); userSession.checkLoggedIn();
try (DbSession dbSession = dbClient.openSession(false)) { try (DbSession dbSession = dbClient.openSession(false)) {
checkPermission(dbSession, profileKey); wsSupport.checkPermission(dbSession, profileKey);
List<ActiveRuleChange> changes = ruleActivator.activate(dbSession, activation, profileKey); List<ActiveRuleChange> changes = ruleActivator.activate(dbSession, activation, profileKey);
dbSession.commit(); dbSession.commit();
activeRuleIndexer.index(changes); activeRuleIndexer.index(changes);
Expand All @@ -118,10 +115,4 @@ public void handle(Request request, Response response) throws Exception {
private static RuleKey readRuleKey(Request request) { private static RuleKey readRuleKey(Request request) {
return RuleKey.parse(request.mandatoryParam(PARAM_RULE_KEY)); return RuleKey.parse(request.mandatoryParam(PARAM_RULE_KEY));
} }

private void checkPermission(DbSession dbSession, String qualityProfileKey) {
QualityProfileDto qualityProfile = dbClient.qualityProfileDao().selectByKey(dbSession, qualityProfileKey);
OrganizationDto organization = wsSupport.getOrganization(dbSession, qualityProfile);
userSession.checkPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
}
} }
Expand Up @@ -24,13 +24,13 @@
import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService;
import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.server.qualityprofile.BulkChangeResult; import org.sonar.server.qualityprofile.BulkChangeResult;
import org.sonar.server.qualityprofile.RuleActivator; import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.rule.ws.RuleQueryFactory; import org.sonar.server.rule.ws.RuleQueryFactory;
import org.sonar.server.user.UserSession; import org.sonar.server.user.UserSession;


import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters; import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;


@ServerSide @ServerSide
Expand All @@ -39,24 +39,25 @@ public class ActivateRulesAction implements QProfileWsAction {
public static final String PROFILE_KEY = "profile_key"; public static final String PROFILE_KEY = "profile_key";
public static final String SEVERITY = "activation_severity"; public static final String SEVERITY = "activation_severity";


public static final String BULK_ACTIVATE_ACTION = "activate_rules"; public static final String ACTIVATE_RULES_ACTION = "activate_rules";


private final RuleQueryFactory ruleQueryFactory; private final RuleQueryFactory ruleQueryFactory;
private final UserSession userSession; private final UserSession userSession;
private final DefaultOrganizationProvider defaultOrganizationProvider;
private final RuleActivator ruleActivator; private final RuleActivator ruleActivator;
private final DbClient dbClient;
private final QProfileWsSupport wsSupport;


public ActivateRulesAction(RuleQueryFactory ruleQueryFactory, UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider, public ActivateRulesAction(RuleQueryFactory ruleQueryFactory, UserSession userSession, RuleActivator ruleActivator, QProfileWsSupport wsSupport, DbClient dbClient) {
RuleActivator ruleActivator) {
this.ruleQueryFactory = ruleQueryFactory; this.ruleQueryFactory = ruleQueryFactory;
this.userSession = userSession; this.userSession = userSession;
this.defaultOrganizationProvider = defaultOrganizationProvider;
this.ruleActivator = ruleActivator; this.ruleActivator = ruleActivator;
this.dbClient = dbClient;
this.wsSupport = wsSupport;
} }


public void define(WebService.NewController controller) { public void define(WebService.NewController controller) {
WebService.NewAction activate = controller WebService.NewAction activate = controller
.createAction(BULK_ACTIVATE_ACTION) .createAction(ACTIVATE_RULES_ACTION)
.setDescription("Bulk-activate rules on one or several Quality profiles") .setDescription("Bulk-activate rules on one or several Quality profiles")
.setPost(true) .setPost(true)
.setSince("4.4") .setSince("4.4")
Expand All @@ -76,15 +77,12 @@ public void define(WebService.NewController controller) {


@Override @Override
public void handle(Request request, Response response) throws Exception { public void handle(Request request, Response response) throws Exception {
verifyAdminPermission(); String qualityProfileKey = request.mandatoryParam(PROFILE_KEY);
BulkChangeResult result = ruleActivator.bulkActivate(ruleQueryFactory.createRuleQuery(request), request.mandatoryParam(PROFILE_KEY), request.param(SEVERITY)); userSession.checkLoggedIn();
try (DbSession dbSession = dbClient.openSession(false)) {
wsSupport.checkPermission(dbSession, qualityProfileKey);
}
BulkChangeResult result = ruleActivator.bulkActivate(ruleQueryFactory.createRuleQuery(request), qualityProfileKey, request.param(SEVERITY));
BulkChangeWsResponse.writeResponse(result, response); BulkChangeWsResponse.writeResponse(result, response);
} }

private void verifyAdminPermission() {
// FIXME check for the permission of the appropriate organization, not the default one
userSession
.checkLoggedIn()
.checkPermission(ADMINISTER_QUALITY_PROFILES, defaultOrganizationProvider.get().getUuid());
}
} }
Expand Up @@ -26,6 +26,10 @@


class BulkChangeWsResponse { class BulkChangeWsResponse {


private BulkChangeWsResponse() {
// use static methods
}

static void writeResponse(BulkChangeResult result, Response response) { static void writeResponse(BulkChangeResult result, Response response) {
JsonWriter json = response.newJsonWriter().beginObject(); JsonWriter json = response.newJsonWriter().beginObject();
json.prop("succeeded", result.countSucceeded()); json.prop("succeeded", result.countSucceeded());
Expand Down
Expand Up @@ -27,10 +27,7 @@
import org.sonar.core.util.Uuids; import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient; import org.sonar.db.DbClient;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.qualityprofile.ActiveRuleKey; import org.sonar.db.qualityprofile.ActiveRuleKey;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.qualityprofile.RuleActivator; import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.user.UserSession; import org.sonar.server.user.UserSession;


Expand Down Expand Up @@ -78,15 +75,9 @@ public void handle(Request request, Response response) throws Exception {
String qualityProfileKey = request.mandatoryParam(PARAM_PROFILE_KEY); String qualityProfileKey = request.mandatoryParam(PARAM_PROFILE_KEY);
userSession.checkLoggedIn(); userSession.checkLoggedIn();
try (DbSession dbSession = dbClient.openSession(false)) { try (DbSession dbSession = dbClient.openSession(false)) {
checkPermission(dbSession, qualityProfileKey); wsSupport.checkPermission(dbSession, qualityProfileKey);
ActiveRuleKey activeRuleKey = ActiveRuleKey.of(qualityProfileKey, ruleKey); ActiveRuleKey activeRuleKey = ActiveRuleKey.of(qualityProfileKey, ruleKey);
ruleActivator.deactivateAndUpdateIndex(dbSession, activeRuleKey); ruleActivator.deactivateAndUpdateIndex(dbSession, activeRuleKey);
} }
} }

private void checkPermission(DbSession dbSession, String qualityProfileKey) {
QualityProfileDto qualityProfile = dbClient.qualityProfileDao().selectByKey(dbSession, qualityProfileKey);
OrganizationDto organization = wsSupport.getOrganization(dbSession, qualityProfile);
userSession.checkPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
}
} }
Expand Up @@ -23,13 +23,13 @@
import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService;
import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.server.qualityprofile.BulkChangeResult; import org.sonar.server.qualityprofile.BulkChangeResult;
import org.sonar.server.qualityprofile.RuleActivator; import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.rule.ws.RuleQueryFactory; import org.sonar.server.rule.ws.RuleQueryFactory;
import org.sonar.server.user.UserSession; import org.sonar.server.user.UserSession;


import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters; import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;


@ServerSide @ServerSide
Expand All @@ -38,24 +38,25 @@ public class DeactivateRulesAction implements QProfileWsAction {
public static final String PROFILE_KEY = "profile_key"; public static final String PROFILE_KEY = "profile_key";
public static final String SEVERITY = "activation_severity"; public static final String SEVERITY = "activation_severity";


public static final String BULK_DEACTIVATE_ACTION = "deactivate_rules"; public static final String DEACTIVATE_RULES_ACTION = "deactivate_rules";


private final RuleQueryFactory ruleQueryFactory; private final RuleQueryFactory ruleQueryFactory;
private final UserSession userSession; private final UserSession userSession;
private final DefaultOrganizationProvider defaultOrganizationProvider;
private final RuleActivator ruleActivator; private final RuleActivator ruleActivator;
private final QProfileWsSupport wsSupport;
private final DbClient dbClient;


public DeactivateRulesAction(RuleQueryFactory ruleQueryFactory, UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider, public DeactivateRulesAction(RuleQueryFactory ruleQueryFactory, UserSession userSession, RuleActivator ruleActivator, QProfileWsSupport wsSupport, DbClient dbClient) {
RuleActivator ruleActivator) {
this.ruleQueryFactory = ruleQueryFactory; this.ruleQueryFactory = ruleQueryFactory;
this.userSession = userSession; this.userSession = userSession;
this.defaultOrganizationProvider = defaultOrganizationProvider;
this.ruleActivator = ruleActivator; this.ruleActivator = ruleActivator;
this.wsSupport = wsSupport;
this.dbClient = dbClient;
} }


public void define(WebService.NewController controller) { public void define(WebService.NewController controller) {
WebService.NewAction deactivate = controller WebService.NewAction deactivate = controller
.createAction(BULK_DEACTIVATE_ACTION) .createAction(DEACTIVATE_RULES_ACTION)
.setDescription("Bulk deactivate rules on Quality profiles") .setDescription("Bulk deactivate rules on Quality profiles")
.setPost(true) .setPost(true)
.setSince("4.4") .setSince("4.4")
Expand All @@ -71,15 +72,12 @@ public void define(WebService.NewController controller) {


@Override @Override
public void handle(Request request, Response response) throws Exception { public void handle(Request request, Response response) throws Exception {
verifyAdminPermission(); String qualityProfileKey = request.mandatoryParam(PROFILE_KEY);
BulkChangeResult result = ruleActivator.bulkDeactivate(ruleQueryFactory.createRuleQuery(request), request.mandatoryParam(PROFILE_KEY)); userSession.checkLoggedIn();
try (DbSession dbSession = dbClient.openSession(false)) {
wsSupport.checkPermission(dbSession, qualityProfileKey);
}
BulkChangeResult result = ruleActivator.bulkDeactivate(ruleQueryFactory.createRuleQuery(request), qualityProfileKey);
BulkChangeWsResponse.writeResponse(result, response); BulkChangeWsResponse.writeResponse(result, response);
} }

private void verifyAdminPermission() {
// FIXME check for the permission of the appropriate organization, not the default one
userSession
.checkLoggedIn()
.checkPermission(ADMINISTER_QUALITY_PROFILES, defaultOrganizationProvider.get().getUuid());
}
} }
Expand Up @@ -27,6 +27,7 @@
import org.sonar.db.DbClient; import org.sonar.db.DbClient;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
import org.sonar.db.organization.OrganizationDto; import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.UserSession; import org.sonar.server.user.UserSession;
Expand Down Expand Up @@ -119,4 +120,10 @@ public QualityProfileDto getProfile(DbSession dbSession, QProfileReference ref)
} }
return profile; return profile;
} }

public void checkPermission(DbSession dbSession, String qualityProfileKey) {
QualityProfileDto qualityProfile = dbClient.qualityProfileDao().selectByKey(dbSession, qualityProfileKey);
OrganizationDto organization = getOrganization(dbSession, qualityProfile);
userSession.checkPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
}
} }
Expand Up @@ -19,19 +19,29 @@
*/ */
package org.sonar.server.qualityprofile.ws; package org.sonar.server.qualityprofile.ws;


import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbClient; import org.sonar.db.DbClient;
import org.sonar.db.DbTester; import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.organization.TestDefaultOrganizationProvider; import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.qualityprofile.RuleActivator; import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.rule.ws.RuleQueryFactory;
import org.sonar.server.tester.UserSessionRule; import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester; import org.sonar.server.ws.WsActionTester;


import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;


public class ActivateRulesActionTest { public class ActivateRulesActionTest {


Expand All @@ -44,8 +54,18 @@ public class ActivateRulesActionTest {


private DbClient dbClient = dbTester.getDbClient(); private DbClient dbClient = dbTester.getDbClient();
private RuleActivator ruleActivator = mock(RuleActivator.class); private RuleActivator ruleActivator = mock(RuleActivator.class);
private ActivateRulesAction underTest = new ActivateRulesAction(null, null, TestDefaultOrganizationProvider.from(dbTester), ruleActivator); private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(dbTester));
private RuleQueryFactory ruleQueryFactory = mock(RuleQueryFactory.class);
private ActivateRulesAction underTest = new ActivateRulesAction(ruleQueryFactory, userSession, ruleActivator, wsSupport, dbClient);
private WsActionTester wsActionTester = new WsActionTester(underTest); private WsActionTester wsActionTester = new WsActionTester(underTest);
private OrganizationDto defaultOrganization;
private OrganizationDto organization;

@Before
public void before() {
defaultOrganization = dbTester.getDefaultOrganization();
organization = dbTester.organizations().insert();
}


@Test @Test
public void define_bulk_activate_rule_action() { public void define_bulk_activate_rule_action() {
Expand Down Expand Up @@ -74,4 +94,26 @@ public void define_bulk_activate_rule_action() {
"severities" "severities"
); );
} }
}
@Test
public void should_fail_if_not_logged_in() {
TestRequest request = wsActionTester.newRequest()
.setMethod("POST")
.setParam("profile_key", randomAlphanumeric(UUID_SIZE));

thrown.expect(UnauthorizedException.class);
request.execute();
}

@Test
public void should_fail_if_not_organization_quality_profile_administrator() {
userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, defaultOrganization);
QualityProfileDto qualityProfile = dbTester.qualityProfiles().insert(organization);
TestRequest request = wsActionTester.newRequest()
.setMethod("POST")
.setParam("profile_key", qualityProfile.getKey());

thrown.expect(ForbiddenException.class);
request.execute();
}
}
Expand Up @@ -19,19 +19,29 @@
*/ */
package org.sonar.server.qualityprofile.ws; package org.sonar.server.qualityprofile.ws;


import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbClient; import org.sonar.db.DbClient;
import org.sonar.db.DbTester; import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.qualityprofile.QualityProfileDto;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.organization.TestDefaultOrganizationProvider; import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.qualityprofile.RuleActivator; import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.rule.ws.RuleQueryFactory;
import org.sonar.server.tester.UserSessionRule; import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester; import org.sonar.server.ws.WsActionTester;


import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;


public class DeactivateRulesActionTest { public class DeactivateRulesActionTest {


Expand All @@ -44,8 +54,18 @@ public class DeactivateRulesActionTest {


private DbClient dbClient = dbTester.getDbClient(); private DbClient dbClient = dbTester.getDbClient();
private RuleActivator ruleActivator = mock(RuleActivator.class); private RuleActivator ruleActivator = mock(RuleActivator.class);
private DeactivateRulesAction underTest = new DeactivateRulesAction(null, null, TestDefaultOrganizationProvider.from(dbTester), ruleActivator); private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(dbTester));
private RuleQueryFactory ruleQueryFactory = mock(RuleQueryFactory.class);
private DeactivateRulesAction underTest = new DeactivateRulesAction(ruleQueryFactory, userSession, ruleActivator, wsSupport, dbClient);
private WsActionTester wsActionTester = new WsActionTester(underTest); private WsActionTester wsActionTester = new WsActionTester(underTest);
private OrganizationDto defaultOrganization;
private OrganizationDto organization;

@Before
public void before() {
defaultOrganization = dbTester.getDefaultOrganization();
organization = dbTester.organizations().insert();
}


@Test @Test
public void define_bulk_deactivate_rule_action() { public void define_bulk_deactivate_rule_action() {
Expand Down Expand Up @@ -73,4 +93,26 @@ public void define_bulk_deactivate_rule_action() {
"severities" "severities"
); );
} }
}
@Test
public void should_fail_if_not_logged_in() {
TestRequest request = wsActionTester.newRequest()
.setMethod("POST")
.setParam("profile_key", randomAlphanumeric(UUID_SIZE));

thrown.expect(UnauthorizedException.class);
request.execute();
}

@Test
public void should_fail_if_not_organization_quality_profile_administrator() {
userSession.logIn().addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, defaultOrganization);
QualityProfileDto qualityProfile = dbTester.qualityProfiles().insert(organization);
TestRequest request = wsActionTester.newRequest()
.setMethod("POST")
.setParam("profile_key", qualityProfile.getKey());

thrown.expect(ForbiddenException.class);
request.execute();
}
}

0 comments on commit bc02e17

Please sign in to comment.