diff --git a/src/Attributes/VikingSession.cs b/src/Attributes/VikingSession.cs new file mode 100644 index 0000000..41674cd --- /dev/null +++ b/src/Attributes/VikingSession.cs @@ -0,0 +1,41 @@ +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Mvc; + +using sodoff.Model; +using sodoff.Controllers.Common; + +namespace sodoff.Attributes; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] +public class VikingSession : Attribute, IAsyncActionFilter { + public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { + DBContext ctx = ((AchievementController)context.Controller).ctx; + + foreach (var a in context.ActionArguments.Keys) { + Console.WriteLine(a); + } + + if (!context.HttpContext.Request.Form.ContainsKey("apiToken")) { + context.Result = new UnauthorizedObjectResult("Unauthorized") { StatusCode = 403 }; + return; + } + + Session? session = ctx.Sessions.FirstOrDefault(x => x.ApiToken == context.HttpContext.Request.Form["apiToken"].ToString()); + if (session?.VikingId is null) { + context.Result = new UnauthorizedObjectResult("Unauthorized") { StatusCode = 403 }; + return; + } + + // NOTE: we can't refer to session.Viking here, because it may cause to ignore modifications from the threads we are waiting for + // we can use session.Viking only after vikingMutex.WaitOne() + + Mutex vikingMutex = new Mutex(false, "SoDOffViking:" + session.VikingId); + try { + vikingMutex.WaitOne(); + context.ActionArguments["viking"] = session.Viking; + await next(); + } finally { + vikingMutex.ReleaseMutex(); + } + } +} diff --git a/src/Controllers/Common/AchievementController.cs b/src/Controllers/Common/AchievementController.cs index 636bd43..ce32aa7 100644 --- a/src/Controllers/Common/AchievementController.cs +++ b/src/Controllers/Common/AchievementController.cs @@ -10,7 +10,7 @@ using sodoff.Util; namespace sodoff.Controllers.Common; public class AchievementController : Controller { - private readonly DBContext ctx; + public readonly DBContext ctx; private AchievementService achievementService; public AchievementController(DBContext ctx, AchievementService achievementService) { this.ctx = ctx; @@ -138,14 +138,10 @@ public class AchievementController : Controller { [Produces("application/xml")] [Route("AchievementWebService.asmx/SetAchievementAndGetReward")] [Route("AchievementWebService.asmx/SetUserAchievementAndGetReward")] - public IActionResult SetAchievementAndGetReward([FromForm] string apiToken, [FromForm] int achievementID) { - Viking? viking = ctx.Sessions.FirstOrDefault(x => x.ApiToken == apiToken).Viking; - - if (viking is null) { - return Unauthorized(); - } - + [VikingSession()] + public IActionResult SetAchievementAndGetReward(Viking viking, [FromForm] int achievementID) { var rewards = achievementService.ApplyAchievementRewardsByID(viking, achievementID); + ctx.SaveChanges(); return Ok(rewards); @@ -155,13 +151,8 @@ public class AchievementController : Controller { [Produces("application/xml")] [Route("V2/AchievementWebService.asmx/SetUserAchievementTask")] [DecryptRequest("achievementTaskSetRequest")] - public IActionResult SetUserAchievementTask([FromForm] string apiToken) { - Viking? viking = ctx.Sessions.FirstOrDefault(x => x.ApiToken == apiToken).Viking; - - if (viking is null) { - return Unauthorized(); - } - + [VikingSession()] + public IActionResult SetUserAchievementTask(Viking viking) { AchievementTaskSetRequest request = XmlUtil.DeserializeXml(Request.Form["achievementTaskSetRequest"]); var response = new List(); diff --git a/src/Resources/achievementsids.xml b/src/Resources/achievementsids.xml index a80f052..45928da 100644 --- a/src/Resources/achievementsids.xml +++ b/src/Resources/achievementsids.xml @@ -51,51 +51,6 @@ 0 - - 201323 - -

2

- 25 - 1 - 21 - 0 -
- -

1

- 50 - 1 - 32 - 0 -
- -

12

- 100 - 1 - 913 - 0 -
- -

12

- 10 - 1 - 920 - 0 -
- -

8

- 200 - 3 - 611 - 0 -
- -

12

- 10 - 3 - 920 - 0 -
-
201323