From fc06d830927a57a89c5eba8b395b5b05c0522a2a Mon Sep 17 00:00:00 2001 From: Adrien Lecharpentier Date: Wed, 18 Jan 2023 15:10:59 +0100 Subject: [PATCH] Protects `/api/scores` against plugins with null version (#177) --- .../scoring/config/VersionNumberType.java | 10 +++------- .../jenkins/pluginhealth/scoring/model/Plugin.java | 2 +- .../pluginhealth/scoring/service/ProbeService.java | 4 ++-- .../pluginhealth/scoring/service/ScoreService.java | 12 +++++++++++- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/jenkins/pluginhealth/scoring/config/VersionNumberType.java b/src/main/java/io/jenkins/pluginhealth/scoring/config/VersionNumberType.java index 9c1b47e3c..08b205e18 100644 --- a/src/main/java/io/jenkins/pluginhealth/scoring/config/VersionNumberType.java +++ b/src/main/java/io/jenkins/pluginhealth/scoring/config/VersionNumberType.java @@ -59,8 +59,7 @@ public int hashCode(VersionNumber x) { @Override public VersionNumber nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException { final String value = rs.getString(position); - return rs.wasNull() || Objects.isNull(value) ? - null : new VersionNumber(value); + return Objects.isNull(value) ? null : new VersionNumber(value); } @Override @@ -74,15 +73,12 @@ public void nullSafeSet(PreparedStatement st, VersionNumber value, int index, Sh @Override public VersionNumber deepCopy(VersionNumber value) { - if (Objects.isNull(value)) { - return null; - } - return new VersionNumber(value.toString()); + return Objects.isNull(value) ? null : new VersionNumber(value.toString()); } @Override public boolean isMutable() { - return true; + return false; } @Override diff --git a/src/main/java/io/jenkins/pluginhealth/scoring/model/Plugin.java b/src/main/java/io/jenkins/pluginhealth/scoring/model/Plugin.java index 2cea939b9..0affac34d 100644 --- a/src/main/java/io/jenkins/pluginhealth/scoring/model/Plugin.java +++ b/src/main/java/io/jenkins/pluginhealth/scoring/model/Plugin.java @@ -52,7 +52,7 @@ public class Plugin { private String name; @Type(VersionNumberType.class) - @Column(name = "version", updatable = false) + @Column(name = "version", nullable = false) private VersionNumber version; @Column(name = "scm") diff --git a/src/main/java/io/jenkins/pluginhealth/scoring/service/ProbeService.java b/src/main/java/io/jenkins/pluginhealth/scoring/service/ProbeService.java index 676c28b82..2c1d29e19 100644 --- a/src/main/java/io/jenkins/pluginhealth/scoring/service/ProbeService.java +++ b/src/main/java/io/jenkins/pluginhealth/scoring/service/ProbeService.java @@ -37,8 +37,8 @@ import io.jenkins.pluginhealth.scoring.probes.ProbeContext; import io.jenkins.pluginhealth.scoring.repository.PluginRepository; -import jakarta.transaction.Transactional; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service public class ProbeService { @@ -54,7 +54,7 @@ public List getProbes() { return probes; } - @Transactional + @Transactional(readOnly = true) public Map getProbesFinalResults() { return probes.stream() .filter(probe -> diff --git a/src/main/java/io/jenkins/pluginhealth/scoring/service/ScoreService.java b/src/main/java/io/jenkins/pluginhealth/scoring/service/ScoreService.java index 90e42d2d6..0482e6ee3 100644 --- a/src/main/java/io/jenkins/pluginhealth/scoring/service/ScoreService.java +++ b/src/main/java/io/jenkins/pluginhealth/scoring/service/ScoreService.java @@ -30,6 +30,7 @@ import java.util.Set; import java.util.stream.Collectors; +import io.jenkins.pluginhealth.scoring.model.Plugin; import io.jenkins.pluginhealth.scoring.model.Score; import io.jenkins.pluginhealth.scoring.model.ScoreResult; import io.jenkins.pluginhealth.scoring.repository.ScoreRepository; @@ -63,10 +64,19 @@ public Map getLatestScoresSummaryMap() { return repository.findLatestScoreForAllPlugins().stream() .collect(Collectors.toMap( score -> score.getPlugin().getName(), - score -> new ScoreSummary(score.getValue(), score.getPlugin().getVersion().toString(), score.getDetails(), score.getComputedAt()) + ScoreSummary::fromScore )); } public record ScoreSummary(long value, String version, Set details, ZonedDateTime timestamp) { + public static ScoreSummary fromScore(Score score) { + final Plugin plugin = score.getPlugin(); + return new ScoreSummary( + score.getValue(), + plugin.getVersion() == null ? "" : plugin.getVersion().toString(), + score.getDetails(), + score.getComputedAt() + ); + } } }