mirror of https://github.com/Squidex/squidex.git
committed by
GitHub
59 changed files with 529 additions and 828 deletions
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@ |
|||||
|
tTFEibLh222u4a7SJ+I4zCkfPRBRF4mHF446OSRQtILNZ2tH0Te/rSM7MCt1FzvLAy5KeNlZHfwdlS+AJZDa6w== |
||||
@ -0,0 +1,17 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> |
||||
|
<metadata> |
||||
|
<id>Fody</id> |
||||
|
<version>2.3.24</version> |
||||
|
<authors>Simon Cropp</authors> |
||||
|
<owners>Simon Cropp</owners> |
||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance> |
||||
|
<developmentDependency>true</developmentDependency> |
||||
|
<licenseUrl>http://www.opensource.org/licenses/mit-license.php</licenseUrl> |
||||
|
<projectUrl>http://github.com/Fody/Fody</projectUrl> |
||||
|
<iconUrl>https://raw.github.com/Fody/Fody/master/package_icon.png</iconUrl> |
||||
|
<description>Extensible tool for weaving .net assemblies.</description> |
||||
|
<copyright></copyright> |
||||
|
<tags>ILWeaving, Fody, Cecil, AOP</tags> |
||||
|
</metadata> |
||||
|
</package> |
||||
@ -0,0 +1,4 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<Weavers> |
||||
|
<Freezable/> |
||||
|
</Weavers> |
||||
@ -0,0 +1,24 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.Infrastructure; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Core.Rules.Actions |
||||
|
{ |
||||
|
[TypeName(nameof(AzureQueueAction))] |
||||
|
public sealed class AzureQueueAction : RuleAction |
||||
|
{ |
||||
|
public string ConnectionString { get; set; } |
||||
|
|
||||
|
public string Queue { get; set; } |
||||
|
|
||||
|
public override T Accept<T>(IRuleActionVisitor<T> visitor) |
||||
|
{ |
||||
|
return visitor.Visit(this); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,72 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Concurrent; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.WindowsAzure.Storage; |
||||
|
using Microsoft.WindowsAzure.Storage.Queue; |
||||
|
using Newtonsoft.Json; |
||||
|
using Newtonsoft.Json.Linq; |
||||
|
using Squidex.Domain.Apps.Core.Rules; |
||||
|
using Squidex.Domain.Apps.Core.Rules.Actions; |
||||
|
using Squidex.Domain.Apps.Events; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.EventSourcing; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Core.HandleRules.Actions |
||||
|
{ |
||||
|
public sealed class AzureQueueActionHandler : RuleActionHandler<AzureQueueAction> |
||||
|
{ |
||||
|
private readonly ConcurrentDictionary<(string ConnectionString, string QueueName), CloudQueue> queues = new ConcurrentDictionary<(string ConnectionString, string QueueName), CloudQueue>(); |
||||
|
private readonly RuleEventFormatter formatter; |
||||
|
|
||||
|
public AzureQueueActionHandler(RuleEventFormatter formatter) |
||||
|
{ |
||||
|
Guard.NotNull(formatter, nameof(formatter)); |
||||
|
|
||||
|
this.formatter = formatter; |
||||
|
} |
||||
|
|
||||
|
protected override (string Description, RuleJobData Data) CreateJob(Envelope<AppEvent> @event, string eventName, AzureQueueAction action) |
||||
|
{ |
||||
|
var body = formatter.ToRouteData(@event, eventName); |
||||
|
|
||||
|
var ruleDescription = $"Send event to azure queue '{action.Queue}'"; |
||||
|
var ruleData = new RuleJobData |
||||
|
{ |
||||
|
["QueueConnectionString"] = action.ConnectionString, |
||||
|
["QueueName"] = action.Queue, |
||||
|
["MessageBody"] = body |
||||
|
}; |
||||
|
|
||||
|
return (ruleDescription, ruleData); |
||||
|
} |
||||
|
|
||||
|
public override async Task<(string Dump, Exception Exception)> ExecuteJobAsync(RuleJobData job) |
||||
|
{ |
||||
|
var queueConnectionString = job["QueueConnectionString"].Value<string>(); |
||||
|
var queueName = job["QueueName"].Value<string>(); |
||||
|
|
||||
|
var queue = queues.GetOrAdd((queueConnectionString, queueName), s => |
||||
|
{ |
||||
|
var storageAccount = CloudStorageAccount.Parse(queueConnectionString); |
||||
|
|
||||
|
var queueClient = storageAccount.CreateCloudQueueClient(); |
||||
|
var queueRef = queueClient.GetQueueReference(queueName); |
||||
|
|
||||
|
return queueRef; |
||||
|
}); |
||||
|
|
||||
|
var messageBody = job["MessageBody"].ToString(Formatting.Indented); |
||||
|
|
||||
|
await queue.AddMessageAsync(new CloudQueueMessage(messageBody)); |
||||
|
|
||||
|
return ("Completed", null); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
namespace Squidex.Infrastructure |
||||
|
{ |
||||
|
public interface IFreezable |
||||
|
{ |
||||
|
void Freeze(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using NJsonSchema.Annotations; |
||||
|
using Squidex.Domain.Apps.Core.Rules; |
||||
|
using Squidex.Domain.Apps.Core.Rules.Actions; |
||||
|
using Squidex.Infrastructure.Reflection; |
||||
|
|
||||
|
namespace Squidex.Areas.Api.Controllers.Rules.Models.Actions |
||||
|
{ |
||||
|
[JsonSchema("AzureQueue")] |
||||
|
public class AzureQueueActionDto : RuleActionDto |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The connection string to the storage account.
|
||||
|
/// </summary>
|
||||
|
[Required] |
||||
|
public string ConnectionString { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The queue name.
|
||||
|
/// </summary>
|
||||
|
[Required] |
||||
|
public string Queue { get; set; } |
||||
|
|
||||
|
public override RuleAction ToAction() |
||||
|
{ |
||||
|
return SimpleMapper.Map(this, new AzureQueueAction()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
<form [formGroup]="actionForm" class="form-horizontal" (ngSubmit)="save()"> |
||||
|
<div class="form-group row"> |
||||
|
<label class="col col-3 col-form-label" for="queue">Connection String</label> |
||||
|
|
||||
|
<div class="col col-9"> |
||||
|
<sqx-control-errors for="text" [submitted]="actionFormSubmitted"></sqx-control-errors> |
||||
|
|
||||
|
<input type="text" class="form-control" id="connectionString" formControlName="connectionString" /> |
||||
|
|
||||
|
<small class="form-text text-muted"> |
||||
|
The connection string to the storage account. |
||||
|
</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="form-group row"> |
||||
|
<label class="col col-3 col-form-label" for="queue">Queue Name</label> |
||||
|
|
||||
|
<div class="col col-9"> |
||||
|
<sqx-control-errors for="queue" [submitted]="actionFormSubmitted"></sqx-control-errors> |
||||
|
|
||||
|
<input type="text" class="form-control" id="queue" formControlName="queue" /> |
||||
|
|
||||
|
<small class="form-text text-muted"> |
||||
|
The name of the queue. |
||||
|
</small> |
||||
|
</div> |
||||
|
</div> |
||||
|
</form> |
||||
@ -0,0 +1,2 @@ |
|||||
|
@import '_vars'; |
||||
|
@import '_mixins'; |
||||
@ -0,0 +1,61 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
||||
|
*/ |
||||
|
|
||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; |
||||
|
import { FormBuilder, Validators } from '@angular/forms'; |
||||
|
|
||||
|
import { ValidatorsEx } from 'shared'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'sqx-azure-queue-action', |
||||
|
styleUrls: ['./azure-queue-action.component.scss'], |
||||
|
templateUrl: './azure-queue-action.component.html' |
||||
|
}) |
||||
|
export class AzureQueueActionComponent implements OnInit { |
||||
|
@Input() |
||||
|
public action: any; |
||||
|
|
||||
|
@Output() |
||||
|
public actionChanged = new EventEmitter<object>(); |
||||
|
|
||||
|
public actionFormSubmitted = false; |
||||
|
public actionForm = |
||||
|
this.formBuilder.group({ |
||||
|
connectionString: ['', |
||||
|
[ |
||||
|
Validators.required |
||||
|
]], |
||||
|
queue: ['squidex', |
||||
|
[ |
||||
|
Validators.required, |
||||
|
ValidatorsEx.pattern('[a-z][a-z0-9]{2,}(\-[a-z0-9]+)*', 'Name must be a valid azure queue name.') |
||||
|
]] |
||||
|
}); |
||||
|
|
||||
|
constructor( |
||||
|
private readonly formBuilder: FormBuilder |
||||
|
) { |
||||
|
} |
||||
|
|
||||
|
public ngOnInit() { |
||||
|
this.action = Object.assign({}, { connectionString: '', queue: 'squidex' }, this.action || {}); |
||||
|
|
||||
|
this.actionFormSubmitted = false; |
||||
|
this.actionForm.reset(); |
||||
|
this.actionForm.setValue(this.action); |
||||
|
} |
||||
|
|
||||
|
public save() { |
||||
|
this.actionFormSubmitted = true; |
||||
|
|
||||
|
if (this.actionForm.valid) { |
||||
|
const action = this.actionForm.value; |
||||
|
|
||||
|
this.actionChanged.emit(action); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Binary file not shown.
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,56 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Domain.Apps.Core.Rules.Actions; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.Rules.Guards.Actions |
||||
|
{ |
||||
|
public sealed class AzureQueueActionTests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public async Task Should_add_error_if_connection_string_is_null() |
||||
|
{ |
||||
|
var action = new AzureQueueAction { ConnectionString = null, Queue = "squidex" }; |
||||
|
|
||||
|
var errors = await RuleActionValidator.ValidateAsync(action); |
||||
|
|
||||
|
Assert.NotEmpty(errors); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_add_error_if_queue_is_null() |
||||
|
{ |
||||
|
var action = new AzureQueueAction { ConnectionString = "connection", Queue = null }; |
||||
|
|
||||
|
var errors = await RuleActionValidator.ValidateAsync(action); |
||||
|
|
||||
|
Assert.NotEmpty(errors); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_add_error_if_queue_is_invalid() |
||||
|
{ |
||||
|
var action = new AzureQueueAction { ConnectionString = "connection", Queue = "Squidex" }; |
||||
|
|
||||
|
var errors = await RuleActionValidator.ValidateAsync(action); |
||||
|
|
||||
|
Assert.NotEmpty(errors); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_not_add_error_if_values_are_valid() |
||||
|
{ |
||||
|
var action = new AzureQueueAction { ConnectionString = "connection", Queue = "squidex" }; |
||||
|
|
||||
|
var errors = await RuleActionValidator.ValidateAsync(action); |
||||
|
|
||||
|
Assert.Empty(errors); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue