/// <inheritdoc />
        public async Task SetWorldValidated(long worldId)
        {
            AvatarEntryModel model = await this.DefaultRepository.RetrieveAsync(worldId)
                                     .ConfigureAwait(false);

            model.IsValidated = true;

            await DefaultRepository.UpdateAsync(worldId, model)
            .ConfigureAwait(false);
        }
Ejemplo n.º 2
0
        public async Task <IActionResult> SetAvatarAsUploaded([FromRoute(Name = "id")] long worldId, [FromServices] IAvatarEntryRepository avatarEntryRepository, [FromServices] IAmazonS3 storageClient)
        {
            //At this point, the user is telling us they finished uploading the world.
            //They could be lying so we should check that the resource exists AND
            //we should also check that it's an asset bundle and gather some information from the header.

            //First we verify a world exists with this id
            if (!await avatarEntryRepository.ContainsAsync(worldId).ConfigureAwait(false))
            {
                //TODO: We should say something more specific
                return(BadRequest());
            }

            AvatarEntryModel model = await avatarEntryRepository.RetrieveAsync(worldId)
                                     .ConfigureAwait(false);

            //Check the model is associated with this account. Only 1 account can own a world resource
            if (model.AccountId != ClaimsReader.GetUserIdInt(User))
            {
                return(Unauthorized());
            }

            //Now that we know the world is in the database and the account making this authorized requests owns it
            //we can now actually check that the resource exists on the storeage system
            //TODO: This relies on some outdated API/deprecated stuff.
            bool resourceExists = await S3ResourceExists(storageClient, "projectvindictiveworlds-dev", model.StorageGuid)
                                  .ConfigureAwait(false); //TODO: Don't hardcore bucket name

            //TODO: Be more descriptive
            if (!resourceExists)
            {
                return(NotFound());
            }

            //Ok, so the user IS the resource owner AND he did upload something, so let's validate the assetbundle header.
            //TODO: Refactor this into an object that does the validation and generates readable data
            //TODO: Actually implement asset bundle validation
            //We haven't implemented this yet, we should do asset bundle parsing and validation
            //This REALLY important to prevent invalid bundles from being uploaded
            //or content that isn't even an asset bundle being uploaded
            //See: https://github.com/HearthSim/UnityPack/wiki/Format-Documentation

            //For now, since it's unimplemented let's just set it validated
            await avatarEntryRepository.SetWorldValidated(model.AvatarId)
            .ConfigureAwait(false);

            return(Ok());
        }
Ejemplo n.º 3
0
        public async Task <IActionResult> RequestAvatarUploadUrl([FromServices] IAvatarEntryRepository avatarEntryRepository, [FromServices] IStorageUrlBuilder urlBuilder)
        {
            if (avatarEntryRepository == null)
            {
                throw new ArgumentNullException(nameof(avatarEntryRepository));
            }

            //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(RequestAvatarUploadUrl)} request from {ClaimsReader.GetUserName(User)}:{ClaimsReader.GetUserId(User)}.");
            }

            int userId = ClaimsReader.GetUserIdInt(User);

            //TODO: We should send this if we can't get a user id
            //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 (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
            AvatarEntryModel world  = new AvatarEntryModel(userId, this.HttpContext.Connection.RemoteIpAddress.ToString(), worldGuid);
            bool             result = await avatarEntryRepository.TryCreateAsync(world); //TODO: Ok to just provide a guid right?

            //TODO: Check world's worldid has been set

            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 {ClaimsReader.GetUserName(User)}:{ClaimsReader.GetUserId(User)} with GUID: {worldGuid}.");
                }

                return(new JsonResult(RequestedUrlResponseModel.CreateFailure("Upload service unavailable.", RequestedUrlResponseCode.ServiceUnavailable)));
            }

            if (Logger.IsEnabled(LogLevel.Information))
            {
                Logger.LogInformation($"Success. Sending {ClaimsReader.GetUserName(User)} URL: {uploadUrl}");
            }

            return(new JsonResult(RequestedUrlResponseModel.CreateSuccess(uploadUrl, world.AvatarId)));
        }
 /// <inheritdoc />
 public Task UpdateAsync(long key, AvatarEntryModel model)
 {
     return(DefaultRepository.UpdateAsync(key, model));
 }
 /// <inheritdoc />
 public Task <bool> TryCreateAsync(AvatarEntryModel model)
 {
     return(DefaultRepository.TryCreateAsync(model));
 }