package org.sonar.server.qualityprofile;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import org.sonar.api.rules.ActiveRuleParam;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.System2;
import org.sonar.api.utils.ValidationMessages;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.MyBatis;
import javax.annotation.CheckForNull;
import java.io.StringReader;
+import java.util.Date;
import java.util.List;
import java.util.Map;
private final ProfileRules profileRules;
private final ProfilesManager profilesManager;
+ private final System2 system;
+
/**
* Used by pico when no plugin provide profile exporter / importer
*/
public QProfileOperations(MyBatis myBatis, QualityProfileDao dao, ActiveRuleDao activeRuleDao, RuleDao ruleDao, PropertiesDao propertiesDao,
PreviewCache dryRunCache, RuleRegistry ruleRegistry, ProfilesManager profilesManager, ProfileRules profileRules) {
this(myBatis, dao, activeRuleDao, ruleDao, propertiesDao, Lists.<ProfileImporter>newArrayList(), dryRunCache, ruleRegistry,
- profilesManager, profileRules);
+ profilesManager, profileRules, System2.INSTANCE);
}
public QProfileOperations(MyBatis myBatis, QualityProfileDao dao, ActiveRuleDao activeRuleDao, RuleDao ruleDao, PropertiesDao propertiesDao,
List<ProfileImporter> importers, PreviewCache dryRunCache, RuleRegistry ruleRegistry,
ProfilesManager profilesManager, ProfileRules profileRules) {
+ this(myBatis, dao, activeRuleDao, ruleDao, propertiesDao, Lists.<ProfileImporter>newArrayList(), dryRunCache, ruleRegistry,
+ profilesManager, profileRules, System2.INSTANCE);
+ }
+
+ @VisibleForTesting
+ QProfileOperations(MyBatis myBatis, QualityProfileDao dao, ActiveRuleDao activeRuleDao, RuleDao ruleDao, PropertiesDao propertiesDao,
+ List<ProfileImporter> importers, PreviewCache dryRunCache, RuleRegistry ruleRegistry,
+ ProfilesManager profilesManager, ProfileRules profileRules, System2 system) {
this.myBatis = myBatis;
this.dao = dao;
this.activeRuleDao = activeRuleDao;
this.ruleRegistry = ruleRegistry;
this.profilesManager = profilesManager;
this.profileRules = profileRules;
+ this.system = system;
}
public NewProfileResult newProfile(String name, String language, Map<String, String> xmlProfilesByPlugin, UserSession userSession) {
SqlSession session = myBatis.openSession();
try {
- createActiveRuleParam(activeRule, key, value, session);
+ RuleParamDto ruleParam = ruleDao.selectParamByRuleAndKey(activeRule.getRulId(), key, session);
+ if (ruleParam == null) {
+ throw new IllegalArgumentException("No rule param found");
+ }
+ ActiveRuleParamDto activeRuleParam = new ActiveRuleParamDto().setActiveRuleId(activeRule.getId()).setKey(key).setValue(value).setRulesParameterId(ruleParam.getId());
+ activeRuleDao.insert(activeRuleParam, session);
session.commit();
profilesManager.ruleParamChanged(activeRule.getProfileId(), activeRule.getId(), key, null, value, userSession.name());
} finally {
}
}
- private ActiveRuleParamDto createActiveRuleParam(ActiveRuleDto activeRule, String key, String value, SqlSession session) {
- RuleParamDto ruleParam = ruleDao.selectParamByRuleAndKey(activeRule.getRulId(), key, session);
- if (ruleParam == null) {
- throw new IllegalArgumentException("No rule param found");
+ public void updateActiveRuleNote(ActiveRuleDto activeRule, String note, UserSession userSession) {
+ checkPermission(userSession);
+ Date now = new Date(system.now());
+
+ if (activeRule.getNoteData() == null) {
+ activeRule.setNoteCreatedAt(now);
+ activeRule.setNoteUserLogin(userSession.login());
}
- ActiveRuleParamDto activeRuleParam = new ActiveRuleParamDto().setActiveRuleId(activeRule.getId()).setKey(key).setValue(value).setRulesParameterId(ruleParam.getId());
- activeRuleDao.insert(activeRuleParam, session);
- return activeRuleParam;
+ activeRule.setNoteUpdatedAt(now);
+ activeRule.setNoteData(note);
+ activeRuleDao.update(activeRule);
+ // TODO notify E/S of active rule change
+ }
+
+ public void deleteActiveRuleNote(ActiveRuleDto activeRule, UserSession userSession) {
+ checkPermission(userSession);
+
+ activeRule.setNoteUpdatedAt(new Date(system.now()));
+ activeRule.setNoteData(null);
+ activeRule.setNoteUserLogin(null);
+ activeRule.setNoteCreatedAt(null);
+ activeRule.setNoteUpdatedAt(null);
+ activeRuleDao.update(activeRule);
+ // TODO notify E/S of active rule change
}
private List<RulesProfile> readProfilesFromXml(NewProfileResult result, Map<String, String> xmlProfilesByPlugin) {
// deactivate a rule (only E/S indexing)
// update severity (only E/S indexing)
// update parameter on a active rule (only E/S indexing)
- // add note on an active rule
- // delete note on an active rule
- // edit note on an active rule
+ // update note on an active rule (only E/S indexing)
+ // delete note on an active rule (only E/S indexing)
// extends extension of a rule
//
// TEMPLATE RULES
} else if (activeRuleParam != null && sanitizedValue == null) {
operations.deleteActiveRuleParam(activeRule, activeRuleParam, userSession);
} else if (activeRuleParam != null) {
- operations.updateActiveRuleParam(activeRule, activeRuleParam, value, UserSession.get());
+ operations.updateActiveRuleParam(activeRule, activeRuleParam, value, userSession);
}
}
+ public void updateActiveRuleNote(int activeRuleId, String note) {
+ String sanitizedNote = Strings.emptyToNull(note);
+ ActiveRuleDto activeRule = findActiveRuleNotNull(activeRuleId);
+ if (sanitizedNote != null) {
+ operations.updateActiveRuleNote(activeRule, sanitizedNote, UserSession.get());
+ }
+ }
+
+ public void deleteActiveRuleNote(int activeRuleId) {
+ ActiveRuleDto activeRule = findActiveRuleNotNull(activeRuleId);
+ operations.deleteActiveRuleNote(activeRule, UserSession.get());
+ }
+
//
// Quality profile validation
//
def update_active_rule_note
verify_post_request
- access_denied unless has_role?(:profileadmin)
require_parameters :active_rule_id, :note
- active_rule = ActiveRule.find(params[:active_rule_id])
- note = active_rule.note
- unless note
- note = ActiveRuleNote.new({:active_rule => active_rule})
- # set the note on the rule to avoid reloading the rule
- active_rule.note = note
+
+ call_backend do
+ Internal.quality_profiles.updateActiveRuleNote(params[:active_rule_id].to_i, params[:note])
end
- note.text = params[:note]
- note.user_login = current_user.login
- note.save!
+
+ # TODO use a QProfileRule instead of rails objects
+ active_rule = ActiveRule.find(params[:active_rule_id])
render :partial => 'active_rule_note', :locals => {:active_rule => active_rule, :profile => active_rule.rules_profile}
end
def delete_active_rule_note
verify_post_request
- access_denied unless has_role?(:profileadmin)
require_parameters :active_rule_id
+
+ call_backend do
+ Internal.quality_profiles.deleteActiveRuleNote(params[:active_rule_id].to_i)
+ end
+
+ # TODO use a QProfileRule instead of rails objects
active_rule = ActiveRule.find(params[:active_rule_id])
- active_rule.note.destroy if active_rule.note
- active_rule.note = nil
render :partial => 'active_rule_note', :locals => {:active_rule => active_rule, :profile => active_rule.rules_profile}
end
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RulePriority;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
import org.sonar.api.utils.ValidationMessages;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.MyBatis;
import java.io.Reader;
import java.util.Collection;
+import java.util.Date;
import java.util.List;
import java.util.Map;
import static com.google.common.collect.Maps.newHashMap;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
-import static org.mockito.Matchers.*;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyCollection;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyListOf;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
@Mock
ProfilesManager profilesManager;
+ @Mock
+ System2 system;
+
List<ProfileImporter> importers = newArrayList();
QProfileOperations operations;
}).when(activeRuleDao).insert(any(ActiveRuleDto.class), any(SqlSession.class));
operations = new QProfileOperations(myBatis, qualityProfileDao, activeRuleDao, ruleDao, propertiesDao, importers, dryRunCache, ruleRegistry, profilesManager,
- profileRules);
+ profileRules, system);
}
@Test
verifyZeroInteractions(profilesManager);
}
+ @Test
+ public void update_active_rule_note_when_no_note() throws Exception {
+ ActiveRuleDto activeRule = new ActiveRuleDto().setId(5).setProfileId(1).setRuleId(10).setSeverity(1).setNoteCreatedAt(null).setNoteData(null);
+
+ long now = System.currentTimeMillis();
+ doReturn(now).when(system).now();
+ operations.updateActiveRuleNote(activeRule, "My note", MockUserSession.create().setLogin("nicolas").setName("Nicolas").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN));
+
+ ArgumentCaptor<ActiveRuleDto> argumentCaptor = ArgumentCaptor.forClass(ActiveRuleDto.class);
+ verify(activeRuleDao).update(argumentCaptor.capture());
+ assertThat(argumentCaptor.getValue().getNoteData()).isEqualTo("My note");
+ assertThat(argumentCaptor.getValue().getNoteUserLogin()).isEqualTo("nicolas");
+ assertThat(argumentCaptor.getValue().getNoteCreatedAt().getTime()).isEqualTo(now);
+ assertThat(argumentCaptor.getValue().getNoteUpdatedAt().getTime()).isEqualTo(now);
+ }
+
+ @Test
+ public void update_active_rule_note_when_already_note() throws Exception {
+ Date createdAt = DateUtils.parseDate("2013-12-20");
+ ActiveRuleDto activeRule = new ActiveRuleDto().setId(5).setProfileId(1).setRuleId(10).setSeverity(1)
+ .setNoteCreatedAt(createdAt).setNoteData("My previous note").setNoteUserLogin("nicolas");
+
+ long now = System.currentTimeMillis();
+ doReturn(now).when(system).now();
+
+ operations.updateActiveRuleNote(activeRule, "My new note", MockUserSession.create().setLogin("guy").setName("Guy").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN));
+
+ ArgumentCaptor<ActiveRuleDto> argumentCaptor = ArgumentCaptor.forClass(ActiveRuleDto.class);
+ verify(activeRuleDao).update(argumentCaptor.capture());
+ assertThat(argumentCaptor.getValue().getNoteData()).isEqualTo("My new note");
+ assertThat(argumentCaptor.getValue().getNoteUserLogin()).isEqualTo("nicolas");
+ assertThat(argumentCaptor.getValue().getNoteCreatedAt()).isEqualTo(createdAt);
+ assertThat(argumentCaptor.getValue().getNoteUpdatedAt().getTime()).isEqualTo(now);
+ }
+
+ @Test
+ public void delete_active_rule_note() throws Exception {
+ Date createdAt = DateUtils.parseDate("2013-12-20");
+ ActiveRuleDto activeRule = new ActiveRuleDto().setId(5).setProfileId(1).setRuleId(10).setSeverity(1).setNoteCreatedAt(createdAt).setNoteData("My note");
+
+ long now = System.currentTimeMillis();
+ doReturn(now).when(system).now();
+
+ operations.deleteActiveRuleNote(activeRule, MockUserSession.create().setName("nicolas").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN));
+
+ ArgumentCaptor<ActiveRuleDto> argumentCaptor = ArgumentCaptor.forClass(ActiveRuleDto.class);
+ verify(activeRuleDao).update(argumentCaptor.capture());
+ assertThat(argumentCaptor.getValue().getNoteData()).isNull();
+ assertThat(argumentCaptor.getValue().getNoteUserLogin()).isNull();
+ assertThat(argumentCaptor.getValue().getNoteCreatedAt()).isNull();
+ assertThat(argumentCaptor.getValue().getNoteUpdatedAt()).isNull();
+ }
}
verifyZeroInteractions(service);
}
+ @Test
+ public void create_active_rule_note() throws Exception {
+ ActiveRuleDto activeRule = new ActiveRuleDto().setId(50);
+ when(activeRuleDao.selectById(50)).thenReturn(activeRule);
+
+ qProfiles.updateActiveRuleNote(50, "My note");
+
+ verify(service).updateActiveRuleNote(eq(activeRule), eq("My note"), any(UserSession.class));
+ }
+
+ @Test
+ public void do_nothing_when_create_active_rule_note_with_empty_note() throws Exception {
+ ActiveRuleDto activeRule = new ActiveRuleDto().setId(50);
+ when(activeRuleDao.selectById(50)).thenReturn(activeRule);
+
+ qProfiles.updateActiveRuleNote(50, "");
+
+ verifyZeroInteractions(service);
+ }
+
+ @Test
+ public void delete_active_rule_note() throws Exception {
+ ActiveRuleDto activeRule = new ActiveRuleDto().setId(50);
+ when(activeRuleDao.selectById(50)).thenReturn(activeRule);
+
+ qProfiles.deleteActiveRuleNote(50);
+
+ verify(service).deleteActiveRuleNote(eq(activeRule), any(UserSession.class));
+ }
+
}