public async Task <ActionResult <PathParseResult> > ParsePath([MaxLength(500)] string?path) { var user = HttpContext.AuthenticatedUser(); if (user != null && HttpContext.AuthenticatedUserRestriction() != AuthenticationScopeRestriction.None) { throw new HttpResponseException() { Status = StatusCodes.Status403Forbidden, Value = "You authentication method has incorrect access restriction for this endpoint" }; } // Return root folder if the path is empty if (string.IsNullOrEmpty(path)) { return(new PathParseResult() { FinalItem = null }); } var pathParts = path.Split('/'); StorageItem?currentItem = null; StorageItem?parentItem = null; foreach (var part in pathParts) { // Skip empty parts to support starting with a slash or having multiple in a row if (string.IsNullOrEmpty(part)) { continue; } // If we have already found a file, then further path parts are invalid if (currentItem?.Ftype == FileType.File) { return(BadRequest("Detected further path components after a file was found")); } var currentId = currentItem?.Id; var nextItem = await database.StorageItems.FirstOrDefaultAsync(i => i.ParentId == currentId && i.Name == part); if (nextItem == null || !nextItem.IsReadableBy(user)) { return(NotFound( $"Path part \"{part}\" doesn't exist or you don't have permission to view it. " + "Logging in may help.")); } // Store the parent item so that when a file's path is parsed also the parent folder info can be found parentItem = currentItem; currentItem = nextItem; } return(new PathParseResult() { ParentFolder = parentItem?.GetDTO(), FinalItem = currentItem?.GetDTO() }); }