mirror of https://github.com/Squidex/squidex.git
Browse Source
# Conflicts: # src/Squidex.Domain.Apps.Entities.MongoDb/History/ParsedHistoryEvent.cs # src/Squidex.Domain.Apps.Entities/Apps/AppHistoryEventsCreator.cspull/285/head
167 changed files with 2956 additions and 1493 deletions
@ -1,44 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using Squidex.Domain.Apps.Entities.Apps.State; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Apps |
|||
{ |
|||
public sealed class MongoAppEntity : IVersionedEntity<Guid> |
|||
{ |
|||
[BsonId] |
|||
[BsonElement] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid Id { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonJson] |
|||
public AppState State { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public long Version { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public string Name { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public string[] UserIds { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonIgnoreIfDefault] |
|||
public bool IsArchived { get; set; } |
|||
} |
|||
} |
|||
@ -1,64 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Apps.Repositories; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Apps |
|||
{ |
|||
public sealed partial class MongoAppRepository : MongoRepositoryBase<MongoAppEntity>, IAppRepository |
|||
{ |
|||
public MongoAppRepository(IMongoDatabase database) |
|||
: base(database) |
|||
{ |
|||
} |
|||
|
|||
protected override string CollectionName() |
|||
{ |
|||
return "States_Apps"; |
|||
} |
|||
|
|||
protected override async Task SetupCollectionAsync(IMongoCollection<MongoAppEntity> collection) |
|||
{ |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.UserIds)); |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.Name)); |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<Guid>> QueryAppIdsAsync() |
|||
{ |
|||
var appEntities = |
|||
await Collection.Find(new BsonDocument()).Only(x => x.Id) |
|||
.ToListAsync(); |
|||
|
|||
return appEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<Guid>> QueryUserAppIdsAsync(string userId) |
|||
{ |
|||
var appEntities = |
|||
await Collection.Find(x => x.UserIds.Contains(userId) && x.IsArchived != true).Only(x => x.Id) |
|||
.ToListAsync(); |
|||
|
|||
return appEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); |
|||
} |
|||
|
|||
public async Task<Guid> FindAppIdByNameAsync(string name) |
|||
{ |
|||
var appEntity = |
|||
await Collection.Find(x => x.Name == name && x.IsArchived != true).Only(x => x.Id) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
return appEntity != null ? Guid.Parse(appEntity["_id"].AsString) : Guid.Empty; |
|||
} |
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Apps.State; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Apps |
|||
{ |
|||
public sealed partial class MongoAppRepository : ISnapshotStore<AppState, Guid> |
|||
{ |
|||
public async Task<(AppState Value, long Version)> ReadAsync(Guid key) |
|||
{ |
|||
var existing = |
|||
await Collection.Find(x => x.Id == key) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
if (existing != null) |
|||
{ |
|||
return (existing.State, existing.Version); |
|||
} |
|||
|
|||
return (null, EtagVersion.NotFound); |
|||
} |
|||
|
|||
public Task WriteAsync(Guid key, AppState value, long oldVersion, long newVersion) |
|||
{ |
|||
return Collection.UpsertVersionedAsync(key, oldVersion, newVersion, u => u |
|||
.Set(x => x.Name, value.Name) |
|||
.Set(x => x.State, value) |
|||
.Set(x => x.UserIds, value.Contributors.Keys.ToArray()) |
|||
.Set(x => x.IsArchived, value.IsArchived)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,41 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using Squidex.Domain.Apps.Entities.Rules.State; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Rules |
|||
{ |
|||
public sealed class MongoRuleEntity : IVersionedEntity<Guid> |
|||
{ |
|||
[BsonId] |
|||
[BsonElement] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid Id { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid AppId { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonJson] |
|||
public RuleState State { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public long Version { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public bool IsDeleted { get; set; } |
|||
} |
|||
} |
|||
@ -1,45 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Rules.Repositories; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Rules |
|||
{ |
|||
public sealed partial class MongoRuleRepository : MongoRepositoryBase<MongoRuleEntity>, IRuleRepository |
|||
{ |
|||
public MongoRuleRepository(IMongoDatabase database) |
|||
: base(database) |
|||
{ |
|||
} |
|||
|
|||
protected override string CollectionName() |
|||
{ |
|||
return "States_Rules"; |
|||
} |
|||
|
|||
protected override async Task SetupCollectionAsync(IMongoCollection<MongoRuleEntity> collection) |
|||
{ |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.AppId)); |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.IsDeleted)); |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<Guid>> QueryRuleIdsAsync(Guid appId) |
|||
{ |
|||
var ruleEntities = |
|||
await Collection.Find(x => x.AppId == appId && !x.IsDeleted).Only(x => x.Id) |
|||
.ToListAsync(); |
|||
|
|||
return ruleEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,42 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Rules.State; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Rules |
|||
{ |
|||
public sealed partial class MongoRuleRepository : ISnapshotStore<RuleState, Guid> |
|||
{ |
|||
public async Task<(RuleState Value, long Version)> ReadAsync(Guid key) |
|||
{ |
|||
var existing = |
|||
await Collection.Find(x => x.Id == key) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
if (existing != null) |
|||
{ |
|||
return (existing.State, existing.Version); |
|||
} |
|||
|
|||
return (null, EtagVersion.NotFound); |
|||
} |
|||
|
|||
public Task WriteAsync(Guid key, RuleState value, long oldVersion, long newVersion) |
|||
{ |
|||
return Collection.UpsertVersionedAsync(key, oldVersion, newVersion, u => u |
|||
.Set(x => x.State, value) |
|||
.Set(x => x.AppId, value.AppId.Id) |
|||
.Set(x => x.IsDeleted, value.IsDeleted)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,45 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using Squidex.Domain.Apps.Entities.Schemas.State; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas |
|||
{ |
|||
public sealed class MongoSchemaEntity : IVersionedEntity<Guid> |
|||
{ |
|||
[BsonId] |
|||
[BsonElement] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid Id { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid AppId { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonJson] |
|||
public SchemaState State { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public string Name { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public long Version { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public bool IsDeleted { get; set; } |
|||
} |
|||
} |
|||
@ -1,54 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Schemas.Repositories; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas |
|||
{ |
|||
public sealed partial class MongoSchemaRepository : MongoRepositoryBase<MongoSchemaEntity>, ISchemaRepository |
|||
{ |
|||
public MongoSchemaRepository(IMongoDatabase database) |
|||
: base(database) |
|||
{ |
|||
} |
|||
|
|||
protected override string CollectionName() |
|||
{ |
|||
return "States_Schemas"; |
|||
} |
|||
|
|||
protected override async Task SetupCollectionAsync(IMongoCollection<MongoSchemaEntity> collection) |
|||
{ |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.AppId).Ascending(x => x.IsDeleted)); |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.AppId).Ascending(x => x.Name).Ascending(x => x.IsDeleted)); |
|||
} |
|||
|
|||
public async Task<Guid> FindSchemaIdAsync(Guid appId, string name) |
|||
{ |
|||
var schemaEntity = |
|||
await Collection.Find(x => x.AppId == appId && x.Name == name && !x.IsDeleted).Only(x => x.Id).SortByDescending(x => x.Version) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
return schemaEntity != null ? Guid.Parse(schemaEntity["_id"].AsString) : Guid.Empty; |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<Guid>> QuerySchemaIdsAsync(Guid appId) |
|||
{ |
|||
var schemaEntities = |
|||
await Collection.Find(x => x.AppId == appId && !x.IsDeleted).Only(x => x.Id) |
|||
.ToListAsync(); |
|||
|
|||
return schemaEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,43 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Schemas.State; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas |
|||
{ |
|||
public sealed partial class MongoSchemaRepository : ISnapshotStore<SchemaState, Guid> |
|||
{ |
|||
public async Task<(SchemaState Value, long Version)> ReadAsync(Guid key) |
|||
{ |
|||
var existing = |
|||
await Collection.Find(x => x.Id == key) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
if (existing != null) |
|||
{ |
|||
return (existing.State, existing.Version); |
|||
} |
|||
|
|||
return (null, EtagVersion.NotFound); |
|||
} |
|||
|
|||
public Task WriteAsync(Guid key, SchemaState value, long oldVersion, long newVersion) |
|||
{ |
|||
return Collection.UpsertVersionedAsync(key, oldVersion, newVersion, u => u |
|||
.Set(x => x.State, value) |
|||
.Set(x => x.AppId, value.AppId.Id) |
|||
.Set(x => x.Name, value.Name) |
|||
.Set(x => x.IsDeleted, value.IsDeleted)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
using Squidex.Domain.Apps.Entities.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Squidex.Infrastructure.Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps.Indexes |
|||
{ |
|||
public sealed class AppsByNameIndexCommandMiddleware : ICommandMiddleware |
|||
{ |
|||
private readonly IAppsByNameIndex index; |
|||
|
|||
public AppsByNameIndexCommandMiddleware(IGrainFactory grainFactory) |
|||
{ |
|||
Guard.NotNull(grainFactory, nameof(grainFactory)); |
|||
|
|||
index = grainFactory.GetGrain<IAppsByNameIndex>(SingleGrain.Id); |
|||
} |
|||
|
|||
public async Task HandleAsync(CommandContext context, Func<Task> next) |
|||
{ |
|||
if (context.IsCompleted) |
|||
{ |
|||
switch (context.Command) |
|||
{ |
|||
case CreateApp createApp: |
|||
await index.AddAppAsync(createApp.AppId, createApp.Name); |
|||
break; |
|||
case ArchiveApp archiveApp: |
|||
await index.RemoveAppAsync(archiveApp.AppId); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
await next(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Orleans; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps.Indexes |
|||
{ |
|||
public sealed class AppsByNameIndexGrain : GrainOfString, IAppsByNameIndex |
|||
{ |
|||
private readonly IStore<string> store; |
|||
private IPersistence<State> persistence; |
|||
private State state = new State(); |
|||
|
|||
[CollectionName("Index_AppsByName")] |
|||
public sealed class State |
|||
{ |
|||
public Dictionary<string, Guid> Apps { get; set; } = new Dictionary<string, Guid>(); |
|||
} |
|||
|
|||
public AppsByNameIndexGrain(IStore<string> store) |
|||
{ |
|||
Guard.NotNull(store, nameof(store)); |
|||
|
|||
this.store = store; |
|||
} |
|||
|
|||
public override Task OnActivateAsync(string key) |
|||
{ |
|||
persistence = store.WithSnapshots<AppsByNameIndexGrain, State, string>(key, s => |
|||
{ |
|||
state = s; |
|||
}); |
|||
|
|||
return persistence.ReadAsync(); |
|||
} |
|||
|
|||
public Task RebuildAsync(Dictionary<string, Guid> apps) |
|||
{ |
|||
state = new State { Apps = apps }; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task AddAppAsync(Guid appId, string name) |
|||
{ |
|||
state.Apps[name] = appId; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task RemoveAppAsync(Guid appId) |
|||
{ |
|||
state.Apps.Remove(state.Apps.FirstOrDefault(x => x.Value == appId).Key ?? string.Empty); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task<Guid> GetAppIdAsync(string appName) |
|||
{ |
|||
state.Apps.TryGetValue(appName, out var appId); |
|||
|
|||
return Task.FromResult(appId); |
|||
} |
|||
|
|||
public Task<List<Guid>> GetAppIdsAsync() |
|||
{ |
|||
return Task.FromResult(state.Apps.Values.ToList()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
using Squidex.Domain.Apps.Entities.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps.Indexes |
|||
{ |
|||
public sealed class AppsByUserIndexCommandMiddleware : ICommandMiddleware |
|||
{ |
|||
private readonly IGrainFactory grainFactory; |
|||
|
|||
public AppsByUserIndexCommandMiddleware(IGrainFactory grainFactory) |
|||
{ |
|||
Guard.NotNull(grainFactory, nameof(grainFactory)); |
|||
|
|||
this.grainFactory = grainFactory; |
|||
} |
|||
|
|||
public async Task HandleAsync(CommandContext context, Func<Task> next) |
|||
{ |
|||
if (context.IsCompleted) |
|||
{ |
|||
switch (context.Command) |
|||
{ |
|||
case CreateApp createApp: |
|||
await Index(GetUserId(createApp)).AddAppAsync(createApp.AppId); |
|||
break; |
|||
case AssignContributor assignContributor: |
|||
await Index(GetUserId(context)).AddAppAsync(assignContributor.AppId); |
|||
break; |
|||
case RemoveContributor removeContributor: |
|||
await Index(GetUserId(removeContributor)).RemoveAppAsync(removeContributor.AppId); |
|||
break; |
|||
case ArchiveApp archiveApp: |
|||
{ |
|||
var appState = await grainFactory.GetGrain<IAppGrain>(archiveApp.AppId).GetStateAsync(); |
|||
|
|||
foreach (var contributorId in appState.Value.Contributors.Keys) |
|||
{ |
|||
await Index(contributorId).RemoveAppAsync(archiveApp.AppId); |
|||
} |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
await next(); |
|||
} |
|||
|
|||
private static string GetUserId(RemoveContributor removeContributor) |
|||
{ |
|||
return removeContributor.ContributorId; |
|||
} |
|||
|
|||
private static string GetUserId(CreateApp createApp) |
|||
{ |
|||
return createApp.Actor.Identifier; |
|||
} |
|||
|
|||
private static string GetUserId(CommandContext context) |
|||
{ |
|||
return context.Result<EntityCreatedResult<string>>().IdOrValue; |
|||
} |
|||
|
|||
private IAppsByUserIndex Index(string id) |
|||
{ |
|||
return grainFactory.GetGrain<IAppsByUserIndex>(id); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Orleans; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps.Indexes |
|||
{ |
|||
public sealed class AppsByUserIndexGrain : GrainOfString, IAppsByUserIndex |
|||
{ |
|||
private readonly IStore<string> store; |
|||
private IPersistence<State> persistence; |
|||
private State state = new State(); |
|||
|
|||
[CollectionName("Index_AppsByUser")] |
|||
public sealed class State |
|||
{ |
|||
public HashSet<Guid> Apps { get; set; } = new HashSet<Guid>(); |
|||
} |
|||
|
|||
public AppsByUserIndexGrain(IStore<string> store) |
|||
{ |
|||
Guard.NotNull(store, nameof(store)); |
|||
|
|||
this.store = store; |
|||
} |
|||
|
|||
public override Task OnActivateAsync(string key) |
|||
{ |
|||
persistence = store.WithSnapshots<AppsByUserIndexGrain, State, string>(key, s => |
|||
{ |
|||
state = s; |
|||
}); |
|||
|
|||
return persistence.ReadAsync(); |
|||
} |
|||
|
|||
public Task RebuildAsync(HashSet<Guid> apps) |
|||
{ |
|||
state = new State { Apps = apps }; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task AddAppAsync(Guid appId) |
|||
{ |
|||
state.Apps.Add(appId); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task RemoveAppAsync(Guid appId) |
|||
{ |
|||
state.Apps.Remove(appId); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task<List<Guid>> GetAppIdsAsync() |
|||
{ |
|||
return Task.FromResult(state.Apps.ToList()); |
|||
} |
|||
} |
|||
} |
|||
@ -1,18 +1,27 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Rules.Repositories |
|||
namespace Squidex.Domain.Apps.Entities.Apps |
|||
{ |
|||
public interface IRuleRepository |
|||
public interface IAppsByNameIndex : IGrainWithStringKey |
|||
{ |
|||
Task<IReadOnlyList<Guid>> QueryRuleIdsAsync(Guid appId); |
|||
Task AddAppAsync(Guid appId, string name); |
|||
|
|||
Task RemoveAppAsync(Guid appId); |
|||
|
|||
Task RebuildAsync(Dictionary<string, Guid> apps); |
|||
|
|||
Task<Guid> GetAppIdAsync(string name); |
|||
|
|||
Task<List<Guid>> GetAppIdsAsync(); |
|||
} |
|||
} |
|||
@ -1,22 +1,25 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps.Repositories |
|||
namespace Squidex.Domain.Apps.Entities.Apps |
|||
{ |
|||
public interface IAppRepository |
|||
public interface IAppsByUserIndex : IGrainWithStringKey |
|||
{ |
|||
Task<Guid> FindAppIdByNameAsync(string name); |
|||
Task AddAppAsync(Guid appId); |
|||
|
|||
Task<IReadOnlyList<Guid>> QueryAppIdsAsync(); |
|||
Task RemoveAppAsync(Guid appId); |
|||
|
|||
Task<IReadOnlyList<Guid>> QueryUserAppIdsAsync(string userId); |
|||
Task RebuildAsync(HashSet<Guid> apps); |
|||
|
|||
Task<List<Guid>> GetAppIdsAsync(); |
|||
} |
|||
} |
|||
@ -1,20 +1,25 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Schemas.Repositories |
|||
namespace Squidex.Domain.Apps.Entities.Rules |
|||
{ |
|||
public interface ISchemaRepository |
|||
public interface IRulesByAppIndex : IGrainWithGuidKey |
|||
{ |
|||
Task<Guid> FindSchemaIdAsync(Guid appId, string name); |
|||
Task AddRuleAsync(Guid ruleId); |
|||
|
|||
Task<IReadOnlyList<Guid>> QuerySchemaIdsAsync(Guid appId); |
|||
Task RemoveRuleAsync(Guid ruleId); |
|||
|
|||
Task RebuildAsync(HashSet<Guid> rules); |
|||
|
|||
Task<List<Guid>> GetRuleIdsAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
using Squidex.Domain.Apps.Entities.Rules.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Rules.Indexes |
|||
{ |
|||
public sealed class RulesByAppIndexCommandMiddleware : ICommandMiddleware |
|||
{ |
|||
private readonly IGrainFactory grainFactory; |
|||
|
|||
public RulesByAppIndexCommandMiddleware(IGrainFactory grainFactory) |
|||
{ |
|||
Guard.NotNull(grainFactory, nameof(grainFactory)); |
|||
|
|||
this.grainFactory = grainFactory; |
|||
} |
|||
|
|||
public async Task HandleAsync(CommandContext context, Func<Task> next) |
|||
{ |
|||
if (context.IsCompleted) |
|||
{ |
|||
switch (context.Command) |
|||
{ |
|||
case CreateRule createRule: |
|||
await Index(createRule.AppId.Id).AddRuleAsync(createRule.RuleId); |
|||
break; |
|||
case DeleteRule deleteRule: |
|||
{ |
|||
var schema = await grainFactory.GetGrain<IRuleGrain>(deleteRule.RuleId).GetStateAsync(); |
|||
|
|||
await Index(schema.Value.AppId.Id).RemoveRuleAsync(deleteRule.RuleId); |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
await next(); |
|||
} |
|||
|
|||
private IRulesByAppIndex Index(Guid appId) |
|||
{ |
|||
return grainFactory.GetGrain<IRulesByAppIndex>(appId); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Orleans; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Rules.Indexes |
|||
{ |
|||
public sealed class RulesByAppIndexGrain : GrainOfGuid, IRulesByAppIndex |
|||
{ |
|||
private readonly IStore<Guid> store; |
|||
private IPersistence<State> persistence; |
|||
private State state = new State(); |
|||
|
|||
[CollectionName("Index_RulesByApp")] |
|||
public sealed class State |
|||
{ |
|||
public HashSet<Guid> Rules { get; set; } = new HashSet<Guid>(); |
|||
} |
|||
|
|||
public RulesByAppIndexGrain(IStore<Guid> store) |
|||
{ |
|||
Guard.NotNull(store, nameof(store)); |
|||
|
|||
this.store = store; |
|||
} |
|||
|
|||
public override Task OnActivateAsync(Guid key) |
|||
{ |
|||
persistence = store.WithSnapshots<RulesByAppIndexGrain, State, Guid>(key, s => |
|||
{ |
|||
state = s; |
|||
}); |
|||
|
|||
return persistence.ReadAsync(); |
|||
} |
|||
|
|||
public Task RebuildAsync(HashSet<Guid> rules) |
|||
{ |
|||
state = new State { Rules = rules }; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task AddRuleAsync(Guid ruleId) |
|||
{ |
|||
state.Rules.Add(ruleId); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task RemoveRuleAsync(Guid ruleId) |
|||
{ |
|||
state.Rules.Remove(ruleId); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task<List<Guid>> GetRuleIdsAsync() |
|||
{ |
|||
return Task.FromResult(state.Rules.ToList()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Schemas |
|||
{ |
|||
public interface ISchemasByAppIndex : IGrainWithGuidKey |
|||
{ |
|||
Task AddSchemaAsync(Guid schemaId, string name); |
|||
|
|||
Task RemoveSchemaAsync(Guid schemaId); |
|||
|
|||
Task RebuildAsync(Dictionary<string, Guid> schemas); |
|||
|
|||
Task<Guid> GetSchemaIdAsync(string name); |
|||
|
|||
Task<List<Guid>> GetSchemaIdsAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
using Squidex.Domain.Apps.Entities.Schemas.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Schemas.Indexes |
|||
{ |
|||
public sealed class SchemasByAppIndexCommandMiddleware : ICommandMiddleware |
|||
{ |
|||
private readonly IGrainFactory grainFactory; |
|||
|
|||
public SchemasByAppIndexCommandMiddleware(IGrainFactory grainFactory) |
|||
{ |
|||
Guard.NotNull(grainFactory, nameof(grainFactory)); |
|||
|
|||
this.grainFactory = grainFactory; |
|||
} |
|||
|
|||
public async Task HandleAsync(CommandContext context, Func<Task> next) |
|||
{ |
|||
if (context.IsCompleted) |
|||
{ |
|||
switch (context.Command) |
|||
{ |
|||
case CreateSchema createSchema: |
|||
await Index(createSchema.AppId.Id).AddSchemaAsync(createSchema.SchemaId, createSchema.Name); |
|||
break; |
|||
case DeleteSchema deleteSchema: |
|||
{ |
|||
var schema = await grainFactory.GetGrain<ISchemaGrain>(deleteSchema.SchemaId).GetStateAsync(); |
|||
|
|||
await Index(schema.Value.AppId.Id).RemoveSchemaAsync(deleteSchema.SchemaId); |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
await next(); |
|||
} |
|||
|
|||
private ISchemasByAppIndex Index(Guid appId) |
|||
{ |
|||
return grainFactory.GetGrain<ISchemasByAppIndex>(appId); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Orleans; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Schemas.Indexes |
|||
{ |
|||
public sealed class SchemasByAppIndexGrain : GrainOfGuid, ISchemasByAppIndex |
|||
{ |
|||
private readonly IStore<Guid> store; |
|||
private IPersistence<State> persistence; |
|||
private State state = new State(); |
|||
|
|||
[CollectionName("Index_SchemasByApp")] |
|||
public sealed class State |
|||
{ |
|||
public Dictionary<string, Guid> Schemas { get; set; } = new Dictionary<string, Guid>(); |
|||
} |
|||
|
|||
public SchemasByAppIndexGrain(IStore<Guid> store) |
|||
{ |
|||
Guard.NotNull(store, nameof(store)); |
|||
|
|||
this.store = store; |
|||
} |
|||
|
|||
public override Task OnActivateAsync(Guid key) |
|||
{ |
|||
persistence = store.WithSnapshots<SchemasByAppIndexGrain, State, Guid>(key, s => |
|||
{ |
|||
state = s; |
|||
}); |
|||
|
|||
return persistence.ReadAsync(); |
|||
} |
|||
|
|||
public Task RebuildAsync(Dictionary<string, Guid> schemas) |
|||
{ |
|||
state = new State { Schemas = schemas }; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task AddSchemaAsync(Guid schemaId, string name) |
|||
{ |
|||
state.Schemas[name] = schemaId; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task RemoveSchemaAsync(Guid schemaId) |
|||
{ |
|||
state.Schemas.Remove(state.Schemas.FirstOrDefault(x => x.Value == schemaId).Key ?? string.Empty); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task<Guid> GetSchemaIdAsync(string name) |
|||
{ |
|||
state.Schemas.TryGetValue(name, out var schemaId); |
|||
|
|||
return Task.FromResult(schemaId); |
|||
} |
|||
|
|||
public Task<List<Guid>> GetSchemaIdsAsync() |
|||
{ |
|||
return Task.FromResult(state.Schemas.Values.ToList()); |
|||
} |
|||
} |
|||
} |
|||
@ -1,16 +1,14 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using Newtonsoft.Json.Linq; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Rules |
|||
namespace Squidex.Infrastructure.Orleans |
|||
{ |
|||
public sealed class RuleJobData : Dictionary<string, JToken> |
|||
public static class SingleGrain |
|||
{ |
|||
public const string Id = "Default"; |
|||
} |
|||
} |
|||
@ -1,3 +1,13 @@ |
|||
<div [formGroup]="editForm"> |
|||
<span>Nothing to setup</span> |
|||
<div class="form-group row"> |
|||
<label class="col col-3 col-form-label" for="{{field.fieldId}}_editorUrl">Editor Url</label> |
|||
|
|||
<div class="col col-6"> |
|||
<input type="text" class="form-control" id="{{field.fieldId}}_editorUrl" formControlName="editorUrl" /> |
|||
|
|||
<small class="form-text text-muted"> |
|||
Url to your plugin if you use a custom editor. |
|||
</small> |
|||
</div> |
|||
</div> |
|||
<div> |
|||
@ -1,2 +1,6 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
@import '_mixins'; |
|||
|
|||
.form-group { |
|||
margin: 0; |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue