Browse Source

Code refactoring and asset protection issue.

pull/613/head
Sebastian 6 years ago
parent
commit
bb0c1cf60e
  1. 2
      backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs
  2. 8
      backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs
  3. 21
      backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
  4. 12
      backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs
  5. 4
      backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs
  6. 2
      backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleDto.cs
  7. 2
      backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs
  8. 10
      backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs
  9. 7
      backend/tools/TestSuite/TestSuite.Shared/Fixtures/AssetFixture.cs

2
backend/src/Squidex/Areas/Api/Controllers/Apps/Models/AppDto.cs

@ -143,7 +143,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
if (app.Image != null) if (app.Image != null)
{ {
AddGetLink("image", resources.Url<AppsController>(x => nameof(x.GetImage), new { app = app.Name })); AddGetLink("image", resources.Url<AppsController>(x => nameof(x.GetImage), values));
} }
if (isContributor) if (isContributor)

8
backend/src/Squidex/Areas/Api/Controllers/Apps/Models/ContributorDto.cs

@ -68,12 +68,16 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
if (resources.CanAssignContributor) if (resources.CanAssignContributor)
{ {
AddPostLink("update", resources.Url<AppContributorsController>(x => nameof(x.PostContributor), new { app })); var values = new { app };
AddPostLink("update", resources.Url<AppContributorsController>(x => nameof(x.PostContributor), values));
} }
if (resources.CanRevokeContributor) if (resources.CanRevokeContributor)
{ {
AddDeleteLink("delete", resources.Url<AppContributorsController>(x => nameof(x.DeleteContributor), new { app, id = ContributorId })); var values = new { app, id = ContributorId };
AddDeleteLink("delete", resources.Url<AppContributorsController>(x => nameof(x.DeleteContributor), values));
} }
} }

21
backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs

@ -80,12 +80,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
asset = await assetRepository.FindAssetBySlugAsync(AppId, idOrSlug); asset = await assetRepository.FindAssetBySlugAsync(AppId, idOrSlug);
} }
if (asset != null && queries.Version > EtagVersion.Any && asset.Version != queries.Version) return await DeliverAssetAsync(asset, queries);
{
asset = await assetLoader.GetAsync(App.Id, asset.Id, queries.Version);
}
return DeliverAsset(asset, queries);
} }
/// <summary> /// <summary>
@ -108,10 +103,10 @@ namespace Squidex.Areas.Api.Controllers.Assets
{ {
var asset = await assetRepository.FindAssetAsync(id); var asset = await assetRepository.FindAssetAsync(id);
return DeliverAsset(asset, queries); return await DeliverAssetAsync(asset, queries);
} }
private IActionResult DeliverAsset(IAssetEntity? asset, AssetContentQueryDto queries) private async Task<IActionResult> DeliverAssetAsync(IAssetEntity? asset, AssetContentQueryDto queries)
{ {
queries ??= new AssetContentQueryDto(); queries ??= new AssetContentQueryDto();
@ -127,6 +122,16 @@ namespace Squidex.Areas.Api.Controllers.Assets
return StatusCode(403); return StatusCode(403);
} }
if (asset != null && queries.Version > EtagVersion.Any && asset.Version != queries.Version)
{
asset = await assetLoader.GetAsync(App.Id, asset.Id, queries.Version);
}
if (asset == null)
{
return NotFound();
}
var resizeOptions = queries.ToResizeOptions(asset); var resizeOptions = queries.ToResizeOptions(asset);
FileCallback callback; FileCallback callback;

12
backend/src/Squidex/Areas/Api/Controllers/Assets/Models/AssetDto.cs

@ -203,13 +203,19 @@ namespace Squidex.Areas.Api.Controllers.Assets.Models
if (!string.IsNullOrWhiteSpace(response.Slug)) if (!string.IsNullOrWhiteSpace(response.Slug))
{ {
response.AddGetLink("content", resources.Url<AssetContentController>(x => nameof(x.GetAssetContentBySlug), new { app, idOrSlug = response.Id, more = response.Slug })); var idValues = new { app, idOrSlug = response.Id, more = response.Slug };
response.AddGetLink("content/slug", resources.Url<AssetContentController>(x => nameof(x.GetAssetContentBySlug), new { app, idOrSlug = response.Slug })); response.AddGetLink("content", resources.Url<AssetContentController>(x => nameof(x.GetAssetContentBySlug), idValues));
var slugValues = new { app, idOrSlug = response.Slug };
response.AddGetLink("content/slug", resources.Url<AssetContentController>(x => nameof(x.GetAssetContentBySlug), slugValues));
} }
else else
{ {
response.AddGetLink("content", resources.Url<AssetContentController>(x => nameof(x.GetAssetContentBySlug), new { app, idOrSlug = response.Id })); var idValues = new { app, idOrSlug = response.Id };
response.AddGetLink("content", resources.Url<AssetContentController>(x => nameof(x.GetAssetContentBySlug), idValues));
} }
return response; return response;

4
backend/src/Squidex/Areas/Api/Controllers/Contents/Models/ContentsDto.cs

@ -70,7 +70,9 @@ namespace Squidex.Areas.Api.Controllers.Contents.Models
{ {
AddPostLink("create", resources.Url<ContentsController>(x => nameof(x.PostContent), values)); AddPostLink("create", resources.Url<ContentsController>(x => nameof(x.PostContent), values));
AddPostLink("create/publish", resources.Url<ContentsController>(x => nameof(x.PostContent), values) + "?publish=true"); var publishValues = new { values.app, values.name, publish = true };
AddPostLink("create/publish", resources.Url<ContentsController>(x => nameof(x.PostContent), publishValues));
} }
} }
} }

2
backend/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleDto.cs

@ -137,7 +137,7 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models
if (canRun && ruleRunnerService.CanRunFromSnapshots(rule)) if (canRun && ruleRunnerService.CanRunFromSnapshots(rule))
{ {
var snaphshotValues = new { app = resources.App, id = Id, fromSnapshots = true }; var snaphshotValues = new { values.app, values.id, fromSnapshots = true };
AddPutLink("run/snapshots", resources.Url<RulesController>(x => nameof(x.PutRuleRun), snaphshotValues)); AddPutLink("run/snapshots", resources.Url<RulesController>(x => nameof(x.PutRuleRun), snaphshotValues));
} }

2
backend/src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldDto.cs

@ -132,7 +132,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas.Models
if (Properties is ArrayFieldPropertiesDto) if (Properties is ArrayFieldPropertiesDto)
{ {
var parentValues = new { app = resources.App, name = schema, parentId = FieldId }; var parentValues = new { values.app, values.name, parentId = FieldId };
AddPostLink("fields/add", resources.Url<SchemaFieldsController>(x => nameof(x.PostNestedField), parentValues)); AddPostLink("fields/add", resources.Url<SchemaFieldsController>(x => nameof(x.PostNestedField), parentValues));

10
backend/tools/TestSuite/TestSuite.ApiTests/AssetTests.cs

@ -178,6 +178,16 @@ namespace TestSuite.ApiTests
// Should return 403 when not authenticated. // Should return 403 when not authenticated.
Assert.Contains("403", ex.Message); Assert.Contains("403", ex.Message);
} }
// STEP 6: Download asset without key and version.
using (var stream = new FileStream("Assets/logo-squared.png", FileMode.Open))
{
var ex = await Assert.ThrowsAsync<HttpRequestException>(() => _.DownloadAsync(asset_1, 0));
// Should return 403 when not authenticated.
Assert.Contains("403", ex.Message);
}
} }
[Fact] [Fact]

7
backend/tools/TestSuite/TestSuite.Shared/Fixtures/AssetFixture.cs

@ -17,7 +17,7 @@ namespace TestSuite.Fixtures
{ {
public IAssetsClient Assets => Squidex.Assets; public IAssetsClient Assets => Squidex.Assets;
public async Task<MemoryStream> DownloadAsync(AssetDto asset) public async Task<MemoryStream> DownloadAsync(AssetDto asset, int? version = null)
{ {
var temp = new MemoryStream(); var temp = new MemoryStream();
@ -25,6 +25,11 @@ namespace TestSuite.Fixtures
{ {
var url = $"{ServerUrl}{asset._links["content"].Href}"; var url = $"{ServerUrl}{asset._links["content"].Href}";
if (version > 0)
{
url += $"?version={version}";
}
var response = await client.GetAsync(url); var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();

Loading…
Cancel
Save