confirmed ban evasion cases stay closed
This commit is contained in:
1 parent
66dace7f2a
commit
974c5c5200
2 files changed
+32
-11
No files matched your search
+28
-9
@@ -70,7 +70,7 @@ final class BanEvasionRepository {
|
|||||||
record Member(UUID uuid, String name) {
|
record Member(UUID uuid, String name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
record Household(long id, @Nullable String note, List<Member> members) {
|
record Household(long id, Instant createdAt, @Nullable String createdByName, @Nullable String note, List<Member> members) {
|
||||||
}
|
}
|
||||||
|
|
||||||
record Exemption(long id, String network, Instant validFrom, Instant validUntil, @Nullable String createdByName, @Nullable String note) {
|
record Exemption(long id, String network, Instant validFrom, Instant validUntil, @Nullable String createdByName, @Nullable String note) {
|
||||||
@@ -156,18 +156,20 @@ final class BanEvasionRepository {
|
|||||||
@Nullable CaseDecision.ExistingCase findCase(Connection connection, UUID first, UUID second) throws SQLException {
|
@Nullable CaseDecision.ExistingCase findCase(Connection connection, UUID first, UUID second) throws SQLException {
|
||||||
long id;
|
long id;
|
||||||
CaseStatus status;
|
CaseStatus status;
|
||||||
try(PreparedStatement statement = connection.prepareStatement("SELECT id, status FROM ban_evasion_cases WHERE uuid_a = ? AND uuid_b = ?")) {
|
String outcome;
|
||||||
|
try(PreparedStatement statement = connection.prepareStatement("SELECT id, status, outcome FROM ban_evasion_cases WHERE uuid_a = ? AND uuid_b = ?")) {
|
||||||
statement.setString(1, first.toString());
|
statement.setString(1, first.toString());
|
||||||
statement.setString(2, second.toString());
|
statement.setString(2, second.toString());
|
||||||
try(ResultSet row = statement.executeQuery()) {
|
try(ResultSet row = statement.executeQuery()) {
|
||||||
if(!row.next()) return null;
|
if(!row.next()) return null;
|
||||||
id = row.getLong("id");
|
id = row.getLong("id");
|
||||||
status = CaseStatus.valueOf(row.getString("status"));
|
status = CaseStatus.valueOf(row.getString("status"));
|
||||||
|
outcome = row.getString("outcome");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Set<Reason> reasons = EnumSet.noneOf(Reason.class);
|
Set<Reason> reasons = EnumSet.noneOf(Reason.class);
|
||||||
this.reasonsOf(connection, id).forEach(reason -> reasons.add(reason.reason()));
|
this.reasonsOf(connection, id).forEach(reason -> reasons.add(reason.reason()));
|
||||||
return new CaseDecision.ExistingCase(id, status, reasons);
|
return new CaseDecision.ExistingCase(id, status, outcome == null ? null : Outcome.valueOf(outcome), reasons);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -458,23 +460,40 @@ final class BanEvasionRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All households, newest first.
|
||||||
|
*/
|
||||||
List<Household> listHouseholds(Connection connection) throws SQLException {
|
List<Household> listHouseholds(Connection connection) throws SQLException {
|
||||||
|
return this.households(connection, "", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable Household household(Connection connection, long id) throws SQLException {
|
||||||
|
List<Household> households = this.households(connection, "WHERE h.id = ?", id);
|
||||||
|
return households.isEmpty() ? null : households.getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Household> households(Connection connection, String where, @Nullable Long id) throws SQLException {
|
||||||
String sql = """
|
String sql = """
|
||||||
SELECT h.id, h.note, m.uuid, %s AS name
|
SELECT h.id, h.created_at, h.note, %s AS created_by_name, m.uuid, %s AS name
|
||||||
FROM ban_evasion_households h
|
FROM ban_evasion_households h
|
||||||
JOIN ban_evasion_household_members m ON m.household_id = h.id
|
JOIN ban_evasion_household_members m ON m.household_id = h.id
|
||||||
ORDER BY h.id, name
|
%s
|
||||||
""".formatted(NAME_OF.formatted("m.uuid"));
|
ORDER BY h.id DESC, name
|
||||||
|
""".formatted(NAME_OF.formatted("h.created_by"), NAME_OF.formatted("m.uuid"), where);
|
||||||
Map<Long, Household> households = new LinkedHashMap<>();
|
Map<Long, Household> households = new LinkedHashMap<>();
|
||||||
try(PreparedStatement statement = connection.prepareStatement(sql); ResultSet row = statement.executeQuery()) {
|
try(PreparedStatement statement = connection.prepareStatement(sql)) {
|
||||||
|
if(id != null) statement.setLong(1, id);
|
||||||
|
try(ResultSet row = statement.executeQuery()) {
|
||||||
while(row.next()) {
|
while(row.next()) {
|
||||||
long id = row.getLong("id");
|
Instant createdAt = fromDb(row, "created_at");
|
||||||
|
String createdByName = row.getString("created_by_name");
|
||||||
String householdNote = row.getString("note");
|
String householdNote = row.getString("note");
|
||||||
UUID uuid = UUID.fromString(row.getString("uuid"));
|
UUID uuid = UUID.fromString(row.getString("uuid"));
|
||||||
households.computeIfAbsent(id, key -> new Household(key, householdNote, new ArrayList<>()))
|
households.computeIfAbsent(row.getLong("id"), key -> new Household(key, createdAt, createdByName, householdNote, new ArrayList<>()))
|
||||||
.members().add(new Member(uuid, nameOr(row.getString("name"), uuid)));
|
.members().add(new Member(uuid, nameOr(row.getString("name"), uuid)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return List.copyOf(households.values());
|
return List.copyOf(households.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -7,10 +7,11 @@ import java.util.Set;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deduplication: one case per pair; admins are only notified about new information.
|
* Deduplication: one case per pair; admins are only notified about new information.
|
||||||
* A closed case reopens only for a new reason of severity HIGH.
|
* A closed case reopens only for a new reason of severity HIGH, a case closed as confirmed evasion never:
|
||||||
|
* further attempts of the banned person are expected there and only recorded.
|
||||||
*/
|
*/
|
||||||
final class CaseDecision {
|
final class CaseDecision {
|
||||||
record ExistingCase(long id, CaseStatus status, Set<Reason> reasons) {
|
record ExistingCase(long id, CaseStatus status, @Nullable Outcome outcome, Set<Reason> reasons) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,6 +36,7 @@ final class CaseDecision {
|
|||||||
.anyMatch(reason -> !reason.informational && finding.reasons().get(reason) == Severity.HIGH);
|
.anyMatch(reason -> !reason.informational && finding.reasons().get(reason) == Severity.HIGH);
|
||||||
|
|
||||||
if(existing.status() == CaseStatus.OPEN) return new Result(false, newReasons, newRelevant);
|
if(existing.status() == CaseStatus.OPEN) return new Result(false, newReasons, newRelevant);
|
||||||
|
if(existing.outcome() == Outcome.CONFIRMED) return new Result(false, newReasons, false);
|
||||||
return new Result(newHigh, newReasons, newHigh);
|
return new Result(newHigh, newReasons, newHigh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user