diff --git a/Refresh.Database/GameDatabaseContext.Contests.cs b/Refresh.Database/GameDatabaseContext.Contests.cs index 8bd91600..02b65b7a 100644 --- a/Refresh.Database/GameDatabaseContext.Contests.cs +++ b/Refresh.Database/GameDatabaseContext.Contests.cs @@ -17,8 +17,9 @@ public GameContest CreateContest(string contestId, ICreateContestInfo createInfo ContestId = contestId, Organizer = organizer, CreationDate = this._time.Now, - StartDate = createInfo.StartDate!.Value, - EndDate = createInfo.EndDate!.Value, + // EF doesn't support timestamps with offsets + StartDate = createInfo.StartDate!.Value.UtcDateTime, + EndDate = createInfo.EndDate!.Value.UtcDateTime, ContestTitle = createInfo.ContestTitle!, BannerUrl = createInfo.BannerUrl ?? "", ContestTag = createInfo.ContestTag ?? $"#{contestId}", @@ -80,9 +81,9 @@ public GameContest UpdateContest(ICreateContestInfo body, GameContest contest, G contest.Organizer = newOrganizer; if(body.StartDate != null) - contest.StartDate = body.StartDate.Value; + contest.StartDate = body.StartDate.Value.UtcDateTime; if(body.EndDate != null) - contest.EndDate = body.EndDate.Value; + contest.EndDate = body.EndDate.Value.UtcDateTime; if(body.ContestTag != null) contest.ContestTag = body.ContestTag; if(body.BannerUrl != null) diff --git a/Refresh.Database/GameDatabaseContext.Users.cs b/Refresh.Database/GameDatabaseContext.Users.cs index 2ec99d8b..977b0cea 100644 --- a/Refresh.Database/GameDatabaseContext.Users.cs +++ b/Refresh.Database/GameDatabaseContext.Users.cs @@ -320,7 +320,7 @@ private void PunishUser(GameUser user, string reason, DateTimeOffset expiryDate, { user.Role = role; user.BanReason = reason; - user.BanExpiryDate = expiryDate; + user.BanExpiryDate = expiryDate.UtcDateTime; // EF doesn't support timestamps with offsets }); } diff --git a/RefreshTests.GameServer/Tests/Levels/ContestTests.cs b/RefreshTests.GameServer/Tests/Levels/ContestTests.cs index c2422567..2e67e8e3 100644 --- a/RefreshTests.GameServer/Tests/Levels/ContestTests.cs +++ b/RefreshTests.GameServer/Tests/Levels/ContestTests.cs @@ -24,7 +24,6 @@ private GameContest CreateContest(TestContext context, GameUser? organizer = nul { organizer ??= context.CreateUser(); GameLevel templateLevel = context.CreateLevel(organizer); - GameContest contest = context.Database.CreateContest(id, new ApiContestRequest { OrganizerId = organizer.UserId.ToString(), @@ -95,6 +94,49 @@ public void CanCreateContestWithLessData() Assert.That(contest, Is.Not.Null); } + [Test] + public void CanCreateAndUpdateContestWithOffsetTimestamps() + { + using TestContext context = this.GetServer(false); + GameUser organizer = context.CreateUser(); + DateTime now = context.Time.Now.DateTime; + + // Create + Assert.That(() => + { + // ReSharper disable once AccessToDisposedClosure + context.Database.CreateContest("contestde", new ApiContestRequest + { + OrganizerId = organizer.UserId.ToString(), + ContestTitle = "geremany contest", + StartDate = new(now, new(2, 0, 0)), + EndDate = new(now.AddHours(4), new(2, 0, 0)), + }, organizer, null); + }, Throws.Nothing); + + GameContest? contest = context.Database.GetContestById("contestde"); + Assert.That(contest, Is.Not.Null); + Assert.That(contest!.StartDate.DateTime.Equals(now.AddHours(-2)), Is.True); + Assert.That(contest!.EndDate.DateTime.Equals(now.AddHours(2)), Is.True); + + // Update + Assert.That(() => + { + // ReSharper disable once AccessToDisposedClosure + context.Database.UpdateContest(new ApiContestRequest + { + OrganizerId = organizer.UserId.ToString(), + StartDate = new(now, new(4, 0, 0)), + EndDate = new(now.AddHours(5), new(4, 0, 0)), + }, contest, organizer, null); + }, Throws.Nothing); + + GameContest? updated = context.Database.GetContestById("contestde"); + Assert.That(updated, Is.Not.Null); + Assert.That(updated!.StartDate.DateTime.Equals(now.AddHours(-4)), Is.True); + Assert.That(updated!.EndDate.DateTime.Equals(now.AddHours(1)), Is.True); + } + [Test] public void CanCreateContestFromApi() { diff --git a/RefreshTests.GameServer/Tests/Moderation/PunishmentTests.cs b/RefreshTests.GameServer/Tests/Moderation/PunishmentTests.cs new file mode 100644 index 00000000..606456b4 --- /dev/null +++ b/RefreshTests.GameServer/Tests/Moderation/PunishmentTests.cs @@ -0,0 +1,42 @@ +using Refresh.Database.Models.Users; + +namespace RefreshTests.GameServer.Tests.Moderation; + +public class PunishmentTests : GameServerTest +{ + [Test] + public void CanPunishWithOffsetExpiryDate() + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + GameUser mod = context.CreateUser(); + DateTime now = context.Time.Now.DateTime; + + // Restrict + Assert.That(() => + { + context.Database.RestrictUser(user, "too many skill issues", new(now.AddHours(4), new(2, 0, 0))); + }, Throws.Nothing); + + context.Database.Refresh(); + GameUser? restrictedUser = context.Database.GetUserByObjectId(user.UserId); + Assert.That(restrictedUser, Is.Not.Null); + Assert.That(restrictedUser!.Role, Is.EqualTo(GameUserRole.Restricted)); + Assert.That(restrictedUser!.BanExpiryDate, Is.Not.Null); + Assert.That(restrictedUser!.BanExpiryDate!.Value.DateTime.Equals(now.AddHours(2)), Is.True); + + // Ban + Assert.That(() => + { + // Passing user here, for some reason, makes the ban not get written but also doesn't cause a throw + context.Database.BanUser(restrictedUser, "even more skill issues", new(now.AddHours(8), new(4, 0, 0))); + }, Throws.Nothing); + + context.Database.Refresh(); + GameUser? bannedUser = context.Database.GetUserByObjectId(restrictedUser.UserId); + Assert.That(bannedUser, Is.Not.Null); + Assert.That(bannedUser!.Role, Is.EqualTo(GameUserRole.Banned)); + Assert.That(bannedUser!.BanExpiryDate, Is.Not.Null); + Assert.That(bannedUser!.BanExpiryDate!.Value.DateTime.Equals(now.AddHours(4)), Is.True); + } +} \ No newline at end of file