Browse Source

Feature/status (#663)

Bulk endpoint improvements.
pull/664/head
Sebastian Stehle 5 years ago
committed by GitHub
parent
commit
58362be283
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      backend/extensions/Squidex.Extensions/Actions/CreateContent/CreateContentActionHandler.cs
  2. 6
      backend/extensions/Squidex.Extensions/Actions/Discourse/DiscourseActionHandler.cs
  3. 4
      backend/i18n/source/backend_en.json
  4. 2
      backend/i18n/source/backend_it.json
  5. 2
      backend/i18n/source/backend_nl.json
  6. 2
      backend/src/Migrations/OldEvents/AssetCreated.cs
  7. 2
      backend/src/Migrations/OldEvents/AssetUpdated.cs
  8. 17
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppPlan.cs
  9. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs
  10. 6
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs
  11. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/Role.cs
  12. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs
  13. 26
      backend/src/Squidex.Domain.Apps.Core.Model/Comments/Comment.cs
  14. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs
  15. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Contents/Status.cs
  16. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Freezable.cs
  17. 2
      backend/src/Squidex.Domain.Apps.Core.Model/InvariantPartitioning.cs
  18. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedAssetEvent.cs
  19. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedCommentEvent.cs
  20. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedContentEvent.cs
  21. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedManualEvent.cs
  22. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedSchemaEvent.cs
  23. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedUsageExceededEvent.cs
  24. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Rules/Rule.cs
  25. 8
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayField.cs
  26. 2
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldCollection.cs
  27. 10
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField.cs
  28. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField{T}.cs
  29. 12
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField.cs
  30. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField{T}.cs
  31. 28
      backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs
  32. 4
      backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs
  33. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EventJsonSchemaGenerator.cs
  34. 4
      backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs
  35. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleRegistry.cs
  36. 4
      backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleTriggerHandler.cs
  37. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentDataProperty.cs
  38. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldObject.cs
  39. 4
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldProperty.cs
  40. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ContentValidator.cs
  41. 18
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultFieldValueValidatorsFactory.cs
  42. 1
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidationContext.cs
  43. 18
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AssetsValidator.cs
  44. 8
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/CollectionValidator.cs
  45. 8
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/RangeValidator.cs
  46. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ReferencesValidator.cs
  47. 6
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/StringLengthValidator.cs
  48. 8
      backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/StringTextValidator.cs
  49. 4
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetEntity.cs
  50. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderEntity.cs
  51. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository.cs
  52. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository_SnapshotStore.cs
  53. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs
  54. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/Visitors/FindExtensions.cs
  55. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs
  56. 20
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs
  57. 7
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/FullText/MongoTextIndex.cs
  58. 4
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleEventEntity.cs
  59. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleEventRepository.cs
  60. 8
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemasHash.cs
  61. 2
      backend/src/Squidex.Domain.Apps.Entities/Apps/Commands/AppUpdateCommand.cs
  62. 2
      backend/src/Squidex.Domain.Apps.Entities/Apps/Commands/CreateApp.cs
  63. 9
      backend/src/Squidex.Domain.Apps.Entities/Apps/DomainObject/AppCommandMiddleware.cs
  64. 2
      backend/src/Squidex.Domain.Apps.Entities/Apps/DomainObject/AppDomainObject.State.cs
  65. 60
      backend/src/Squidex.Domain.Apps.Entities/Apps/DomainObject/AppDomainObject.cs
  66. 2
      backend/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEventConsumer.cs
  67. 2
      backend/src/Squidex.Domain.Apps.Entities/Apps/Plans/NoopAppPlanBillingManager.cs
  68. 4
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateBlogCommandMiddleware.cs
  69. 10
      backend/src/Squidex.Domain.Apps.Entities/Assets/AssetChangedTriggerHandler.cs
  70. 14
      backend/src/Squidex.Domain.Apps.Entities/Assets/AssetDuplicate.cs
  71. 4
      backend/src/Squidex.Domain.Apps.Entities/Assets/AssetEntity.cs
  72. 8
      backend/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker_EventHandling.cs
  73. 2
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/AssetCommand.cs
  74. 2
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/AssetFolderCommand.cs
  75. 8
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/BulkUpdateAssetType.cs
  76. 13
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/BulkUpdateAssets.cs
  77. 38
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/BulkUpdateJob.cs
  78. 9
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs
  79. 2
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/DeleteAsset.cs
  80. 2
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/MoveAsset.cs
  81. 3
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/UploadAssetCommand.cs
  82. 39
      backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpsertAsset.cs
  83. 127
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetCommandMiddleware.cs
  84. 20
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetDomainObject.State.cs
  85. 128
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetDomainObject.cs
  86. 2
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetDomainObjectGrain.cs
  87. 2
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetFolderDomainObject.State.cs
  88. 36
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetFolderDomainObject.cs
  89. 117
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetFolderResolver.cs
  90. 210
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetsBulkUpdateCommandMiddleware.cs
  91. 7
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/Guards/GuardAsset.cs
  92. 18
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/IAssetFolderResolver.cs
  93. 19
      backend/src/Squidex.Domain.Apps.Entities/Assets/FileTagAssetMetadataSource.cs
  94. 6
      backend/src/Squidex.Domain.Apps.Entities/Assets/FileTypeAssetMetadataSource.cs
  95. 2
      backend/src/Squidex.Domain.Apps.Entities/Assets/IAssetMetadataSource.cs
  96. 12
      backend/src/Squidex.Domain.Apps.Entities/Assets/ImageAssetMetadataSource.cs
  97. 4
      backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs
  98. 2
      backend/src/Squidex.Domain.Apps.Entities/Backup/BackupContextBase.cs
  99. 2
      backend/src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs
  100. 4
      backend/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs

5
backend/extensions/Squidex.Extensions/Actions/CreateContent/CreateContentActionHandler.cs

@ -68,7 +68,10 @@ namespace Squidex.Extensions.Actions.CreateContent
ruleJob.Actor = userEvent.Actor;
}
ruleJob.Publish = action.Publish;
if (action.Publish)
{
ruleJob.Status = Status.Published;
}
return (Description, ruleJob);
}

6
backend/extensions/Squidex.Extensions/Actions/Discourse/DiscourseActionHandler.cs

@ -37,12 +37,12 @@ namespace Squidex.Extensions.Actions.Discourse
["title"] = await FormatAsync(action.Title, @event)
};
if (action.Topic.HasValue)
if (action.Topic != null)
{
json.Add("topic_id", action.Topic.Value);
}
if (action.Category.HasValue)
if (action.Category != null)
{
json.Add("category", action.Category.Value);
}
@ -58,7 +58,7 @@ namespace Squidex.Extensions.Actions.Discourse
};
var description =
action.Topic.HasValue ?
action.Topic != null ?
DescriptionCreateTopic :
DescriptionCreatePost;

4
backend/i18n/source/backend_en.json

@ -137,7 +137,7 @@
"contents.singletonNotChangeable": "Singleton content cannot be updated.",
"contents.singletonNotCreatable": "Singleton content cannot be created.",
"contents.singletonNotDeletable": "Singleton content cannot be deleted.",
"contents.statusSchedulingNotInFuture": "Due time must be in the future.",
"contents.statusNotValid": "Status is not defined in the workflow.",
"contents.statusTransitionNotAllowed": "Cannot change status from {oldStatus} to {newStatus}.",
"contents.validation.aspectRatio": "Must have aspect ratio {width}:{height}.",
"contents.validation.assetNotFound": "Id {id} not found.",
@ -173,7 +173,6 @@
"contents.validation.normalCharactersBetween": "Must have between {min} and {max} text character(s).",
"contents.validation.notAllowed": "Not an allowed value.",
"contents.validation.pattern": "Must follow the pattern.",
"contents.validation.reference": "Geolocation can only have latitude and longitude property.",
"contents.validation.referenceNotFound": "Reference '{id}' not found.",
"contents.validation.referenceToInvalidSchema": "Reference '{id}' has invalid schema.",
"contents.validation.regexTooSlow": "Regex is too slow.",
@ -182,7 +181,6 @@
"contents.validation.unknownField": "Not a known {fieldType}.",
"contents.validation.wordCount": "Must have exactly {count} word(s).",
"contents.validation.wordsBetween": "Must have between {min} and {max} word(s).",
"contents.workflowErorPublishing": "Content workflow prevents publishing.",
"contents.workflowErrorUpdate": "The workflow does not allow updates at status {status}",
"dotnet_identity_DefaultEror": "An unknown failure has occurred.",
"dotnet_identity_DuplicateEmail": "Email is already taken.",

2
backend/i18n/source/backend_it.json

@ -137,7 +137,6 @@
"contents.singletonNotChangeable": "Il contenuto singleton non può essere aggiornato",
"contents.singletonNotCreatable": "Il contenuto singleton non può essere creato.",
"contents.singletonNotDeletable": "Il contenuto singleton non può essere eliminato.",
"contents.statusSchedulingNotInFuture": "L'ora deve essere futura.",
"contents.statusTransitionNotAllowed": "Non è possibile cambiare stato da {oldStatus} a {newStatus}.",
"contents.validation.aspectRatio": "Deve essere le proporzioni {width}:{height}.",
"contents.validation.assetNotFound": "Id {id} non trovato.",
@ -182,7 +181,6 @@
"contents.validation.unknownField": "Non è noto {fieldType}.",
"contents.validation.wordCount": "Deve avere esattamente {count} parola(e).",
"contents.validation.wordsBetween": "Deve essere tra {min} e {max} parola(e).",
"contents.workflowErorPublishing": "Il workflow del contenuto impedisce la pubblicazione.",
"contents.workflowErrorUpdate": "Il workflow non consente le modifiche per lo stato {status}",
"dotnet_identity_DefaultEror": "Si è verificato un errore sconosciuto.",
"dotnet_identity_DuplicateEmail": "Email già in uso.",

2
backend/i18n/source/backend_nl.json

@ -133,7 +133,6 @@
"contents.singletonNotChangeable": "Singleton-inhoud kan niet worden bijgewerkt.",
"contents.singletonNotCreatable": "Singleton-inhoud kan niet worden gemaakt.",
"contents.singletonNotDeletable": "Singleton-inhoud kan niet worden verwijderd.",
"contents.statusSchedulingNotInFuture": "De tijd moet in de toekomst liggen.",
"contents.statusTransitionNotAllowed": "Kan status niet wijzigen van {oldStatus} in {newStatus}.",
"contents.validation.aspectRatio": "Moet aspectverhouding {breedte}: {hoogte} hebben.",
"contents.validation.assetNotFound": "Id {id} niet gevonden.",
@ -177,7 +176,6 @@
"contents.validation.unknownField": "Onbekend {fieldType}.",
"contents.validation.wordCount": "Moet exact {count} woord (en) bevatten.",
"contents.validation.wordsBetween": "Moet tussen {min} en {max} woord (en) bevatten.",
"contents.workflowErorPublishing": "Contentworkflow verhindert publiceren.",
"contents.workflowErrorUpdate": "De werkstroom staat geen updates toe met status {status}",
"dotnet_identity_DefaultEror": "Er is een onbekende fout opgetreden.",
"dotnet_identity_DuplicateEmail": "E-mail is al in gebruik.",

2
backend/src/Migrations/OldEvents/AssetCreated.cs

@ -48,7 +48,7 @@ namespace Migrations.OldEvents
result.Metadata = new AssetMetadata();
if (IsImage && PixelWidth.HasValue && PixelHeight.HasValue)
if (IsImage && PixelWidth != null && PixelHeight != null)
{
result.Type = AssetType.Image;

2
backend/src/Migrations/OldEvents/AssetUpdated.cs

@ -37,7 +37,7 @@ namespace Migrations.OldEvents
result.Metadata = new AssetMetadata();
if (IsImage && PixelWidth.HasValue && PixelHeight.HasValue)
if (IsImage && PixelWidth != null && PixelHeight != null)
{
result.Type = AssetType.Image;

17
backend/src/Squidex.Domain.Apps.Core.Model/Apps/AppPlan.cs

@ -7,22 +7,11 @@
using Squidex.Infrastructure;
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
namespace Squidex.Domain.Apps.Core.Apps
{
public sealed record AppPlan
public sealed record AppPlan(RefToken Owner, string PlanId)
{
public RefToken Owner { get; }
public string PlanId { get; }
public AppPlan(RefToken owner, string planId)
{
Guard.NotNull(owner, nameof(owner));
Guard.NotNullOrEmpty(planId, nameof(planId));
Owner = owner;
PlanId = planId;
}
}
}

2
backend/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs

@ -23,7 +23,7 @@ namespace Squidex.Domain.Apps.Core.Apps
public IEnumerable<Language> Fallbacks
{
get { return fallbacks; }
get => fallbacks;
}
public LanguageConfig(bool isOptional = false, params Language[]? fallbacks)

6
backend/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs

@ -26,17 +26,17 @@ namespace Squidex.Domain.Apps.Core.Apps
public string Master
{
get { return master; }
get => master;
}
public IEnumerable<string> AllKeys
{
get { return languages.Keys; }
get => languages.Keys;
}
public IReadOnlyDictionary<string, LanguageConfig> Languages
{
get { return languages; }
get => languages;
}
public LanguagesConfig(Dictionary<string, LanguageConfig> languages, string master)

2
backend/src/Squidex.Domain.Apps.Core.Model/Apps/Role.cs

@ -46,7 +46,7 @@ namespace Squidex.Domain.Apps.Core.Apps
[IgnoreDuringEquals]
public bool IsDefault
{
get { return Roles.IsDefault(this); }
get => Roles.IsDefault(this);
}
public Role(string name, PermissionSet permissions, JsonObject properties)

8
backend/src/Squidex.Domain.Apps.Core.Model/Apps/Roles.cs

@ -62,22 +62,22 @@ namespace Squidex.Domain.Apps.Core.Apps
public int CustomCount
{
get { return inner.Count; }
get => inner.Count;
}
public Role this[string name]
{
get { return inner[name]; }
get => inner[name];
}
public IEnumerable<Role> Custom
{
get { return inner.Values; }
get => inner.Values;
}
public IEnumerable<Role> All
{
get { return inner.Values.Union(Defaults.Values); }
get => inner.Values.Union(Defaults.Values);
}
private Roles(ImmutableDictionary<string, Role> roles)

26
backend/src/Squidex.Domain.Apps.Core.Model/Comments/Comment.cs

@ -9,31 +9,11 @@ using System;
using NodaTime;
using Squidex.Infrastructure;
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
namespace Squidex.Domain.Apps.Core.Comments
{
public sealed class Comment
public sealed record Comment(DomainId Id, Instant Time, RefToken User, string Text, Uri? Url = null)
{
public DomainId Id { get; }
public Instant Time { get; }
public RefToken User { get; }
public string Text { get; }
public Uri? Url { get; }
public Comment(DomainId id, Instant time, RefToken user, string text, Uri? url = null)
{
Guard.NotEmpty(id, nameof(id));
Guard.NotNull(user, nameof(user));
Guard.NotNull(text, nameof(text));
Id = id;
Text = text;
Time = time;
User = user;
Url = url;
}
}
}

2
backend/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs

@ -16,7 +16,7 @@ namespace Squidex.Domain.Apps.Core.Contents
{
public IEnumerable<KeyValuePair<string, ContentFieldData?>> ValidValues
{
get { return this.Where(x => x.Value != null); }
get => this.Where(x => x.Value != null);
}
public ContentData()

2
backend/src/Squidex.Domain.Apps.Core.Model/Contents/Status.cs

@ -21,7 +21,7 @@ namespace Squidex.Domain.Apps.Core.Contents
public string Name
{
get { return name ?? "Unknown"; }
get => name ?? "Unknown";
}
public Status(string? name)

2
backend/src/Squidex.Domain.Apps.Core.Model/Freezable.cs

@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Core
[IgnoreDuringEquals]
public bool IsFrozen
{
get { return isFrozen; }
get => isFrozen;
}
protected void CheckIfFrozen()

2
backend/src/Squidex.Domain.Apps.Core.Model/InvariantPartitioning.cs

@ -16,7 +16,7 @@ namespace Squidex.Domain.Apps.Core
public string Master
{
get { return Key; }
get => Key;
}
public IEnumerable<string> AllKeys

4
backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedAssetEvent.cs

@ -41,12 +41,12 @@ namespace Squidex.Domain.Apps.Core.Rules.EnrichedEvents
public bool IsImage
{
get { return AssetType == AssetType.Image; }
get => AssetType == AssetType.Image;
}
public override long Partition
{
get { return Id.GetHashCode(); }
get => Id.GetHashCode();
}
}
}

2
backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedCommentEvent.cs

@ -25,7 +25,7 @@ namespace Squidex.Domain.Apps.Core.Rules.EnrichedEvents
[IgnoreDataMember]
public override long Partition
{
get { return MentionedUser.Id.GetHashCode(); }
get => MentionedUser.Id.GetHashCode();
}
public bool ShouldSerializeMentionedUser()

2
backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedContentEvent.cs

@ -33,7 +33,7 @@ namespace Squidex.Domain.Apps.Core.Rules.EnrichedEvents
public override long Partition
{
get { return Id.GetHashCode(); }
get => Id.GetHashCode();
}
}
}

2
backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedManualEvent.cs

@ -11,7 +11,7 @@ namespace Squidex.Domain.Apps.Core.Rules.EnrichedEvents
{
public override long Partition
{
get { return 0; }
get => 0;
}
}
}

4
backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedSchemaEvent.cs

@ -15,12 +15,12 @@ namespace Squidex.Domain.Apps.Core.Rules.EnrichedEvents
public DomainId Id
{
get { return SchemaId.Id; }
get => SchemaId.Id;
}
public override long Partition
{
get { return SchemaId.GetHashCode(); }
get => SchemaId.GetHashCode();
}
}
}

2
backend/src/Squidex.Domain.Apps.Core.Model/Rules/EnrichedEvents/EnrichedUsageExceededEvent.cs

@ -15,7 +15,7 @@ namespace Squidex.Domain.Apps.Core.Rules.EnrichedEvents
public override long Partition
{
get { return AppId.GetHashCode(); }
get => AppId.GetHashCode();
}
}
}

8
backend/src/Squidex.Domain.Apps.Core.Model/Rules/Rule.cs

@ -20,22 +20,22 @@ namespace Squidex.Domain.Apps.Core.Rules
public string Name
{
get { return name; }
get => name;
}
public RuleTrigger Trigger
{
get { return trigger; }
get => trigger;
}
public RuleAction Action
{
get { return action; }
get => action;
}
public bool IsEnabled
{
get { return isEnabled; }
get => isEnabled;
}
public Rule(RuleTrigger trigger, RuleAction action)

8
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/ArrayField.cs

@ -18,22 +18,22 @@ namespace Squidex.Domain.Apps.Core.Schemas
public IReadOnlyList<NestedField> Fields
{
get { return fields.Ordered; }
get => fields.Ordered;
}
public IReadOnlyDictionary<long, NestedField> FieldsById
{
get { return fields.ById; }
get => fields.ById;
}
public IReadOnlyDictionary<string, NestedField> FieldsByName
{
get { return fields.ByName; }
get => fields.ByName;
}
public FieldCollection<NestedField> FieldCollection
{
get { return fields; }
get => fields;
}
public ArrayField(long id, string name, Partitioning partitioning, ArrayFieldProperties? properties = null, IFieldSettings? settings = null)

2
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldCollection.cs

@ -26,7 +26,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
public IReadOnlyList<T> Ordered
{
get { return fieldsOrdered; }
get => fieldsOrdered;
}
public IReadOnlyDictionary<long, T> ById

10
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField.cs

@ -20,27 +20,27 @@ namespace Squidex.Domain.Apps.Core.Schemas
public long Id
{
get { return fieldId; }
get => fieldId;
}
public string Name
{
get { return fieldName; }
get => fieldName;
}
public bool IsLocked
{
get { return isLocked; }
get => isLocked;
}
public bool IsHidden
{
get { return isHidden; }
get => isHidden;
}
public bool IsDisabled
{
get { return isDisabled; }
get => isDisabled;
}
public abstract FieldProperties RawProperties { get; }

4
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/NestedField{T}.cs

@ -17,12 +17,12 @@ namespace Squidex.Domain.Apps.Core.Schemas
public T Properties
{
get { return properties; }
get => properties;
}
public override FieldProperties RawProperties
{
get { return properties; }
get => properties;
}
public NestedField(long id, string name, T? properties = null, IFieldSettings? settings = null)

12
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField.cs

@ -21,32 +21,32 @@ namespace Squidex.Domain.Apps.Core.Schemas
public long Id
{
get { return fieldId; }
get => fieldId;
}
public string Name
{
get { return fieldName; }
get => fieldName;
}
public bool IsLocked
{
get { return isLocked; }
get => isLocked;
}
public bool IsHidden
{
get { return isHidden; }
get => isHidden;
}
public bool IsDisabled
{
get { return isDisabled; }
get => isDisabled;
}
public Partitioning Partitioning
{
get { return partitioning; }
get => partitioning;
}
public abstract FieldProperties RawProperties { get; }

4
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/RootField{T}.cs

@ -17,12 +17,12 @@ namespace Squidex.Domain.Apps.Core.Schemas
public T Properties
{
get { return properties; }
get => properties;
}
public override FieldProperties RawProperties
{
get { return properties; }
get => properties;
}
public RootField(long id, string name, Partitioning partitioning, T? properties = null, IFieldSettings? settings = null)

28
backend/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs

@ -30,72 +30,72 @@ namespace Squidex.Domain.Apps.Core.Schemas
public string Name
{
get { return name; }
get => name;
}
public string Category
{
get { return category; }
get => category;
}
public bool IsPublished
{
get { return isPublished; }
get => isPublished;
}
public bool IsSingleton
{
get { return isSingleton; }
get => isSingleton;
}
public IReadOnlyList<RootField> Fields
{
get { return fields.Ordered; }
get => fields.Ordered;
}
public IReadOnlyDictionary<long, RootField> FieldsById
{
get { return fields.ById; }
get => fields.ById;
}
public IReadOnlyDictionary<string, RootField> FieldsByName
{
get { return fields.ByName; }
get => fields.ByName;
}
public IReadOnlyDictionary<string, string> PreviewUrls
{
get { return previewUrls; }
get => previewUrls;
}
public FieldCollection<RootField> FieldCollection
{
get { return fields; }
get => fields;
}
public FieldRules FieldRules
{
get { return fieldRules; }
get => fieldRules;
}
public FieldNames FieldsInLists
{
get { return fieldsInLists; }
get => fieldsInLists;
}
public FieldNames FieldsInReferences
{
get { return fieldsInReferences; }
get => fieldsInReferences;
}
public SchemaScripts Scripts
{
get { return scripts; }
get => scripts;
}
public SchemaProperties Properties
{
get { return properties; }
get => properties;
}
public Schema(string name, SchemaProperties? properties = null, bool isSingleton = false)

4
backend/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/JsonTypeVisitor.cs

@ -116,12 +116,12 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema
{
var property = SchemaBuilder.NumberProperty();
if (field.Properties.MinValue.HasValue)
if (field.Properties.MinValue != null)
{
property.Minimum = (decimal)field.Properties.MinValue.Value;
}
if (field.Properties.MaxValue.HasValue)
if (field.Properties.MaxValue != null)
{
property.Maximum = (decimal)field.Properties.MaxValue.Value;
}

2
backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EventJsonSchemaGenerator.cs

@ -21,7 +21,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules
public IReadOnlyCollection<string> AllTypes
{
get { return schemas.Value.Keys; }
get => schemas.Value.Keys;
}
public EventJsonSchemaGenerator(JsonSchemaGenerator schemaGenerator)

4
backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandler.cs

@ -22,12 +22,12 @@ namespace Squidex.Domain.Apps.Core.HandleRules
Type IRuleActionHandler.ActionType
{
get { return typeof(TAction); }
get => typeof(TAction);
}
Type IRuleActionHandler.DataType
{
get { return typeof(TData); }
get => typeof(TData);
}
protected RuleActionHandler(RuleEventFormatter formatter)

2
backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleRegistry.cs

@ -27,7 +27,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules
public IReadOnlyDictionary<string, RuleActionDefinition> Actions
{
get { return actionTypes; }
get => actionTypes;
}
public RuleRegistry(IEnumerable<RuleActionRegistration>? registrations = null)

4
backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleTriggerHandler.cs

@ -25,12 +25,12 @@ namespace Squidex.Domain.Apps.Core.HandleRules
public Type TriggerType
{
get { return typeof(TTrigger); }
get => typeof(TTrigger);
}
public virtual bool CanCreateSnapshotEvents
{
get { return false; }
get => false;
}
public virtual async IAsyncEnumerable<EnrichedEvent> CreateSnapshotEvents(TTrigger trigger, DomainId appId)

2
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentDataProperty.cs

@ -48,7 +48,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
public ContentFieldObject? ContentField
{
get { return contentField; }
get => contentField;
}
public ContentDataProperty(ContentDataObject contentData, ContentFieldObject? contentField = null)

2
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldObject.cs

@ -28,7 +28,7 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
public ContentFieldData? FieldData
{
get { return fieldData; }
get => fieldData;
}
public override bool Extensible => true;

4
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ContentWrapper/ContentFieldProperty.cs

@ -47,12 +47,12 @@ namespace Squidex.Domain.Apps.Core.Scripting.ContentWrapper
public IJsonValue ContentValue
{
get { return contentValue ??= JsonMapper.Map(value); }
get => contentValue ??= JsonMapper.Map(value);
}
public bool IsChanged
{
get { return isChanged; }
get => isChanged;
}
public ContentFieldProperty(ContentFieldObject contentField, IJsonValue? contentValue = null)

2
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ContentValidator.cs

@ -29,7 +29,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
public IReadOnlyCollection<ValidationError> Errors
{
get { return errors; }
get => errors;
}
public ContentValidator(PartitionResolver partitionResolver, ValidationContext context, IEnumerable<IValidatorsFactory> factories, ISemanticLog log)

18
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/DefaultFieldValueValidatorsFactory.cs

@ -49,7 +49,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
var isRequired = IsRequired(properties, args.Context);
if (isRequired || properties.MinItems.HasValue || properties.MaxItems.HasValue)
if (isRequired || properties.MinItems != null || properties.MaxItems != null)
{
yield return new CollectionValidator(isRequired, properties.MinItems, properties.MaxItems);
}
@ -92,7 +92,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
yield return new RequiredValidator();
}
if (properties.MinValue.HasValue || properties.MaxValue.HasValue)
if (properties.MinValue != null || properties.MaxValue != null)
{
yield return new RangeValidator<Instant>(properties.MinValue, properties.MaxValue);
}
@ -133,7 +133,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
yield return new RequiredValidator();
}
if (properties.MinValue.HasValue || properties.MaxValue.HasValue)
if (properties.MinValue != null || properties.MaxValue != null)
{
yield return new RangeValidator<double>(properties.MinValue, properties.MaxValue);
}
@ -160,15 +160,15 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
yield return new RequiredStringValidator(true);
}
if (properties.MinLength.HasValue || properties.MaxLength.HasValue)
if (properties.MinLength != null || properties.MaxLength != null)
{
yield return new StringLengthValidator(properties.MinLength, properties.MaxLength);
}
if (properties.MinCharacters.HasValue ||
properties.MaxCharacters.HasValue ||
properties.MinWords.HasValue ||
properties.MaxWords.HasValue)
if (properties.MinCharacters != null ||
properties.MaxCharacters != null ||
properties.MinWords != null ||
properties.MaxWords != null)
{
Func<string, string>? transform = null;
@ -206,7 +206,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
var isRequired = IsRequired(properties, args.Context);
if (isRequired || properties.MinItems.HasValue || properties.MaxItems.HasValue)
if (isRequired || properties.MinItems != null || properties.MaxItems != null)
{
yield return new CollectionValidator(isRequired, properties.MinItems, properties.MaxItems);
}

1
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ValidationContext.cs

@ -32,6 +32,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
: base(appId, schemaId, schema)
{
JsonSerializer = jsonSerializer;
ContentId = contentId;
}

18
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/AssetsValidator.cs

@ -33,7 +33,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
this.properties = properties;
if (isRequired || properties.MinItems.HasValue || properties.MaxItems.HasValue)
if (isRequired || properties.MinItems != null || properties.MaxItems != null)
{
collectionValidator = new CollectionValidator(isRequired, properties.MinItems, properties.MaxItems);
}
@ -101,14 +101,14 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
private void ValidateCommon(IAssetInfo asset, ImmutableQueue<string> path, AddError addError)
{
if (properties.MinSize.HasValue && asset.FileSize < properties.MinSize)
if (properties.MinSize != null && asset.FileSize < properties.MinSize)
{
var min = properties.MinSize.Value.ToReadableSize();
addError(path, T.Get("contents.validation.minimumSize", new { size = asset.FileSize.ToReadableSize(), min }));
}
if (properties.MaxSize.HasValue && asset.FileSize > properties.MaxSize)
if (properties.MaxSize != null && asset.FileSize > properties.MaxSize)
{
var max = properties.MaxSize.Value.ToReadableSize();
@ -136,34 +136,34 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
var pixelWidth = asset.Metadata.GetPixelWidth();
var pixelHeight = asset.Metadata.GetPixelHeight();
if (pixelWidth.HasValue && pixelHeight.HasValue)
if (pixelWidth != null && pixelHeight != null)
{
var w = pixelWidth.Value;
var h = pixelHeight.Value;
var actualRatio = (double)w / h;
if (properties.MinWidth.HasValue && w < properties.MinWidth)
if (properties.MinWidth != null && w < properties.MinWidth)
{
addError(path, T.Get("contents.validation.minimumWidth", new { width = w, min = properties.MinWidth }));
}
if (properties.MaxWidth.HasValue && w > properties.MaxWidth)
if (properties.MaxWidth != null && w > properties.MaxWidth)
{
addError(path, T.Get("contents.validation.maximumWidth", new { width = w, max = properties.MaxWidth }));
}
if (properties.MinHeight.HasValue && h < properties.MinHeight)
if (properties.MinHeight != null && h < properties.MinHeight)
{
addError(path, T.Get("contents.validation.minimumHeight", new { height = h, min = properties.MinHeight }));
}
if (properties.MaxHeight.HasValue && h > properties.MaxHeight)
if (properties.MaxHeight != null && h > properties.MaxHeight)
{
addError(path, T.Get("contents.validation.maximumHeight", new { height = h, max = properties.MaxHeight }));
}
if (properties.AspectHeight.HasValue && properties.AspectWidth.HasValue)
if (properties.AspectHeight != null && properties.AspectWidth != null)
{
var expectedRatio = (double)properties.AspectWidth.Value / properties.AspectHeight.Value;

8
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/CollectionValidator.cs

@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
public CollectionValidator(bool isRequired, int? minItems = null, int? maxItems = null)
{
if (minItems.HasValue && minItems > maxItems)
if (minItems != null && minItems > maxItems)
{
throw new ArgumentException("Min length must be greater than max length.", nameof(minItems));
}
@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
return Task.CompletedTask;
}
if (minItems.HasValue && maxItems.HasValue)
if (minItems != null && maxItems != null)
{
if (minItems == maxItems && minItems != items.Count)
{
@ -55,12 +55,12 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
}
else
{
if (minItems.HasValue && items.Count < minItems)
if (minItems != null && items.Count < minItems)
{
addError(context.Path, T.Get("contents.validation.minItems", new { min = minItems }));
}
if (maxItems.HasValue && items.Count > maxItems)
if (maxItems != null && items.Count > maxItems)
{
addError(context.Path, T.Get("contents.validation.maxItems", new { max = maxItems }));
}

8
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/RangeValidator.cs

@ -18,7 +18,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
public RangeValidator(TValue? min, TValue? max)
{
if (min.HasValue && max.HasValue && min.Value.CompareTo(max.Value) > 0)
if (min != null && max != null && min.Value.CompareTo(max.Value) > 0)
{
throw new ArgumentException("Min value must be greater than max value.", nameof(min));
}
@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
if (value is TValue typedValue)
{
if (min.HasValue && max.HasValue)
if (min != null && max != null)
{
if (Equals(min, max) && Equals(min.Value, max.Value))
{
@ -44,12 +44,12 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
}
else
{
if (min.HasValue && typedValue.CompareTo(min.Value) < 0)
if (min != null && typedValue.CompareTo(min.Value) < 0)
{
addError(context.Path, T.Get("contents.validation.min", new { min }));
}
if (max.HasValue && typedValue.CompareTo(max.Value) > 0)
if (max != null && typedValue.CompareTo(max.Value) > 0)
{
addError(context.Path, T.Get("contents.validation.max", new { max }));
}

2
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/ReferencesValidator.cs

@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
this.properties = properties;
if (isRequired || properties.MinItems.HasValue || properties.MaxItems.HasValue)
if (isRequired || properties.MinItems != null || properties.MaxItems != null)
{
collectionValidator = new CollectionValidator(isRequired, properties.MinItems, properties.MaxItems);
}

6
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/StringLengthValidator.cs

@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
{
if (value is string stringValue && !string.IsNullOrEmpty(stringValue))
{
if (minLength.HasValue && maxLength.HasValue)
if (minLength != null && maxLength != null)
{
if (minLength == maxLength && minLength != stringValue.Length)
{
@ -44,12 +44,12 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
}
else
{
if (minLength.HasValue && stringValue.Length < minLength)
if (minLength != null && stringValue.Length < minLength)
{
addError(context.Path, T.Get("contents.validation.minLength", new { min = minLength }));
}
if (maxLength.HasValue && stringValue.Length > maxLength)
if (maxLength != null && stringValue.Length > maxLength)
{
addError(context.Path, T.Get("contents.validation.maxLength", new { max = maxLength }));
}

8
backend/src/Squidex.Domain.Apps.Core.Operations/ValidateContent/Validators/StringTextValidator.cs

@ -52,11 +52,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
stringValue = transform(stringValue);
}
if (minWords.HasValue || maxWords.HasValue)
if (minWords != null || maxWords != null)
{
var words = stringValue.WordCount();
if (minWords.HasValue && maxWords.HasValue)
if (minWords != null && maxWords != null)
{
if (minWords == maxWords && minWords != words)
{
@ -81,11 +81,11 @@ namespace Squidex.Domain.Apps.Core.ValidateContent.Validators
}
}
if (minCharacters.HasValue || maxCharacters.HasValue)
if (minCharacters != null || maxCharacters != null)
{
var characters = stringValue.CharacterCount();
if (minCharacters.HasValue && maxCharacters.HasValue)
if (minCharacters != null && maxCharacters != null)
{
if (minCharacters == maxCharacters && minCharacters != characters)
{

4
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetEntity.cs

@ -104,12 +104,12 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public DomainId AssetId
{
get { return Id; }
get => Id;
}
public DomainId UniqueId
{
get { return DocumentId; }
get => DocumentId;
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderEntity.cs

@ -65,7 +65,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
public DomainId UniqueId
{
get { return DocumentId; }
get => DocumentId;
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository.cs

@ -94,7 +94,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
Filter.Eq(x => x.IsDeleted, false)
};
if (parentId.HasValue)
if (parentId != null)
{
if (parentId == DomainId.Empty)
{

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository_SnapshotStore.cs

@ -34,7 +34,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
return (Map(existing), existing.Version);
}
return (null!, EtagVersion.NotFound);
return (null!, EtagVersion.Empty);
}
}

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs

@ -34,7 +34,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
return (Map(existing), existing.Version);
}
return (null!, EtagVersion.NotFound);
return (null!, EtagVersion.Empty);
}
}

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/Visitors/FindExtensions.cs

@ -41,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets.Visitors
Filter.Eq(x => x.IsDeleted, false)
};
if (parentId.HasValue)
if (parentId != null)
{
if (parentId == DomainId.Empty)
{

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs

@ -93,7 +93,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public DomainId UniqueId
{
get { return DocumentId; }
get => DocumentId;
}
}
}

20
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs

@ -25,6 +25,11 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
throw new NotSupportedException();
}
Task<(ContentDomainObject.State Value, long Version)> ISnapshotStore<ContentDomainObject.State, DomainId>.ReadAsync(DomainId key)
{
return Task.FromResult<(ContentDomainObject.State, long Version)>((null!, EtagVersion.Empty));
}
async Task ISnapshotStore<ContentDomainObject.State, DomainId>.ClearAsync()
{
using (Profiler.TraceMethod<MongoContentRepository>())
@ -43,21 +48,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
}
}
async Task<(ContentDomainObject.State Value, long Version)> ISnapshotStore<ContentDomainObject.State, DomainId>.ReadAsync(DomainId key)
{
using (Profiler.TraceMethod<MongoContentRepository>())
{
var contentEntity = await collectionAll.FindAsync(key);
if (contentEntity != null)
{
return (SimpleMapper.Map(contentEntity, new ContentDomainObject.State()), contentEntity.Version);
}
return (null!, EtagVersion.NotFound);
}
}
async Task ISnapshotStore<ContentDomainObject.State, DomainId>.WriteAsync(DomainId key, ContentDomainObject.State value, long oldVersion, long newVersion)
{
using (Profiler.TraceMethod<MongoContentRepository>())

7
backend/src/Squidex.Domain.Apps.Entities.MongoDb/FullText/MongoTextIndex.cs

@ -114,10 +114,9 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.FullText
}
else
{
var (bySchema, byApp) =
await AsyncHelper.WhenAll(
SearchBySchemaAsync(queryText, app, filter, scope, LimitHalf),
SearchByAppAsync(queryText, app, scope, LimitHalf));
var (bySchema, byApp) = await AsyncHelper.WhenAll(
SearchBySchemaAsync(queryText, app, filter, scope, LimitHalf),
SearchByAppAsync(queryText, app, scope, LimitHalf));
return bySchema.Union(byApp).Distinct().ToList();
}

4
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleEventEntity.cs

@ -72,12 +72,12 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
DomainId IEntity.Id
{
get { return DocumentId; }
get => DocumentId;
}
DomainId IEntity.UniqueId
{
get { return DocumentId; }
get => DocumentId;
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleEventRepository.cs

@ -67,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
{
var filter = Filter.Eq(x => x.AppId, appId);
if (ruleId.HasValue && ruleId.Value != DomainId.Empty)
if (ruleId != null && ruleId.Value != DomainId.Empty)
{
filter = Filter.And(filter, Filter.Eq(x => x.RuleId, ruleId.Value));
}

8
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemasHash.cs

@ -24,22 +24,22 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas
{
public int BatchSize
{
get { return 1000; }
get => 1000;
}
public int BatchDelay
{
get { return 500; }
get => 500;
}
public string Name
{
get { return GetType().Name; }
get => GetType().Name;
}
public string EventsFilter
{
get { return "^(app-|schema-)"; }
get => "^(app-|schema-)";
}
public MongoSchemasHash(IMongoDatabase database, bool setup = false)

2
backend/src/Squidex.Domain.Apps.Entities/Apps/Commands/AppUpdateCommand.cs

@ -17,7 +17,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Commands
[IgnoreDataMember]
public override DomainId AggregateId
{
get { return AppId.Id; }
get => AppId.Id;
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities/Apps/Commands/CreateApp.cs

@ -22,7 +22,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Commands
[IgnoreDataMember]
public override DomainId AggregateId
{
get { return AppId; }
get => AppId;
}
public CreateApp()

9
backend/src/Squidex.Domain.Apps.Entities/Apps/DomainObject/AppCommandMiddleware.cs

@ -45,14 +45,17 @@ namespace Squidex.Domain.Apps.Entities.Apps.DomainObject
await UploadAsync(uploadImage);
}
await ExecuteCommandAsync(context);
await base.HandleAsync(context, next);
}
if (context.PlainResult is IAppEntity app)
protected override Task<object> EnrichResultAsync(CommandContext context, CommandResult result)
{
if (result.Payload is IAppEntity app)
{
contextProvider.Context.App = app;
}
await next(context);
return base.EnrichResultAsync(context, result);
}
private async Task UploadAsync(UploadAppImage uploadImage)

2
backend/src/Squidex.Domain.Apps.Entities/Apps/DomainObject/AppDomainObject.State.cs

@ -50,7 +50,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.DomainObject
[IgnoreDataMember]
public DomainId UniqueId
{
get { return Id; }
get => Id;
}
public override bool ApplyEvent(IEvent @event)

60
backend/src/Squidex.Domain.Apps.Entities/Apps/DomainObject/AppDomainObject.cs

@ -64,12 +64,12 @@ namespace Squidex.Domain.Apps.Entities.Apps.DomainObject
return command is AppUpdateCommand update && Equals(update?.AppId?.Id, Snapshot.Id);
}
public override Task<object?> ExecuteAsync(IAggregateCommand command)
public override Task<CommandResult> ExecuteAsync(IAggregateCommand command)
{
switch (command)
{
case CreateApp createApp:
return CreateReturn(createApp, c =>
case CreateApp create:
return CreateReturn(create, c =>
{
GuardApp.CanCreate(c);
@ -78,8 +78,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.DomainObject
return Snapshot;
});
case UpdateApp updateApp:
return UpdateReturn(updateApp, c =>
case UpdateApp update:
return UpdateReturn(update, c =>
{
GuardApp.CanUpdate(c);
@ -304,8 +304,8 @@ namespace Squidex.Domain.Apps.Entities.Apps.DomainObject
}
});
case ArchiveApp archiveApp:
return UpdateAsync(archiveApp, async c =>
case ArchiveApp archive:
return UpdateAsync(archive, async c =>
{
await appPlansBillingManager.ChangePlanAsync(c.Actor.Identifier, Snapshot.NamedId(), null, null);
@ -322,7 +322,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.DomainObject
return appPlansProvider.GetPlanForApp(Snapshot).Plan;
}
public void Create(CreateApp command)
private void Create(CreateApp command)
{
var appId = NamedId.Of(command.AppId, command.Name);
@ -350,7 +350,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.DomainObject
}
}
public void ChangePlan(ChangePlan command)
private void ChangePlan(ChangePlan command)
{
if (string.Equals(appPlansProvider.GetFreePlan()?.Id, command.PlanId))
{
@ -362,107 +362,107 @@ namespace Squidex.Domain.Apps.Entities.Apps.DomainObject
}
}
public void Update(UpdateApp command)
private void Update(UpdateApp command)
{
Raise(command, new AppUpdated());
}
public void UpdateClient(UpdateClient command)
private void UpdateClient(UpdateClient command)
{
Raise(command, new AppClientUpdated());
}
public void UploadImage(UploadAppImage command)
private void UploadImage(UploadAppImage command)
{
Raise(command, new AppImageUploaded { Image = new AppImage(command.File.MimeType) });
}
public void RemoveImage(RemoveAppImage command)
private void RemoveImage(RemoveAppImage command)
{
Raise(command, new AppImageRemoved());
}
public void UpdateLanguage(UpdateLanguage command)
private void UpdateLanguage(UpdateLanguage command)
{
Raise(command, new AppLanguageUpdated());
}
public void AssignContributor(AssignContributor command, bool isAdded)
private void AssignContributor(AssignContributor command, bool isAdded)
{
Raise(command, new AppContributorAssigned { IsAdded = isAdded });
}
public void RemoveContributor(RemoveContributor command)
private void RemoveContributor(RemoveContributor command)
{
Raise(command, new AppContributorRemoved());
}
public void AttachClient(AttachClient command)
private void AttachClient(AttachClient command)
{
Raise(command, new AppClientAttached());
}
public void RevokeClient(RevokeClient command)
private void RevokeClient(RevokeClient command)
{
Raise(command, new AppClientRevoked());
}
public void AddWorkflow(AddWorkflow command)
private void AddWorkflow(AddWorkflow command)
{
Raise(command, new AppWorkflowAdded());
}
public void UpdateWorkflow(UpdateWorkflow command)
private void UpdateWorkflow(UpdateWorkflow command)
{
Raise(command, new AppWorkflowUpdated());
}
public void DeleteWorkflow(DeleteWorkflow command)
private void DeleteWorkflow(DeleteWorkflow command)
{
Raise(command, new AppWorkflowDeleted());
}
public void AddLanguage(AddLanguage command)
private void AddLanguage(AddLanguage command)
{
Raise(command, new AppLanguageAdded());
}
public void RemoveLanguage(RemoveLanguage command)
private void RemoveLanguage(RemoveLanguage command)
{
Raise(command, new AppLanguageRemoved());
}
public void AddPattern(AddPattern command)
private void AddPattern(AddPattern command)
{
Raise(command, new AppPatternAdded());
}
public void DeletePattern(DeletePattern command)
private void DeletePattern(DeletePattern command)
{
Raise(command, new AppPatternDeleted());
}
public void UpdatePattern(UpdatePattern command)
private void UpdatePattern(UpdatePattern command)
{
Raise(command, new AppPatternUpdated());
}
public void AddRole(AddRole command)
private void AddRole(AddRole command)
{
Raise(command, new AppRoleAdded());
}
public void DeleteRole(DeleteRole command)
private void DeleteRole(DeleteRole command)
{
Raise(command, new AppRoleDeleted());
}
public void UpdateRole(UpdateRole command)
private void UpdateRole(UpdateRole command)
{
Raise(command, new AppRoleUpdated());
}
public void ArchiveApp(ArchiveApp command)
private void ArchiveApp(ArchiveApp command)
{
Raise(command, new AppArchived());
}

2
backend/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InvitationEventConsumer.cs

@ -25,7 +25,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation
public string Name
{
get { return "NotificationEmailSender"; }
get => "NotificationEmailSender";
}
public string EventsFilter

2
backend/src/Squidex.Domain.Apps.Entities/Apps/Plans/NoopAppPlanBillingManager.cs

@ -14,7 +14,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Plans
{
public bool HasPortal
{
get { return false; }
get => false;
}
public Task<IChangePlanResult> ChangePlanAsync(string userId, NamedId<DomainId> appId, string? planId, string? referer)

4
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateBlogCommandMiddleware.cs

@ -64,7 +64,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
.AddField("text",
new ContentFieldData()
.AddInvariant("Just created a blog with Squidex. I love it!")),
Publish = true
Status = Status.Published
});
}
@ -83,7 +83,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
.AddField("text",
new ContentFieldData()
.AddInvariant("I love Squidex and SciFi!")),
Publish = true
Status = Status.Published
});
}

10
backend/src/Squidex.Domain.Apps.Entities/Assets/AssetChangedTriggerHandler.cs

@ -73,14 +73,12 @@ namespace Squidex.Domain.Apps.Entities.Assets
@event.Payload.AssetId,
@event.Headers.EventStreamNumber());
if (asset == null)
if (asset != null)
{
throw new DomainObjectNotFoundException(@event.Payload.AssetId.ToString());
}
SimpleMapper.Map(asset, result);
SimpleMapper.Map(asset, result);
result.AssetType = asset.Type;
result.AssetType = asset.Type;
}
switch (@event.Payload)
{

14
backend/src/Squidex.Domain.Apps.Entities/Assets/AssetCreatedResult.cs → backend/src/Squidex.Domain.Apps.Entities/Assets/AssetDuplicate.cs

@ -5,19 +5,11 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
namespace Squidex.Domain.Apps.Entities.Assets
{
public sealed class AssetCreatedResult
public sealed record AssetDuplicate(IEnrichedAssetEntity Asset)
{
public IEnrichedAssetEntity Asset { get; }
public bool IsDuplicate { get; }
public AssetCreatedResult(IEnrichedAssetEntity asset, bool isDuplicate)
{
Asset = asset;
IsDuplicate = isDuplicate;
}
}
}

4
backend/src/Squidex.Domain.Apps.Entities/Assets/AssetEntity.cs

@ -58,12 +58,12 @@ namespace Squidex.Domain.Apps.Entities.Assets
public DomainId AssetId
{
get { return Id; }
get => Id;
}
public DomainId UniqueId
{
get { return DomainId.Combine(AppId, Id); }
get => DomainId.Combine(AppId, Id);
}
}
}

8
backend/src/Squidex.Domain.Apps.Entities/Assets/AssetUsageTracker_EventHandling.cs

@ -18,22 +18,22 @@ namespace Squidex.Domain.Apps.Entities.Assets
{
public int BatchSize
{
get { return 1000; }
get => 1000;
}
public int BatchDelay
{
get { return 1000; }
get => 1000;
}
public string Name
{
get { return GetType().Name; }
get => GetType().Name;
}
public string EventsFilter
{
get { return "^asset-"; }
get => "^asset-";
}
public Task On(Envelope<IEvent> @event)

2
backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/AssetCommand.cs

@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Commands
[IgnoreDataMember]
public DomainId AggregateId
{
get { return DomainId.Combine(AppId, AssetId); }
get => DomainId.Combine(AppId, AssetId);
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/AssetFolderCommand.cs

@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Commands
[IgnoreDataMember]
public DomainId AggregateId
{
get { return DomainId.Combine(AppId, AssetFolderId); }
get => DomainId.Combine(AppId, AssetFolderId);
}
}
}

8
backend/src/Squidex.Infrastructure/EventSourcing/IEventEnricher.cs → backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/BulkUpdateAssetType.cs

@ -5,10 +5,12 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
namespace Squidex.Infrastructure.EventSourcing
namespace Squidex.Domain.Apps.Entities.Assets.Commands
{
public interface IEventEnricher<in T>
public enum BulkUpdateAssetType
{
void Enrich(Envelope<IEvent> @event, T key);
Annotate,
Move,
Delete
}
}

13
backend/src/Squidex.Infrastructure/Commands/EntitySavedResult.cs → backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/BulkUpdateAssets.cs

@ -5,15 +5,14 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
namespace Squidex.Infrastructure.Commands
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Entities.Assets.Commands
{
public class EntitySavedResult
public sealed class BulkUpdateAssets : SquidexCommand, IAppCommand
{
public long Version { get; }
public NamedId<DomainId> AppId { get; set; }
public EntitySavedResult(long version)
{
Version = version;
}
public BulkUpdateJob[]? Jobs { get; set; }
}
}

38
backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/BulkUpdateJob.cs

@ -0,0 +1,38 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using Squidex.Domain.Apps.Core.Assets;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Entities.Assets.Commands
{
public sealed class BulkUpdateJob
{
public BulkUpdateAssetType Type { get; set; }
public DomainId Id { get; set; }
public DomainId ParentId { get; set; }
public string? ParentPath { get; set; }
public string? FileName { get; set; }
public string? Slug { get; set; }
public bool? IsProtected { get; set; }
public bool Permanent { get; set; }
public HashSet<string> Tags { get; set; }
public AssetMetadata? Metadata { get; set; }
public long ExpectedVersion { get; set; } = EtagVersion.Any;
}
}

9
backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/CreateAsset.cs

@ -5,8 +5,8 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Entities.Assets.Commands
{
@ -14,7 +14,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Commands
{
public DomainId ParentId { get; set; }
public HashSet<string> Tags { get; set; } = new HashSet<string>();
public string? ParentPath { get; set; }
public bool Duplicate { get; set; }
@ -22,5 +22,10 @@ namespace Squidex.Domain.Apps.Entities.Assets.Commands
{
AssetId = DomainId.NewGuid();
}
public MoveAsset AsMove()
{
return SimpleMapper.Map(this, new MoveAsset());
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/DeleteAsset.cs

@ -10,5 +10,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Commands
public sealed class DeleteAsset : AssetCommand
{
public bool CheckReferrers { get; set; }
public bool Permanent { get; set; }
}
}

2
backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/MoveAsset.cs

@ -12,5 +12,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Commands
public sealed class MoveAsset : AssetCommand
{
public DomainId ParentId { get; set; }
public string? ParentPath { get; set; }
}
}

3
backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/UploadAssetCommand.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Collections.Generic;
using Squidex.Assets;
using Squidex.Domain.Apps.Core.Assets;
@ -12,6 +13,8 @@ namespace Squidex.Domain.Apps.Entities.Assets.Commands
{
public abstract class UploadAssetCommand : AssetCommand
{
public HashSet<string> Tags { get; set; } = new HashSet<string>();
public AssetFile File { get; set; }
public AssetMetadata Metadata { get; } = new AssetMetadata();

39
backend/src/Squidex.Domain.Apps.Entities/Assets/Commands/UpsertAsset.cs

@ -0,0 +1,39 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Infrastructure;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Domain.Apps.Entities.Assets.Commands
{
public sealed class UpsertAsset : UploadAssetCommand
{
public DomainId? ParentId { get; set; }
public string? ParentPath { get; set; }
public UpsertAsset()
{
AssetId = DomainId.NewGuid();
}
public CreateAsset AsCreate()
{
return SimpleMapper.Map(this, new CreateAsset());
}
public UpdateAsset AsUpdate()
{
return SimpleMapper.Map(this, new UpdateAsset());
}
public MoveAsset AsMove(DomainId parentId)
{
return SimpleMapper.Map(this, new MoveAsset { ParentId = parentId });
}
}
}

127
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetCommandMiddleware.cs

@ -19,6 +19,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
public sealed class AssetCommandMiddleware : GrainCommandMiddleware<AssetCommand, IAssetGrain>
{
private readonly IAssetFileStore assetFileStore;
private readonly IAssetFolderResolver assetFolderResolver;
private readonly IAssetEnricher assetEnricher;
private readonly IAssetQueryService assetQuery;
private readonly IContextProvider contextProvider;
@ -28,6 +29,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
IGrainFactory grainFactory,
IAssetEnricher assetEnricher,
IAssetFileStore assetFileStore,
IAssetFolderResolver assetFolderResolver,
IAssetQueryService assetQuery,
IContextProvider contextProvider,
IEnumerable<IAssetMetadataSource> assetMetadataSources)
@ -35,25 +37,27 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{
Guard.NotNull(assetEnricher, nameof(assetEnricher));
Guard.NotNull(assetFileStore, nameof(assetFileStore));
Guard.NotNull(assetQuery, nameof(assetQuery));
Guard.NotNull(assetFolderResolver, nameof(assetFolderResolver));
Guard.NotNull(assetMetadataSources, nameof(assetMetadataSources));
Guard.NotNull(assetQuery, nameof(assetQuery));
Guard.NotNull(contextProvider, nameof(contextProvider));
this.assetFileStore = assetFileStore;
this.assetEnricher = assetEnricher;
this.assetQuery = assetQuery;
this.assetFileStore = assetFileStore;
this.assetFolderResolver = assetFolderResolver;
this.assetMetadataSources = assetMetadataSources;
this.assetQuery = assetQuery;
this.contextProvider = contextProvider;
}
public override async Task HandleAsync(CommandContext context, NextDelegate next)
{
var tempFile = context.ContextId.ToString();
switch (context.Command)
{
case CreateAsset createAsset:
{
var tempFile = context.ContextId.ToString();
try
{
await EnrichWithHashAndUploadAsync(createAsset, tempFile);
@ -68,16 +72,25 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
if (existing != null)
{
var result = new AssetCreatedResult(existing, true);
context.Complete(result);
context.Complete(new AssetDuplicate(existing));
await next(context);
return;
}
}
await UploadAsync(context, tempFile, createAsset, createAsset.Tags, true, next);
if (!string.IsNullOrWhiteSpace(createAsset.ParentPath))
{
createAsset.ParentId =
await assetFolderResolver.ResolveOrCreateAsync(
contextProvider.Context,
context.CommandBus,
createAsset.ParentPath);
}
await EnrichWithMetadataAsync(createAsset);
await base.HandleAsync(context, next);
}
finally
{
@ -89,63 +102,97 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
break;
}
case UpdateAsset updateAsset:
case MoveAsset move:
{
try
if (!string.IsNullOrWhiteSpace(move.ParentPath))
{
await EnrichWithHashAndUploadAsync(updateAsset, tempFile);
await UploadAsync(context, tempFile, updateAsset, null, false, next);
move.ParentId =
await assetFolderResolver.ResolveOrCreateAsync(
contextProvider.Context,
context.CommandBus,
move.ParentPath);
}
finally
{
await assetFileStore.DeleteAsync(tempFile);
updateAsset.File.Dispose();
await base.HandleAsync(context, next);
break;
}
case UpsertAsset upsert:
{
if (!string.IsNullOrWhiteSpace(upsert.ParentPath))
{
upsert.ParentId =
await assetFolderResolver.ResolveOrCreateAsync(
contextProvider.Context,
context.CommandBus,
upsert.ParentPath);
}
await UploadAndHandleAsync(context, next, upsert);
break;
}
case UpdateAsset upload:
{
await UploadAndHandleAsync(context, next, upload);
break;
}
default:
await HandleCoreAsync(context, false, next);
await base.HandleAsync(context, next);
break;
}
}
private async Task UploadAsync(CommandContext context, string tempFile, UploadAssetCommand command, HashSet<string>? tags, bool created, NextDelegate next)
private async Task UploadAndHandleAsync(CommandContext context, NextDelegate next, UploadAssetCommand upload)
{
await EnrichWithMetadataAsync(command, tags);
var tempFile = context.ContextId.ToString();
var asset = await HandleCoreAsync(context, created, next);
try
{
await EnrichWithHashAndUploadAsync(upload, tempFile);
await EnrichWithMetadataAsync(upload);
if (asset != null)
await base.HandleAsync(context, next);
}
finally
{
await assetFileStore.CopyAsync(tempFile, command.AppId.Id, command.AssetId, asset.FileVersion);
await assetFileStore.DeleteAsync(tempFile);
upload.File.Dispose();
}
}
private async Task<IEnrichedAssetEntity?> HandleCoreAsync(CommandContext context, bool created, NextDelegate next)
protected override async Task<object> EnrichResultAsync(CommandContext context, CommandResult result)
{
await base.HandleAsync(context, next);
var payload = await base.EnrichResultAsync(context, result);
if (context.PlainResult is IAssetEntity asset && !(context.PlainResult is IEnrichedAssetEntity))
if (payload is IAssetEntity asset)
{
var enriched = await assetEnricher.EnrichAsync(asset, contextProvider.Context);
if (created)
if (result.IsChanged && context.Command is UploadAssetCommand)
{
context.Complete(new AssetCreatedResult(enriched, false));
var tempFile = context.ContextId.ToString();
try
{
await assetFileStore.CopyAsync(tempFile, asset.AppId.Id, asset.AssetId, asset.FileVersion);
}
catch (AssetAlreadyExistsException) when (context.Command is not UpsertAsset)
{
throw;
}
}
else
if (payload is not IEnrichedAssetEntity)
{
context.Complete(enriched);
payload = await assetEnricher.EnrichAsync(asset, contextProvider.Context);
}
return enriched;
}
return null;
return payload;
}
private async Task EnrichWithHashAndUploadAsync(UploadAssetCommand command, string tempFile)
@ -156,16 +203,18 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{
await assetFileStore.UploadAsync(tempFile, hashStream);
command.FileHash = $"{hashStream.GetHashStringAndReset()}{command.File.FileName}{command.File.FileSize}".Sha256Base64();
var hash = $"{hashStream.GetHashStringAndReset()}{command.File.FileName}{command.File.FileSize}".Sha256Base64();
command.FileHash = hash;
}
}
}
private async Task EnrichWithMetadataAsync(UploadAssetCommand command, HashSet<string>? tags)
private async Task EnrichWithMetadataAsync(UploadAssetCommand command)
{
foreach (var metadataSource in assetMetadataSources)
{
await metadataSource.EnhanceAsync(command, tags);
await metadataSource.EnhanceAsync(command);
}
}
}

20
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetDomainObject.State.cs

@ -49,13 +49,13 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
[IgnoreDataMember]
public DomainId AssetId
{
get { return Id; }
get => Id;
}
[IgnoreDataMember]
public DomainId UniqueId
{
get { return DomainId.Combine(AppId, Id); }
get => DomainId.Combine(AppId, Id);
}
public override bool ApplyEvent(IEvent @event)
@ -68,15 +68,9 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
SimpleMapper.Map(e, this);
FileName = e.FileName;
if (string.IsNullOrWhiteSpace(e.Slug))
{
Slug = e.FileName.ToAssetSlug();
}
else
if (string.IsNullOrWhiteSpace(Slug))
{
Slug = e.Slug;
Slug = FileName.ToAssetSlug();
}
TotalSize += e.FileSize;
@ -86,7 +80,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
return true;
}
case AssetUpdated e:
case AssetUpdated e when Is.Change(e.FileHash, FileHash):
{
SimpleMapper.Map(e, this);
@ -122,14 +116,14 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
hasChanged = true;
}
if (Is.OptionalChange(Tags, e.Tags))
if (Is.OptionalSetChange(Tags, e.Tags))
{
Tags = e.Tags;
hasChanged = true;
}
if (Is.OptionalChange(Metadata, e.Metadata))
if (Is.OptionalMapChange(Metadata, e.Metadata))
{
Metadata = e.Metadata;

128
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetDomainObject.cs

@ -24,7 +24,7 @@ using IAssetTagService = Squidex.Domain.Apps.Core.Tags.ITagService;
namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{
public sealed partial class AssetDomainObject : LogSnapshotDomainObject<AssetDomainObject.State>
public sealed partial class AssetDomainObject : DomainObject<AssetDomainObject.State>
{
private readonly IContentRepository contentRepository;
private readonly IAssetTagService assetTags;
@ -43,6 +43,8 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
this.assetTags = assetTags;
this.assetQuery = assetQuery;
this.contentRepository = contentRepository;
Capacity = int.MaxValue;
}
protected override bool IsDeleted()
@ -50,6 +52,11 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
return Snapshot.IsDeleted;
}
protected override bool CanRecreate()
{
return true;
}
protected override bool CanAcceptCreation(ICommand command)
{
return command is AssetCommand;
@ -62,27 +69,45 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
Equals(assetCommand.AssetId, Snapshot.Id);
}
public override Task<object?> ExecuteAsync(IAggregateCommand command)
public override Task<CommandResult> ExecuteAsync(IAggregateCommand command)
{
switch (command)
{
case CreateAsset createAsset:
return CreateReturnAsync(createAsset, async c =>
case UpsertAsset upsert:
return UpsertReturnAsync(upsert, async c =>
{
await GuardAsset.CanCreate(c, assetQuery);
if (Version > EtagVersion.Empty && !IsDeleted())
{
UpdateCore(c.AsUpdate());
}
else
{
await CreateCore(c.AsCreate());
}
if (c.Tags != null)
if (Is.OptionalChange(Snapshot.ParentId, c.ParentId))
{
c.Tags = await NormalizeTagsAsync(c.AppId.Id, c.Tags);
await MoveCore(c.AsMove(c.ParentId.Value));
}
Create(c);
return Snapshot;
});
case CreateAsset c:
return CreateReturnAsync(c, async create =>
{
await CreateCore(create);
if (Is.Change(Snapshot.ParentId, c.ParentId))
{
await MoveCore(c.AsMove());
}
return Snapshot;
});
case AnnotateAsset annotateAsset:
return UpdateReturnAsync(annotateAsset, async c =>
case AnnotateAsset c:
return UpdateReturnAsync(c, async c =>
{
GuardAsset.CanAnnotate(c);
@ -96,48 +121,81 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
return Snapshot;
});
case UpdateAsset updateAsset:
return UpdateReturn(updateAsset, c =>
case UpdateAsset update:
return UpdateReturn(update, update =>
{
GuardAsset.CanUpdate(c);
Update(c);
Update(update);
return Snapshot;
});
case MoveAsset moveAsset:
return UpdateReturnAsync(moveAsset, async c =>
case MoveAsset move:
return UpdateReturnAsync(move, async c =>
{
await GuardAsset.CanMove(c, Snapshot, assetQuery);
Move(c);
await MoveCore(c);
return Snapshot;
});
case DeleteAsset deleteAsset:
return UpdateAsync(deleteAsset, async c =>
case DeleteAsset delete when (delete.Permanent):
return DeletePermanentAsync(delete, async c =>
{
await GuardAsset.CanDelete(c, Snapshot, contentRepository);
await assetTags.NormalizeTagsAsync(Snapshot.AppId.Id, TagGroups.Assets, null, Snapshot.Tags);
await DeleteCore(c);
});
Delete(c);
case DeleteAsset delete:
return UpdateAsync(delete, async c =>
{
await DeleteCore(c);
});
default:
throw new NotSupportedException();
}
}
private async Task<HashSet<string>> NormalizeTagsAsync(DomainId appId, HashSet<string> tags)
private async Task CreateCore(CreateAsset create)
{
GuardAsset.CanCreate(create);
if (create.Tags != null)
{
create.Tags = await NormalizeTagsAsync(create.AppId.Id, create.Tags);
}
Create(create);
}
private async Task MoveCore(MoveAsset move)
{
await GuardAsset.CanMove(move, Snapshot, assetQuery);
Move(move);
}
private void UpdateCore(UpdateAsset update)
{
GuardAsset.CanUpdate(update);
Update(update);
}
private async Task DeleteCore(DeleteAsset delete)
{
await GuardAsset.CanDelete(delete, Snapshot, contentRepository);
await NormalizeTagsAsync(Snapshot.AppId.Id, null);
Delete(delete);
}
private async Task<HashSet<string>> NormalizeTagsAsync(DomainId appId, HashSet<string>? tags)
{
var normalized = await assetTags.NormalizeTagsAsync(appId, TagGroups.Assets, tags, Snapshot.Tags);
return new HashSet<string>(normalized.Values);
}
public void Create(CreateAsset command)
private void Create(CreateAsset command)
{
Raise(command, new AssetCreated
{
@ -149,7 +207,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
});
}
public void Update(UpdateAsset command)
private void Update(UpdateAsset command)
{
Raise(command, new AssetUpdated
{
@ -159,28 +217,24 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
});
}
public void Annotate(AnnotateAsset command)
private void Annotate(AnnotateAsset command)
{
Raise(command, new AssetAnnotated());
}
public void Move(MoveAsset command)
private void Move(MoveAsset command)
{
Raise(command, new AssetMoved());
}
public void Delete(DeleteAsset command)
private void Delete(DeleteAsset command)
{
Raise(command, new AssetDeleted { DeletedSize = Snapshot.TotalSize });
}
private void Raise<T, TEvent>(T command, TEvent @event) where T : class where TEvent : AppEvent
{
SimpleMapper.Map(command, @event);
@event.AppId ??= Snapshot.AppId;
RaiseEvent(Envelope.Create(@event));
RaiseEvent(Envelope.Create(SimpleMapper.Map(command, @event)));
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetDomainObjectGrain.cs

@ -34,7 +34,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{
await DomainObject.EnsureLoadedAsync();
return DomainObject.GetSnapshot(version);
return await DomainObject.GetSnapshotAsync(version);
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetFolderDomainObject.State.cs

@ -27,7 +27,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
[IgnoreDataMember]
public DomainId UniqueId
{
get { return DomainId.Combine(AppId, Id); }
get => DomainId.Combine(AppId, Id);
}
public override bool ApplyEvent(IEvent @event)

36
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetFolderDomainObject.cs

@ -50,22 +50,22 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
Equals(assetFolderCommand.AssetFolderId, Snapshot.Id);
}
public override Task<object?> ExecuteAsync(IAggregateCommand command)
public override Task<CommandResult> ExecuteAsync(IAggregateCommand command)
{
switch (command)
{
case CreateAssetFolder createAssetFolder:
return CreateReturnAsync(createAssetFolder, async c =>
case CreateAssetFolder c:
return CreateReturnAsync(c, async create =>
{
await GuardAssetFolder.CanCreate(c, assetQuery);
await GuardAssetFolder.CanCreate(create, assetQuery);
Create(c);
Create(create);
return Snapshot;
});
case MoveAssetFolder moveAssetFolder:
return UpdateReturnAsync(moveAssetFolder, async c =>
case MoveAssetFolder move:
return UpdateReturnAsync(move, async c =>
{
await GuardAssetFolder.CanMove(c, Snapshot, assetQuery);
@ -74,8 +74,8 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
return Snapshot;
});
case RenameAssetFolder renameAssetFolder:
return UpdateReturn(renameAssetFolder, c =>
case RenameAssetFolder rename:
return UpdateReturn(rename, c =>
{
GuardAssetFolder.CanRename(c);
@ -84,8 +84,8 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
return Snapshot;
});
case DeleteAssetFolder deleteAssetFolder:
return Update(deleteAssetFolder, c =>
case DeleteAssetFolder delete:
return Update(delete, c =>
{
GuardAssetFolder.CanDelete(c);
@ -97,33 +97,29 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
}
}
public void Create(CreateAssetFolder command)
private void Create(CreateAssetFolder command)
{
Raise(command, new AssetFolderCreated());
}
public void Move(MoveAssetFolder command)
private void Move(MoveAssetFolder command)
{
Raise(command, new AssetFolderMoved());
}
public void Rename(RenameAssetFolder command)
private void Rename(RenameAssetFolder command)
{
Raise(command, new AssetFolderRenamed());
}
public void Delete(DeleteAssetFolder command)
private void Delete(DeleteAssetFolder command)
{
Raise(command, new AssetFolderDeleted());
}
private void Raise<T, TEvent>(T command, TEvent @event) where T : class where TEvent : AppEvent
{
SimpleMapper.Map(command, @event);
@event.AppId ??= Snapshot.AppId;
RaiseEvent(Envelope.Create(@event));
RaiseEvent(Envelope.Create(SimpleMapper.Map(command, @event)));
}
}
}

117
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetFolderResolver.cs

@ -0,0 +1,117 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Caching;
using Squidex.Domain.Apps.Entities.Assets.Commands;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{
public sealed class AssetFolderResolver : IAssetFolderResolver
{
private static readonly char[] TrimChars = { '/', '\\' };
private static readonly char[] SplitChars = { ' ', '/', '\\' };
private readonly ILocalCache localCache;
private readonly IAssetQueryService assetQuery;
public AssetFolderResolver(ILocalCache localCache, IAssetQueryService assetQuery)
{
Guard.NotNull(localCache, nameof(localCache));
Guard.NotNull(assetQuery, nameof(assetQuery));
this.localCache = localCache;
this.assetQuery = assetQuery;
}
public async Task<DomainId> ResolveOrCreateAsync(Context context, ICommandBus commandBus, string path)
{
Guard.NotNull(commandBus, nameof(commandBus));
Guard.NotNull(path, nameof(path));
path = path.Trim(TrimChars);
var elements = path.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries);
if (elements.Length == 0)
{
return DomainId.Empty;
}
var currentId = DomainId.Empty;
var i = elements.Length;
for (; i > 0; i--)
{
var subPath = string.Join('/', elements.Take(i));
if (localCache.TryGetValue(GetCacheKey(subPath), out var cached) && cached is DomainId id)
{
currentId = id;
break;
}
}
var creating = false;
for (; i < elements.Length; i++)
{
var name = elements[i];
var isResolved = false;
if (!creating)
{
var children = await assetQuery.QueryAssetFoldersAsync(context, currentId);
foreach (var child in children)
{
var childPath = string.Join('/', elements.Take(i).Union(Enumerable.Repeat(child.FolderName, 1)));
localCache.Add(GetCacheKey(childPath), child.Id);
}
foreach (var child in children)
{
if (child.FolderName == name)
{
currentId = child.Id;
isResolved = true;
break;
}
}
}
if (!isResolved)
{
var command = new CreateAssetFolder { ParentId = currentId, FolderName = name };
await commandBus.PublishAsync(command);
currentId = command.AssetFolderId;
creating = true;
}
var newPath = string.Join('/', elements.Take(i).Union(Enumerable.Repeat(name, 1)));
localCache.Add(GetCacheKey(newPath), currentId);
}
return currentId;
}
private static object GetCacheKey(string path)
{
return $"ASSET_FOLDERS_{path}";
}
}
}

210
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetsBulkUpdateCommandMiddleware.cs

@ -0,0 +1,210 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using Squidex.Domain.Apps.Entities.Assets.Commands;
using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Reflection;
using Squidex.Shared;
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
#pragma warning disable RECS0082 // Parameter has the same name as a member and hides it
namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{
public sealed class AssetsBulkUpdateCommandMiddleware : ICommandMiddleware
{
private readonly IContextProvider contextProvider;
private sealed record BulkTaskCommand(BulkTask Task, DomainId Id, ICommand Command)
{
}
private sealed record BulkTask(
ICommandBus Bus,
int JobIndex,
BulkUpdateJob Job,
BulkUpdateAssets Command,
ConcurrentBag<BulkUpdateResultItem> Results
)
{
}
public AssetsBulkUpdateCommandMiddleware(IContextProvider contextProvider)
{
Guard.NotNull(contextProvider, nameof(contextProvider));
this.contextProvider = contextProvider;
}
public async Task HandleAsync(CommandContext context, NextDelegate next)
{
if (context.Command is BulkUpdateAssets bulkUpdates)
{
if (bulkUpdates.Jobs?.Length > 0)
{
var executionOptions = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount / 2)
};
var createCommandsBlock = new TransformBlock<BulkTask, BulkTaskCommand?>(task =>
{
return CreateCommand(task);
}, executionOptions);
var executeCommandBlock = new ActionBlock<BulkTaskCommand?>(async command =>
{
if (command != null)
{
await ExecuteCommandAsync(command);
}
}, executionOptions);
createCommandsBlock.LinkTo(executeCommandBlock, new DataflowLinkOptions
{
PropagateCompletion = true
});
contextProvider.Context.Change(b => b
.WithoutAssetEnrichment()
.WithoutCleanup()
.WithUnpublished(true)
.WithoutTotal());
var results = new ConcurrentBag<BulkUpdateResultItem>();
for (var i = 0; i < bulkUpdates.Jobs.Length; i++)
{
var task = new BulkTask(
context.CommandBus,
i,
bulkUpdates.Jobs[i],
bulkUpdates,
results);
await createCommandsBlock.SendAsync(task);
}
createCommandsBlock.Complete();
await executeCommandBlock.Completion;
context.Complete(new BulkUpdateResult(results));
}
else
{
context.Complete(new BulkUpdateResult());
}
}
else
{
await next(context);
}
}
private static async Task ExecuteCommandAsync(BulkTaskCommand bulkCommand)
{
var (task, id, command) = bulkCommand;
Exception? exception = null;
try
{
await task.Bus.PublishAsync(command);
}
catch (Exception ex)
{
exception = ex;
}
task.Results.Add(new BulkUpdateResultItem
{
Id = id,
JobIndex = task.JobIndex,
Exception = exception
});
}
private BulkTaskCommand? CreateCommand(BulkTask task)
{
var id = task.Job.Id;
try
{
var command = CreateCommandCore(task);
command.AssetId = id;
return new BulkTaskCommand(task, id, command);
}
catch (Exception ex)
{
task.Results.Add(new BulkUpdateResultItem
{
Id = id,
JobIndex = task.JobIndex,
Exception = ex
});
return null;
}
}
private AssetCommand CreateCommandCore(BulkTask task)
{
var job = task.Job;
switch (job.Type)
{
case BulkUpdateAssetType.Annotate:
{
var command = new AnnotateAsset();
Enrich(task, command, Permissions.AppAssetsUpdate);
return command;
}
case BulkUpdateAssetType.Move:
{
var command = new MoveAsset();
Enrich(task, command, Permissions.AppAssetsUpdate);
return command;
}
case BulkUpdateAssetType.Delete:
{
var command = new DeleteAsset();
Enrich(task, command, Permissions.AppAssetsDelete);
return command;
}
default:
throw new NotSupportedException();
}
}
private void Enrich<T>(BulkTask task, T command, string permissionId) where T : AssetCommand
{
SimpleMapper.Map(task.Command, command);
SimpleMapper.Map(task.Job, command);
if (!contextProvider.Context.Allows(permissionId))
{
throw new DomainForbiddenException("Forbidden");
}
command.ExpectedVersion = task.Command.ExpectedVersion;
}
}
}

7
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/Guards/GuardAsset.cs

@ -22,14 +22,9 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
Guard.NotNull(command, nameof(command));
}
public static Task CanCreate(CreateAsset command, IAssetQueryService assetQuery)
public static void CanCreate(CreateAsset command)
{
Guard.NotNull(command, nameof(command));
return Validate.It(async e =>
{
await CheckPathAsync(command.AppId.Id, command.ParentId, assetQuery, e);
});
}
public static Task CanMove(MoveAsset command, IAssetEntity asset, IAssetQueryService assetQuery)

18
backend/src/Squidex.Infrastructure/EventSourcing/DefaultEventEnricher.cs → backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/IAssetFolderResolver.cs

@ -5,16 +5,14 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
namespace Squidex.Infrastructure.EventSourcing
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{
public class DefaultEventEnricher<TKey> : IEventEnricher<TKey>
public interface IAssetFolderResolver
{
public virtual void Enrich(Envelope<IEvent> @event, TKey key)
{
if (key is DomainId domainId)
{
@event.SetAggregateId(domainId);
}
}
Task<DomainId> ResolveOrCreateAsync(Context context, ICommandBus commandBus, string path);
}
}
}

19
backend/src/Squidex.Domain.Apps.Entities/Assets/FileTagAssetMetadataSource.cs

@ -28,12 +28,12 @@ namespace Squidex.Domain.Apps.Entities.Assets
public string Name
{
get { return file.FileName; }
get => file.FileName;
}
public Stream ReadStream
{
get { return file.OpenRead(); }
get => file.OpenRead();
}
public Stream WriteStream
@ -52,14 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
}
}
public Task EnhanceAsync(UploadAssetCommand command, HashSet<string>? tags)
{
Enhance(command);
return Task.CompletedTask;
}
private static void Enhance(UploadAssetCommand command)
public Task EnhanceAsync(UploadAssetCommand command)
{
try
{
@ -67,7 +60,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
{
if (file.Properties == null)
{
return;
return Task.CompletedTask;
}
var type = file.Properties.MediaTypes;
@ -146,10 +139,12 @@ namespace Squidex.Domain.Apps.Entities.Assets
TryAddString("description", file.Properties.Description);
}
return Task.CompletedTask;
}
catch
{
return;
return Task.CompletedTask;
}
}

6
backend/src/Squidex.Domain.Apps.Entities/Assets/FileTypeAssetMetadataSource.cs

@ -14,15 +14,15 @@ namespace Squidex.Domain.Apps.Entities.Assets
{
public sealed class FileTypeAssetMetadataSource : IAssetMetadataSource
{
public Task EnhanceAsync(UploadAssetCommand command, HashSet<string>? tags)
public Task EnhanceAsync(UploadAssetCommand command)
{
if (tags != null)
if (command.Tags != null)
{
var extension = command.File?.FileName?.FileType();
if (!string.IsNullOrWhiteSpace(extension))
{
tags.Add($"type/{extension.ToLowerInvariant()}");
command.Tags.Add($"type/{extension.ToLowerInvariant()}");
}
}

2
backend/src/Squidex.Domain.Apps.Entities/Assets/IAssetMetadataSource.cs

@ -13,7 +13,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
{
public interface IAssetMetadataSource
{
Task EnhanceAsync(UploadAssetCommand command, HashSet<string>? tags);
Task EnhanceAsync(UploadAssetCommand command);
IEnumerable<string> Format(IAssetEntity asset);
}

12
backend/src/Squidex.Domain.Apps.Entities/Assets/ImageAssetMetadataSource.cs

@ -58,7 +58,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
}
}
public async Task EnhanceAsync(UploadAssetCommand command, HashSet<string>? tags)
public async Task EnhanceAsync(UploadAssetCommand command)
{
if (command.Type == AssetType.Unknown || command.Type == AssetType.Image)
{
@ -96,23 +96,23 @@ namespace Squidex.Domain.Apps.Entities.Assets
}
}
if (command.Type == AssetType.Image && tags != null)
if (command.Type == AssetType.Image && command.Tags != null)
{
tags.Add("image");
command.Tags.Add("image");
var wh = command.Metadata.GetPixelWidth() + command.Metadata.GetPixelWidth();
if (wh > 2000)
{
tags.Add("image/large");
command.Tags.Add("image/large");
}
else if (wh > 1000)
{
tags.Add("image/medium");
command.Tags.Add("image/medium");
}
else
{
tags.Add("image/small");
command.Tags.Add("image/small");
}
}
}

4
backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs

@ -28,12 +28,12 @@ namespace Squidex.Domain.Apps.Entities.Assets
public string Name
{
get { return GetType().Name; }
get => GetType().Name;
}
public string EventsFilter
{
get { return "^assetFolder-"; }
get => "^assetFolder-";
}
public RecursiveDeleter(

2
backend/src/Squidex.Domain.Apps.Entities/Backup/BackupContextBase.cs

@ -17,7 +17,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
public RefToken Initiator
{
get { return UserMapping.Initiator; }
get => UserMapping.Initiator;
}
protected BackupContextBase(DomainId appId, IUserMapping userMapping)

2
backend/src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs

@ -85,7 +85,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
private async Task RecoverAfterRestartAsync()
{
state.Value.Jobs.RemoveAll(x => !x.Stopped.HasValue);
state.Value.Jobs.RemoveAll(x => x.Stopped == null);
await state.WriteAsync();
}

4
backend/src/Squidex.Domain.Apps.Entities/Backup/BackupReader.cs

@ -27,12 +27,12 @@ namespace Squidex.Domain.Apps.Entities.Backup
public int ReadEvents
{
get { return readEvents; }
get => readEvents;
}
public int ReadAttachments
{
get { return readAttachments; }
get => readAttachments;
}
public BackupReader(IJsonSerializer serializer, Stream stream)

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save