Exemple #1
0
        /// <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();
            }
        }
Exemple #2
0
        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}")));
            }
        }
Exemple #3
0
        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)));
        }
Exemple #4
0
        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)));
        }
Exemple #5
0
        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));
        }