mirror of https://github.com/Squidex/squidex.git
Browse Source
* More tests and a fix to etag handling. * Fix content form. * Tests improved. * Make username and password optional. * Simplified tests again. * Fix API testspull/1052/head
committed by
GitHub
127 changed files with 1855 additions and 667 deletions
@ -0,0 +1,18 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
|
||||
|
namespace Squidex.Web; |
||||
|
|
||||
|
public static class BuilderExtensions |
||||
|
{ |
||||
|
public static void UseWhenPath(this IApplicationBuilder builder, string path, Action<IApplicationBuilder> configurator) |
||||
|
{ |
||||
|
builder.UseWhen(c => c.Request.Path.StartsWithSegments(path, StringComparison.OrdinalIgnoreCase), configurator); |
||||
|
} |
||||
|
} |
||||
@ -1,58 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
namespace Squidex.Web; |
|
||||
|
|
||||
public static class ETagUtils |
|
||||
{ |
|
||||
public static string ToWeakEtag(string? etag) |
|
||||
{ |
|
||||
return $"W/{etag}"; |
|
||||
} |
|
||||
|
|
||||
public static bool IsStrongEtag(string etag) |
|
||||
{ |
|
||||
return !IsWeakEtag(etag.AsSpan()); |
|
||||
} |
|
||||
|
|
||||
public static bool IsWeakEtag(string etag) |
|
||||
{ |
|
||||
return IsWeakEtag(etag.AsSpan()); |
|
||||
} |
|
||||
|
|
||||
public static bool IsWeakEtag(ReadOnlySpan<char> etag) |
|
||||
{ |
|
||||
return etag.StartsWith("W/", StringComparison.OrdinalIgnoreCase); |
|
||||
} |
|
||||
|
|
||||
public static bool IsSameEtag(string lhs, string rhs) |
|
||||
{ |
|
||||
return IsSameEtag(lhs.AsSpan(), rhs.AsSpan()); |
|
||||
} |
|
||||
|
|
||||
public static bool IsSameEtag(ReadOnlySpan<char> lhs, ReadOnlySpan<char> rhs) |
|
||||
{ |
|
||||
var isMatch = lhs.Equals(rhs, StringComparison.Ordinal); |
|
||||
|
|
||||
if (isMatch) |
|
||||
{ |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
if (lhs.StartsWith("W/", StringComparison.OrdinalIgnoreCase)) |
|
||||
{ |
|
||||
lhs = lhs[2..]; |
|
||||
} |
|
||||
|
|
||||
if (rhs.StartsWith("W/", StringComparison.OrdinalIgnoreCase)) |
|
||||
{ |
|
||||
rhs = rhs[2..]; |
|
||||
} |
|
||||
|
|
||||
return lhs.Equals(rhs, StringComparison.Ordinal); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,151 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.ClientLibrary; |
||||
|
using TestSuite.Fixtures; |
||||
|
|
||||
|
#pragma warning disable SA1300 // Element should begin with upper-case letter
|
||||
|
#pragma warning disable SA1507 // Code should not contain multiple blank lines in a row
|
||||
|
|
||||
|
namespace TestSuite.ApiTests; |
||||
|
|
||||
|
public class AssetScriptingTests : IClassFixture<ClientFixture> |
||||
|
{ |
||||
|
public ClientFixture _ { get; } |
||||
|
|
||||
|
public AssetScriptingTests(ClientFixture fixture) |
||||
|
{ |
||||
|
_ = fixture; |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_disallow_jpeg_file_on_create() |
||||
|
{ |
||||
|
var (client, _) = await _.PostAppAsync(); |
||||
|
|
||||
|
// STEP 0: Configure script.
|
||||
|
var scriptRequest = new UpdateAssetScriptsDto |
||||
|
{ |
||||
|
Create = @"
|
||||
|
if (ctx.command.mimeType == 'image/jpg') { |
||||
|
disallow('We do not use jpeg anymore.'); |
||||
|
}"
|
||||
|
}; |
||||
|
|
||||
|
await client.Apps.PutAssetScriptsAsync(scriptRequest); |
||||
|
|
||||
|
|
||||
|
// STEP 1: Upload jpeg.
|
||||
|
var ex = await Assert.ThrowsAnyAsync<SquidexException>(() => client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpg")); |
||||
|
|
||||
|
Assert.Contains("We do not use jpeg anymore.", ex.ToString(), StringComparison.Ordinal); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_update_metadata_and_tags_on_create() |
||||
|
{ |
||||
|
var (client, _) = await _.PostAppAsync(); |
||||
|
|
||||
|
// STEP 0: Configure script.
|
||||
|
var scriptRequest = new UpdateAssetScriptsDto |
||||
|
{ |
||||
|
Create = @"
|
||||
|
ctx.command.metadata['key1'] = 'value1'; |
||||
|
ctx.command.metadata['key2'] = 'value2'; |
||||
|
ctx.command.tags.add('tag1'); |
||||
|
ctx.command.tags.add('tag2');"
|
||||
|
}; |
||||
|
|
||||
|
await client.Apps.PutAssetScriptsAsync(scriptRequest); |
||||
|
|
||||
|
|
||||
|
// STEP 1: Upload jpeg.
|
||||
|
var asset = await client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpg"); |
||||
|
|
||||
|
Assert.Equal("value1", asset.Metadata["key1"]); |
||||
|
Assert.Equal("value2", asset.Metadata["key2"]); |
||||
|
Assert.Contains("tag1", asset.Tags); |
||||
|
Assert.Contains("tag2", asset.Tags); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_disallow_jpeg_file_on_update() |
||||
|
{ |
||||
|
var (client, _) = await _.PostAppAsync(); |
||||
|
|
||||
|
// STEP 0: Configure script.
|
||||
|
var scriptRequest = new UpdateAssetScriptsDto |
||||
|
{ |
||||
|
Update = @"
|
||||
|
if (ctx.command.mimeType == 'image/jpg') { |
||||
|
disallow('We do not use jpeg anymore.'); |
||||
|
}"
|
||||
|
}; |
||||
|
|
||||
|
await client.Apps.PutAssetScriptsAsync(scriptRequest); |
||||
|
|
||||
|
|
||||
|
// STEP 1. Upload initial png.
|
||||
|
var asset_0 = await client.Assets.UploadFileAsync("Assets/logo-wide.png", "image/png"); |
||||
|
|
||||
|
|
||||
|
// STEP 2: Upload jpeg.
|
||||
|
var ex = await Assert.ThrowsAnyAsync<SquidexException>(() => client.Assets.ReplaceFileAsync(asset_0.Id, "Assets/logo-wide-rotated.jpg", "image/jpg")); |
||||
|
|
||||
|
Assert.Contains("We do not use jpeg anymore.", ex.ToString(), StringComparison.Ordinal); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_update_metadata_on_update() |
||||
|
{ |
||||
|
var (client, _) = await _.PostAppAsync(); |
||||
|
|
||||
|
// STEP 0: Configure script.
|
||||
|
var scriptRequest = new UpdateAssetScriptsDto |
||||
|
{ |
||||
|
Update = @"
|
||||
|
ctx.command.metadata['key1'] = 'value1'; |
||||
|
ctx.command.metadata['key2'] = 'value2';"
|
||||
|
}; |
||||
|
|
||||
|
await client.Apps.PutAssetScriptsAsync(scriptRequest); |
||||
|
|
||||
|
|
||||
|
// STEP 1. Upload initial png.
|
||||
|
var asset_0 = await client.Assets.UploadFileAsync("Assets/logo-wide.png", "image/png"); |
||||
|
|
||||
|
|
||||
|
// STEP 2: Upload jpeg.
|
||||
|
var asset = await client.Assets.ReplaceFileAsync(asset_0.Id, "Assets/logo-wide-rotated.jpg", "image/jpg"); |
||||
|
|
||||
|
Assert.Equal("value1", asset.Metadata["key1"]); |
||||
|
Assert.Equal("value2", asset.Metadata["key2"]); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_query_asset_with_scripting() |
||||
|
{ |
||||
|
var (client, _) = await _.PostAppAsync(); |
||||
|
|
||||
|
// STEP 0: Configure script.
|
||||
|
var scriptRequest = new UpdateAssetScriptsDto |
||||
|
{ |
||||
|
Query = @"
|
||||
|
if (ctx.asset.mimeType == 'image/jpg') { |
||||
|
disallow('We do not use jpeg anymore.'); |
||||
|
}"
|
||||
|
}; |
||||
|
|
||||
|
await client.Apps.PutAssetScriptsAsync(scriptRequest); |
||||
|
|
||||
|
|
||||
|
// STEP 1. Upload initial jpg.
|
||||
|
var ex = await Assert.ThrowsAnyAsync<SquidexException>(() => client.Assets.UploadFileAsync("Assets/logo-wide-rotated.jpg", "image/jpg")); |
||||
|
|
||||
|
Assert.Contains("We do not use jpeg anymore.", ex.ToString(), StringComparison.Ordinal); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,128 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.ClientLibrary; |
||||
|
using TestSuite.Fixtures; |
||||
|
|
||||
|
#pragma warning disable SA1300 // Element should begin with upper-case letter
|
||||
|
#pragma warning disable SA1507 // Code should not contain multiple blank lines in a row
|
||||
|
|
||||
|
namespace TestSuite.ApiTests; |
||||
|
|
||||
|
[UsesVerify] |
||||
|
public class TeamContributorTests : IClassFixture<ClientFixture> |
||||
|
{ |
||||
|
public ClientFixture _ { get; } |
||||
|
|
||||
|
public TeamContributorTests(ClientFixture fixture) |
||||
|
{ |
||||
|
_ = fixture; |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_not_invite_contributor_if_flag_is_false() |
||||
|
{ |
||||
|
// STEP 0: Create team.
|
||||
|
var team = await _.PostTeamAsync(); |
||||
|
|
||||
|
|
||||
|
// STEP 1: Do not invite contributors when flag is false.
|
||||
|
var createRequest = new AssignContributorDto |
||||
|
{ |
||||
|
ContributorId = "test@squidex.io" |
||||
|
}; |
||||
|
|
||||
|
var ex = await Assert.ThrowsAnyAsync<SquidexException>(() => |
||||
|
{ |
||||
|
return _.Client.Teams.PostContributorAsync(team.Id, createRequest); |
||||
|
}); |
||||
|
|
||||
|
Assert.Equal(404, ex.StatusCode); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_invite_contributor() |
||||
|
{ |
||||
|
// STEP 0: Create team.
|
||||
|
var team = await _.PostTeamAsync(); |
||||
|
|
||||
|
|
||||
|
// STEP 0: Create app.
|
||||
|
var (app, _) = await _.PostAppAsync(); |
||||
|
|
||||
|
|
||||
|
// STEP 1: Assign contributor.
|
||||
|
ContributorDto contributor_1 = await InviteAsync(team.Id); |
||||
|
|
||||
|
Assert.Equal("Owner", contributor_1?.Role); |
||||
|
|
||||
|
await Verify(contributor_1) |
||||
|
.IgnoreMember<ContributorDto>(x => x.ContributorId) |
||||
|
.IgnoreMember<ContributorDto>(x => x.ContributorEmail) |
||||
|
.IgnoreMember<ContributorDto>(x => x.ContributorName); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_remove_contributor() |
||||
|
{ |
||||
|
// STEP 0: Create team.
|
||||
|
var team = await _.PostTeamAsync(); |
||||
|
|
||||
|
|
||||
|
// STEP 1: Assign first contributor.
|
||||
|
await InviteAsync(team.Id); |
||||
|
|
||||
|
|
||||
|
// STEP 2: Assign other contributor.
|
||||
|
var contributor2 = await InviteAsync(team.Id); |
||||
|
|
||||
|
|
||||
|
// STEP 2: Remove contributor.
|
||||
|
var contributors_2 = await _.Client.Teams.DeleteContributorAsync(team.Id, contributor2.ContributorId); |
||||
|
|
||||
|
Assert.DoesNotContain(contributors_2.Items, x => x.ContributorId == contributor2.ContributorId); |
||||
|
|
||||
|
await Verify(contributors_2) |
||||
|
.IgnoreMember<ContributorDto>(x => x.ContributorId) |
||||
|
.IgnoreMember<ContributorDto>(x => x.ContributorEmail) |
||||
|
.IgnoreMember<ContributorDto>(x => x.ContributorName); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_not_remove_single_owner() |
||||
|
{ |
||||
|
// STEP 0: Create team.
|
||||
|
var team = await _.PostTeamAsync(); |
||||
|
|
||||
|
|
||||
|
// STEP 1: Get contributors
|
||||
|
var contributor = await InviteAsync(team.Id); |
||||
|
|
||||
|
|
||||
|
// STEP 2: Remove contributor.
|
||||
|
await Assert.ThrowsAnyAsync<SquidexException>(() => _.Client.Teams.DeleteContributorAsync(team.Id, contributor.ContributorId)); |
||||
|
} |
||||
|
|
||||
|
private async Task<ContributorDto> InviteAsync(string teamId) |
||||
|
{ |
||||
|
var email = $"{Guid.NewGuid()}@squidex.io"; |
||||
|
|
||||
|
var createInviteRequest = new AssignContributorDto |
||||
|
{ |
||||
|
ContributorId = email, |
||||
|
// Invite must be true, otherwise new users are not created.
|
||||
|
Invite = true, |
||||
|
// This is the only allowed role for teams.
|
||||
|
Role = "Owner" |
||||
|
}; |
||||
|
|
||||
|
var contributors = await _.Client.Teams.PostContributorAsync(teamId, createInviteRequest); |
||||
|
var contributor = contributors.Items.Find(x => x.ContributorName == email); |
||||
|
|
||||
|
return contributor!; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.ClientLibrary; |
||||
|
using TestSuite.Fixtures; |
||||
|
|
||||
|
#pragma warning disable SA1300 // Element should begin with upper-case letter
|
||||
|
#pragma warning disable SA1507 // Code should not contain multiple blank lines in a row
|
||||
|
|
||||
|
namespace TestSuite.ApiTests; |
||||
|
|
||||
|
[UsesVerify] |
||||
|
public class TeamTests : IClassFixture<CreatedTeamFixture> |
||||
|
{ |
||||
|
public CreatedTeamFixture _ { get; } |
||||
|
|
||||
|
public TeamTests(CreatedTeamFixture fixture) |
||||
|
{ |
||||
|
_ = fixture; |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_set_name() |
||||
|
{ |
||||
|
// STEP 1: Update app.
|
||||
|
var updateRequest = new UpdateTeamDto |
||||
|
{ |
||||
|
Name = Guid.NewGuid().ToString() |
||||
|
}; |
||||
|
|
||||
|
var app_1 = await _.Client.Teams.PutTeamAsync(_.TeamId, updateRequest); |
||||
|
|
||||
|
Assert.Equal(updateRequest.Name, app_1.Name); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_transfer_app_to_team() |
||||
|
{ |
||||
|
// STEP 0: Create app.
|
||||
|
var (client, _) = await _.PostAppAsync(); |
||||
|
|
||||
|
|
||||
|
// STEP 1: Assign app to team.
|
||||
|
var transferRequest = new TransferToTeamDto |
||||
|
{ |
||||
|
TeamId = _.TeamId |
||||
|
}; |
||||
|
|
||||
|
var app_1 = await client.Apps.PutAppTeamAsync(transferRequest); |
||||
|
|
||||
|
Assert.Equal(_.TeamId, app_1.TeamId); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_remove_app_from_team() |
||||
|
{ |
||||
|
// STEP 0: Create app.
|
||||
|
var (client, _) = await _.PostAppAsync(); |
||||
|
|
||||
|
|
||||
|
// STEP 1: Assign app to team.
|
||||
|
var transferRequest = new TransferToTeamDto |
||||
|
{ |
||||
|
TeamId = _.TeamId |
||||
|
}; |
||||
|
|
||||
|
var app_1 = await client.Apps.PutAppTeamAsync(transferRequest); |
||||
|
|
||||
|
Assert.Equal(_.TeamId, app_1.TeamId); |
||||
|
|
||||
|
|
||||
|
// STEP 2: Remove app from team.
|
||||
|
var untransferRequest = new TransferToTeamDto |
||||
|
{ |
||||
|
TeamId = null |
||||
|
}; |
||||
|
|
||||
|
var app_2 = await client.Apps.PutAppTeamAsync(untransferRequest); |
||||
|
|
||||
|
Assert.Null(app_2.TeamId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
{ |
||||
|
Id: Guid_1, |
||||
|
ParentId: Guid_Empty, |
||||
|
FileName: My Image, |
||||
|
FileHash: pAp0RDvipkoNCCTgey1HTJekRKKEWT6Ft5JdRLuAfAc=, |
||||
|
IsProtected: false, |
||||
|
Slug: logo-squared.png, |
||||
|
MimeType: image/png, |
||||
|
FileType: blob, |
||||
|
MetadataText: 600x600px, 19 kB, |
||||
|
Metadata: { |
||||
|
description: PNG File, |
||||
|
pixelHeight: 600, |
||||
|
pixelWidth: 600 |
||||
|
}, |
||||
|
Tags: [ |
||||
|
type/png, |
||||
|
image, |
||||
|
image/medium |
||||
|
], |
||||
|
FileSize: 19430, |
||||
|
Type: Image, |
||||
|
Version: 1, |
||||
|
Links: { |
||||
|
content: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
content/slug: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
delete: { |
||||
|
Method: DELETE |
||||
|
}, |
||||
|
move: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
self: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
update: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
upload: { |
||||
|
Method: PUT |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
{ |
||||
|
Id: Guid_1, |
||||
|
ParentId: Guid_Empty, |
||||
|
FileName: logo-squared.png, |
||||
|
FileHash: pAp0RDvipkoNCCTgey1HTJekRKKEWT6Ft5JdRLuAfAc=, |
||||
|
IsProtected: false, |
||||
|
Slug: logo-squared.png, |
||||
|
MimeType: image/png, |
||||
|
FileType: png, |
||||
|
MetadataText: 19 kB, |
||||
|
Metadata: { |
||||
|
ph: 20, |
||||
|
pw: 100 |
||||
|
}, |
||||
|
Tags: [ |
||||
|
type/png, |
||||
|
image, |
||||
|
image/medium |
||||
|
], |
||||
|
FileSize: 19430, |
||||
|
Type: Image, |
||||
|
Version: 1, |
||||
|
Links: { |
||||
|
content: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
content/slug: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
delete: { |
||||
|
Method: DELETE |
||||
|
}, |
||||
|
move: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
self: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
update: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
upload: { |
||||
|
Method: PUT |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
{ |
||||
|
Id: Guid_1, |
||||
|
ParentId: Guid_Empty, |
||||
|
FileName: logo-squared.png, |
||||
|
FileHash: pAp0RDvipkoNCCTgey1HTJekRKKEWT6Ft5JdRLuAfAc=, |
||||
|
IsProtected: false, |
||||
|
Slug: my-image, |
||||
|
MimeType: image/png, |
||||
|
FileType: png, |
||||
|
MetadataText: 600x600px, 19 kB, |
||||
|
Metadata: { |
||||
|
description: PNG File, |
||||
|
pixelHeight: 600, |
||||
|
pixelWidth: 600 |
||||
|
}, |
||||
|
Tags: [ |
||||
|
type/png, |
||||
|
image, |
||||
|
image/medium |
||||
|
], |
||||
|
FileSize: 19430, |
||||
|
Type: Image, |
||||
|
Version: 1, |
||||
|
Links: { |
||||
|
content: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
content/slug: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
delete: { |
||||
|
Method: DELETE |
||||
|
}, |
||||
|
move: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
self: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
update: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
upload: { |
||||
|
Method: PUT |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
{ |
||||
|
Id: Guid_1, |
||||
|
ParentId: Guid_Empty, |
||||
|
FileName: logo-squared.png, |
||||
|
FileHash: pAp0RDvipkoNCCTgey1HTJekRKKEWT6Ft5JdRLuAfAc=, |
||||
|
IsProtected: false, |
||||
|
Slug: logo-squared.png, |
||||
|
MimeType: image/png, |
||||
|
FileType: png, |
||||
|
MetadataText: 600x600px, 19 kB, |
||||
|
Metadata: { |
||||
|
description: PNG File, |
||||
|
pixelHeight: 600, |
||||
|
pixelWidth: 600 |
||||
|
}, |
||||
|
Tags: [ |
||||
|
tag1, |
||||
|
tag2 |
||||
|
], |
||||
|
FileSize: 19430, |
||||
|
Type: Image, |
||||
|
Version: 1, |
||||
|
Links: { |
||||
|
content: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
content/slug: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
delete: { |
||||
|
Method: DELETE |
||||
|
}, |
||||
|
move: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
self: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
update: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
upload: { |
||||
|
Method: PUT |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
{ |
||||
|
Id: Guid_1, |
||||
|
ParentId: Guid_Empty, |
||||
|
FileName: logo-squared.png, |
||||
|
FileHash: pAp0RDvipkoNCCTgey1HTJekRKKEWT6Ft5JdRLuAfAc=, |
||||
|
IsProtected: true, |
||||
|
Slug: logo-squared.png, |
||||
|
MimeType: image/png, |
||||
|
FileType: png, |
||||
|
MetadataText: 600x600px, 19 kB, |
||||
|
Metadata: { |
||||
|
description: PNG File, |
||||
|
pixelHeight: 600, |
||||
|
pixelWidth: 600 |
||||
|
}, |
||||
|
Tags: [ |
||||
|
type/png, |
||||
|
image, |
||||
|
image/medium |
||||
|
], |
||||
|
FileSize: 19430, |
||||
|
Type: Image, |
||||
|
Version: 1, |
||||
|
Links: { |
||||
|
content: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
content/slug: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
delete: { |
||||
|
Method: DELETE |
||||
|
}, |
||||
|
move: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
self: { |
||||
|
Method: GET |
||||
|
}, |
||||
|
update: { |
||||
|
Method: PUT |
||||
|
}, |
||||
|
upload: { |
||||
|
Method: PUT |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
{ |
||||
|
Role: Owner, |
||||
|
Links: { |
||||
|
delete: { |
||||
|
Method: DELETE |
||||
|
}, |
||||
|
update: { |
||||
|
Method: POST |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
{ |
||||
|
Items: [ |
||||
|
{ |
||||
|
Role: Owner, |
||||
|
Links: { |
||||
|
delete: { |
||||
|
Method: DELETE |
||||
|
}, |
||||
|
update: { |
||||
|
Method: POST |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
Links: { |
||||
|
create: { |
||||
|
Method: POST |
||||
|
}, |
||||
|
self: { |
||||
|
Method: GET |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue