From 865378dbdfcfd34eca99bfd1134395af5b68a71f Mon Sep 17 00:00:00 2001 From: biss Date: Tue, 28 Jul 2026 20:08:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=BE=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/AttendanceController.cs | 4 +-- .../AttendanceControllerTests.cs | 15 +++++++++++ tests/Jiaowu.Api.Tests/MySqlMigrationTests.cs | 25 +++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/Jiaowu.Api/Controllers/AttendanceController.cs b/src/Jiaowu.Api/Controllers/AttendanceController.cs index 8df9643..636ca58 100644 --- a/src/Jiaowu.Api/Controllers/AttendanceController.cs +++ b/src/Jiaowu.Api/Controllers/AttendanceController.cs @@ -275,8 +275,8 @@ public sealed class AttendanceController( .Where(x => x.IsSuccessful && x.CreatedAt >= now.AddHours(-24) && - x.DeviceIdentifierHash != null && - deviceHashes.Contains(x.DeviceIdentifierHash)) + x.DeviceIdentifierHash != null) + .WhereIn(deviceHashes, x => x.DeviceIdentifierHash!) .GroupBy(x => x.DeviceIdentifierHash!) .Select(x => new { diff --git a/tests/Jiaowu.Api.Tests/AttendanceControllerTests.cs b/tests/Jiaowu.Api.Tests/AttendanceControllerTests.cs index 160fa02..67ce918 100644 --- a/tests/Jiaowu.Api.Tests/AttendanceControllerTests.cs +++ b/tests/Jiaowu.Api.Tests/AttendanceControllerTests.cs @@ -302,6 +302,21 @@ public sealed class AttendanceControllerTests Assert.Contains( "SharedDevice", sharedDeviceAttempt.RiskFlags ?? string.Empty); + var sheetDetailResult = await controller.GetSheet( + qrSheet.Id, + CancellationToken.None); + var sheetDetailOk = Assert.IsType(sheetDetailResult); + var sheetDetail = sheetDetailOk.Value!.GetType() + .GetProperty("Sheet")! + .GetValue(sheetDetailOk.Value)!; + var riskSummary = sheetDetail.GetType() + .GetProperty("RiskSummary")! + .GetValue(sheetDetail)!; + Assert.Equal( + 2, + riskSummary.GetType() + .GetProperty("SharedDeviceStudentCount")! + .GetValue(riskSummary)); var locationRecord = new AttendanceRecord { diff --git a/tests/Jiaowu.Api.Tests/MySqlMigrationTests.cs b/tests/Jiaowu.Api.Tests/MySqlMigrationTests.cs index 1d228da..6e46eb6 100644 --- a/tests/Jiaowu.Api.Tests/MySqlMigrationTests.cs +++ b/tests/Jiaowu.Api.Tests/MySqlMigrationTests.cs @@ -108,6 +108,31 @@ public sealed class MySqlMigrationTests Assert.Contains(ids[1].ToString(), sql, StringComparison.OrdinalIgnoreCase); } + [Fact] + public void MySql_attendance_device_hash_query_uses_provider_safe_predicates() + { + using var db = new AppDbContext(CreateMySqlOptions()); + var deviceHashes = new[] { "device-hash-one", "device-hash-two" }; + + var sql = db.AttendanceCheckInAttempts + .Where(x => + x.IsSuccessful && + x.CreatedAt >= DateTime.UtcNow.AddHours(-24) && + x.DeviceIdentifierHash != null) + .WhereIn(deviceHashes, x => x.DeviceIdentifierHash!) + .GroupBy(x => x.DeviceIdentifierHash!) + .Select(x => new + { + DeviceIdentifierHash = x.Key, + StudentCount = x.Select(a => a.StudentId).Distinct().Count() + }) + .ToQueryString(); + + Assert.Contains(" IN (", sql, StringComparison.OrdinalIgnoreCase); + Assert.Contains(deviceHashes[0], sql, StringComparison.Ordinal); + Assert.Contains(deviceHashes[1], sql, StringComparison.Ordinal); + } + [Fact] public void MySql_invigilator_candidate_query_is_translatable_without_uuid_ordering() {