Ver código fonte

File upload safety checks

Lukas Angerer 3 anos atrás
pai
commit
5343cbe91e

+ 12 - 0
src/RunnersMeet.Server/ApiException.cs

@@ -0,0 +1,12 @@
+namespace RunnersMeet.Server;
+
+public class ApiException : Exception
+{
+	public ApiException(string message) : base(message)
+	{
+	}
+
+	public ApiException(string message, Exception inner) : base(message, inner)
+	{
+	}
+}

+ 21 - 6
src/RunnersMeet.Server/Controllers/TracksController.cs

@@ -16,12 +16,14 @@ public class TracksController : ControllerBase
 	private readonly IFileStorage _fileStorage;
 	private readonly GpxParser _gpxParser;
 	private readonly QueryFactory _queryFactory;
+	private readonly IConfiguration _config;
 
-	public TracksController(IFileStorage fileStorage, GpxParser gpxParser, QueryFactory queryFactory)
+	public TracksController(IFileStorage fileStorage, GpxParser gpxParser, QueryFactory queryFactory, IConfiguration config)
 	{
 		_fileStorage = fileStorage;
 		_gpxParser = gpxParser;
 		_queryFactory = queryFactory;
+		_config = config;
 	}
 
 	[HttpGet]
@@ -33,13 +35,26 @@ public class TracksController : ControllerBase
 	[HttpPost]
 	public async Task<ActionResult<Track>> CreateTrack([FromForm] IFormFile file, CancellationToken cancellationToken = default)
 	{
-		var fileName = await _fileStorage.UploadFileAsync(file, cancellationToken);
+		var limit = _config.GetValue<long>("GpxFileSizeLimit");
+		if (file.Length > limit)
+		{
+			throw new ApiException($"Uploaded tracks cannot be larger than {limit / (1024 * 1024)}MB");
+		}
 
-		var gpxSummary = _gpxParser.ExtractSummary(_fileStorage.OpenFileRead(fileName));
-		var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? "<unknown>";
-		var track = _queryFactory.CreateTrackCommand().Create(userId, fileName, gpxSummary);
+		var fileName = await _fileStorage.UploadFileAsync(file, cancellationToken);
 
-		return Ok(track);
+		try
+		{
+			var gpxSummary = _gpxParser.ExtractSummary(_fileStorage.OpenFileRead(fileName));
+			var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? "<unknown>";
+			var track = _queryFactory.CreateTrackCommand().Create(userId, fileName, gpxSummary);
+			return Ok(track);
+		}
+		catch (Exception e)
+		{
+			_fileStorage.DeleteFile(fileName);
+			throw new ApiException("Error while creating track", e);
+		}
 	}
 
 	[HttpGet("{id}")]

+ 2 - 1
src/RunnersMeet.Server/appsettings.json

@@ -16,5 +16,6 @@
 	"Persistence": {
 		"DataFilePath": "./data/tracks.db",
 		"FileStorageRootPath": "./data/files"
-	}
+	},
+	"GpxFileSizeLimit": 2097152
 }