/// <inheritdoc /> public override async Task OnConnectedAsync() { await base.OnConnectedAsync() .ConfigureAwaitFalseVoid(); if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Account Connected: {ClaimsReader.GetAccountName(Context.User)}:{ClaimsReader.GetAccountId(Context.User)} with SignalR UserId: {Context.UserIdentifier}"); } try { foreach (var listener in OnConnectionHubListeners) { HubOnConnectionState connectionState = await listener.OnConnected(this).ConfigureAwaitFalse(); //if the listener indicated we need to abort for whatever reason we //should believe it and just abort. if (connectionState == HubOnConnectionState.Abort) { Context.Abort(); break; } } } catch (Exception e) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Account: {ClaimsReader.GetAccountName(Context.User)}:{ClaimsReader.GetAccountId(Context.User)} failed to properly connect to hub. Error: {e.ToString()}\n\nStack: {e.StackTrace}"); } Context.Abort(); } }
public async Task <IActionResult> CreateZoneServerAccount([FromBody][JetBrains.Annotations.NotNull] ZoneServerAccountRegistrationRequest request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } //We want to log this out for information purposes whenever an auth request begins if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Zone Register Request by UserAccount: {ClaimsReader.GetAccountName(this.User)}:{ClaimsReader.GetAccountIdInt(this.User)} {HttpContext.Connection.RemoteIpAddress}:{HttpContext.Connection.RemotePort}"); } //TODO: Create cryptographically secure random bytes for password and user. string zoneUserName = Guid.NewGuid().ToString(); string zonePassword = Guid.NewGuid().ToString(); ZoneServerApplicationUser user = new ZoneServerApplicationUser(ClaimsReader.GetAccountIdInt(this.User)) { UserName = zoneUserName, Email = "*****@*****.**", //TODO: Real email??? }; IdentityResult identityResult = await UserManager.CreateAsync(user, zonePassword); if (identityResult.Succeeded) { //Adds the vrgid account owner claim. await UserManager.AddClaimAsync(user, new Claim(GladMMOAuthConstants.ACCOUNT_ID_OWNER_CLAIM_NAME, ClaimsReader.GetAccountId(this.User))); //Here we inherit each role the user account has to the zoneserver account foreach (var claim in User.Claims) { if (claim.Type == "role") //TODO: Is there a constant for this?? { if (claim.Value.ToLower() != GladMMOAuthConstants.PLAYERACCOUNT_AUTHORIZATION_ROLE) //DO NOT add the player role. { await UserManager.AddToRoleAsync(user, claim.Value); } } } //Also add the ZoneServer role await UserManager.AddToRoleAsync(user, GladMMOAuthConstants.ZONESERVER_AUTHORIZATION_ROLE); //At this point, the account has the PlayFab id claim so it's ready for use. return(Json(new ZoneServerAccountRegistrationResponse(user.Id, zoneUserName, zonePassword))); } else { return(BadRequest(identityResult.Errors.Aggregate("", (s, error) => $"{s} {error.Code}:{error.Description}"))); } }
private async Task <IActionResult> GenerateUploadTokenResponse(IStorageUrlBuilder urlBuilder, TContentType content) { string uploadUrl = await urlBuilder.BuildUploadUrl(ContentType, content.StorageGuid); if (String.IsNullOrEmpty(uploadUrl)) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Failed to create content upload URL for {ClaimsReader.GetAccountName(User)}:{ClaimsReader.GetAccountId(User)} with GUID: {content.StorageGuid}."); } return(BuildFailedResponseModel(ContentUploadResponseCode.ServiceUnavailable)); } if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Success. Sending {ClaimsReader.GetAccountName(User)} URL: {uploadUrl}"); } return(BuildSuccessfulResponseModel(new ContentUploadToken(uploadUrl, content.ContentId, content.StorageGuid))); }
public async Task <IActionResult> RequestContentDownloadURL( [FromRoute(Name = "id")] long contentId, [FromServices] ICustomContentRepository <TContentType> contentEntryRepository, [FromServices] IStorageUrlBuilder urlBuilder, [FromServices] IContentDownloadAuthroizationValidator downloadAuthorizer) { if (contentEntryRepository == null) { throw new ArgumentNullException(nameof(contentEntryRepository)); } //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(RequestContentDownloadURL)} request from {ClaimsReader.GetAccountName(User)}:{ClaimsReader.GetAccountId(User)}."); } //TODO: We should probably check the flags of content 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 content that doesn't exist //Could be malicious or it could have been deleted for whatever reason if (!await contentEntryRepository.ContainsAsync(contentId).ConfigureAwaitFalse()) { return(Json(new ContentDownloadURLResponse(ContentDownloadURLResponseCode.NoContentId))); } //TODO: Refactor this into a validation dependency //Now we need to do some validation to determine if they should even be downloading this content //we do not want people downloading a content they have no business of going to int userId = ClaimsReader.GetAccountIdInt(User); //TODO: Need to NOT call it world content if (!await downloadAuthorizer.CanUserAccessWorldContet(userId, contentId)) { return(Json(new ContentDownloadURLResponse(ContentDownloadURLResponseCode.AuthorizationFailed))); } TContentType contentEntry = await contentEntryRepository.RetrieveAsync(contentId); //We can get the URL from the urlbuilder if we provide the content storage GUID string downloadUrl = await urlBuilder.BuildRetrivalUrl(ContentType, contentEntry.StorageGuid); //TODO: Should we be validating S3 availability? if (String.IsNullOrEmpty(downloadUrl)) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"Failed to create content upload URL for {ClaimsReader.GetAccountName(User)}:{ClaimsReader.GetAccountId(User)} with ID: {contentId}."); } return(Json(new ContentDownloadURLResponse(ContentDownloadURLResponseCode.ContentDownloadServiceUnavailable))); } if (Logger.IsEnabled(LogLevel.Information)) { Logger.LogInformation($"Success. Sending {ClaimsReader.GetAccountName(User)} URL: {downloadUrl}"); } return(Json(new ContentDownloadURLResponse(downloadUrl, contentEntry.Version))); }
public async Task <IActionResult> RequestContentUploadUrl( [FromServices] ICustomContentRepository <TContentType> contentEntryRepository, [FromServices] IStorageUrlBuilder urlBuilder) { if (contentEntryRepository == null) { throw new ArgumentNullException(nameof(contentEntryRepository)); } //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(RequestContentUploadUrl)} request from {ClaimsReader.GetAccountName(User)}:{ClaimsReader.GetAccountId(User)}."); } //TODO: Check if the result is valid? We should maybe return bool from this API (we do return bool from this API now) //The idea is to create an entry which will contain a GUID. From that GUID we can then generate the upload URL TContentType content = GenerateNewModel(); bool result = await contentEntryRepository.TryCreateAsync(content); return(await GenerateUploadTokenResponse(urlBuilder, content)); }