public async Task <JsonResult> TryEnterGameServer([FromServices] IGameSessionRepository gameSessionRepository) { if (!ModelState.IsValid) { return(Json(new ServerEntryResponse(ServerEntryResponseCode.FailedConnectionActivelyRefused))); } int userId = int.Parse(HaloLiveUserManager.GetUserId(User)); //TODO: Should we try parse? Or change the signature for this? //If there is a session and we're already logged in reject the requesting user //It is possible for there to be an existing session yet not logged in //that would mean an existing session was unclaimined and hasn't been cleaned up yet or someone is connecting in the middle of the session transfer bool hasSessionAlready = await gameSessionRepository.HasSession(userId); if (hasSessionAlready) { return(Json(new ServerEntryResponse(ServerEntryResponseCode.FailedAlreadyLoggedIn))); } //This could result in a data race so we need to check the result after we create. Don't assume this won't fail or be exploited SessionCreationResult result = await gameSessionRepository.TryCreateSession(userId, Request.HttpContext.Connection.RemoteIpAddress.ToString()); if (!result.isSessionCreated) { return(Json(new ServerEntryResponse(ServerEntryResponseCode.GeneralServerError))); } //TODO: Handle gameserver/zoneserver redirection based on session information. return(Json(new ServerEntryResponse(result.SessionGuid, new ResolvedEndpoint("127.0.0.1", 8051)))); //TODO: Obviously we want to look in the DB and provide a real token. }
public async Task <IActionResult> RequestWorldDownloadUrl([FromServices] IReadOnlyWorldEntryRepository worldEntryRepository, [FromServices] IStorageUrlBuilder urlBuilder, [FromBody] WorldDownloadURLRequest downloadRequest) { if (worldEntryRepository == null) { throw new ArgumentNullException(nameof(worldEntryRepository)); } //TODO: We want to rate limit access to this API //TODO: We should use both app logging but also another logging service that always gets hit //TODO: Consolidate this shared logic between controllers if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Recieved {nameof(RequestWorldDownloadUrl)} request from {HaloLiveUserManager.GetUserName(User)}:{HaloLiveUserManager.GetUserId(User)}."); } int userId; if (!int.TryParse(HaloLiveUserManager.GetUserId(User), out userId)) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Error: Encountered authorized user with unparsable UserId from User: {HaloLiveUserManager.GetUserName(User)}."); } return(Json(new WorldDownloadURLResponse(WorldDownloadURLResponseCode.AuthorizationFailed))); } //TODO: We should probably check the flags of world to see if it's private (IE hidden from user). Or if it's unlisted or removed. //It's possible a user is requesting a world that doesn't exist //Could be malicious or it could have been deleted for whatever reason if (!await worldEntryRepository.HasEntry(downloadRequest.WorldId)) { return(Json(new WorldDownloadURLResponse(WorldDownloadURLResponseCode.NoWorld))); } //We can get the URL from the urlbuilder if we provide the world storage GUID string downloadUrl = await urlBuilder.BuildRetrivalUrl(UserContentType.World, (await worldEntryRepository.GetWorldEntry(downloadRequest.WorldId)).StorageGuid); //TODO: Should we both validating S3 availability? if (String.IsNullOrEmpty(downloadUrl)) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Failed to create world upload URL for {HaloLiveUserManager.GetUserName(User)}:{HaloLiveUserManager.GetUserId(User)} with ID: {downloadRequest.WorldId}."); } return(Json(new WorldDownloadURLResponse(WorldDownloadURLResponseCode.WorldDownloadServiceUnavailable))); } if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Success. Sending {HaloLiveUserManager.GetUserName(User)} URL: {downloadUrl}"); } return(Json(new WorldDownloadURLResponse(downloadUrl))); }
public async Task <IActionResult> RequestWorldUploadUrl([FromServices] IWorldEntryRepository worldEntryRepository, [FromServices] IStorageUrlBuilder urlBuilder) { if (worldEntryRepository == null) { throw new ArgumentNullException(nameof(worldEntryRepository)); } //TODO: We want to rate limit access to this API //TODO: We should use both app logging but also another logging service that always gets hit if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Recieved {nameof(RequestWorldUploadUrl)} request from {HaloLiveUserManager.GetUserName(User)}:{HaloLiveUserManager.GetUserId(User)}."); } int userId; if (!int.TryParse(HaloLiveUserManager.GetUserId(User), out userId)) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Error: Encountered authorized user with unparsable UserId from User: {HaloLiveUserManager.GetUserName(User)}."); } return(new JsonResult(RequestedUrlResponseModel.CreateFailure("Failed to authorize action.", RequestedUrlResponseCode.AuthorizationFailed))); } //TODO: Abstract this behind an issuer Guid worldGuid = Guid.NewGuid(); //TODO: Check if the result is valid? We should maybe return bool from this API //The idea is to create an entry which will contain a GUID. From that GUID we can then generate the upload URL await worldEntryRepository.AddWorldEntry(userId, this.HttpContext.Connection.RemoteIpAddress.ToString(), worldGuid); //TODO: Ok to just provide a guid right? string uploadUrl = await urlBuilder.BuildUploadUrl(UserContentType.World, worldGuid); if (String.IsNullOrEmpty(uploadUrl)) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Failed to create world upload URL for {HaloLiveUserManager.GetUserName(User)}:{HaloLiveUserManager.GetUserId(User)} with GUID: {worldGuid}."); } return(new JsonResult(RequestedUrlResponseModel.CreateFailure("Upload service unavailable.", RequestedUrlResponseCode.ServiceUnavailable))); } if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Success. Sending {HaloLiveUserManager.GetUserName(User)} URL: {uploadUrl}"); } return(new JsonResult(RequestedUrlResponseModel.CreateSuccess(uploadUrl))); }