示例#1
0
        public async Task <IActionResult> UpdateUploadedContent(
            [FromRoute(Name = "id")] long contentId,
            [FromServices] ICustomContentRepository <TContentType> contentEntryRepository,
            [FromServices] IStorageUrlBuilder urlBuilder)
        {
            //Content must exist.
            if (!await contentEntryRepository.ContainsAsync(contentId))
            {
                return(BuildFailedResponseModel(ContentUploadResponseCode.InvalidRequest));
            }

            //Unlike creation, we just load an existing one.
            TContentType content = await contentEntryRepository.RetrieveAsync(contentId)
                                   .ConfigureAwaitFalse();

            //WE MUST MAKE SURE THE AUTHORIZED USER OWNS THE CONTENT!!
            if (ClaimsReader.GetAccountIdInt(User) != content.AccountId)
            {
                return(BuildFailedResponseModel(ContentUploadResponseCode.AuthorizationFailed));
            }

            try
            {
                IActionResult response = await GenerateUploadTokenResponse(urlBuilder, content);

                //This is where we update the content versioning.
                content.Version += 1;
                await contentEntryRepository.UpdateAsync(content.ContentId, content)
                .ConfigureAwaitFalseVoid();

                return(response);
            }
            catch (Exception e)
            {
                if (Logger.IsEnabled(LogLevel.Error))
                {
                    Logger.LogError($"Failed to update content. Reason: {e.Message}");
                }

                return(BuildFailedResponseModel(ContentUploadResponseCode.InvalidRequest));
            }
        }
示例#2
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));
        }
示例#3
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)));
        }