mirror of
https://github.com/SoDOff-Project/sodoff.git
synced 2025-10-11 08:18:49 -07:00
Achievement race condition fix (#28)
This commit is contained in:
parent
e564a44b13
commit
d0eacb75b6
41
src/Attributes/VikingSession.cs
Normal file
41
src/Attributes/VikingSession.cs
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ using sodoff.Util;
|
|||||||
namespace sodoff.Controllers.Common;
|
namespace sodoff.Controllers.Common;
|
||||||
public class AchievementController : Controller {
|
public class AchievementController : Controller {
|
||||||
|
|
||||||
private readonly DBContext ctx;
|
public readonly DBContext ctx;
|
||||||
private AchievementService achievementService;
|
private AchievementService achievementService;
|
||||||
public AchievementController(DBContext ctx, AchievementService achievementService) {
|
public AchievementController(DBContext ctx, AchievementService achievementService) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
@ -138,14 +138,10 @@ public class AchievementController : Controller {
|
|||||||
[Produces("application/xml")]
|
[Produces("application/xml")]
|
||||||
[Route("AchievementWebService.asmx/SetAchievementAndGetReward")]
|
[Route("AchievementWebService.asmx/SetAchievementAndGetReward")]
|
||||||
[Route("AchievementWebService.asmx/SetUserAchievementAndGetReward")]
|
[Route("AchievementWebService.asmx/SetUserAchievementAndGetReward")]
|
||||||
public IActionResult SetAchievementAndGetReward([FromForm] string apiToken, [FromForm] int achievementID) {
|
[VikingSession()]
|
||||||
Viking? viking = ctx.Sessions.FirstOrDefault(x => x.ApiToken == apiToken).Viking;
|
public IActionResult SetAchievementAndGetReward(Viking viking, [FromForm] int achievementID) {
|
||||||
|
|
||||||
if (viking is null) {
|
|
||||||
return Unauthorized();
|
|
||||||
}
|
|
||||||
|
|
||||||
var rewards = achievementService.ApplyAchievementRewardsByID(viking, achievementID);
|
var rewards = achievementService.ApplyAchievementRewardsByID(viking, achievementID);
|
||||||
|
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
|
|
||||||
return Ok(rewards);
|
return Ok(rewards);
|
||||||
@ -155,13 +151,8 @@ public class AchievementController : Controller {
|
|||||||
[Produces("application/xml")]
|
[Produces("application/xml")]
|
||||||
[Route("V2/AchievementWebService.asmx/SetUserAchievementTask")]
|
[Route("V2/AchievementWebService.asmx/SetUserAchievementTask")]
|
||||||
[DecryptRequest("achievementTaskSetRequest")]
|
[DecryptRequest("achievementTaskSetRequest")]
|
||||||
public IActionResult SetUserAchievementTask([FromForm] string apiToken) {
|
[VikingSession()]
|
||||||
Viking? viking = ctx.Sessions.FirstOrDefault(x => x.ApiToken == apiToken).Viking;
|
public IActionResult SetUserAchievementTask(Viking viking) {
|
||||||
|
|
||||||
if (viking is null) {
|
|
||||||
return Unauthorized();
|
|
||||||
}
|
|
||||||
|
|
||||||
AchievementTaskSetRequest request = XmlUtil.DeserializeXml<AchievementTaskSetRequest>(Request.Form["achievementTaskSetRequest"]);
|
AchievementTaskSetRequest request = XmlUtil.DeserializeXml<AchievementTaskSetRequest>(Request.Form["achievementTaskSetRequest"]);
|
||||||
|
|
||||||
var response = new List<AchievementTaskSetResponse>();
|
var response = new List<AchievementTaskSetResponse>();
|
||||||
|
@ -51,51 +51,6 @@
|
|||||||
<ii>0</ii>
|
<ii>0</ii>
|
||||||
</AR>
|
</AR>
|
||||||
</AchievementsIdInfo>
|
</AchievementsIdInfo>
|
||||||
<AchievementsIdInfo>
|
|
||||||
<AID>201323</AID>
|
|
||||||
<AR>
|
|
||||||
<p>2</p>
|
|
||||||
<a>25</a>
|
|
||||||
<t>1</t>
|
|
||||||
<r>21</r>
|
|
||||||
<ii>0</ii>
|
|
||||||
</AR>
|
|
||||||
<AR>
|
|
||||||
<p>1</p>
|
|
||||||
<a>50</a>
|
|
||||||
<t>1</t>
|
|
||||||
<r>32</r>
|
|
||||||
<ii>0</ii>
|
|
||||||
</AR>
|
|
||||||
<AR>
|
|
||||||
<p>12</p>
|
|
||||||
<a>100</a>
|
|
||||||
<t>1</t>
|
|
||||||
<r>913</r>
|
|
||||||
<ii>0</ii>
|
|
||||||
</AR>
|
|
||||||
<AR>
|
|
||||||
<p>12</p>
|
|
||||||
<a>10</a>
|
|
||||||
<t>1</t>
|
|
||||||
<r>920</r>
|
|
||||||
<ii>0</ii>
|
|
||||||
</AR>
|
|
||||||
<AR>
|
|
||||||
<p>8</p>
|
|
||||||
<a>200</a>
|
|
||||||
<t>3</t>
|
|
||||||
<r>611</r>
|
|
||||||
<ii>0</ii>
|
|
||||||
</AR>
|
|
||||||
<AR>
|
|
||||||
<p>12</p>
|
|
||||||
<a>10</a>
|
|
||||||
<t>3</t>
|
|
||||||
<r>920</r>
|
|
||||||
<ii>0</ii>
|
|
||||||
</AR>
|
|
||||||
</AchievementsIdInfo>
|
|
||||||
<AchievementsIdInfo>
|
<AchievementsIdInfo>
|
||||||
<AID>201323</AID>
|
<AID>201323</AID>
|
||||||
<AR>
|
<AR>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user