Added support paging and filtering contract Web UI

Added Creator Steam ID to the contract Web UI
Added styling to the contract Web UI
Added support for singleplayer scores
Changed server port from 80 to 40147 to prevent issues for most users
Fixed issue where Web UI wouldn't show any contracts
Fixed exploit where self-made contracts could be replayed and earn you too much money
This commit is contained in:
Lennard Fonteijn 2023-07-18 22:18:28 +02:00
parent 8c6a678012
commit 266cbe81c6
13 changed files with 260 additions and 72 deletions

View File

@ -6,8 +6,8 @@ log=true
game=hm5
[hm5]
webserviceurl=http://localhost/hm5
webserviceurl=http://localhost:40147/hm5
skiplauncher=true
[sniper]
webserviceurl=http://localhost/sniper
webserviceurl=http://localhost:40147/sniper

View File

@ -6,8 +6,8 @@ log=true
game=hm5
[hm5]
webserviceurl=http://localhost/hm5
webserviceurl=http://localhost:40147/hm5
skiplauncher=true
[sniper]
webserviceurl=http://localhost/sniper
webserviceurl=http://localhost:40147/sniper

View File

@ -19,24 +19,25 @@ namespace HM5.Server.Controllers
return View("~/Views/Contracts.cshtml");
}
[HttpGet("all")]
public IActionResult GetContracts()
[HttpGet("all/{page}/{filter=}")]
public IActionResult GetContracts(int page, string filter = null)
{
const int pageSize = 1000;
const int pageSize = 20;
var contracts = _contractsService.GetContracts(new HitmanController.SearchForContracts2Request
{
LevelIndex = -1,
CheckpointId = -1,
Difficulty = -1,
ContractId = string.Empty,
StartIndex = 0,
ContractName = filter,
StartIndex = page * pageSize,
Range = pageSize
});
return Json(contracts.Select(x => new
{
x.Id,
x.UserId,
Name = x.DisplayId,
x.Description,
Level = _contractsService.GetLevelName(x),
@ -44,7 +45,7 @@ namespace HM5.Server.Controllers
.Select(y => y.Name)
.ToList(),
Difficulty = _contractsService.GetDifficultyName(x),
Score = x.UserScore
Score = x.HighestScoringFriendScore
}));
}
@ -53,7 +54,7 @@ namespace HM5.Server.Controllers
{
var contractLink = _contractsService.GetShareableContractLink(contractId);
return Json($"http://localhost/contracts/create/{contractLink}");
return Json($"http://localhost:40147/contracts/create/{contractLink}");
}
[HttpGet("create/{compressedBase64Contract}")]

View File

@ -1,7 +1,6 @@
using HM5.Server.Attributes;
using HM5.Server.Enums;
using HM5.Server.Interfaces;
using HM5.Server.Models;
using Microsoft.AspNetCore.Mvc;
namespace HM5.Server.Controllers.Hitman
@ -36,14 +35,7 @@ namespace HM5.Server.Controllers.Hitman
[Route("GetScoreComparison")]
public IActionResult GetScoreComparison([FromQuery] GetScoreComparisonRequest request)
{
return JsonEntryResponse(new ScoreComparison
{
//NOTE: Has to be a SteamID
FriendName = "76561198161220058",
FriendScore = 1337,
CountryAverage = 101,
WorldAverage = 101
});
return JsonEntryResponse(_hitmanServer.GetScoreComparison(request));
}
}
}

View File

@ -10,6 +10,7 @@
<ItemGroup>
<Content Remove="Contracts\**" />
<None Remove="Logs\**" />
<Content Remove="userprofile.json" />
</ItemGroup>
</Project>

View File

@ -6,8 +6,8 @@ namespace HM5.Server.Interfaces
public interface IContractsService
{
void RebuildCache();
void CreateContract(HitmanController.UploadContractRequest request);
void CreateContract(string compressedBase64Contract);
string CreateContract(HitmanController.UploadContractRequest request);
string CreateContract(string compressedBase64Contract);
void RemoveContract(string contractId);
IEnumerable<Contract> GetContracts(HitmanController.SearchForContracts2Request request, Func<Contract, bool> additionalFilter = null);
string GetShareableContractLink(string contractId);

View File

@ -21,5 +21,6 @@ namespace HM5.Server.Interfaces
List<Contract> SearchForContracts2(HitmanController.SearchForContracts2Request request);
void UpdateUserInfo(HitmanController.UpdateUserInfoRequest request);
void UploadContract(HitmanController.UploadContractRequest request);
ScoreComparison GetScoreComparison(HitmanController.GetScoreComparisonRequest request);
}
}

View File

@ -6,7 +6,7 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:80;https://localhost:443"
"applicationUrl": "http://localhost:40147"
}
}
}

View File

@ -61,7 +61,7 @@ namespace HM5.Server.Services
}
}
public void CreateContract(HitmanController.UploadContractRequest request)
public string CreateContract(HitmanController.UploadContractRequest request)
{
var simpleContract = new SimpleContract
{
@ -79,10 +79,10 @@ namespace HM5.Server.Services
Score = request.Score
};
CreateContract(simpleContract);
return CreateContract(simpleContract);
}
public void CreateContract(string compressedBase64Contract)
public string CreateContract(string compressedBase64Contract)
{
using var inputStream = new MemoryStream(
Base64UrlTextEncoder.Decode(compressedBase64Contract)
@ -95,7 +95,7 @@ namespace HM5.Server.Services
var simpleContract = JsonSerializer.Deserialize<SimpleContract>(outputStream.ToArray());
CreateContract(simpleContract);
return CreateContract(simpleContract);
}
public void RemoveContract(string contractId)
@ -118,7 +118,11 @@ namespace HM5.Server.Services
(request.LevelIndex == -1 || x.LevelIndex == request.LevelIndex) &&
(request.CheckpointId == -1 || x.CheckpointIndex == request.CheckpointId) &&
(request.Difficulty == -1 || x.Difficulty == request.Difficulty) &&
(request.ContractName == string.Empty || x.DisplayId.Contains(request.ContractName) || x.Title.Contains(request.ContractName, StringComparison.InvariantCultureIgnoreCase)) &&
(
string.IsNullOrWhiteSpace(request.ContractName) ||
x.DisplayId.Contains(request.ContractName) ||
x.Title.Contains(request.ContractName, StringComparison.InvariantCultureIgnoreCase)
) &&
(additionalFilter == null || additionalFilter(x))
)
.OrderBy(x => x.DisplayId)
@ -210,7 +214,7 @@ namespace HM5.Server.Services
};
}
private void CreateContract(SimpleContract simpleContract)
private string CreateContract(SimpleContract simpleContract)
{
var requestBytes = JsonSerializer.SerializeToUtf8Bytes(simpleContract);
using var sha1 = SHA1.Create();
@ -221,7 +225,7 @@ namespace HM5.Server.Services
if (File.Exists(contractsPath))
{
return;
return contractId;
}
var contract = MapSimpleContractToContract(contractId, simpleContract);
@ -230,6 +234,8 @@ namespace HM5.Server.Services
var contractJson = JsonSerializer.Serialize(simpleContract);
File.WriteAllTextAsync(contractsPath, contractJson);
return contractId;
}
private Contract MapSimpleContractToContract(string contractId, SimpleContract simpleContract)
@ -239,7 +245,7 @@ namespace HM5.Server.Services
Id = contractId,
DisplayId = simpleContract.Title,
UserId = simpleContract.UserId,
UserName = string.Empty,
UserName = simpleContract.UserId,
Title = simpleContract.Title,
Description = simpleContract.Description,
Targets = new TargetsWrapper

View File

@ -98,10 +98,17 @@ namespace HM5.Server.Services
.GetContracts(new HitmanController.SearchForContracts2Request
{
LevelIndex = request.LevelIndex,
CheckpointId = -1,
Difficulty = -1,
StartIndex = 0,
Range = 1
}, contract => !_userProfile.PlayedContracts.ContainsKey(contract.Id))
.FirstOrDefault();
}, contract => GetPlayedContract(contract.Id)?.Plays == 0)
.FirstOrDefault();
if (contract != null)
{
contract.UserScore = GetPlayedContract(contract.Id)?.Score ?? 0;
}
return contract;
}
@ -130,12 +137,7 @@ namespace HM5.Server.Services
{
SaveUserProfile(() =>
{
if (!_userProfile.PlayedContracts.TryGetValue(request.ContractId, out var playedContract))
{
playedContract = new UserProfile.PlayedContract();
_userProfile.PlayedContracts[request.ContractId] = playedContract;
}
var playedContract = GetOrAddPlayedContract(request.ContractId);
playedContract.Plays++;
});
@ -147,12 +149,7 @@ namespace HM5.Server.Services
SaveUserProfile(() =>
{
if (!_userProfile.PlayedContracts.TryGetValue(request.LeaderboardId, out var playedContract))
{
playedContract = new UserProfile.PlayedContract();
_userProfile.PlayedContracts[request.LeaderboardId] = playedContract;
}
var playedContract = GetOrAddPlayedContract(request.LeaderboardId);
difference = request.Score - playedContract.Score;
@ -162,7 +159,7 @@ namespace HM5.Server.Services
_userProfile.WalletAmount += difference;
}
_userProfile.PlayedContracts[request.LeaderboardId].Score = Math.Max(request.Score, playedContract.Score);
playedContract.Score = Math.Max(request.Score, playedContract.Score);
});
return difference;
@ -204,7 +201,9 @@ namespace HM5.Server.Services
contracts.ForEach(x =>
{
if (!_userProfile.PlayedContracts.TryGetValue(x.Id, out var playedContract))
var playedContract = GetPlayedContract(x.Id);
if (playedContract == null)
{
return;
}
@ -229,14 +228,35 @@ namespace HM5.Server.Services
public void UploadContract(HitmanController.UploadContractRequest request)
{
_contractsService.CreateContract(request);
var contractId = _contractsService.CreateContract(request);
SaveUserProfile(() =>
{
var playedContract = GetOrAddPlayedContract(contractId);
playedContract.Score = request.Score;
_userProfile.ContractsCreated++;
});
}
public ScoreComparison GetScoreComparison(HitmanController.GetScoreComparisonRequest request)
{
var playedContract = GetPlayedContract(request.LeaderboardId);
if (playedContract == null)
{
return null;
}
return new ScoreComparison
{
FriendName = _userProfile.UserId,
FriendScore = playedContract.Score,
CountryAverage = 0,
WorldAverage = 0
};
}
private UserProfile LoadUserProfile()
{
lock (_profileLock)
@ -276,5 +296,28 @@ namespace HM5.Server.Services
File.WriteAllText(USERPROFILE_PATH, JsonSerializer.Serialize(_userProfile));
}
}
private UserProfile.PlayedContract GetPlayedContract(string contractId)
{
return _userProfile.PlayedContracts.TryGetValue(contractId, out var playedContract)
? playedContract
: null;
}
private UserProfile.PlayedContract GetOrAddPlayedContract(string contractId)
{
var playedContract = GetPlayedContract(contractId);
if (playedContract != null)
{
return playedContract;
}
playedContract = new UserProfile.PlayedContract();
_userProfile.PlayedContracts[contractId] = playedContract;
return playedContract;
}
}
}

View File

@ -341,5 +341,17 @@ namespace HM5.Server.Services
{
//Do nothing
}
public ScoreComparison GetScoreComparison(HitmanController.GetScoreComparisonRequest request)
{
return new ScoreComparison
{
//NOTE: Has to be a SteamID
FriendName = "76561198161220058",
FriendScore = 1337,
CountryAverage = 101,
WorldAverage = 101
};
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:80"
"Url": "http://localhost:40147"
}
}
},