Skip to content

Commit

Permalink
SONAR-8919 Set default assignee within members of the project's organ…
Browse files Browse the repository at this point in the history
…ization
  • Loading branch information
julienlancelot committed Mar 21, 2017
1 parent 55fa19b commit fb65076
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 43 deletions.
Expand Up @@ -23,10 +23,12 @@
import javax.annotation.CheckForNull; import javax.annotation.CheckForNull;
import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Loggers;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.user.UserDto;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.component.SettingsRepository; import org.sonar.server.computation.task.projectanalysis.component.SettingsRepository;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder; import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
import org.sonar.server.user.index.UserDoc;
import org.sonar.server.user.index.UserIndex;


import static org.sonar.api.CoreProperties.DEFAULT_ISSUE_ASSIGNEE; import static org.sonar.api.CoreProperties.DEFAULT_ISSUE_ASSIGNEE;


Expand All @@ -38,37 +40,50 @@ public class DefaultAssignee {


private static final Logger LOG = Loggers.get(DefaultAssignee.class); private static final Logger LOG = Loggers.get(DefaultAssignee.class);


private final DbClient dbClient;
private final TreeRootHolder treeRootHolder; private final TreeRootHolder treeRootHolder;
private final UserIndex userIndex;
private final SettingsRepository settingsRepository; private final SettingsRepository settingsRepository;
private final AnalysisMetadataHolder analysisMetadataHolder;


private boolean loaded = false; private boolean loaded = false;
private String login = null; private String login = null;


public DefaultAssignee(TreeRootHolder treeRootHolder, UserIndex userIndex, SettingsRepository settingsRepository) { public DefaultAssignee(DbClient dbClient, TreeRootHolder treeRootHolder, SettingsRepository settingsRepository, AnalysisMetadataHolder analysisMetadataHolder) {
this.dbClient = dbClient;
this.treeRootHolder = treeRootHolder; this.treeRootHolder = treeRootHolder;
this.userIndex = userIndex;
this.settingsRepository = settingsRepository; this.settingsRepository = settingsRepository;
this.analysisMetadataHolder = analysisMetadataHolder;
} }


@CheckForNull @CheckForNull
public String getLogin() { public String loadDefaultAssigneeLogin() {
if (!loaded) { if (loaded) {
String configuredLogin = settingsRepository.getSettings(treeRootHolder.getRoot()).getString(DEFAULT_ISSUE_ASSIGNEE); return login;
if (!Strings.isNullOrEmpty(configuredLogin) && isValidLogin(configuredLogin)) { }
this.login = configuredLogin; String configuredLogin = settingsRepository.getSettings(treeRootHolder.getRoot()).getString(DEFAULT_ISSUE_ASSIGNEE);
} if (!Strings.isNullOrEmpty(configuredLogin) && isValidLogin(configuredLogin)) {
loaded = true; this.login = configuredLogin;
} }
loaded = true;
return login; return login;
} }


private boolean isValidLogin(String s) { private boolean isValidLogin(String login) {
UserDoc user = userIndex.getNullableByLogin(s); try (DbSession dbSession = dbClient.openSession(false)) {
if (user == null || !user.active()) { UserDto user = dbClient.userDao().selectActiveUserByLogin(dbSession, login);
LOG.info("Property {} is set with an unknown login: {}", DEFAULT_ISSUE_ASSIGNEE, s); if (user == null) {
return false; LOG.info("Property {} is set with an unknown login: {}", DEFAULT_ISSUE_ASSIGNEE, login);
return false;
}
if (!isUserMemberOfOrganization(dbSession, user)) {
LOG.info("Property {} is set with a user which is not member of the organization of the project : {}", DEFAULT_ISSUE_ASSIGNEE, login);
return false;
}
return true;
} }
return true; }

private boolean isUserMemberOfOrganization(DbSession dbSession, UserDto user) {
return dbClient.organizationMemberDao().select(dbSession, analysisMetadataHolder.getOrganization().getUuid(), user.getId()).isPresent();
} }
} }
Expand Up @@ -80,7 +80,7 @@ public void onIssue(Component component, DefaultIssue issue) {
} }
} }
if (authorWasSet && issue.assignee() == null) { if (authorWasSet && issue.assignee() == null) {
String assigneeLogin = StringUtils.defaultIfEmpty(scmAccountToUser.getNullable(issue.authorLogin()), defaultAssignee.getLogin()); String assigneeLogin = StringUtils.defaultIfEmpty(scmAccountToUser.getNullable(issue.authorLogin()), defaultAssignee.loadDefaultAssigneeLogin());
issueUpdater.setNewAssignee(issue, assigneeLogin, changeContext); issueUpdater.setNewAssignee(issue, assigneeLogin, changeContext);
} }
} }
Expand Down
Expand Up @@ -20,64 +20,95 @@
package org.sonar.server.computation.task.projectanalysis.issue; package org.sonar.server.computation.task.projectanalysis.issue;


import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito;
import org.sonar.api.CoreProperties; import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.config.MapSettings; import org.sonar.api.config.MapSettings;
import org.sonar.server.computation.task.projectanalysis.component.Component; import org.sonar.api.config.Settings;
import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderImpl;
import org.sonar.server.computation.task.projectanalysis.analysis.Organization;
import org.sonar.server.computation.task.projectanalysis.component.SettingsRepository; import org.sonar.server.computation.task.projectanalysis.component.SettingsRepository;
import org.sonar.server.computation.task.projectanalysis.component.TestSettingsRepository;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule; import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.user.index.UserDoc;
import org.sonar.server.user.index.UserIndex;


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.sonar.server.computation.task.projectanalysis.component.ReportComponent.DUMB_PROJECT;
import static org.mockito.Mockito.when;


public class DefaultAssigneeTest { public class DefaultAssigneeTest {


public static final String PROJECT_KEY = "PROJECT_KEY"; public static final String PROJECT_KEY = "PROJECT_KEY";
public static final String ORGANIZATION_UUID = "ORGANIZATION_UUID";

@Rule
public DbTester db = DbTester.create();

@Rule
public TreeRootHolderRule rootHolder = new TreeRootHolderRule().setRoot(DUMB_PROJECT);


TreeRootHolderRule rootHolder = mock(TreeRootHolderRule.class, Mockito.RETURNS_DEEP_STUBS); private Settings settings = new MapSettings();
UserIndex userIndex = mock(UserIndex.class); private SettingsRepository settingsRepository = new TestSettingsRepository(settings);
Settings settings = new MapSettings(); private AnalysisMetadataHolderImpl analysisMetadataHolder = new AnalysisMetadataHolderImpl();
SettingsRepository settingsRepository = mock(SettingsRepository.class); private OrganizationDto organizationDto;


DefaultAssignee underTest = new DefaultAssignee(rootHolder, userIndex, settingsRepository); private DefaultAssignee underTest = new DefaultAssignee(db.getDbClient(), rootHolder, settingsRepository, analysisMetadataHolder);


@Before @Before
public void before() { public void setUp() throws Exception {
when(rootHolder.getRoot()).thenReturn(mock(Component.class)); organizationDto = db.organizations().insertForUuid(ORGANIZATION_UUID);
when(settingsRepository.getSettings(rootHolder.getRoot())).thenReturn(settings); analysisMetadataHolder.setOrganization(Organization.from(new OrganizationDto().setUuid(ORGANIZATION_UUID).setKey("Organization key").setName("Organization name")));
} }


@Test @Test
public void no_default_assignee() { public void no_default_assignee() {
assertThat(underTest.getLogin()).isNull(); assertThat(underTest.loadDefaultAssigneeLogin()).isNull();
} }


@Test @Test
public void default_assignee() { public void set_default_assignee() {
settings.setProperty(CoreProperties.DEFAULT_ISSUE_ASSIGNEE, "erik"); settings.setProperty(CoreProperties.DEFAULT_ISSUE_ASSIGNEE, "erik");
when(userIndex.getNullableByLogin("erik")).thenReturn(new UserDoc().setLogin("erik").setActive(true)); UserDto userDto = db.users().insertUser("erik");
db.organizations().addMember(organizationDto, userDto);


assertThat(underTest.getLogin()).isEqualTo("erik"); assertThat(underTest.loadDefaultAssigneeLogin()).isEqualTo("erik");
} }


@Test @Test
public void configured_login_does_not_exist() { public void configured_login_does_not_exist() {
settings.setProperty(CoreProperties.DEFAULT_ISSUE_ASSIGNEE, "erik"); settings.setProperty(CoreProperties.DEFAULT_ISSUE_ASSIGNEE, "erik");
when(userIndex.getNullableByLogin("erik")).thenReturn(null);


assertThat(underTest.getLogin()).isNull(); assertThat(underTest.loadDefaultAssigneeLogin()).isNull();
} }


@Test @Test
public void configured_login_is_disabled() { public void configured_login_is_disabled() {
settings.setProperty(CoreProperties.DEFAULT_ISSUE_ASSIGNEE, "erik"); settings.setProperty(CoreProperties.DEFAULT_ISSUE_ASSIGNEE, "erik");
when(userIndex.getNullableByLogin("erik")).thenReturn(new UserDoc().setLogin("erik").setActive(false)); db.users().insertUser(user -> user.setLogin("erik").setActive(false));

assertThat(underTest.loadDefaultAssigneeLogin()).isNull();
}

@Test
public void configured_login_is_not_member_of_organization() {
settings.setProperty(CoreProperties.DEFAULT_ISSUE_ASSIGNEE, "erik");
OrganizationDto otherOrganization = db.organizations().insert();
UserDto userDto = db.users().insertUser("erik");
db.organizations().addMember(otherOrganization, userDto);

assertThat(underTest.loadDefaultAssigneeLogin()).isNull();
}

@Test
public void default_assignee_is_cached() {
settings.setProperty(CoreProperties.DEFAULT_ISSUE_ASSIGNEE, "erik");
UserDto userDto = db.users().insertUser("erik");
db.organizations().addMember(organizationDto, userDto);
assertThat(underTest.loadDefaultAssigneeLogin()).isEqualTo("erik");


assertThat(underTest.getLogin()).isNull(); // The setting is updated but the assignee hasn't changed
settings.setProperty(CoreProperties.DEFAULT_ISSUE_ASSIGNEE, "other");
assertThat(underTest.loadDefaultAssigneeLogin()).isEqualTo("erik");
} }
} }
Expand Up @@ -100,7 +100,7 @@ public void set_assignee_to_issue() throws Exception {
public void set_default_assignee_if_author_not_found() throws Exception { public void set_default_assignee_if_author_not_found() throws Exception {
addScmUser("john", null); addScmUser("john", null);
setSingleChangeset("john", 123456789L, "rev-1"); setSingleChangeset("john", 123456789L, "rev-1");
when(defaultAssignee.getLogin()).thenReturn("John C"); when(defaultAssignee.loadDefaultAssigneeLogin()).thenReturn("John C");
DefaultIssue issue = new DefaultIssue().setLine(1); DefaultIssue issue = new DefaultIssue().setLine(1);


underTest.onIssue(FILE, issue); underTest.onIssue(FILE, issue);
Expand Down

0 comments on commit fb65076

Please sign in to comment.