Convert to new namespace stuff and implicit usings

This commit is contained in:
AeonLucid
2022-01-07 06:07:05 +01:00
parent ce2ea7f295
commit 2f01cf7411
85 changed files with 2538 additions and 2696 deletions
@@ -1,8 +1,7 @@
namespace Prospect.Server.Api.Config
namespace Prospect.Server.Api.Config;
public class DatabaseSettings
{
public class DatabaseSettings
{
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}
@@ -1,8 +1,7 @@
namespace Prospect.Server.Api.Config
namespace Prospect.Server.Api.Config;
public class PlayFabSettings
{
public class PlayFabSettings
{
public string PublisherId { get; set; }
public string TitleId { get; set; }
}
public string PublisherId { get; set; }
public string TitleId { get; set; }
}
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Prospect.Server.Api.Config;
@@ -15,256 +12,258 @@ using Prospect.Server.Api.Services.Database.Models;
using Prospect.Server.Api.Services.UserData;
using Prospect.Server.Steam;
namespace Prospect.Server.Api.Controllers
namespace Prospect.Server.Api.Controllers;
[ApiController]
[Route("Client")]
public class ClientController : Controller
{
[ApiController]
[Route("Client")]
public class ClientController : Controller
{
private readonly PlayFabSettings _settings;
private readonly AuthTokenService _authTokenService;
private readonly DbUserService _userService;
private readonly DbEntityService _entityService;
private readonly UserDataService _userDataService;
private readonly TitleDataService _titleDataService;
public ClientController(IOptions<PlayFabSettings> settings,
AuthTokenService authTokenService,
DbUserService userService,
DbEntityService entityService,
UserDataService userDataService,
TitleDataService titleDataService)
{
_settings = settings.Value;
_authTokenService = authTokenService;
_userService = userService;
_entityService = entityService;
_userDataService = userDataService;
_titleDataService = titleDataService;
}
private const int AppIdDefault = 480;
private const int AppIdCycleBeta = 1600361;
[AllowAnonymous]
[HttpPost("LoginWithSteam")]
[Produces("application/json")]
public async Task<IActionResult> LoginWithSteam(ClientLoginWithSteamRequest request)
{
if (!string.IsNullOrEmpty(request.SteamTicket))
{
var ticket = AppTicket.Parse(request.SteamTicket);
if (ticket.IsValid && ticket.HasValidSignature)
{
var userSteamId = ticket.SteamId.ToString();
var user = await _userService.FindOrCreateAsync(PlayFabUserAuthType.Steam, userSteamId);
var entity = await _entityService.FindOrCreateAsync(user.Id);
var userTicket = _authTokenService.GenerateUser(entity);
var entityTicket = _authTokenService.GenerateEntity(entity);
private readonly PlayFabSettings _settings;
private readonly AuthTokenService _authTokenService;
private readonly DbUserService _userService;
private readonly DbEntityService _entityService;
private readonly UserDataService _userDataService;
private readonly TitleDataService _titleDataService;
await _userDataService.InitAsync(user.Id);
public ClientController(IOptions<PlayFabSettings> settings,
AuthTokenService authTokenService,
DbUserService userService,
DbEntityService entityService,
UserDataService userDataService,
TitleDataService titleDataService)
{
_settings = settings.Value;
_authTokenService = authTokenService;
_userService = userService;
_entityService = entityService;
_userDataService = userDataService;
_titleDataService = titleDataService;
}
[AllowAnonymous]
[HttpPost("LoginWithSteam")]
[Produces("application/json")]
public async Task<IActionResult> LoginWithSteam(ClientLoginWithSteamRequest request)
{
if (!string.IsNullOrEmpty(request.SteamTicket))
{
var ticket = AppTicket.Parse(request.SteamTicket);
if (ticket.IsValid && ticket.HasValidSignature && (ticket.AppId == AppIdDefault || ticket.AppId == AppIdCycleBeta))
{
var userSteamId = ticket.SteamId.ToString();
return Ok(new ClientResponse<FServerLoginResult>
var user = await _userService.FindOrCreateAsync(PlayFabUserAuthType.Steam, userSteamId);
var entity = await _entityService.FindOrCreateAsync(user.Id);
var userTicket = _authTokenService.GenerateUser(entity);
var entityTicket = _authTokenService.GenerateEntity(entity);
await _userDataService.InitAsync(user.Id);
return Ok(new ClientResponse<FServerLoginResult>
{
Code = 200,
Status = "OK",
Data = new FServerLoginResult
{
Code = 200,
Status = "OK",
Data = new FServerLoginResult
EntityToken = new FEntityTokenResponse
{
EntityToken = new FEntityTokenResponse
Entity = new FEntityKey
{
Entity = new FEntityKey
{
Id = entity.Id,
Type = "title_player_account",
TypeString = "title_player_account"
},
EntityToken = entityTicket,
TokenExpiration = DateTime.UtcNow.AddDays(6), // TODO:
Id = entity.Id,
Type = "title_player_account",
TypeString = "title_player_account"
},
InfoResultPayload = new FGetPlayerCombinedInfoResultPayload
EntityToken = entityTicket,
TokenExpiration = DateTime.UtcNow.AddDays(6), // TODO:
},
InfoResultPayload = new FGetPlayerCombinedInfoResultPayload
{
CharacterInventories = new List<object>(),
PlayerProfile = new FPlayerProfileModel
{
CharacterInventories = new List<object>(),
PlayerProfile = new FPlayerProfileModel
{
DisplayName = user.DisplayName,
PlayerId = user.Id,
PublisherId = _settings.PublisherId,
TitleId = _settings.TitleId
},
UserDataVersion = 0,
UserInventory = new List<object>(),
UserReadOnlyDataVersion = 0
DisplayName = user.DisplayName,
PlayerId = user.Id,
PublisherId = _settings.PublisherId,
TitleId = _settings.TitleId
},
LastLoginTime = DateTime.UtcNow, // TODO:
NewlyCreated = false, // TODO:
PlayFabId = user.Id,
SessionTicket = userTicket,
SettingsForUser = new FUserSettings
{
GatherDeviceInfo = true,
GatherFocusInfo = true,
NeedsAttribution = false,
},
TreatmentAssignment = new FTreatmentAssignment
{
Variables = new List<FVariable>(),
Variants = new List<string>()
}
UserDataVersion = 0,
UserInventory = new List<object>(),
UserReadOnlyDataVersion = 0
},
LastLoginTime = DateTime.UtcNow, // TODO:
NewlyCreated = false, // TODO:
PlayFabId = user.Id,
SessionTicket = userTicket,
SettingsForUser = new FUserSettings
{
GatherDeviceInfo = true,
GatherFocusInfo = true,
NeedsAttribution = false,
},
TreatmentAssignment = new FTreatmentAssignment
{
Variables = new List<FVariable>(),
Variants = new List<string>()
}
});
}
}
});
}
}
return BadRequest(new ClientResponse
{
Code = 400,
Status = "BadRequest",
Error = "InvalidSteamTicket",
ErrorCode = 1010,
ErrorMessage = "Steam API AuthenticateUserTicket error response .."
});
}
[HttpPost("AddGenericID")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult AddGenericId(FAddGenericIDRequest request)
return BadRequest(new ClientResponse
{
return Ok(new ClientResponse<object>
{
Code = 200,
Status = "OK",
Data = new object()
});
}
Code = 400,
Status = "BadRequest",
Error = "InvalidSteamTicket",
ErrorCode = 1010,
ErrorMessage = "Steam API AuthenticateUserTicket error response .."
});
}
[HttpPost("UpdateUserTitleDisplayName")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult UpdateUserTitleDisplayName(FUpdateUserTitleDisplayNameRequest request)
[HttpPost("AddGenericID")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult AddGenericId(FAddGenericIDRequest request)
{
return Ok(new ClientResponse<object>
{
return Ok(new ClientResponse<FUpdateUserTitleDisplayNameResult>
{
Code = 200,
Status = "OK",
Data = new FUpdateUserTitleDisplayNameResult
{
DisplayName = request.DisplayName
}
});
}
Code = 200,
Status = "OK",
Data = new {}
});
}
[HttpPost("UpdateUserData")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public async Task<IActionResult> UpdateUserData(FUpdateUserDataRequest request)
[HttpPost("UpdateUserTitleDisplayName")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult UpdateUserTitleDisplayName(FUpdateUserTitleDisplayNameRequest request)
{
return Ok(new ClientResponse<FUpdateUserTitleDisplayNameResult>
{
var userId = User.FindAuthUserId();
await _userDataService.UpdateAsync(userId, request.PlayFabId, request.Data);
Code = 200,
Status = "OK",
Data = new FUpdateUserTitleDisplayNameResult
{
DisplayName = request.DisplayName
}
});
}
[HttpPost("UpdateUserData")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public async Task<IActionResult> UpdateUserData(FUpdateUserDataRequest request)
{
var userId = User.FindAuthUserId();
await _userDataService.UpdateAsync(userId, request.PlayFabId, request.Data);
return Ok(new ClientResponse<FUpdateUserDataResult>
{
Code = 200,
Status = "OK",
Data = new FUpdateUserDataResult
{
DataVersion = 0
}
});
}
[HttpPost("GetUserData")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public async Task<IActionResult> GetUserData(FGetUserDataRequest request)
return Ok(new ClientResponse<FUpdateUserDataResult>
{
var userId = User.FindAuthUserId();
var userData = await _userDataService.FindAsync(userId, request.PlayFabId, request.Keys);
Code = 200,
Status = "OK",
Data = new FUpdateUserDataResult
{
DataVersion = 0
}
});
}
[HttpPost("GetUserData")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public async Task<IActionResult> GetUserData(FGetUserDataRequest request)
{
var userId = User.FindAuthUserId();
var userData = await _userDataService.FindAsync(userId, request.PlayFabId, request.Keys);
return Ok(new ClientResponse<FGetUserDataResult>
{
Code = 200,
Status = "OK",
Data = new FGetUserDataResult
{
Data = userData,
DataVersion = 0
}
});
}
[HttpPost("GetUserReadOnlyData")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult GetUserReadOnlyData(FGetUserDataRequest request)
return Ok(new ClientResponse<FGetUserDataResult>
{
return Ok(new ClientResponse<FGetUserDataResult>
Code = 200,
Status = "OK",
Data = new FGetUserDataResult
{
Code = 200,
Status = "OK",
Data = new FGetUserDataResult
{
Data = new Dictionary<string, FUserDataRecord>(),
DataVersion = 0
}
});
}
Data = userData,
DataVersion = 0
}
});
}
[HttpPost("GetUserInventory")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult GetUserReadOnlyData(FGetUserInventoryRequest request)
[HttpPost("GetUserReadOnlyData")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult GetUserReadOnlyData(FGetUserDataRequest request)
{
return Ok(new ClientResponse<FGetUserDataResult>
{
return Ok(new ClientResponse<FGetUserInventoryResult>
Code = 200,
Status = "OK",
Data = new FGetUserDataResult
{
Code = 200,
Status = "OK",
Data = new FGetUserInventoryResult
{
Inventory = new List<FItemInstance>
{
// new FItemInstance
// {
// ItemId = "Helmet_03",
// ItemInstanceId = "0102030405060708",
// ItemClass = "Helmet",
// PurchaseDate = DateTime.Now.AddDays(-1),
// CatalogVersion = "StaticItems",
// DisplayName = "Helmet",
// UnitPrice = 0,
// CustomData = new Dictionary<string, string>
// {
// ["insurance"] = "None",
// ["mods"] = "{\"m\":[]}",
// ["vanity_misc_data"] = "{\"v\":\"\",\"s\":\"\",\"l\":3,\"a\":1,\"d\":300}"
// }
// }
},
VirtualCurrency = new Dictionary<string, int>
{
["AE"] = 0,
["AS"] = 0,
["AU"] = int.MaxValue,
["SC"] = int.MaxValue
},
VirtualCurrencyRechargeTimes = new Dictionary<string, FVirtualCurrencyRechargeTime>()
}
});
}
Data = new Dictionary<string, FUserDataRecord>(),
DataVersion = 0
}
});
}
[HttpPost("GetTitleData")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult GetTitleData(FGetTitleDataRequest request)
[HttpPost("GetUserInventory")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult GetUserReadOnlyData(FGetUserInventoryRequest request)
{
return Ok(new ClientResponse<FGetUserInventoryResult>
{
return Ok(new ClientResponse<FGetTitleDataResult>
Code = 200,
Status = "OK",
Data = new FGetUserInventoryResult
{
Code = 200,
Status = "OK",
Data = new FGetTitleDataResult()
Inventory = new List<FItemInstance>
{
Data = _titleDataService.Find(request.Keys)
}
});
}
// new FItemInstance
// {
// ItemId = "Helmet_03",
// ItemInstanceId = "0102030405060708",
// ItemClass = "Helmet",
// PurchaseDate = DateTime.Now.AddDays(-1),
// CatalogVersion = "StaticItems",
// DisplayName = "Helmet",
// UnitPrice = 0,
// CustomData = new Dictionary<string, string>
// {
// ["insurance"] = "None",
// ["mods"] = "{\"m\":[]}",
// ["vanity_misc_data"] = "{\"v\":\"\",\"s\":\"\",\"l\":3,\"a\":1,\"d\":300}"
// }
// }
},
VirtualCurrency = new Dictionary<string, int>
{
["AE"] = 0,
["AS"] = 0,
["AU"] = int.MaxValue,
["SC"] = int.MaxValue
},
VirtualCurrencyRechargeTimes = new Dictionary<string, FVirtualCurrencyRechargeTime>()
}
});
}
[HttpPost("GetTitleData")]
[Produces("application/json")]
[Authorize(AuthenticationSchemes = UserAuthenticationOptions.DefaultScheme)]
public IActionResult GetTitleData(FGetTitleDataRequest request)
{
return Ok(new ClientResponse<FGetTitleDataResult>
{
Code = 200,
Status = "OK",
Data = new FGetTitleDataResult()
{
Data = _titleDataService.Find(request.Keys)
}
});
}
}
@@ -1,306 +1,302 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Prospect.Server.Api.Models.Client;
using Prospect.Server.Api.Models.CloudScript;
using Prospect.Server.Api.Models.CloudScript.Data;
using Prospect.Server.Api.Services.Auth.Entity;
using Prospect.Server.Api.Services.Auth.Extensions;
namespace Prospect.Server.Api.Controllers
namespace Prospect.Server.Api.Controllers;
[Route("CloudScript")]
[ApiController]
[Authorize(AuthenticationSchemes = EntityAuthenticationOptions.DefaultScheme)]
public class CloudScriptController : Controller
{
[Route("CloudScript")]
[ApiController]
[Authorize(AuthenticationSchemes = EntityAuthenticationOptions.DefaultScheme)]
public class CloudScriptController : Controller
private readonly ILogger<CloudScriptController> _logger;
public CloudScriptController(ILogger<CloudScriptController> logger)
{
private readonly ILogger<CloudScriptController> _logger;
public CloudScriptController(ILogger<CloudScriptController> logger)
{
_logger = logger;
}
_logger = logger;
}
[HttpPost("ExecuteFunction")]
[Produces("application/json")]
public IActionResult ExecuteFunction(FExecuteFunctionRequest request)
[HttpPost("ExecuteFunction")]
[Produces("application/json")]
public IActionResult ExecuteFunction(FExecuteFunctionRequest request)
{
_logger.LogInformation("Executing function {Function}", request.FunctionName);
object result = null;
switch (request.FunctionName)
{
_logger.LogInformation("Executing function {Function}", request.FunctionName);
object result = null;
switch (request.FunctionName)
{
case "RequestMaintenanceModeState":
result = new
{
enabled = false
};
break;
case "GetCharacterVanity":
result = new
case "RequestMaintenanceModeState":
result = new
{
enabled = false
};
break;
case "GetCharacterVanity":
result = new
{
userId = User.FindAuthUserId(),
error = (object) null,
returnVanity = new
{
userId = User.FindAuthUserId(),
error = (object) null,
returnVanity = new
head_item = new
{
userId = User.FindAuthUserId(),
head_item = new
{
id = "Black02M_Head1",
materialIndex = 0,
},
boots_item = new
{
id = "StarterOutfit01_Boots_M",
materialIndex = 0,
},
chest_item = new
{
id = "StarterOutfit01_Chest_M",
materialIndex = 0,
},
glove_item = new
{
id = "StarterOutfit01_Gloves_M",
materialIndex = 0,
},
base_suit_item = new
{
id = "StarterOutfit01M_BaseSuit",
materialIndex = 0,
},
melee_weapon_item = new
{
id = "Melee_Omega",
materialIndex = 0,
},
body_type = 1,
archetype_id = "TheProspector",
slot_index = 0
}
};
break;
case "SetMatchAllowJoin":
result = new
{
sessionId = (object)null,
success = false
};
break;
case "GetFriendList":
// TODO: ?
result = new
{
};
break;
case "GetPlayerSets":
result = new
{
success = true,
entries = new []
{
new
{
setData = new
{
id = "",
userId = User.FindAuthUserId(),
kit = "",
shield = "",
helmet = "",
weaponOne = "",
weaponTwo = "",
bag = "",
bagItemsAsJsonStr = "",
safeItemsAsJsonStr = ""
},
items = Array.Empty<object>()
}
}
};
break;
case "RequestFactionProgression":
result = new
{
factions = new []
{
new
{
factionId = "ICA",
currentProgression = 0
},
new
{
factionId = "Korolev",
currentProgression = 0
},
new
{
factionId = "Osiris",
currentProgression = 0
},
id = "Black02M_Head1",
materialIndex = 0,
},
userId = User.FindAuthUserId(),
error = ""
};
break;
case "GetPlayersInventoriesLimits":
result = new
{
success = true,
entries = new []
boots_item = new
{
new {
id = "StarterOutfit01_Boots_M",
materialIndex = 0,
},
chest_item = new
{
id = "StarterOutfit01_Chest_M",
materialIndex = 0,
},
glove_item = new
{
id = "StarterOutfit01_Gloves_M",
materialIndex = 0,
},
base_suit_item = new
{
id = "StarterOutfit01M_BaseSuit",
materialIndex = 0,
},
melee_weapon_item = new
{
id = "Melee_Omega",
materialIndex = 0,
},
body_type = 1,
archetype_id = "TheProspector",
slot_index = 0
}
};
break;
case "SetMatchAllowJoin":
result = new
{
sessionId = (object)null,
success = false
};
break;
case "GetFriendList":
// TODO: ?
result = new
{
};
break;
case "GetPlayerSets":
result = new
{
success = true,
entries = new []
{
new
{
setData = new
{
id = "",
userId = User.FindAuthUserId(),
inventoryStashLimit = 75,
inventoryBagLimit = 300,
inventorySafeLimit = 5
}
kit = "",
shield = "",
helmet = "",
weaponOne = "",
weaponTwo = "",
bag = "",
bagItemsAsJsonStr = "",
safeItemsAsJsonStr = ""
},
items = Array.Empty<object>()
}
};
break;
case "UpdateRetentionBonus":
result = new
}
};
break;
case "RequestFactionProgression":
result = new
{
factions = new []
{
playerData = new
new
{
daysClaimed = 0,
lastClaimTime = new
{
seconds = 1635033600
}
factionId = "ICA",
currentProgression = 0
},
userId = User.FindAuthUserId(),
error = (object)null
};
break;
case "GetCraftingInProgressData":
result = new FYGetCraftingInProgressDataResult
{
UserId = User.FindAuthUserId(),
Error = null,
ItemCurrentlyBeingCrafted = new FYItemCurrentlyBeingCrafted
new
{
ItemId = null,
ItemRarity = -1,
PurchaseAmount = -1,
UtcTimestampWhenCraftingStarted = new FYTimestamp
{
Seconds = 0
}
factionId = "Korolev",
currentProgression = 0
},
new
{
factionId = "Osiris",
currentProgression = 0
},
},
userId = User.FindAuthUserId(),
error = ""
};
break;
case "GetPlayersInventoriesLimits":
result = new
{
success = true,
entries = new []
{
new {
userId = User.FindAuthUserId(),
inventoryStashLimit = 75,
inventoryBagLimit = 300,
inventorySafeLimit = 5
}
};
break;
case "RequestPlayerContracts":
result = new FYGetPlayerContractsResult
}
};
break;
case "UpdateRetentionBonus":
result = new
{
playerData = new
{
UserId = User.FindAuthUserId(),
Error = null,
ActiveContracts = new List<FYActiveContractPlayerData>(),
FactionsContracts = new FYFactionsContractsData
daysClaimed = 0,
lastClaimTime = new
{
Boards = new List<FYFactionContractsData>
seconds = 1635033600
}
},
userId = User.FindAuthUserId(),
error = (object)null
};
break;
case "GetCraftingInProgressData":
result = new FYGetCraftingInProgressDataResult
{
UserId = User.FindAuthUserId(),
Error = null,
ItemCurrentlyBeingCrafted = new FYItemCurrentlyBeingCrafted
{
ItemId = null,
ItemRarity = -1,
PurchaseAmount = -1,
UtcTimestampWhenCraftingStarted = new FYTimestamp
{
Seconds = 0
}
}
};
break;
case "RequestPlayerContracts":
result = new FYGetPlayerContractsResult
{
UserId = User.FindAuthUserId(),
Error = null,
ActiveContracts = new List<FYActiveContractPlayerData>(),
FactionsContracts = new FYFactionsContractsData
{
Boards = new List<FYFactionContractsData>
{
new FYFactionContractsData
{
new FYFactionContractsData
FactionId = "ICA",
Contracts = new List<FYFactionContractData>
{
FactionId = "ICA",
Contracts = new List<FYFactionContractData>
new FYFactionContractData
{
new FYFactionContractData
{
ContractId = "NEW-Easy-ICA-Gather-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-ICA-Uplink-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-ICA-Uplink-1",
ContractIsLockedDueToLowFactionReputation = false
}
}
},
new FYFactionContractsData
{
FactionId = "Korolev",
Contracts = new List<FYFactionContractData>
ContractId = "NEW-Easy-ICA-Gather-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
new FYFactionContractData
{
ContractId = "NEW-Easy-KOR-Mine-4",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-KOR-Mine-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-KOR-PvP-6",
ContractIsLockedDueToLowFactionReputation = false
}
}
},
new FYFactionContractsData
{
FactionId = "Osiris",
Contracts = new List<FYFactionContractData>
ContractId = "NEW-Medium-ICA-Uplink-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
new FYFactionContractData
{
ContractId = "NEW-Easy-Osiris-Brightcaps-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-Osiris-Gather-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-Osiris-Gather-7",
ContractIsLockedDueToLowFactionReputation = false
}
ContractId = "NEW-Hard-ICA-Uplink-1",
ContractIsLockedDueToLowFactionReputation = false
}
}
},
LastBoardRefreshTimeUtc = new FYTimestamp
new FYFactionContractsData
{
Seconds = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()
FactionId = "Korolev",
Contracts = new List<FYFactionContractData>
{
new FYFactionContractData
{
ContractId = "NEW-Easy-KOR-Mine-4",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-KOR-Mine-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-KOR-PvP-6",
ContractIsLockedDueToLowFactionReputation = false
}
}
},
new FYFactionContractsData
{
FactionId = "Osiris",
Contracts = new List<FYFactionContractData>
{
new FYFactionContractData
{
ContractId = "NEW-Easy-Osiris-Brightcaps-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-Osiris-Gather-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-Osiris-Gather-7",
ContractIsLockedDueToLowFactionReputation = false
}
}
}
},
RefreshHours24UtcFromBackend = 12
};
break;
default:
_logger.LogWarning("Missing function {Function}", request.FunctionName);
LastBoardRefreshTimeUtc = new FYTimestamp
{
Seconds = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()
}
},
RefreshHours24UtcFromBackend = 12
};
break;
default:
_logger.LogWarning("Missing function {Function}", request.FunctionName);
result = new
{
};
break;
}
return Ok(new ClientResponse<FExecuteFunctionResult>
{
Code = 200,
Status = "OK",
Data = new FExecuteFunctionResult
result = new
{
ExecutionTimeMilliseconds = 12,
FunctionName = request.FunctionName,
FunctionResult = result
}
});
};
break;
}
return Ok(new ClientResponse<FExecuteFunctionResult>
{
Code = 200,
Status = "OK",
Data = new FExecuteFunctionResult
{
ExecutionTimeMilliseconds = 12,
FunctionName = request.FunctionName,
FunctionResult = result
}
});
}
}
@@ -1,24 +1,22 @@
using System;
using System.Diagnostics;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Converters
{
// By default System.Text.Json outputs and we want:
// Output: 2021-11-04T04:58:20.4232184Z
// Want : 2021-10-24T02:54:56.652Z
public class DateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Debug.Assert(typeToConvert == typeof(DateTime));
return DateTime.Parse(reader.GetString());
}
namespace Prospect.Server.Api.Converters;
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK"));
}
// By default System.Text.Json outputs and we want:
// Output: 2021-11-04T04:58:20.4232184Z
// Want : 2021-10-24T02:54:56.652Z
public class DateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Debug.Assert(typeToConvert == typeof(DateTime));
return DateTime.Parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK"));
}
}
@@ -1,24 +1,22 @@
using System;
using System.Runtime.Serialization;
using System.Runtime.Serialization;
namespace Prospect.Server.Api.Exceptions
namespace Prospect.Server.Api.Exceptions;
public class ProspectException : Exception
{
public class ProspectException : Exception
public ProspectException()
{
public ProspectException()
{
}
}
protected ProspectException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
protected ProspectException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
public ProspectException(string message) : base(message)
{
}
public ProspectException(string message) : base(message)
{
}
public ProspectException(string message, Exception innerException) : base(message, innerException)
{
}
public ProspectException(string message, Exception innerException) : base(message, innerException)
{
}
}
@@ -1,64 +1,59 @@
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using System.Text;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace Prospect.Server.Api.Middleware
namespace Prospect.Server.Api.Middleware;
public class RequestLoggerMiddleware
{
public class RequestLoggerMiddleware
private readonly ILogger<RequestLoggerMiddleware> _logger;
private readonly RequestDelegate _next;
public RequestLoggerMiddleware(ILogger<RequestLoggerMiddleware> logger, RequestDelegate next)
{
private readonly ILogger<RequestLoggerMiddleware> _logger;
private readonly RequestDelegate _next;
_logger = logger;
_next = next;
}
public RequestLoggerMiddleware(ILogger<RequestLoggerMiddleware> logger, RequestDelegate next)
public async Task Invoke(HttpContext context)
{
var body = await RequestAsync(context.Request);
if (context.Request.Method == "POST")
{
_logger = logger;
_next = next;
}
public async Task Invoke(HttpContext context)
{
var body = await RequestAsync(context.Request);
if (context.Request.Method == "POST")
var requestId = "NULL";
if (context.Request.Headers.TryGetValue("X-RequestID", out var requestIdValues))
{
var requestId = "NULL";
if (context.Request.Headers.TryGetValue("X-RequestID", out var requestIdValues))
{
requestId = requestIdValues.ToString();
}
_logger.LogDebug("URL {Url} RequestId {RequestId} Body {Body}", context.Request.GetDisplayUrl(), requestId, body);
requestId = requestIdValues.ToString();
}
_logger.LogDebug("URL {Url} RequestId {RequestId} Body {Body}", context.Request.GetDisplayUrl(), requestId, body);
}
await _next(context);
}
await _next(context);
}
private static async Task<string> RequestAsync(HttpRequest request)
private static async Task<string> RequestAsync(HttpRequest request)
{
request.EnableBuffering();
try
{
request.EnableBuffering();
try
using (var reader = new StreamReader(request.Body, Encoding.UTF8, false, 4096, true))
{
using (var reader = new StreamReader(request.Body, Encoding.UTF8, false, 4096, true))
var body = await reader.ReadToEndAsync();
if (body.StartsWith("{"))
{
var body = await reader.ReadToEndAsync();
if (body.StartsWith("{"))
{
return JsonConvert.SerializeObject(JsonConvert.DeserializeObject(body), Formatting.Indented);
}
return body;
return JsonConvert.SerializeObject(JsonConvert.DeserializeObject(body), Formatting.Indented);
}
return body;
}
finally
{
request.Body.Position = 0;
}
}
finally
{
request.Body.Position = 0;
}
}
}
@@ -1,59 +1,58 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class ClientLoginWithSteamRequest
{
public class ClientLoginWithSteamRequest
{
[JsonPropertyName("CreateAccount")]
public bool CreateAccount { get; set; }
[JsonPropertyName("CreateAccount")]
public bool CreateAccount { get; set; }
[JsonPropertyName("CustomTags")]
public JsonDocument CustomTags { get; set; }
[JsonPropertyName("CustomTags")]
public JsonDocument CustomTags { get; set; }
[JsonPropertyName("EncryptedRequest")]
public string EncryptedRequest { get; set; }
[JsonPropertyName("EncryptedRequest")]
public string EncryptedRequest { get; set; }
[JsonPropertyName("InfoRequestParameters")]
public InfoParameters InfoRequestParameters { get; set; }
[JsonPropertyName("InfoRequestParameters")]
public InfoParameters InfoRequestParameters { get; set; }
[JsonPropertyName("PlayerSecret")]
public string PlayerSecret { get; set; }
[JsonPropertyName("PlayerSecret")]
public string PlayerSecret { get; set; }
[JsonPropertyName("SteamTicket")]
public string SteamTicket { get; set; }
}
[JsonPropertyName("SteamTicket")]
public string SteamTicket { get; set; }
}
public class InfoParameters
{
[JsonPropertyName("GetCharacterInventories")]
public bool GetCharacterInventories { get; set; }
public class InfoParameters
{
[JsonPropertyName("GetCharacterInventories")]
public bool GetCharacterInventories { get; set; }
[JsonPropertyName("GetCharacterList")]
public bool GetCharacterList { get; set; }
[JsonPropertyName("GetCharacterList")]
public bool GetCharacterList { get; set; }
[JsonPropertyName("GetPlayerProfile")]
public bool GetPlayerProfile { get; set; }
[JsonPropertyName("GetPlayerProfile")]
public bool GetPlayerProfile { get; set; }
[JsonPropertyName("GetPlayerStatistics")]
public bool GetPlayerStatistics { get; set; }
[JsonPropertyName("GetPlayerStatistics")]
public bool GetPlayerStatistics { get; set; }
[JsonPropertyName("GetTitleData")]
public bool GetTitleData { get; set; }
[JsonPropertyName("GetTitleData")]
public bool GetTitleData { get; set; }
[JsonPropertyName("GetUserAccountInfo")]
public bool GetUserAccountInfo { get; set; }
[JsonPropertyName("GetUserAccountInfo")]
public bool GetUserAccountInfo { get; set; }
[JsonPropertyName("GetUserData")]
public bool GetUserData { get; set; }
[JsonPropertyName("GetUserData")]
public bool GetUserData { get; set; }
[JsonPropertyName("GetUserInventory")]
public bool GetUserInventory { get; set; }
[JsonPropertyName("GetUserInventory")]
public bool GetUserInventory { get; set; }
[JsonPropertyName("GetUserReadOnlyData")]
public bool GetUserReadOnlyData { get; set; }
[JsonPropertyName("GetUserReadOnlyData")]
public bool GetUserReadOnlyData { get; set; }
[JsonPropertyName("GetUserVirtualCurrency")]
public bool GetUserVirtualCurrency { get; set; }
}
[JsonPropertyName("GetUserVirtualCurrency")]
public bool GetUserVirtualCurrency { get; set; }
}
@@ -1,32 +1,31 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class ClientResponse
{
public class ClientResponse
{
[JsonPropertyName("code")]
public int Code { get; set; }
[JsonPropertyName("code")]
public int Code { get; set; }
[JsonPropertyName("status")]
public string Status { get; set; }
[JsonPropertyName("status")]
public string Status { get; set; }
[JsonPropertyName("error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Error { get; set; }
[JsonPropertyName("error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Error { get; set; }
[JsonPropertyName("errorCode")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int ErrorCode { get; set; }
[JsonPropertyName("errorCode")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int ErrorCode { get; set; }
[JsonPropertyName("errorMessage")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string ErrorMessage { get; set; }
}
[JsonPropertyName("errorMessage")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string ErrorMessage { get; set; }
}
public class ClientResponse<T> : ClientResponse
{
[JsonPropertyName("data")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public T Data { get; set; }
}
public class ClientResponse<T> : ClientResponse
{
[JsonPropertyName("data")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public T Data { get; set; }
}
@@ -1,9 +1,8 @@
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public enum CloudScriptRevisionOption
{
public enum CloudScriptRevisionOption
{
Live,
Latest,
Specific
}
Live,
Latest,
Specific
}
@@ -1,23 +1,22 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FEntityKey
{
public class FEntityKey
{
/// <summary>
/// Unique ID of the entity.
/// </summary>
[JsonPropertyName("Id")]
public string Id { get; set; }
/// <summary>
/// Unique ID of the entity.
/// </summary>
[JsonPropertyName("Id")]
public string Id { get; set; }
/// <summary>
/// [optional] Entity type. See https://docs.microsoft.com/gaming/playfab/features/data/entities/available-built-in-entity-types
/// </summary>
[JsonPropertyName("Type")]
public string Type { get; set; }
/// <summary>
/// [optional] Entity type. See https://docs.microsoft.com/gaming/playfab/features/data/entities/available-built-in-entity-types
/// </summary>
[JsonPropertyName("Type")]
public string Type { get; set; }
// Not in PlayFab SDK
[JsonPropertyName("TypeString")]
public string TypeString { get; set; }
}
// Not in PlayFab SDK
[JsonPropertyName("TypeString")]
public string TypeString { get; set; }
}
@@ -1,29 +1,27 @@
using System;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FEntityTokenResponse
{
public class FEntityTokenResponse
{
/// <summary>
/// [optional] The entity id and type.
/// </summary>
[JsonPropertyName("Entity")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FEntityKey Entity { get; set; }
/// <summary>
/// [optional] The entity id and type.
/// </summary>
[JsonPropertyName("Entity")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FEntityKey Entity { get; set; }
/// <summary>
/// [optional] The token used to set X-EntityToken for all entity based API calls.
/// </summary>
[JsonPropertyName("EntityToken")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string EntityToken { get; set; }
/// <summary>
/// [optional] The token used to set X-EntityToken for all entity based API calls.
/// </summary>
[JsonPropertyName("EntityToken")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string EntityToken { get; set; }
/// <summary>
/// [optional] The time the token will expire, if it is an expiring token, in UTC.
/// </summary>
[JsonPropertyName("TokenExpiration")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public DateTime? TokenExpiration { get; set; }
}
/// <summary>
/// [optional] The time the token will expire, if it is an expiring token, in UTC.
/// </summary>
[JsonPropertyName("TokenExpiration")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public DateTime? TokenExpiration { get; set; }
}
@@ -1,29 +1,28 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FFunctionExecutionError
{
public class FFunctionExecutionError
{
/// <summary>
/// [optional] Error code, such as CloudScriptAzureFunctionsExecutionTimeLimitExceeded, CloudScriptAzureFunctionsArgumentSizeExceeded,
/// CloudScriptAzureFunctionsReturnSizeExceeded or CloudScriptAzureFunctionsHTTPRequestError
/// </summary>
[JsonPropertyName("Error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Error { get; set; }
/// <summary>
/// [optional] Error code, such as CloudScriptAzureFunctionsExecutionTimeLimitExceeded, CloudScriptAzureFunctionsArgumentSizeExceeded,
/// CloudScriptAzureFunctionsReturnSizeExceeded or CloudScriptAzureFunctionsHTTPRequestError
/// </summary>
[JsonPropertyName("Error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Error { get; set; }
/// <summary>
/// [optional] Details about the error
/// </summary>
[JsonPropertyName("Message")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Message { get; set; }
/// <summary>
/// [optional] Details about the error
/// </summary>
[JsonPropertyName("Message")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Message { get; set; }
/// <summary>
/// [optional] Point during the execution of the function at which the error occurred, if any
/// </summary>
[JsonPropertyName("StackTrace")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string StackTrace { get; set; }
}
/// <summary>
/// [optional] Point during the execution of the function at which the error occurred, if any
/// </summary>
[JsonPropertyName("StackTrace")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string StackTrace { get; set; }
}
@@ -1,19 +1,18 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FGenericServiceId
{
public class FGenericServiceId
{
/// <summary>
/// Name of the service for which the player has a unique identifier.
/// </summary>
[JsonPropertyName("ServiceName")]
public string ServiceName { get; set; }
/// <summary>
/// Name of the service for which the player has a unique identifier.
/// </summary>
[JsonPropertyName("ServiceName")]
public string ServiceName { get; set; }
/// <summary>
/// Unique identifier of the player in that service.
/// </summary>
[JsonPropertyName("UserId")]
public string UserId { get; set; }
}
/// <summary>
/// Unique identifier of the player in that service.
/// </summary>
[JsonPropertyName("UserId")]
public string UserId { get; set; }
}
@@ -1,60 +1,58 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FGetPlayerCombinedInfoResultPayload
{
public class FGetPlayerCombinedInfoResultPayload
{
// TSharedPtr<FUserAccountInfo> AccountInfo;
// TSharedPtr<FUserAccountInfo> AccountInfo;
/// <summary>
/// [optional] Inventories for each character for the user.
/// </summary>
[JsonPropertyName("CharacterInventories")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<object> CharacterInventories { get; set; }
/// <summary>
/// [optional] Inventories for each character for the user.
/// </summary>
[JsonPropertyName("CharacterInventories")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<object> CharacterInventories { get; set; }
// TArray<FCharacterResult> CharacterList;
// TArray<FCharacterResult> CharacterList;
/// <summary>
/// [optional] The profile of the players. This profile is not guaranteed to be up-to-date. For a new player, this profile will not
/// exist.
/// </summary>
[JsonPropertyName("PlayerProfile")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FPlayerProfileModel PlayerProfile { get; set; }
/// <summary>
/// [optional] The profile of the players. This profile is not guaranteed to be up-to-date. For a new player, this profile will not
/// exist.
/// </summary>
[JsonPropertyName("PlayerProfile")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FPlayerProfileModel PlayerProfile { get; set; }
// TArray<FStatisticValue> PlayerStatistics;
// TArray<FStatisticValue> PlayerStatistics;
// TMap<FString, FString> TitleData;
// TMap<FString, FString> TitleData;
// TMap<FString, FUserDataRecord> UserData;
// TMap<FString, FUserDataRecord> UserData;
/// <summary>
/// The version of the UserData that was returned.
/// </summary>
[JsonPropertyName("UserDataVersion")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint? UserDataVersion { get; set; }
/// <summary>
/// The version of the UserData that was returned.
/// </summary>
[JsonPropertyName("UserDataVersion")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint? UserDataVersion { get; set; }
/// <summary>
/// [optional] Array of inventory items in the user's current inventory.
/// </summary>
[JsonPropertyName("UserInventory")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<object> UserInventory { get; set; }
/// <summary>
/// [optional] Array of inventory items in the user's current inventory.
/// </summary>
[JsonPropertyName("UserInventory")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<object> UserInventory { get; set; }
// TMap<FString, FUserDataRecord> UserReadOnlyData;
// TMap<FString, FUserDataRecord> UserReadOnlyData;
/// <summary>
/// The version of the Read-Only UserData that was returned.
/// </summary>
[JsonPropertyName("UserReadOnlyDataVersion")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint? UserReadOnlyDataVersion { get; set; }
/// <summary>
/// The version of the Read-Only UserData that was returned.
/// </summary>
[JsonPropertyName("UserReadOnlyDataVersion")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint? UserReadOnlyDataVersion { get; set; }
// TMap<FString, int32> UserVirtualCurrency;
// TMap<FString, int32> UserVirtualCurrency;
// TMap<FString, FVirtualCurrencyRechargeTime> UserVirtualCurrencyRechargeTimes;
}
// TMap<FString, FVirtualCurrencyRechargeTime> UserVirtualCurrencyRechargeTimes;
}
@@ -1,116 +1,113 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FItemInstance
{
public class FItemInstance
{
/// <summary>
/// [optional] Game specific comment associated with this instance when it was added to the user inventory.
/// </summary>
[JsonPropertyName("Annotation")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Annotation { get; set; }
/// <summary>
/// [optional] Game specific comment associated with this instance when it was added to the user inventory.
/// </summary>
[JsonPropertyName("Annotation")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Annotation { get; set; }
/// <summary>
/// [optional] Array of unique items that were awarded when this catalog item was purchased.
/// </summary>
[JsonPropertyName("BundleContents")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<string> BundleContents { get; set; }
/// <summary>
/// [optional] Array of unique items that were awarded when this catalog item was purchased.
/// </summary>
[JsonPropertyName("BundleContents")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<string> BundleContents { get; set; }
/// <summary>
/// [optional] Unique identifier for the parent inventory item, as defined in the catalog, for object which were added from a bundle or
/// container.
/// </summary>
[JsonPropertyName("BundleParent")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string BundleParent { get; set; }
/// <summary>
/// [optional] Unique identifier for the parent inventory item, as defined in the catalog, for object which were added from a bundle or
/// container.
/// </summary>
[JsonPropertyName("BundleParent")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string BundleParent { get; set; }
/// <summary>
/// [optional] Catalog version for the inventory item, when this instance was created.
/// </summary>
[JsonPropertyName("CatalogVersion")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string CatalogVersion { get; set; }
/// <summary>
/// [optional] Catalog version for the inventory item, when this instance was created.
/// </summary>
[JsonPropertyName("CatalogVersion")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string CatalogVersion { get; set; }
/// <summary>
/// [optional] A set of custom key-value pairs on the instance of the inventory item, which is not to be confused with the catalog
/// item's custom data.
/// </summary>
[JsonPropertyName("CustomData")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomData { get; set; }
/// <summary>
/// [optional] A set of custom key-value pairs on the instance of the inventory item, which is not to be confused with the catalog
/// item's custom data.
/// </summary>
[JsonPropertyName("CustomData")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomData { get; set; }
/// <summary>
/// [optional] CatalogItem.DisplayName at the time this item was purchased.
/// </summary>
[JsonPropertyName("DisplayName")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string DisplayName { get; set; }
/// <summary>
/// [optional] CatalogItem.DisplayName at the time this item was purchased.
/// </summary>
[JsonPropertyName("DisplayName")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string DisplayName { get; set; }
/// <summary>
/// [optional] Timestamp for when this instance will expire.
/// </summary>
[JsonPropertyName("Expiration")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public DateTime? Expiration { get; set; }
/// <summary>
/// [optional] Timestamp for when this instance will expire.
/// </summary>
[JsonPropertyName("Expiration")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public DateTime? Expiration { get; set; }
/// <summary>
/// [optional] Class name for the inventory item, as defined in the catalog.
/// </summary>
[JsonPropertyName("ItemClass")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string ItemClass { get; set; }
/// <summary>
/// [optional] Class name for the inventory item, as defined in the catalog.
/// </summary>
[JsonPropertyName("ItemClass")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string ItemClass { get; set; }
/// <summary>
/// [optional] Unique identifier for the inventory item, as defined in the catalog.
/// </summary>
[JsonPropertyName("ItemId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string ItemId { get; set; }
/// <summary>
/// [optional] Unique identifier for the inventory item, as defined in the catalog.
/// </summary>
[JsonPropertyName("ItemId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string ItemId { get; set; }
/// <summary>
/// [optional] Unique item identifier for this specific instance of the item.
/// </summary>
[JsonPropertyName("ItemInstanceId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string ItemInstanceId { get; set; }
/// <summary>
/// [optional] Unique item identifier for this specific instance of the item.
/// </summary>
[JsonPropertyName("ItemInstanceId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string ItemInstanceId { get; set; }
/// <summary>
/// [optional] Timestamp for when this instance was purchased.
/// </summary>
[JsonPropertyName("PurchaseDate")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public DateTime? PurchaseDate { get; set; }
/// <summary>
/// [optional] Timestamp for when this instance was purchased.
/// </summary>
[JsonPropertyName("PurchaseDate")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public DateTime? PurchaseDate { get; set; }
/// <summary>
/// [optional] Total number of remaining uses, if this is a consumable item.
/// </summary>
[JsonPropertyName("RemainingUses")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int? RemainingUses { get; set; }
/// <summary>
/// [optional] Total number of remaining uses, if this is a consumable item.
/// </summary>
[JsonPropertyName("RemainingUses")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int? RemainingUses { get; set; }
/// <summary>
/// [optional] Currency type for the cost of the catalog item. Not available when granting items.
/// </summary>
[JsonPropertyName("UnitCurrency")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string UnitCurrency { get; set; }
/// <summary>
/// [optional] Currency type for the cost of the catalog item. Not available when granting items.
/// </summary>
[JsonPropertyName("UnitCurrency")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string UnitCurrency { get; set; }
/// <summary>
/// Cost of the catalog item in the given currency. Not available when granting items.
/// </summary>
[JsonPropertyName("UnitPrice")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint? UnitPrice { get; set; }
/// <summary>
/// Cost of the catalog item in the given currency. Not available when granting items.
/// </summary>
[JsonPropertyName("UnitPrice")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public uint? UnitPrice { get; set; }
/// <summary>
/// [optional] The number of uses that were added or removed to this item in this call.
/// </summary>
[JsonPropertyName("UsesIncrementedBy")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int? UsesIncrementedBy { get; set; }
}
/// <summary>
/// [optional] The number of uses that were added or removed to this item in this call.
/// </summary>
[JsonPropertyName("UsesIncrementedBy")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int? UsesIncrementedBy { get; set; }
}
@@ -1,28 +1,27 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FLogStatement
{
public class FLogStatement
{
/// <summary>
/// [optional] Optional object accompanying the message as contextual information
/// </summary>
[JsonPropertyName("Data")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public object Data { get; set; }
/// <summary>
/// [optional] Optional object accompanying the message as contextual information
/// </summary>
[JsonPropertyName("Data")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public object Data { get; set; }
/// <summary>
/// [optional] 'Debug', 'Info', or 'Error'
/// </summary>
[JsonPropertyName("Level")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Level { get; set; }
/// <summary>
/// [optional] 'Debug', 'Info', or 'Error'
/// </summary>
[JsonPropertyName("Level")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Level { get; set; }
/// <summary>
/// [optional] undefined
/// </summary>
[JsonPropertyName("Message")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Message { get; set; }
}
/// <summary>
/// [optional] undefined
/// </summary>
[JsonPropertyName("Message")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Message { get; set; }
}
@@ -1,35 +1,34 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
{
public class FPlayerProfileModel
{
/// <summary>
/// [optional] Player display name
/// </summary>
[JsonPropertyName("DisplayName")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string DisplayName { get; set; }
/// <summary>
/// [optional] PlayFab player account unique identifier
/// </summary>
[JsonPropertyName("PlayerId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string PlayerId { get; set; }
/// <summary>
/// [optional] Publisher this player belongs to
/// </summary>
[JsonPropertyName("PublisherId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string PublisherId { get; set; }
namespace Prospect.Server.Api.Models.Client.Data;
/// <summary>
/// [optional] Title ID this player profile applies to
/// </summary>
[JsonPropertyName("TitleId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string TitleId { get; set; }
}
public class FPlayerProfileModel
{
/// <summary>
/// [optional] Player display name
/// </summary>
[JsonPropertyName("DisplayName")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string DisplayName { get; set; }
/// <summary>
/// [optional] PlayFab player account unique identifier
/// </summary>
[JsonPropertyName("PlayerId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string PlayerId { get; set; }
/// <summary>
/// [optional] Publisher this player belongs to
/// </summary>
[JsonPropertyName("PublisherId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string PublisherId { get; set; }
/// <summary>
/// [optional] Title ID this player profile applies to
/// </summary>
[JsonPropertyName("TitleId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string TitleId { get; set; }
}
@@ -1,29 +1,28 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FScriptExecutionError
{
public class FScriptExecutionError
{
/// <summary>
/// [optional] Error code, such as CloudScriptNotFound, JavascriptException, CloudScriptFunctionArgumentSizeExceeded,
/// CloudScriptAPIRequestCountExceeded, CloudScriptAPIRequestError, or CloudScriptHTTPRequestError
/// </summary>
[JsonPropertyName("Error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Error { get; set; }
/// <summary>
/// [optional] Error code, such as CloudScriptNotFound, JavascriptException, CloudScriptFunctionArgumentSizeExceeded,
/// CloudScriptAPIRequestCountExceeded, CloudScriptAPIRequestError, or CloudScriptHTTPRequestError
/// </summary>
[JsonPropertyName("Error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Error { get; set; }
/// <summary>
/// [optional] Details about the error
/// </summary>
[JsonPropertyName("Message")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Message { get; set; }
/// <summary>
/// [optional] Details about the error
/// </summary>
[JsonPropertyName("Message")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Message { get; set; }
/// <summary>
/// [optional] Point during the execution of the script at which the error occurred, if any
/// </summary>
[JsonPropertyName("StackTrace")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string StackTrace { get; set; }
}
/// <summary>
/// [optional] Point during the execution of the script at which the error occurred, if any
/// </summary>
[JsonPropertyName("StackTrace")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string StackTrace { get; set; }
}
@@ -1,22 +1,20 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FTreatmentAssignment
{
public class FTreatmentAssignment
{
/// <summary>
/// [optional] List of the experiment variables.
/// </summary>
[JsonPropertyName("Variables")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<FVariable> Variables { get; set; }
/// <summary>
/// [optional] List of the experiment variables.
/// </summary>
[JsonPropertyName("Variables")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<FVariable> Variables { get; set; }
/// <summary>
/// [optional] List of the experiment variants.
/// </summary>
[JsonPropertyName("Variants")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<string> Variants { get; set; }
}
/// <summary>
/// [optional] List of the experiment variants.
/// </summary>
[JsonPropertyName("Variants")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<string> Variants { get; set; }
}
@@ -1,29 +1,27 @@
using System;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FUserDataRecord
{
public class FUserDataRecord
{
/// <summary>
/// Timestamp for when this data was last updated.
/// </summary>
[JsonPropertyName("LastUpdated")]
public DateTime LastUpdated { get; set; }
/// <summary>
/// Timestamp for when this data was last updated.
/// </summary>
[JsonPropertyName("LastUpdated")]
public DateTime LastUpdated { get; set; }
/// <summary>
/// [optional] Indicates whether this data can be read by all users (public) or only the user (private). This is used for GetUserData
/// requests being made by one player about another player.
/// </summary>
[JsonPropertyName("Permission")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public UserDataPermission Permission { get; set; }
/// <summary>
/// [optional] Indicates whether this data can be read by all users (public) or only the user (private). This is used for GetUserData
/// requests being made by one player about another player.
/// </summary>
[JsonPropertyName("Permission")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public UserDataPermission Permission { get; set; }
/// <summary>
/// [optional] Data stored for the specified user data key.
/// </summary>
[JsonPropertyName("Value")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Value { get; set; }
}
/// <summary>
/// [optional] Data stored for the specified user data key.
/// </summary>
[JsonPropertyName("Value")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Value { get; set; }
}
@@ -1,25 +1,24 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FUserSettings
{
public class FUserSettings
{
/// <summary>
/// Boolean for whether this player is eligible for gathering device info.
/// </summary>
[JsonPropertyName("GatherDeviceInfo")]
public bool GatherDeviceInfo { get; set; }
/// <summary>
/// Boolean for whether this player is eligible for gathering device info.
/// </summary>
[JsonPropertyName("GatherDeviceInfo")]
public bool GatherDeviceInfo { get; set; }
/// <summary>
/// Boolean for whether this player should report OnFocus play-time tracking.
/// </summary>
[JsonPropertyName("GatherFocusInfo")]
public bool GatherFocusInfo { get; set; }
/// <summary>
/// Boolean for whether this player should report OnFocus play-time tracking.
/// </summary>
[JsonPropertyName("GatherFocusInfo")]
public bool GatherFocusInfo { get; set; }
/// <summary>
/// Boolean for whether this player is eligible for ad tracking.
/// </summary>
[JsonPropertyName("NeedsAttribution")]
public bool NeedsAttribution { get; set; }
}
/// <summary>
/// Boolean for whether this player is eligible for ad tracking.
/// </summary>
[JsonPropertyName("NeedsAttribution")]
public bool NeedsAttribution { get; set; }
}
@@ -1,20 +1,19 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FVariable
{
public class FVariable
{
/// <summary>
/// Name of the variable.
/// </summary>
[JsonPropertyName("Name")]
public string Name { get; set; }
/// <summary>
/// Name of the variable.
/// </summary>
[JsonPropertyName("Name")]
public string Name { get; set; }
/// <summary>
/// [optional] Value of the variable.
/// </summary>
[JsonPropertyName("Value")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Value { get; set; }
}
/// <summary>
/// [optional] Value of the variable.
/// </summary>
[JsonPropertyName("Value")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string Value { get; set; }
}
@@ -1,28 +1,26 @@
using System;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public class FVirtualCurrencyRechargeTime
{
public class FVirtualCurrencyRechargeTime
{
/// <summary>
/// Maximum value to which the regenerating currency will automatically increment. Note that it can exceed this value
/// through use of the AddUserVirtualCurrency API call. However, it will not regenerate automatically until it has fallen
/// below this value.
/// </summary>
[JsonPropertyName("RechargeMax")]
public int RechargeMax { get; set; }
/// <summary>
/// Maximum value to which the regenerating currency will automatically increment. Note that it can exceed this value
/// through use of the AddUserVirtualCurrency API call. However, it will not regenerate automatically until it has fallen
/// below this value.
/// </summary>
[JsonPropertyName("RechargeMax")]
public int RechargeMax { get; set; }
/// <summary>
/// Server timestamp in UTC indicating the next time the virtual currency will be incremented.
/// </summary>
[JsonPropertyName("RechargeTime")]
public DateTime RechargeTime { get; set; }
/// <summary>
/// Server timestamp in UTC indicating the next time the virtual currency will be incremented.
/// </summary>
[JsonPropertyName("RechargeTime")]
public DateTime RechargeTime { get; set; }
/// <summary>
/// Time remaining (in seconds) before the next recharge increment of the virtual currency.
/// </summary>
[JsonPropertyName("SecondsToRecharge")]
public int SecondsToRecharge { get; set; }
}
/// <summary>
/// Time remaining (in seconds) before the next recharge increment of the virtual currency.
/// </summary>
[JsonPropertyName("SecondsToRecharge")]
public int SecondsToRecharge { get; set; }
}
@@ -1,8 +1,7 @@
namespace Prospect.Server.Api.Models.Client.Data
namespace Prospect.Server.Api.Models.Client.Data;
public enum UserDataPermission
{
public enum UserDataPermission
{
Public,
Private
}
Public,
Private
}
@@ -1,11 +1,10 @@
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.Client.Data;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FAddGenericIDRequest
{
public class FAddGenericIDRequest
{
[JsonPropertyName("GenericId")]
public FGenericServiceId GenericId { get; set; }
}
[JsonPropertyName("GenericId")]
public FGenericServiceId GenericId { get; set; }
}
@@ -1,85 +1,83 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.Client.Data;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FExecuteCloudScriptResult
{
public class FExecuteCloudScriptResult
{
/// <summary>
/// Number of PlayFab API requests issued by the CloudScript function
/// </summary>
[JsonPropertyName("APIRequestsIssued")]
public int APIRequestsIssued { get; set; }
/// <summary>
/// Number of PlayFab API requests issued by the CloudScript function
/// </summary>
[JsonPropertyName("APIRequestsIssued")]
public int APIRequestsIssued { get; set; }
/// <summary>
/// [optional] Information about the error, if any, that occurred during execution
/// </summary>
[JsonPropertyName("Error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FScriptExecutionError Error { get; set; }
/// <summary>
/// [optional] Information about the error, if any, that occurred during execution
/// </summary>
[JsonPropertyName("Error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FScriptExecutionError Error { get; set; }
[JsonPropertyName("ExecutionTimeSeconds")]
public double? ExecutionTimeSeconds { get; set; }
[JsonPropertyName("ExecutionTimeSeconds")]
public double? ExecutionTimeSeconds { get; set; }
/// <summary>
/// [optional] The name of the function that executed
/// </summary>
[JsonPropertyName("FunctionName")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string FunctionName { get; set; }
/// <summary>
/// [optional] The name of the function that executed
/// </summary>
[JsonPropertyName("FunctionName")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string FunctionName { get; set; }
/// <summary>
/// [optional] The object returned from the CloudScript function, if any
/// </summary>
[JsonPropertyName("FunctionResult")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public object FunctionResult { get; set; }
/// <summary>
/// [optional] The object returned from the CloudScript function, if any
/// </summary>
[JsonPropertyName("FunctionResult")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public object FunctionResult { get; set; }
/// <summary>
/// [optional] Flag indicating if the FunctionResult was too large and was subsequently dropped from this event. This only occurs if
/// the total event size is larger than 350KB.
/// </summary>
[JsonPropertyName("FunctionResultTooLarge")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? FunctionResultTooLarge { get; set; }
/// <summary>
/// [optional] Flag indicating if the FunctionResult was too large and was subsequently dropped from this event. This only occurs if
/// the total event size is larger than 350KB.
/// </summary>
[JsonPropertyName("FunctionResultTooLarge")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? FunctionResultTooLarge { get; set; }
/// <summary>
/// Number of external HTTP requests issued by the CloudScript function
/// </summary>
[JsonPropertyName("HttpRequestsIssued")]
public int HttpRequestsIssued { get; set; }
/// <summary>
/// Number of external HTTP requests issued by the CloudScript function
/// </summary>
[JsonPropertyName("HttpRequestsIssued")]
public int HttpRequestsIssued { get; set; }
/// <summary>
/// [optional] Entries logged during the function execution. These include both entries logged in the function code using log.info()
/// and log.error() and error entries for API and HTTP request failures.
/// </summary>
[JsonPropertyName("Logs")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<FLogStatement> Logs { get; set; }
/// <summary>
/// [optional] Entries logged during the function execution. These include both entries logged in the function code using log.info()
/// and log.error() and error entries for API and HTTP request failures.
/// </summary>
[JsonPropertyName("Logs")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<FLogStatement> Logs { get; set; }
/// <summary>
/// [optional] Flag indicating if the logs were too large and were subsequently dropped from this event. This only occurs if the total
/// event size is larger than 350KB after the FunctionResult was removed.
/// </summary>
[JsonPropertyName("LogsTooLarge")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? LogsTooLarge { get; set; }
/// <summary>
/// [optional] Flag indicating if the logs were too large and were subsequently dropped from this event. This only occurs if the total
/// event size is larger than 350KB after the FunctionResult was removed.
/// </summary>
[JsonPropertyName("LogsTooLarge")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? LogsTooLarge { get; set; }
[JsonPropertyName("MemoryConsumedBytes")]
public uint MemoryConsumedBytes { get; set; }
[JsonPropertyName("MemoryConsumedBytes")]
public uint MemoryConsumedBytes { get; set; }
/// <summary>
/// Processor time consumed while executing the function. This does not include time spent waiting on API calls or HTTP
/// requests.
/// </summary>
[JsonPropertyName("ProcessorTimeSeconds")]
public double ProcessorTimeSeconds { get; set; }
/// <summary>
/// Processor time consumed while executing the function. This does not include time spent waiting on API calls or HTTP
/// requests.
/// </summary>
[JsonPropertyName("ProcessorTimeSeconds")]
public double ProcessorTimeSeconds { get; set; }
/// <summary>
/// The revision of the CloudScript that executed
/// </summary>
[JsonPropertyName("Revision")]
public int Revision { get; set; }
}
/// <summary>
/// The revision of the CloudScript that executed
/// </summary>
[JsonPropertyName("Revision")]
public int Revision { get; set; }
}
@@ -1,60 +1,58 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.Client.Data;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FExecuteCloudScriptServerRequest
{
public class FExecuteCloudScriptServerRequest
{
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
/// <summary>
/// The name of the CloudScript function to execute
/// </summary>
[JsonPropertyName("FunctionName")]
public string FunctionName { get; set; }
/// <summary>
/// The name of the CloudScript function to execute
/// </summary>
[JsonPropertyName("FunctionName")]
public string FunctionName { get; set; }
/// <summary>
/// [optional] Object that is passed in to the function as the first argument
/// </summary>
[JsonPropertyName("FunctionParameter")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string FunctionParameter { get; set; }
/// <summary>
/// [optional] Object that is passed in to the function as the first argument
/// </summary>
[JsonPropertyName("FunctionParameter")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string FunctionParameter { get; set; }
/// <summary>
/// [optional] Generate a 'player_executed_cloudscript' PlayStream event containing the results of the function execution and other
/// contextual information. This event will show up in the PlayStream debugger console for the player in Game Manager.
/// </summary>
[JsonPropertyName("GeneratePlayStreamEvent")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? GeneratePlayStreamEvent { get; set; }
/// <summary>
/// [optional] Generate a 'player_executed_cloudscript' PlayStream event containing the results of the function execution and other
/// contextual information. This event will show up in the PlayStream debugger console for the player in Game Manager.
/// </summary>
[JsonPropertyName("GeneratePlayStreamEvent")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? GeneratePlayStreamEvent { get; set; }
/// <summary>
/// The unique user identifier for the player on whose behalf the script is being run
/// </summary>
[JsonPropertyName("PlayFabId")]
public string PlayFabId { get; set; }
/// <summary>
/// The unique user identifier for the player on whose behalf the script is being run
/// </summary>
[JsonPropertyName("PlayFabId")]
public string PlayFabId { get; set; }
/// <summary>
/// [optional] Option for which revision of the CloudScript to execute. 'Latest' executes the most recently created revision, 'Live'
/// executes the current live, published revision, and 'Specific' executes the specified revision. The default value is
/// 'Specific', if the SpeificRevision parameter is specified, otherwise it is 'Live'.
/// </summary>
[JsonPropertyName("RevisionSelection")]
[JsonConverter(typeof(JsonStringEnumConverter))]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public CloudScriptRevisionOption? RevisionSelection { get; set; }
/// <summary>
/// [optional] Option for which revision of the CloudScript to execute. 'Latest' executes the most recently created revision, 'Live'
/// executes the current live, published revision, and 'Specific' executes the specified revision. The default value is
/// 'Specific', if the SpeificRevision parameter is specified, otherwise it is 'Live'.
/// </summary>
[JsonPropertyName("RevisionSelection")]
[JsonConverter(typeof(JsonStringEnumConverter))]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public CloudScriptRevisionOption? RevisionSelection { get; set; }
/// <summary>
/// [optional] The specivic revision to execute, when RevisionSelection is set to 'Specific'
/// </summary>
[JsonPropertyName("SpecificRevision")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int? SpecificRevision { get; set; }
}
/// <summary>
/// [optional] The specivic revision to execute, when RevisionSelection is set to 'Specific'
/// </summary>
[JsonPropertyName("SpecificRevision")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int? SpecificRevision { get; set; }
}
@@ -1,44 +1,42 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.Client.Data;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FExecuteFunctionRequest
{
public class FExecuteFunctionRequest
{
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
/// <summary>
/// [optional] The entity to perform this action on.
/// </summary>
[JsonPropertyName("Entity")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FEntityKey Entity { get; set; }
/// <summary>
/// [optional] The entity to perform this action on.
/// </summary>
[JsonPropertyName("Entity")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FEntityKey Entity { get; set; }
/// <summary>
/// The name of the CloudScript function to execute
/// </summary>
[JsonPropertyName("FunctionName")]
public string FunctionName { get; set; }
/// <summary>
/// The name of the CloudScript function to execute
/// </summary>
[JsonPropertyName("FunctionName")]
public string FunctionName { get; set; }
/// <summary>
/// [optional] Object that is passed in to the function as the FunctionArgument field of the FunctionExecutionContext data structure
/// </summary>
[JsonPropertyName("FunctionParameter")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string FunctionParameter { get; set; }
/// <summary>
/// [optional] Object that is passed in to the function as the FunctionArgument field of the FunctionExecutionContext data structure
/// </summary>
[JsonPropertyName("FunctionParameter")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string FunctionParameter { get; set; }
/// <summary>
/// [optional] Generate a 'entity_executed_cloudscript_function' PlayStream event containing the results of the function execution and
/// other contextual information. This event will show up in the PlayStream debugger console for the player in Game Manager.
/// </summary>
[JsonPropertyName("GeneratePlayStreamEvent")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? GeneratePlayStreamEvent { get; set; }
}
/// <summary>
/// [optional] Generate a 'entity_executed_cloudscript_function' PlayStream event containing the results of the function execution and
/// other contextual information. This event will show up in the PlayStream debugger console for the player in Game Manager.
/// </summary>
[JsonPropertyName("GeneratePlayStreamEvent")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? GeneratePlayStreamEvent { get; set; }
}
@@ -1,41 +1,40 @@
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.Client.Data;
namespace Prospect.Server.Api.Models.Client
{
public class FExecuteFunctionResult
{
/// <summary>
/// [optional] Error from the CloudScript Azure Function.
/// </summary>
[JsonPropertyName("Error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FFunctionExecutionError Error { get; set; }
/// <summary>
/// The amount of time the function took to execute
/// </summary>
[JsonPropertyName("ExecutionTimeMilliseconds")]
public int ExecutionTimeMilliseconds { get; set; }
namespace Prospect.Server.Api.Models.Client;
/// <summary>
/// [optional] The name of the function that executed
/// </summary>
[JsonPropertyName("FunctionName")]
public string FunctionName { get; set; }
public class FExecuteFunctionResult
{
/// <summary>
/// [optional] Error from the CloudScript Azure Function.
/// </summary>
[JsonPropertyName("Error")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FFunctionExecutionError Error { get; set; }
/// <summary>
/// [optional] The object returned from the function, if any
/// </summary>
[JsonPropertyName("FunctionResult")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public object FunctionResult { get; set; }
/// <summary>
/// The amount of time the function took to execute
/// </summary>
[JsonPropertyName("ExecutionTimeMilliseconds")]
public int ExecutionTimeMilliseconds { get; set; }
/// <summary>
/// [optional] The name of the function that executed
/// </summary>
[JsonPropertyName("FunctionName")]
public string FunctionName { get; set; }
/// <summary>
/// [optional] Flag indicating if the FunctionResult was too large and was subsequently dropped from this event.
/// </summary>
[JsonPropertyName("FunctionResultTooLarge")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? FunctionResultTooLarge { get; set; }
}
/// <summary>
/// [optional] The object returned from the function, if any
/// </summary>
[JsonPropertyName("FunctionResult")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public object FunctionResult { get; set; }
/// <summary>
/// [optional] Flag indicating if the FunctionResult was too large and was subsequently dropped from this event.
/// </summary>
[JsonPropertyName("FunctionResultTooLarge")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? FunctionResultTooLarge { get; set; }
}
@@ -1,21 +1,19 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FGetTitleDataRequest
{
public class FGetTitleDataRequest
{
/// <summary>
/// [optional] Specific keys to search for in the title data (leave null to get all keys)
/// </summary>
[JsonPropertyName("Keys")]
public List<string> Keys { get; set; }
/// <summary>
/// [optional] Specific keys to search for in the title data (leave null to get all keys)
/// </summary>
[JsonPropertyName("Keys")]
public List<string> Keys { get; set; }
/// <summary>
/// [optional] Name of the override. This value is ignored when used by the game client; otherwise, the overrides are applied
/// automatically to the title data.
/// </summary>
[JsonPropertyName("OverrideLabel")]
public string OverrideLabel { get; set; }
}
/// <summary>
/// [optional] Name of the override. This value is ignored when used by the game client; otherwise, the overrides are applied
/// automatically to the title data.
/// </summary>
[JsonPropertyName("OverrideLabel")]
public string OverrideLabel { get; set; }
}
@@ -1,14 +1,12 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FGetTitleDataResult
{
public class FGetTitleDataResult
{
/// <summary>
/// [optional] a dictionary object of key / value pairs
/// </summary>
[JsonPropertyName("Data")]
public Dictionary<string, string> Data { get; set; }
}
/// <summary>
/// [optional] a dictionary object of key / value pairs
/// </summary>
[JsonPropertyName("Data")]
public Dictionary<string, string> Data { get; set; }
}
@@ -1,28 +1,26 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FGetUserDataRequest
{
public class FGetUserDataRequest
{
/// <summary>
/// [optional] The version that currently exists according to the caller. The call will return the data for all of the keys if the
/// version in the system is greater than this.
/// </summary>
[JsonPropertyName("IfChangedFromDataVersion")]
public List<uint> IfChangedFromDataVersion { get; set; }
/// <summary>
/// [optional] The version that currently exists according to the caller. The call will return the data for all of the keys if the
/// version in the system is greater than this.
/// </summary>
[JsonPropertyName("IfChangedFromDataVersion")]
public List<uint> IfChangedFromDataVersion { get; set; }
/// <summary>
/// [optional] List of unique keys to load from.
/// </summary>
[JsonPropertyName("Keys")]
public List<string> Keys { get; set; }
/// <summary>
/// [optional] List of unique keys to load from.
/// </summary>
[JsonPropertyName("Keys")]
public List<string> Keys { get; set; }
/// <summary>
/// [optional] Unique PlayFab identifier of the user to load data for. Optional, defaults to yourself if not set. When specified to a
/// PlayFab id of another player, then this will only return public keys for that account.
/// </summary>
[JsonPropertyName("PlayFabId")]
public string PlayFabId { get; set; }
}
/// <summary>
/// [optional] Unique PlayFab identifier of the user to load data for. Optional, defaults to yourself if not set. When specified to a
/// PlayFab id of another player, then this will only return public keys for that account.
/// </summary>
[JsonPropertyName("PlayFabId")]
public string PlayFabId { get; set; }
}
@@ -1,22 +1,20 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.Client.Data;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FGetUserDataResult
{
public class FGetUserDataResult
{
/// <summary>
/// [optional] User specific data for this title.
/// </summary>
[JsonPropertyName("Data")]
public Dictionary<string, FUserDataRecord> Data { get; set; }
/// <summary>
/// [optional] User specific data for this title.
/// </summary>
[JsonPropertyName("Data")]
public Dictionary<string, FUserDataRecord> Data { get; set; }
/// <summary>
/// [optional] Indicates the current version of the data that has been set. This is incremented with every set call for that type of
/// data (read-only, internal, etc). This version can be provided in Get calls to find updated data.
/// </summary>
[JsonPropertyName("DataVersion")]
public uint DataVersion { get; set; }
}
/// <summary>
/// [optional] Indicates the current version of the data that has been set. This is incremented with every set call for that type of
/// data (read-only, internal, etc). This version can be provided in Get calls to find updated data.
/// </summary>
[JsonPropertyName("DataVersion")]
public uint DataVersion { get; set; }
}
@@ -1,15 +1,13 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FGetUserInventoryRequest
{
public class FGetUserInventoryRequest
{
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
}
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
}
@@ -1,30 +1,28 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.Client.Data;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FGetUserInventoryResult
{
public class FGetUserInventoryResult
{
/// <summary>
/// [optional] Array of inventory items belonging to the user.
/// </summary>
[JsonPropertyName("Inventory")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<FItemInstance> Inventory { get; set; }
/// <summary>
/// [optional] Array of inventory items belonging to the user.
/// </summary>
[JsonPropertyName("Inventory")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public List<FItemInstance> Inventory { get; set; }
/// <summary>
/// [optional] Array of virtual currency balance(s) belonging to the user.
/// </summary>
[JsonPropertyName("VirtualCurrency")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, int> VirtualCurrency { get; set; }
/// <summary>
/// [optional] Array of virtual currency balance(s) belonging to the user.
/// </summary>
[JsonPropertyName("VirtualCurrency")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, int> VirtualCurrency { get; set; }
/// <summary>
/// [optional] Array of virtual currency balance(s) belonging to the user.
/// </summary>
[JsonPropertyName("VirtualCurrencyRechargeTimes")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, FVirtualCurrencyRechargeTime> VirtualCurrencyRechargeTimes { get; set; }
}
/// <summary>
/// [optional] Array of virtual currency balance(s) belonging to the user.
/// </summary>
[JsonPropertyName("VirtualCurrencyRechargeTimes")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, FVirtualCurrencyRechargeTime> VirtualCurrencyRechargeTimes { get; set; }
}
@@ -1,64 +1,62 @@
using System;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.Client.Data;
namespace Prospect.Server.Api.Models.Client
{
public class FServerLoginResult
{
/// <summary>
/// [optional] If LoginTitlePlayerAccountEntity flag is set on the login request the title_player_account will also be logged in and
/// returned.
/// </summary>
[JsonPropertyName("EntityToken")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FEntityTokenResponse EntityToken { get; set; }
/// <summary>
/// [optional] Results for requested info.
/// </summary>
[JsonPropertyName("InfoResultPayload")]
public FGetPlayerCombinedInfoResultPayload InfoResultPayload { get; set; }
/// <summary>
/// [optional] The time of this user's previous login. If there was no previous login, then it's DateTime.MinValue
/// </summary>
[JsonPropertyName("LastLoginTime")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public DateTime? LastLoginTime { get; set; }
/// <summary>
/// True if the account was newly created on this login.
/// </summary>
[JsonPropertyName("NewlyCreated")]
public bool NewlyCreated { get; set; }
/// <summary>
/// [optional] Player's unique PlayFabId.
/// </summary>
[JsonPropertyName("PlayFabId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string PlayFabId { get; set; }
/// <summary>
/// [optional] Unique token authorizing the user and game at the server level, for the current session.
/// </summary>
[JsonPropertyName("SessionTicket")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string SessionTicket { get; set; }
/// <summary>
/// [optional] Settings specific to this user.
/// </summary>
[JsonPropertyName("SettingsForUser")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FUserSettings SettingsForUser { get; set; }
namespace Prospect.Server.Api.Models.Client;
/// <summary>
/// [optional] The experimentation treatments for this user at the time of login.
/// </summary>
[JsonPropertyName("TreatmentAssignment")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FTreatmentAssignment TreatmentAssignment { get; set; }
}
public class FServerLoginResult
{
/// <summary>
/// [optional] If LoginTitlePlayerAccountEntity flag is set on the login request the title_player_account will also be logged in and
/// returned.
/// </summary>
[JsonPropertyName("EntityToken")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FEntityTokenResponse EntityToken { get; set; }
/// <summary>
/// [optional] Results for requested info.
/// </summary>
[JsonPropertyName("InfoResultPayload")]
public FGetPlayerCombinedInfoResultPayload InfoResultPayload { get; set; }
/// <summary>
/// [optional] The time of this user's previous login. If there was no previous login, then it's DateTime.MinValue
/// </summary>
[JsonPropertyName("LastLoginTime")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public DateTime? LastLoginTime { get; set; }
/// <summary>
/// True if the account was newly created on this login.
/// </summary>
[JsonPropertyName("NewlyCreated")]
public bool NewlyCreated { get; set; }
/// <summary>
/// [optional] Player's unique PlayFabId.
/// </summary>
[JsonPropertyName("PlayFabId")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string PlayFabId { get; set; }
/// <summary>
/// [optional] Unique token authorizing the user and game at the server level, for the current session.
/// </summary>
[JsonPropertyName("SessionTicket")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public string SessionTicket { get; set; }
/// <summary>
/// [optional] Settings specific to this user.
/// </summary>
[JsonPropertyName("SettingsForUser")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FUserSettings SettingsForUser { get; set; }
/// <summary>
/// [optional] The experimentation treatments for this user at the time of login.
/// </summary>
[JsonPropertyName("TreatmentAssignment")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public FTreatmentAssignment TreatmentAssignment { get; set; }
}
@@ -1,38 +1,36 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.Client.Data;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FUpdateUserDataRequest
{
public class FUpdateUserDataRequest
{
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
/// <summary>
/// [optional] Key-value pairs to be written to the custom data. Note that keys are trimmed of whitespace, are limited in size, and may
/// not begin with a '!' character or be null.
/// </summary>
public Dictionary<string, string> Data { get; set; }
/// <summary>
/// [optional] Key-value pairs to be written to the custom data. Note that keys are trimmed of whitespace, are limited in size, and may
/// not begin with a '!' character or be null.
/// </summary>
public Dictionary<string, string> Data { get; set; }
/// <summary>
/// [optional] Optional list of Data-keys to remove from UserData. Some SDKs cannot insert null-values into Data due to language
/// constraints. Use this to delete the keys directly.
/// </summary>
public List<string> KeysToRemove { get; set; }
/// <summary>
/// [optional] Optional list of Data-keys to remove from UserData. Some SDKs cannot insert null-values into Data due to language
/// constraints. Use this to delete the keys directly.
/// </summary>
public List<string> KeysToRemove { get; set; }
/// <summary>
/// [optional] Permission to be applied to all user data keys written in this request. Defaults to "private" if not set.
/// </summary>
public UserDataPermission? Permission { get; set; }
/// <summary>
/// [optional] Permission to be applied to all user data keys written in this request. Defaults to "private" if not set.
/// </summary>
public UserDataPermission? Permission { get; set; }
/// <summary>
/// Unique PlayFab assigned ID of the user on whom the operation will be performed.
/// </summary>
public string PlayFabId { get; set; }
}
/// <summary>
/// Unique PlayFab assigned ID of the user on whom the operation will be performed.
/// </summary>
public string PlayFabId { get; set; }
}
@@ -1,11 +1,10 @@
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FUpdateUserDataResult
{
public class FUpdateUserDataResult
{
/// <summary>
/// Indicates the current version of the data that has been set. This is incremented with every set call for that type of
/// data (read-only, internal, etc). This version can be provided in Get calls to find updated data.
/// </summary>
public uint DataVersion { get; set; }
}
/// <summary>
/// Indicates the current version of the data that has been set. This is incremented with every set call for that type of
/// data (read-only, internal, etc). This version can be provided in Get calls to find updated data.
/// </summary>
public uint DataVersion { get; set; }
}
@@ -1,21 +1,19 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FUpdateUserTitleDisplayNameRequest
{
public class FUpdateUserTitleDisplayNameRequest
{
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
/// <summary>
/// [optional] The optional custom tags associated with the request (e.g. build number, external trace identifiers, etc.).
/// </summary>
[JsonPropertyName("CustomTags")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public Dictionary<string, string> CustomTags { get; set; }
/// <summary>
/// New title display name for the user - must be between 3 and 25 characters.
/// </summary>
[JsonPropertyName("DisplayName")]
public string DisplayName { get; set; }
}
/// <summary>
/// New title display name for the user - must be between 3 and 25 characters.
/// </summary>
[JsonPropertyName("DisplayName")]
public string DisplayName { get; set; }
}
@@ -1,10 +1,9 @@
namespace Prospect.Server.Api.Models.Client
namespace Prospect.Server.Api.Models.Client;
public class FUpdateUserTitleDisplayNameResult
{
public class FUpdateUserTitleDisplayNameResult
{
/// <summary>
/// [optional] Current title display name for the user (this will be the original display name if the rename attempt failed).
/// </summary>
public string DisplayName { get; set; }
}
/// <summary>
/// [optional] Current title display name for the user (this will be the original display name if the rename attempt failed).
/// </summary>
public string DisplayName { get; set; }
}
@@ -1,14 +1,12 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data
namespace Prospect.Server.Api.Models.CloudScript.Data;
public class FYActiveContractPlayerData
{
public class FYActiveContractPlayerData
{
[JsonPropertyName("contractId")]
public string ContractId { get; set; }
[JsonPropertyName("contractId")]
public string ContractId { get; set; }
[JsonPropertyName("progress")]
public List<int> Progress { get; set; }
}
[JsonPropertyName("progress")]
public List<int> Progress { get; set; }
}
@@ -1,13 +1,12 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data
{
public class FYFactionContractData
{
[JsonPropertyName("contractId")]
public string ContractId { get; set; }
namespace Prospect.Server.Api.Models.CloudScript.Data;
[JsonPropertyName("contractIsLockedDueToLowFactionReputation")]
public bool ContractIsLockedDueToLowFactionReputation { get; set; }
}
public class FYFactionContractData
{
[JsonPropertyName("contractId")]
public string ContractId { get; set; }
[JsonPropertyName("contractIsLockedDueToLowFactionReputation")]
public bool ContractIsLockedDueToLowFactionReputation { get; set; }
}
@@ -1,14 +1,12 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data
namespace Prospect.Server.Api.Models.CloudScript.Data;
public class FYFactionContractsData
{
public class FYFactionContractsData
{
[JsonPropertyName("factionId")]
public string FactionId { get; set; }
[JsonPropertyName("factionId")]
public string FactionId { get; set; }
[JsonPropertyName("contracts")]
public List<FYFactionContractData> Contracts { get; set; }
}
[JsonPropertyName("contracts")]
public List<FYFactionContractData> Contracts { get; set; }
}
@@ -1,14 +1,12 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data
namespace Prospect.Server.Api.Models.CloudScript.Data;
public class FYFactionsContractsData
{
public class FYFactionsContractsData
{
[JsonPropertyName("boards")]
public List<FYFactionContractsData> Boards { get; set; }
[JsonPropertyName("boards")]
public List<FYFactionContractsData> Boards { get; set; }
[JsonPropertyName("lastBoardRefreshTimeUtc")]
public FYTimestamp LastBoardRefreshTimeUtc { get; set; }
}
[JsonPropertyName("lastBoardRefreshTimeUtc")]
public FYTimestamp LastBoardRefreshTimeUtc { get; set; }
}
@@ -1,19 +1,18 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data
namespace Prospect.Server.Api.Models.CloudScript.Data;
public class FYItemCurrentlyBeingCrafted
{
public class FYItemCurrentlyBeingCrafted
{
[JsonPropertyName("itemId")]
public string ItemId { get; set; }
[JsonPropertyName("itemId")]
public string ItemId { get; set; }
[JsonPropertyName("itemRarity")]
public int ItemRarity { get; set; }
[JsonPropertyName("itemRarity")]
public int ItemRarity { get; set; }
[JsonPropertyName("purchaseAmount")]
public int PurchaseAmount { get; set; }
[JsonPropertyName("purchaseAmount")]
public int PurchaseAmount { get; set; }
[JsonPropertyName("utcTimestampWhenCraftingStarted")]
public FYTimestamp UtcTimestampWhenCraftingStarted { get; set; }
}
[JsonPropertyName("utcTimestampWhenCraftingStarted")]
public FYTimestamp UtcTimestampWhenCraftingStarted { get; set; }
}
@@ -1,10 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data
namespace Prospect.Server.Api.Models.CloudScript.Data;
public class FYTimestamp
{
public class FYTimestamp
{
[JsonPropertyName("seconds")]
public int Seconds { get; set; }
}
[JsonPropertyName("seconds")]
public int Seconds { get; set; }
}
@@ -1,17 +1,16 @@
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.CloudScript.Data;
namespace Prospect.Server.Api.Models.CloudScript
namespace Prospect.Server.Api.Models.CloudScript;
public class FYGetCraftingInProgressDataResult
{
public class FYGetCraftingInProgressDataResult
{
[JsonPropertyName("userId")]
public string UserId { get; set; }
[JsonPropertyName("userId")]
public string UserId { get; set; }
[JsonPropertyName("error")]
public string Error { get; set; }
[JsonPropertyName("error")]
public string Error { get; set; }
[JsonPropertyName("itemCurrentlyBeingCrafted")]
public FYItemCurrentlyBeingCrafted ItemCurrentlyBeingCrafted { get; set; }
}
[JsonPropertyName("itemCurrentlyBeingCrafted")]
public FYItemCurrentlyBeingCrafted ItemCurrentlyBeingCrafted { get; set; }
}
@@ -1,24 +1,22 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.CloudScript.Data;
namespace Prospect.Server.Api.Models.CloudScript
namespace Prospect.Server.Api.Models.CloudScript;
public class FYGetPlayerContractsResult
{
public class FYGetPlayerContractsResult
{
[JsonPropertyName("userId")]
public string UserId { get; set; }
[JsonPropertyName("userId")]
public string UserId { get; set; }
[JsonPropertyName("error")]
public string Error { get; set; }
[JsonPropertyName("error")]
public string Error { get; set; }
[JsonPropertyName("activeContracts")]
public List<FYActiveContractPlayerData> ActiveContracts { get; set; }
[JsonPropertyName("activeContracts")]
public List<FYActiveContractPlayerData> ActiveContracts { get; set; }
[JsonPropertyName("factionsContracts")]
public FYFactionsContractsData FactionsContracts { get; set; }
[JsonPropertyName("factionsContracts")]
public FYFactionsContractsData FactionsContracts { get; set; }
[JsonPropertyName("refreshHours24UtcFromBackend")]
public int RefreshHours24UtcFromBackend { get; set; }
}
[JsonPropertyName("refreshHours24UtcFromBackend")]
public int RefreshHours24UtcFromBackend { get; set; }
}
+33 -37
View File
@@ -1,46 +1,42 @@
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
namespace Prospect.Server.Api
namespace Prospect.Server.Api;
public static class Program
{
public static class Program
public static int Main(string[] args)
{
public static int Main(string[] args)
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
try
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
try
{
Log.Information("Starting web host");
CreateHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
Log.Information("Starting web host");
CreateHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
@@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
@@ -1,9 +1,8 @@
namespace Prospect.Server.Api.Services.Auth
namespace Prospect.Server.Api.Services.Auth;
public static class AuthClaimTypes
{
public static class AuthClaimTypes
{
public const string UserId = "user_id";
public const string EntityId = "entity_id";
public const string Type = "type";
}
public const string UserId = "user_id";
public const string EntityId = "entity_id";
public const string Type = "type";
}
@@ -1,83 +1,80 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Prospect.Server.Api.Services.Database.Models;
namespace Prospect.Server.Api.Services.Auth
namespace Prospect.Server.Api.Services.Auth;
public class AuthTokenService
{
public class AuthTokenService
private const string DefaultIssuer = "ProspectApi";
private const string DefaultAudience = "Prospect";
private readonly SymmetricSecurityKey _securityKey;
private readonly JwtSecurityTokenHandler _tokenHandler;
public AuthTokenService(IOptions<AuthTokenSettings> options)
{
private const string DefaultIssuer = "ProspectApi";
private const string DefaultAudience = "Prospect";
private readonly SymmetricSecurityKey _securityKey;
private readonly JwtSecurityTokenHandler _tokenHandler;
public AuthTokenService(IOptions<AuthTokenSettings> options)
{
_securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(options.Value.Secret));
_tokenHandler = new JwtSecurityTokenHandler();
}
_securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(options.Value.Secret));
_tokenHandler = new JwtSecurityTokenHandler();
}
private string CreateToken(IEnumerable<Claim> claims)
private string CreateToken(IEnumerable<Claim> claims)
{
var tokenDescriptor = new SecurityTokenDescriptor
{
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.UtcNow.AddDays(7),
Issuer = DefaultIssuer,
Audience = DefaultAudience,
SigningCredentials = new SigningCredentials(_securityKey, SecurityAlgorithms.HmacSha256Signature)
};
Subject = new ClaimsIdentity(claims),
Expires = DateTime.UtcNow.AddDays(7),
Issuer = DefaultIssuer,
Audience = DefaultAudience,
SigningCredentials = new SigningCredentials(_securityKey, SecurityAlgorithms.HmacSha256Signature)
};
var token = _tokenHandler.CreateToken(tokenDescriptor);
return _tokenHandler.WriteToken(token);
}
var token = _tokenHandler.CreateToken(tokenDescriptor);
return _tokenHandler.WriteToken(token);
}
public string GenerateUser(PlayFabEntity entity)
public string GenerateUser(PlayFabEntity entity)
{
return CreateToken(new[]
{
return CreateToken(new[]
{
new Claim(AuthClaimTypes.UserId, entity.UserId),
new Claim(AuthClaimTypes.EntityId, entity.Id),
new Claim(AuthClaimTypes.Type, AuthType.User),
});
}
new Claim(AuthClaimTypes.UserId, entity.UserId),
new Claim(AuthClaimTypes.EntityId, entity.Id),
new Claim(AuthClaimTypes.Type, AuthType.User),
});
}
public string GenerateEntity(PlayFabEntity entity)
public string GenerateEntity(PlayFabEntity entity)
{
return CreateToken(new[]
{
return CreateToken(new[]
{
new Claim(AuthClaimTypes.UserId, entity.UserId),
new Claim(AuthClaimTypes.EntityId, entity.Id),
new Claim(AuthClaimTypes.Type, AuthType.Entity),
});
}
new Claim(AuthClaimTypes.UserId, entity.UserId),
new Claim(AuthClaimTypes.EntityId, entity.Id),
new Claim(AuthClaimTypes.Type, AuthType.Entity),
});
}
public ClaimsPrincipal Validate(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
public ClaimsPrincipal Validate(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
try
try
{
return tokenHandler.ValidateToken(token, new TokenValidationParameters
{
return tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = DefaultIssuer,
ValidAudience = DefaultAudience,
IssuerSigningKey = _securityKey
}, out _);
}
catch
{
return null;
}
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = DefaultIssuer,
ValidAudience = DefaultAudience,
IssuerSigningKey = _securityKey
}, out _);
}
catch
{
return null;
}
}
}
@@ -1,7 +1,6 @@
namespace Prospect.Server.Api.Services.Auth
namespace Prospect.Server.Api.Services.Auth;
public class AuthTokenSettings
{
public class AuthTokenSettings
{
public string Secret { get; set; }
}
public string Secret { get; set; }
}
@@ -1,8 +1,7 @@
namespace Prospect.Server.Api.Services.Auth
namespace Prospect.Server.Api.Services.Auth;
public static class AuthType
{
public static class AuthType
{
public const string User = "User";
public const string Entity = "Entity";
}
public const string User = "User";
public const string Entity = "Entity";
}
@@ -1,20 +1,18 @@
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication;
using Prospect.Server.Api.Services.Auth.Entity;
using Prospect.Server.Api.Services.Auth.User;
namespace Prospect.Server.Api.Services.Auth
namespace Prospect.Server.Api.Services.Auth;
public static class AuthenticationBuilderExtensions
{
public static class AuthenticationBuilderExtensions
public static AuthenticationBuilder AddUserAuthentication(this AuthenticationBuilder authenticationBuilder, Action<UserAuthenticationOptions> options)
{
public static AuthenticationBuilder AddUserAuthentication(this AuthenticationBuilder authenticationBuilder, Action<UserAuthenticationOptions> options)
{
return authenticationBuilder.AddScheme<UserAuthenticationOptions, UserAuthenticationHandler>(UserAuthenticationOptions.DefaultScheme, options);
}
return authenticationBuilder.AddScheme<UserAuthenticationOptions, UserAuthenticationHandler>(UserAuthenticationOptions.DefaultScheme, options);
}
public static AuthenticationBuilder AddEntityAuthentication(this AuthenticationBuilder authenticationBuilder, Action<EntityAuthenticationOptions> options)
{
return authenticationBuilder.AddScheme<EntityAuthenticationOptions, EntityAuthenticationHandler>(EntityAuthenticationOptions.DefaultScheme, options);
}
public static AuthenticationBuilder AddEntityAuthentication(this AuthenticationBuilder authenticationBuilder, Action<EntityAuthenticationOptions> options)
{
return authenticationBuilder.AddScheme<EntityAuthenticationOptions, EntityAuthenticationHandler>(EntityAuthenticationOptions.DefaultScheme, options);
}
}
@@ -1,87 +1,81 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Prospect.Server.Api.Models.Client;
using Prospect.Server.Api.Services.Auth.Extensions;
namespace Prospect.Server.Api.Services.Auth.Entity
namespace Prospect.Server.Api.Services.Auth.Entity;
public class EntityAuthenticationHandler : AuthenticationHandler<EntityAuthenticationOptions>
{
public class EntityAuthenticationHandler : AuthenticationHandler<EntityAuthenticationOptions>
private const string Header = "X-EntityToken";
private const string Type = AuthType.Entity;
private readonly AuthTokenService _authTokenService;
public EntityAuthenticationHandler(
IOptionsMonitor<EntityAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
AuthTokenService authTokenService) : base(options, logger, encoder, clock)
{
private const string Header = "X-EntityToken";
private const string Type = AuthType.Entity;
_authTokenService = authTokenService;
}
private readonly AuthTokenService _authTokenService;
public EntityAuthenticationHandler(
IOptionsMonitor<EntityAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
AuthTokenService authTokenService) : base(options, logger, encoder, clock)
{
_authTokenService = authTokenService;
}
private ClientResponse Res { get; set; } = new ClientResponse
{
Code = 401,
Status = "Unauthorized",
Error = "NotAuthenticated",
ErrorCode = 1074,
ErrorMessage = "This API method does not allow anonymous callers."
};
private ClientResponse Res { get; set; } = new ClientResponse
{
Code = 401,
Status = "Unauthorized",
Error = "NotAuthenticated",
ErrorCode = 1074,
ErrorMessage = "This API method does not allow anonymous callers."
};
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.TryGetValue(Header, out var headerValues) || headerValues.Count == 0)
{
if (!Request.Headers.TryGetValue(Header, out var headerValues) || headerValues.Count == 0)
{
return Task.FromResult(AuthenticateResult.Fail("No header"));
}
return Task.FromResult(AuthenticateResult.Fail("No header"));
}
var headerValue = headerValues.FirstOrDefault();
var headerValue = headerValues.FirstOrDefault();
if (string.IsNullOrWhiteSpace(headerValue))
{
return Task.FromResult(AuthenticateResult.Fail("Empty header value"));
}
Res.Error = "EntityTokenInvalid";
Res.ErrorCode = 1335;
Res.ErrorMessage = "EntityTokenInvalid";
var token = _authTokenService.Validate(headerValue);
if (token != null)
{
var identity = new ClaimsIdentity(token.Claims, Options.AuthenticationType);
var identities = new List<ClaimsIdentity> { identity };
var principal = new ClaimsPrincipal(identities);
if (principal.FindAuthType() != Type)
{
return Task.FromResult(AuthenticateResult.Fail("Invalid auth type"));
}
var ticket = new AuthenticationTicket(principal, Options.Scheme);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
return Task.FromResult(AuthenticateResult.Fail("Invalid JWT"));
}
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
if (string.IsNullOrWhiteSpace(headerValue))
{
Response.StatusCode = 401;
Response.ContentType = "application/json";
await Response.WriteAsync(JsonSerializer.Serialize(Res));
return Task.FromResult(AuthenticateResult.Fail("Empty header value"));
}
Res.Error = "EntityTokenInvalid";
Res.ErrorCode = 1335;
Res.ErrorMessage = "EntityTokenInvalid";
var token = _authTokenService.Validate(headerValue);
if (token != null)
{
var identity = new ClaimsIdentity(token.Claims, Options.AuthenticationType);
var identities = new List<ClaimsIdentity> { identity };
var principal = new ClaimsPrincipal(identities);
if (principal.FindAuthType() != Type)
{
return Task.FromResult(AuthenticateResult.Fail("Invalid auth type"));
}
var ticket = new AuthenticationTicket(principal, Options.Scheme);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
return Task.FromResult(AuthenticateResult.Fail("Invalid JWT"));
}
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
{
Response.StatusCode = 401;
Response.ContentType = "application/json";
await Response.WriteAsync(JsonSerializer.Serialize(Res));
}
}
@@ -1,11 +1,10 @@
using Microsoft.AspNetCore.Authentication;
namespace Prospect.Server.Api.Services.Auth.Entity
namespace Prospect.Server.Api.Services.Auth.Entity;
public class EntityAuthenticationOptions : AuthenticationSchemeOptions
{
public class EntityAuthenticationOptions : AuthenticationSchemeOptions
{
public const string DefaultScheme = "EntityAuth";
public string Scheme => DefaultScheme;
public string AuthenticationType = DefaultScheme;
}
public const string DefaultScheme = "EntityAuth";
public string Scheme => DefaultScheme;
public string AuthenticationType = DefaultScheme;
}
@@ -1,34 +1,33 @@
using System.Security.Claims;
using Prospect.Server.Api.Exceptions;
namespace Prospect.Server.Api.Services.Auth.Extensions
namespace Prospect.Server.Api.Services.Auth.Extensions;
public static class ClaimsPrincipalExtensions
{
public static class ClaimsPrincipalExtensions
public static string FindAuthUserId(this ClaimsPrincipal principal)
{
public static string FindAuthUserId(this ClaimsPrincipal principal)
{
return Find(principal, AuthClaimTypes.UserId);
}
return Find(principal, AuthClaimTypes.UserId);
}
public static string FindAuthEntityId(this ClaimsPrincipal principal)
{
return Find(principal, AuthClaimTypes.EntityId);
}
public static string FindAuthEntityId(this ClaimsPrincipal principal)
{
return Find(principal, AuthClaimTypes.EntityId);
}
public static string FindAuthType(this ClaimsPrincipal principal)
public static string FindAuthType(this ClaimsPrincipal principal)
{
return Find(principal, AuthClaimTypes.Type);
}
private static string Find(ClaimsPrincipal principal, string claimType)
{
var claim = principal.FindFirst(claimType);
if (claim == null)
{
return Find(principal, AuthClaimTypes.Type);
throw new ProspectException($"Failed to find claim {claimType}");
}
private static string Find(ClaimsPrincipal principal, string claimType)
{
var claim = principal.FindFirst(claimType);
if (claim == null)
{
throw new ProspectException($"Failed to find claim {claimType}");
}
return claim.Value;
}
return claim.Value;
}
}
@@ -1,85 +1,79 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Prospect.Server.Api.Models.Client;
using Prospect.Server.Api.Services.Auth.Extensions;
namespace Prospect.Server.Api.Services.Auth.User
namespace Prospect.Server.Api.Services.Auth.User;
public class UserAuthenticationHandler : AuthenticationHandler<UserAuthenticationOptions>
{
public class UserAuthenticationHandler : AuthenticationHandler<UserAuthenticationOptions>
private const string Header = "X-Authorization";
private const string Type = AuthType.User;
private readonly AuthTokenService _authTokenService;
public UserAuthenticationHandler(
IOptionsMonitor<UserAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
AuthTokenService authTokenService) : base(options, logger, encoder, clock)
{
private const string Header = "X-Authorization";
private const string Type = AuthType.User;
_authTokenService = authTokenService;
}
private readonly AuthTokenService _authTokenService;
public UserAuthenticationHandler(
IOptionsMonitor<UserAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
AuthTokenService authTokenService) : base(options, logger, encoder, clock)
{
_authTokenService = authTokenService;
}
private string Failure { get; set; } = "Not Authenticated";
private string Failure { get; set; } = "Not Authenticated";
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.TryGetValue(Header, out var headerValues) || headerValues.Count == 0)
{
if (!Request.Headers.TryGetValue(Header, out var headerValues) || headerValues.Count == 0)
{
return Task.FromResult(AuthenticateResult.Fail("No header"));
}
return Task.FromResult(AuthenticateResult.Fail("No header"));
}
var headerValue = headerValues.FirstOrDefault();
var headerValue = headerValues.FirstOrDefault();
if (string.IsNullOrWhiteSpace(headerValue))
{
return Task.FromResult(AuthenticateResult.Fail("Empty header value"));
}
Failure = "X-Authentication HTTP header contains invalid ticket";
var token = _authTokenService.Validate(headerValue);
if (token != null)
{
var identity = new ClaimsIdentity(token.Claims, Options.AuthenticationType);
var identities = new List<ClaimsIdentity> { identity };
var principal = new ClaimsPrincipal(identities);
if (principal.FindAuthType() != Type)
{
return Task.FromResult(AuthenticateResult.Fail("Invalid auth type"));
}
var ticket = new AuthenticationTicket(principal, Options.Scheme);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
return Task.FromResult(AuthenticateResult.Fail("Invalid JWT"));
}
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
if (string.IsNullOrWhiteSpace(headerValue))
{
Response.StatusCode = 401;
Response.ContentType = "application/json";
await Response.WriteAsync(JsonSerializer.Serialize(new ClientResponse
{
Code = 401,
Status = "Unauthorized",
Error = "NotAuthenticated",
ErrorCode = 1074,
ErrorMessage = Failure
}));
return Task.FromResult(AuthenticateResult.Fail("Empty header value"));
}
Failure = "X-Authentication HTTP header contains invalid ticket";
var token = _authTokenService.Validate(headerValue);
if (token != null)
{
var identity = new ClaimsIdentity(token.Claims, Options.AuthenticationType);
var identities = new List<ClaimsIdentity> { identity };
var principal = new ClaimsPrincipal(identities);
if (principal.FindAuthType() != Type)
{
return Task.FromResult(AuthenticateResult.Fail("Invalid auth type"));
}
var ticket = new AuthenticationTicket(principal, Options.Scheme);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
return Task.FromResult(AuthenticateResult.Fail("Invalid JWT"));
}
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
{
Response.StatusCode = 401;
Response.ContentType = "application/json";
await Response.WriteAsync(JsonSerializer.Serialize(new ClientResponse
{
Code = 401,
Status = "Unauthorized",
Error = "NotAuthenticated",
ErrorCode = 1074,
ErrorMessage = Failure
}));
}
}
@@ -1,11 +1,10 @@
using Microsoft.AspNetCore.Authentication;
namespace Prospect.Server.Api.Services.Auth.User
namespace Prospect.Server.Api.Services.Auth.User;
public class UserAuthenticationOptions : AuthenticationSchemeOptions
{
public class UserAuthenticationOptions : AuthenticationSchemeOptions
{
public const string DefaultScheme = "UserAuth";
public string Scheme => DefaultScheme;
public string AuthenticationType = DefaultScheme;
}
public const string DefaultScheme = "UserAuth";
public string Scheme => DefaultScheme;
public string AuthenticationType = DefaultScheme;
}
@@ -2,19 +2,18 @@
using MongoDB.Driver;
using Prospect.Server.Api.Config;
namespace Prospect.Server.Api.Services.Database
{
public abstract class BaseDbService<T>
{
protected BaseDbService(IOptions<DatabaseSettings> options, string collection)
{
var settings = options.Value;
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);
namespace Prospect.Server.Api.Services.Database;
Collection = database.GetCollection<T>(collection);
}
protected IMongoCollection<T> Collection { get; }
public abstract class BaseDbService<T>
{
protected BaseDbService(IOptions<DatabaseSettings> options, string collection)
{
var settings = options.Value;
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);
Collection = database.GetCollection<T>(collection);
}
protected IMongoCollection<T> Collection { get; }
}
@@ -1,38 +1,36 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using Prospect.Server.Api.Config;
using Prospect.Server.Api.Services.Database.Models;
namespace Prospect.Server.Api.Services.Database
namespace Prospect.Server.Api.Services.Database;
public class DbEntityService : BaseDbService<PlayFabEntity>
{
public class DbEntityService : BaseDbService<PlayFabEntity>
public DbEntityService(IOptions<DatabaseSettings> settings) : base(settings, nameof(PlayFabEntity))
{
public DbEntityService(IOptions<DatabaseSettings> settings) : base(settings, nameof(PlayFabEntity))
{
}
}
public async Task<PlayFabEntity> FindAsync(string userId)
{
return await Collection.Find(user => user.UserId == userId).SingleOrDefaultAsync();
}
public async Task<PlayFabEntity> FindAsync(string userId)
{
return await Collection.Find(user => user.UserId == userId).SingleOrDefaultAsync();
}
private async Task<PlayFabEntity> CreateAsync(string userId)
private async Task<PlayFabEntity> CreateAsync(string userId)
{
var user = new PlayFabEntity
{
var user = new PlayFabEntity
{
UserId = userId
};
UserId = userId
};
await Collection.InsertOneAsync(user);
await Collection.InsertOneAsync(user);
return user;
}
return user;
}
public async Task<PlayFabEntity> FindOrCreateAsync(string userId)
{
return await FindAsync(userId) ??
await CreateAsync(userId);
}
public async Task<PlayFabEntity> FindOrCreateAsync(string userId)
{
return await FindAsync(userId) ??
await CreateAsync(userId);
}
}
@@ -1,60 +1,57 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using Prospect.Server.Api.Config;
using Prospect.Server.Api.Services.Database.Models;
namespace Prospect.Server.Api.Services.Database
namespace Prospect.Server.Api.Services.Database;
public class DbUserDataService : BaseDbService<PlayFabUserData>
{
public class DbUserDataService : BaseDbService<PlayFabUserData>
public DbUserDataService(IOptions<DatabaseSettings> options) : base(options, nameof(PlayFabUserData))
{
public DbUserDataService(IOptions<DatabaseSettings> options) : base(options, nameof(PlayFabUserData))
{
}
}
public async Task<bool> HasAsync(string playFabId, string key)
{
return await Collection.Find(data => data.PlayFabId == playFabId && data.Key == key).AnyAsync();
}
public async Task<bool> HasAsync(string playFabId, string key)
{
return await Collection.Find(data => data.PlayFabId == playFabId && data.Key == key).AnyAsync();
}
public async Task<PlayFabUserData> FindAsync(string playFabId, string key)
{
return await Collection.Find(data => data.PlayFabId == playFabId && data.Key == key).SingleOrDefaultAsync();
}
public async Task<PlayFabUserData> FindAsync(string playFabId, string key)
{
return await Collection.Find(data => data.PlayFabId == playFabId && data.Key == key).SingleOrDefaultAsync();
}
public async Task<PlayFabUserData> InsertAsync(string playFabId, string key, string value, bool isPublic)
public async Task<PlayFabUserData> InsertAsync(string playFabId, string key, string value, bool isPublic)
{
var data = new PlayFabUserData
{
var data = new PlayFabUserData
{
PlayFabId = playFabId,
Key = key,
Value = value,
Public = isPublic,
LastUpdated = DateTime.UtcNow
};
PlayFabId = playFabId,
Key = key,
Value = value,
Public = isPublic,
LastUpdated = DateTime.UtcNow
};
await Collection.InsertOneAsync(data);
await Collection.InsertOneAsync(data);
return data;
}
return data;
}
public async Task<IAsyncCursor<PlayFabUserData>> AllAsync(string playFabId, bool publicOnly)
{
var query = publicOnly
? Collection.Find(data => data.PlayFabId == playFabId && data.Public)
: Collection.Find(data => data.PlayFabId == playFabId);
public async Task<IAsyncCursor<PlayFabUserData>> AllAsync(string playFabId, bool publicOnly)
{
var query = publicOnly
? Collection.Find(data => data.PlayFabId == playFabId && data.Public)
: Collection.Find(data => data.PlayFabId == playFabId);
return await query.ToCursorAsync();
}
return await query.ToCursorAsync();
}
public async Task UpdateValueAsync(string dataId, string value)
{
var update = Builders<PlayFabUserData>.Update
.Set(data => data.Value, value)
.Set(data => data.LastUpdated, DateTime.UtcNow);
public async Task UpdateValueAsync(string dataId, string value)
{
var update = Builders<PlayFabUserData>.Update
.Set(data => data.Value, value)
.Set(data => data.LastUpdated, DateTime.UtcNow);
await Collection.UpdateOneAsync(data => data.Id == dataId, update);
}
await Collection.UpdateOneAsync(data => data.Id == dataId, update);
}
}
@@ -1,50 +1,46 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Options;
using MongoDB.Driver;
using Prospect.Server.Api.Config;
using Prospect.Server.Api.Services.Database.Models;
namespace Prospect.Server.Api.Services.Database
namespace Prospect.Server.Api.Services.Database;
public class DbUserService : BaseDbService<PlayFabUser>
{
public class DbUserService : BaseDbService<PlayFabUser>
public DbUserService(IOptions<DatabaseSettings> settings) : base(settings, nameof(PlayFabUser))
{
public DbUserService(IOptions<DatabaseSettings> settings) : base(settings, nameof(PlayFabUser))
{
}
}
public async Task<PlayFabUser> FindAsync(PlayFabUserAuthType type, string key)
{
return await Collection.Find(user => user.Auth.Any(auth =>
auth.Type == type &&
auth.Key == key)).FirstOrDefaultAsync();
}
public async Task<PlayFabUser> FindAsync(PlayFabUserAuthType type, string key)
{
return await Collection.Find(user => user.Auth.Any(auth =>
auth.Type == type &&
auth.Key == key)).FirstOrDefaultAsync();
}
private async Task<PlayFabUser> CreateAsync(PlayFabUserAuthType type, string key)
private async Task<PlayFabUser> CreateAsync(PlayFabUserAuthType type, string key)
{
var user = new PlayFabUser
{
var user = new PlayFabUser
DisplayName = "Unknown",
Auth = new List<PlayFabUserAuth>
{
DisplayName = "Unknown",
Auth = new List<PlayFabUserAuth>
new PlayFabUserAuth
{
new PlayFabUserAuth
{
Type = type,
Key = key
}
Type = type,
Key = key
}
};
}
};
await Collection.InsertOneAsync(user);
await Collection.InsertOneAsync(user);
return user;
}
return user;
}
public async Task<PlayFabUser> FindOrCreateAsync(PlayFabUserAuthType type, string key)
{
return await FindAsync(type, key) ??
await CreateAsync(type, key);
}
public async Task<PlayFabUser> FindOrCreateAsync(PlayFabUserAuthType type, string key)
{
return await FindAsync(type, key) ??
await CreateAsync(type, key);
}
}
@@ -1,23 +1,21 @@
using System;
using System.Security.Cryptography;
using System.Security.Cryptography;
using MongoDB.Bson.Serialization;
namespace Prospect.Server.Api.Services.Database.Generator
{
public class PlayFabIdGenerator : IIdGenerator
{
private static readonly RNGCryptoServiceProvider Random = new RNGCryptoServiceProvider();
public object GenerateId(object container, object document)
{
Span<byte> data = stackalloc byte[8];
Random.GetBytes(data);
return Convert.ToHexString(data);
}
namespace Prospect.Server.Api.Services.Database.Generator;
public bool IsEmpty(object id)
{
return id is not string idStr || string.IsNullOrEmpty(idStr);
}
public class PlayFabIdGenerator : IIdGenerator
{
private static readonly RNGCryptoServiceProvider Random = new RNGCryptoServiceProvider();
public object GenerateId(object container, object document)
{
Span<byte> data = stackalloc byte[8];
Random.GetBytes(data);
return Convert.ToHexString(data);
}
public bool IsEmpty(object id)
{
return id is not string idStr || string.IsNullOrEmpty(idStr);
}
}
@@ -1,18 +1,17 @@
using MongoDB.Bson.Serialization.Attributes;
using Prospect.Server.Api.Services.Database.Generator;
namespace Prospect.Server.Api.Services.Database.Models
namespace Prospect.Server.Api.Services.Database.Models;
/// <summary>
/// title_player_account
/// </summary>
public class PlayFabEntity
{
/// <summary>
/// title_player_account
/// </summary>
public class PlayFabEntity
{
[BsonId(IdGenerator = typeof(PlayFabIdGenerator))]
public string Id { get; set; }
[BsonId(IdGenerator = typeof(PlayFabIdGenerator))]
public string Id { get; set; }
[BsonRequired]
[BsonElement("UserId")]
public string UserId { get; set; }
}
[BsonRequired]
[BsonElement("UserId")]
public string UserId { get; set; }
}
@@ -1,23 +1,21 @@
using System.Collections.Generic;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Bson.Serialization.Attributes;
using Prospect.Server.Api.Services.Database.Generator;
namespace Prospect.Server.Api.Services.Database.Models
namespace Prospect.Server.Api.Services.Database.Models;
/// <summary>
/// master_player_account
/// </summary>
public class PlayFabUser
{
/// <summary>
/// master_player_account
/// </summary>
public class PlayFabUser
{
[BsonId(IdGenerator = typeof(PlayFabIdGenerator))]
public string Id { get; set; }
[BsonId(IdGenerator = typeof(PlayFabIdGenerator))]
public string Id { get; set; }
[BsonRequired]
[BsonElement("DisplayName")]
public string DisplayName { get; set; }
[BsonRequired]
[BsonElement("DisplayName")]
public string DisplayName { get; set; }
[BsonRequired]
[BsonElement("Auth")]
public List<PlayFabUserAuth> Auth { get; set; }
}
[BsonRequired]
[BsonElement("Auth")]
public List<PlayFabUserAuth> Auth { get; set; }
}
@@ -1,13 +1,12 @@
using MongoDB.Bson.Serialization.Attributes;
namespace Prospect.Server.Api.Services.Database.Models
namespace Prospect.Server.Api.Services.Database.Models;
public class PlayFabUserAuth
{
public class PlayFabUserAuth
{
[BsonElement("Type")]
public PlayFabUserAuthType Type { get; set; }
[BsonElement("Type")]
public PlayFabUserAuthType Type { get; set; }
[BsonElement("Key")]
public string Key { get; set; }
}
[BsonElement("Key")]
public string Key { get; set; }
}
@@ -1,8 +1,7 @@
namespace Prospect.Server.Api.Services.Database.Models
namespace Prospect.Server.Api.Services.Database.Models;
public enum PlayFabUserAuthType
{
public enum PlayFabUserAuthType
{
Epic,
Steam
}
Epic,
Steam
}
@@ -1,36 +1,34 @@
using System;
using MongoDB.Bson;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace Prospect.Server.Api.Services.Database.Models
{
public class PlayFabUserData
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
/// <summary>
/// PlayFabUser.Id
/// </summary>
[BsonRequired]
[BsonElement("PlayFabId")]
public string PlayFabId { get; set; }
namespace Prospect.Server.Api.Services.Database.Models;
[BsonRequired]
[BsonElement("Key")]
public string Key { get; set; }
public class PlayFabUserData
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[BsonRequired]
[BsonElement("Value")]
public string Value { get; set; }
/// <summary>
/// PlayFabUser.Id
/// </summary>
[BsonRequired]
[BsonElement("PlayFabId")]
public string PlayFabId { get; set; }
[BsonRequired]
[BsonElement("Key")]
public string Key { get; set; }
[BsonRequired]
[BsonElement("Public")]
public bool Public { get; set; }
[BsonRequired]
[BsonElement("Value")]
public string Value { get; set; }
[BsonRequired]
[BsonElement("LastUpdated")]
public DateTime LastUpdated { get; set; }
}
[BsonRequired]
[BsonElement("Public")]
public bool Public { get; set; }
[BsonRequired]
[BsonElement("LastUpdated")]
public DateTime LastUpdated { get; set; }
}
File diff suppressed because one or more lines are too long
@@ -1,33 +1,29 @@
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
namespace Prospect.Server.Api.Services.UserData;
namespace Prospect.Server.Api.Services.UserData
public class TitleDataService
{
public class TitleDataService
{
public TitleDataService(ILogger<TitleDataService> logger)
{
public TitleDataService(ILogger<TitleDataService> logger)
{
}
}
public Dictionary<string, string> Find(List<string> keys)
{
if (keys != null && keys.Count > 0)
{
var result = new Dictionary<string, string>();
public Dictionary<string, string> Find(List<string> keys)
{
if (keys != null && keys.Count > 0)
{
var result = new Dictionary<string, string>();
foreach (var key in keys)
{
if (TitleDataDefault.Data.TryGetValue(key, out var value))
{
result.Add(key, value);
}
}
foreach (var key in keys)
{
if (TitleDataDefault.Data.TryGetValue(key, out var value))
{
result.Add(key, value);
}
}
return result;
}
return result;
}
return TitleDataDefault.Data;
}
}
return TitleDataDefault.Data;
}
}
@@ -1,182 +1,177 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Prospect.Server.Api.Models.Client.Data;
using Prospect.Server.Api.Models.Client.Data;
using Prospect.Server.Api.Services.Database;
namespace Prospect.Server.Api.Services.UserData
namespace Prospect.Server.Api.Services.UserData;
public class UserDataService
{
public class UserDataService
private readonly ILogger<UserDataService> _logger;
private readonly DbUserDataService _dbUserDataService;
public UserDataService(ILogger<UserDataService> logger, DbUserDataService dbUserDataService)
{
private readonly ILogger<UserDataService> _logger;
private readonly DbUserDataService _dbUserDataService;
_logger = logger;
_dbUserDataService = dbUserDataService;
}
public UserDataService(ILogger<UserDataService> logger, DbUserDataService dbUserDataService)
/// <summary>
/// Initialize data for the given PlayFabId.
/// </summary>
public async Task InitAsync(string playFabId)
{
// TODO: Proper objects.
var defaultData = new Dictionary<string, (bool isPublic, string value)>
{
_logger = logger;
_dbUserDataService = dbUserDataService;
["Generators__2021_09_09"] = (true, "[{\"generatorId\":\"playerquarters_gen_aurum\",\"lastClaimTime\":{\"seconds\":0}},{\"generatorId\":\"playerquarters_gen_kmarks\",\"lastClaimTime\":{\"seconds\":0}},{\"generatorId\":\"playerquarters_gen_crate\",\"lastClaimTime\":{\"seconds\":0}}]"),
["InventoryInfo"] = (true, "{\"inventoryStashLimit\":75,\"inventoryBagLimit\":300,\"inventorySafeLimit\":5}"),
["LOADOUT"] = (true, $"{{\"id\":\"\",\"userId\":\"{playFabId}\",\"kit\":\"\",\"shield\":\"\",\"helmet\":\"\",\"weaponOne\":\"\",\"weaponTwo\":\"\",\"bag\":null,\"bagItemsAsJsonStr\":\"\",\"safeItemsAsJsonStr\":\"\"}}"),
["OnboardingProgression"] = (true, "{\"currentMissionID\":\"TalkToBadum\",\"progress\":0,\"showPopup\":true}"),
["PickaxeUpgradeLevel"] = (true, "0"),
["PlayerQuartersLevel"] = (true, "{\"level\":1,\"upgradeStartedTime\":{\"seconds\":0}}"),
};
foreach (var (key, (isPublic, value)) in defaultData)
{
if (!await _dbUserDataService.HasAsync(playFabId, key))
{
await _dbUserDataService.InsertAsync(playFabId, key, value, isPublic);
}
}
}
/// <summary>
///
/// </summary>
/// <param name="currentUserId">
/// The authenticated user id.
/// </param>
/// <param name="requestUserId">
/// The requested user id.
/// </param>
/// <param name="keys"></param>
/// <returns></returns>
public async Task<Dictionary<string, FUserDataRecord>> FindAsync(
string currentUserId,
string requestUserId,
List<string> keys)
{
if (string.IsNullOrEmpty(currentUserId))
{
throw new ArgumentNullException(nameof(currentUserId));
}
if (requestUserId == null)
{
requestUserId = currentUserId;
}
/// <summary>
/// Initialize data for the given PlayFabId.
/// </summary>
public async Task InitAsync(string playFabId)
var other = currentUserId != requestUserId;
var result = new Dictionary<string, FUserDataRecord>();
if (keys != null && keys.Count > 0)
{
// TODO: Proper objects.
var defaultData = new Dictionary<string, (bool isPublic, string value)>
foreach (var key in keys)
{
["Generators__2021_09_09"] = (true, "[{\"generatorId\":\"playerquarters_gen_aurum\",\"lastClaimTime\":{\"seconds\":0}},{\"generatorId\":\"playerquarters_gen_kmarks\",\"lastClaimTime\":{\"seconds\":0}},{\"generatorId\":\"playerquarters_gen_crate\",\"lastClaimTime\":{\"seconds\":0}}]"),
["InventoryInfo"] = (true, "{\"inventoryStashLimit\":75,\"inventoryBagLimit\":300,\"inventorySafeLimit\":5}"),
["LOADOUT"] = (true, $"{{\"id\":\"\",\"userId\":\"{playFabId}\",\"kit\":\"\",\"shield\":\"\",\"helmet\":\"\",\"weaponOne\":\"\",\"weaponTwo\":\"\",\"bag\":null,\"bagItemsAsJsonStr\":\"\",\"safeItemsAsJsonStr\":\"\"}}"),
["OnboardingProgression"] = (true, "{\"currentMissionID\":\"TalkToBadum\",\"progress\":0,\"showPopup\":true}"),
["PickaxeUpgradeLevel"] = (true, "0"),
["PlayerQuartersLevel"] = (true, "{\"level\":1,\"upgradeStartedTime\":{\"seconds\":0}}"),
};
foreach (var (key, (isPublic, value)) in defaultData)
{
if (!await _dbUserDataService.HasAsync(playFabId, key))
var data = await _dbUserDataService.FindAsync(requestUserId, key);
if (data == null)
{
await _dbUserDataService.InsertAsync(playFabId, key, value, isPublic);
// TODO: Error?
continue;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="currentUserId">
/// The authenticated user id.
/// </param>
/// <param name="requestUserId">
/// The requested user id.
/// </param>
/// <param name="keys"></param>
/// <returns></returns>
public async Task<Dictionary<string, FUserDataRecord>> FindAsync(
string currentUserId,
string requestUserId,
List<string> keys)
{
if (string.IsNullOrEmpty(currentUserId))
{
throw new ArgumentNullException(nameof(currentUserId));
}
if (requestUserId == null)
{
requestUserId = currentUserId;
}
var other = currentUserId != requestUserId;
var result = new Dictionary<string, FUserDataRecord>();
if (keys != null && keys.Count > 0)
{
foreach (var key in keys)
if (!data.Public && other)
{
var data = await _dbUserDataService.FindAsync(requestUserId, key);
if (data == null)
{
// TODO: Error?
continue;
}
if (!data.Public && other)
{
// TODO: Error?
continue;
}
// TODO: Error?
continue;
}
result.Add(data.Key, new FUserDataRecord
{
LastUpdated = data.LastUpdated,
Permission = data.Public ? UserDataPermission.Public : UserDataPermission.Private,
Value = data.Value
});
}
}
else
{
var cursor = await _dbUserDataService.AllAsync(requestUserId, other);
while (await cursor.MoveNextAsync())
{
foreach (var data in cursor.Current)
{
result.Add(data.Key, new FUserDataRecord
{
LastUpdated = data.LastUpdated,
Permission = data.Public ? UserDataPermission.Public : UserDataPermission.Private,
Value = data.Value
});
}
}
else
{
var cursor = await _dbUserDataService.AllAsync(requestUserId, other);
while (await cursor.MoveNextAsync())
{
foreach (var data in cursor.Current)
{
result.Add(data.Key, new FUserDataRecord
{
LastUpdated = data.LastUpdated,
Permission = data.Public ? UserDataPermission.Public : UserDataPermission.Private,
Value = data.Value
});
}
}
}
return result;
}
/// <summary>
///
/// </summary>
/// <param name="currentUserId">
/// The authenticated user id.
/// </param>
/// <param name="requestUserId">
/// The requested user id.
/// </param>
/// <param name="changes"></param>
/// <returns></returns>
public async Task UpdateAsync(
string currentUserId,
string requestUserId,
Dictionary<string, string> changes)
{
if (changes.Count == 0)
{
return;
}
if (string.IsNullOrEmpty(currentUserId))
{
throw new ArgumentNullException(nameof(currentUserId));
}
if (requestUserId == null)
{
requestUserId = currentUserId;
}
return result;
}
// Whether we are updating someone else.
var other = currentUserId != requestUserId;
/// <summary>
///
/// </summary>
/// <param name="currentUserId">
/// The authenticated user id.
/// </param>
/// <param name="requestUserId">
/// The requested user id.
/// </param>
/// <param name="changes"></param>
/// <returns></returns>
public async Task UpdateAsync(
string currentUserId,
string requestUserId,
Dictionary<string, string> changes)
{
if (changes.Count == 0)
{
return;
}
foreach (var (key, value) in changes)
if (string.IsNullOrEmpty(currentUserId))
{
throw new ArgumentNullException(nameof(currentUserId));
}
if (requestUserId == null)
{
requestUserId = currentUserId;
}
// Whether we are updating someone else.
var other = currentUserId != requestUserId;
foreach (var (key, value) in changes)
{
var data = await _dbUserDataService.FindAsync(currentUserId, key);
if (data == null)
{
var data = await _dbUserDataService.FindAsync(currentUserId, key);
if (data == null)
if (other)
{
if (other)
{
_logger.LogWarning("User {PlayFabId} attempted to update non-existing key {Key} of another user {PlayFabIdOther}", currentUserId, key, requestUserId);
}
else
{
await _dbUserDataService.InsertAsync(currentUserId, key, value, false);
}
_logger.LogWarning("User {PlayFabId} attempted to update non-existing key {Key} of another user {PlayFabIdOther}", currentUserId, key, requestUserId);
}
else
{
await _dbUserDataService.InsertAsync(currentUserId, key, value, false);
}
continue;
}
if (!data.Public && other)
{
_logger.LogWarning("User {PlayFabId} attempted to update non-public key {Key} of another user {PlayFabIdOther}", currentUserId, key, data.PlayFabId);
continue;
}
await _dbUserDataService.UpdateValueAsync(data.Id, value);
continue;
}
if (!data.Public && other)
{
_logger.LogWarning("User {PlayFabId} attempted to update non-public key {Key} of another user {PlayFabIdOther}", currentUserId, key, data.PlayFabId);
continue;
}
await _dbUserDataService.UpdateValueAsync(data.Id, value);
}
}
}
+43 -50
View File
@@ -1,72 +1,65 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Prospect.Server.Api.Config;
using Prospect.Server.Api.Converters;
using Prospect.Server.Api.Middleware;
using Prospect.Server.Api.Services.Auth;
using Prospect.Server.Api.Services.Auth.User;
using Prospect.Server.Api.Services.Database;
using Prospect.Server.Api.Services.UserData;
using Serilog;
namespace Prospect.Server.Api
namespace Prospect.Server.Api;
public class Startup
{
public class Startup
public Startup(IConfiguration configuration)
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
Configuration = configuration;
}
private IConfiguration Configuration { get; }
private IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AuthTokenSettings>(Configuration.GetSection(nameof(AuthTokenSettings)));
services.Configure<DatabaseSettings>(Configuration.GetSection(nameof(DatabaseSettings)));
services.Configure<PlayFabSettings>(Configuration.GetSection(nameof(PlayFabSettings)));
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AuthTokenSettings>(Configuration.GetSection(nameof(AuthTokenSettings)));
services.Configure<DatabaseSettings>(Configuration.GetSection(nameof(DatabaseSettings)));
services.Configure<PlayFabSettings>(Configuration.GetSection(nameof(PlayFabSettings)));
services.AddSingleton<AuthTokenService>();
services.AddSingleton<UserDataService>();
services.AddSingleton<TitleDataService>();
services.AddSingleton<AuthTokenService>();
services.AddSingleton<UserDataService>();
services.AddSingleton<TitleDataService>();
services.AddSingleton<DbUserService>();
services.AddSingleton<DbEntityService>();
services.AddSingleton<DbUserService>();
services.AddSingleton<DbEntityService>();
services.AddSingleton<DbUserDataService>();
services.AddSingleton<DbUserDataService>();
services.AddAuthentication(_ =>
{
services.AddAuthentication(_ =>
{
})
.AddUserAuthentication(_ => {})
.AddEntityAuthentication(_ => {});
})
.AddUserAuthentication(_ => {})
.AddEntityAuthentication(_ => {});
services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
services.AddControllers().AddJsonOptions(options =>
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSerilogRequestLogging();
app.UseMiddleware<RequestLoggerMiddleware>();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
options.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSerilogRequestLogging();
app.UseMiddleware<RequestLoggerMiddleware>();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}