Пример #1
0
        public async Task <ActionResult <DebugSymbolUploadResult> > StartUpload(
            [Required][FromBody] DebugSymbolUploadRequest request)
        {
            if (request.SymbolPath.Contains('\\'))
            {
                return(BadRequest("The path contains a Windows line separator"));
            }

            if (request.SymbolPath.StartsWith("/") || request.SymbolPath.Contains(".."))
            {
                return(BadRequest("The path must not start with a slash or contain two dots in a row"));
            }

            logger.LogInformation("Upload request for symbol: {SymbolPath}", request.SymbolPath);

            if (request.SymbolPath.Count(c => c == '/') < 2 || !request.SymbolPath.EndsWith(".sym"))
            {
                return(BadRequest("The path must contain at least two path separators and end in .sym"));
            }

            if (!remoteStorage.Configured)
            {
                throw new HttpResponseException()
                      {
                          Status = StatusCodes.Status500InternalServerError,
                          Value  = "Remote storage is not configured",
                      };
            }

            var folder = await StorageItem.GetSymbolsFolder(database);

            if (folder == null)
            {
                throw new HttpResponseException()
                      {
                          Status = StatusCodes.Status500InternalServerError,
                          Value  = "Storage folder is missing",
                      };
            }

            var user = HttpContext.AuthenticatedUser() !;

            var symbol = new DebugSymbol()
            {
                // Start in non-active state until the upload is ready
                Active       = false,
                Uploaded     = false,
                Name         = request.SymbolPath.Split("/").Last(),
                RelativePath = request.SymbolPath,
                CreatedById  = user.Id,
                Size         = request.Size,
            };

            var storageItem = new StorageItem()
            {
                Name        = symbol.StorageFileName,
                Parent      = folder,
                Ftype       = FileType.File,
                Special     = true,
                ReadAccess  = FileAccess.Developer,
                WriteAccess = FileAccess.Nobody,
            };

            symbol.StoredInItem = storageItem;

            await database.StorageItems.AddAsync(storageItem);

            await database.DebugSymbols.AddAsync(symbol);

            // This save will fail if duplicate upload was attempted
            await database.SaveChangesAsync();

            jobClient.Enqueue <CountFolderItemsJob>((x) => x.Execute(folder.Id, CancellationToken.None));

            logger.LogInformation("New DebugSymbol ({Id}) \"{RelativePath}\" created by {Email}", symbol.Id,
                                  symbol.RelativePath, user.Email);

            // Create a version to upload to
            var version = await symbol.StoredInItem.CreateNextVersion(database);

            var file = await version.CreateStorageFile(database,
                                                       DateTime.UtcNow + AppInfo.RemoteStorageUploadExpireTime,
                                                       request.Size);

            if (request.Size != file.Size)
            {
                throw new Exception("Logic error in StorageFile size setting");
            }

            await database.SaveChangesAsync();

            logger.LogInformation("Upload of DebugSymbol {Id} starting from {RemoteIpAddress}",
                                  symbol.Id, HttpContext.Connection.RemoteIpAddress);

            jobClient.Schedule <DeleteDebugSymbolIfUploadFailedJob>(x => x.Execute(symbol.Id, CancellationToken.None),
                                                                    AppInfo.RemoteStorageUploadExpireTime * 2);

            return(new DebugSymbolUploadResult()
            {
                UploadUrl = remoteStorage.CreatePresignedUploadURL(file.UploadPath,
                                                                   AppInfo.RemoteStorageUploadExpireTime),
                VerifyToken = new StorageUploadVerifyToken(dataProtector, file.UploadPath, file.StoragePath,
                                                           file.Size.Value, file.Id, symbol.Id, null, null).ToString()
            });
        }