Skip to content

Commit 059d8fa

Browse files
committed
Subscription and Polling endpoints
1 parent a9c7608 commit 059d8fa

File tree

8 files changed

+341
-3
lines changed

8 files changed

+341
-3
lines changed

src/Umbraco.Forms.Integrations.Automation.Zapier/Constants.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ public class Constants
55
{
66
public const string UmbracoFormsIntegrationsAutomationZapierUserGroup = "Umbraco.Forms.Integrations.Automation.Zapier.UserGroup";
77

8+
public static class ZapierAppConfiguration
9+
{
10+
public const string UsernameHeaderKey = "X-USERNAME";
11+
12+
public const string PasswordHeaderKey = "X-PASSWORD";
13+
}
14+
815
public static class Configuration
916
{
1017
public const string Settings = "Umbraco:Forms:Integrations:Automation:Zapier:Settings";
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
using System.Linq;
5+
using Umbraco.Forms.Core.Data.Storage;
6+
using Umbraco.Forms.Core.Providers.Models;
7+
using Umbraco.Forms.Core.Services;
8+
using Umbraco.Forms.Integrations.Automation.Zapier.Configuration;
9+
using Umbraco.Forms.Integrations.Automation.Zapier.Services;
10+
11+
#if NETCOREAPP
12+
using Microsoft.Extensions.Options;
13+
14+
using Umbraco.Cms.Web.Common.Controllers;
15+
using Umbraco.Cms.Core.Services;
16+
#else
17+
using System.Configuration;
18+
19+
using Umbraco.Web.WebApi;
20+
using Umbraco.Core.Services;
21+
#endif
22+
23+
namespace Umbraco.Forms.Integrations.Automation.Zapier.Controllers
24+
{
25+
public class PollingController : UmbracoApiController
26+
{
27+
private readonly ZapierSettings Options;
28+
29+
private readonly IFormService _formService;
30+
31+
private readonly IWorkflowService _workflowService;
32+
33+
private readonly IRecordReaderService _recordReaderService;
34+
35+
private readonly IUserValidationService _userValidationService;
36+
37+
#if NETCOREAPP
38+
public PollingController(IOptions<ZapierSettings> options, IFormService formService, IWorkflowService workflowService,
39+
IRecordReaderService recordReaderService, IUserValidationService userValidationService)
40+
#else
41+
public PollingController(IFormService formService, IWorkflowService workflowService,
42+
IRecordReaderService recordReaderService, IUserValidationService userValidationService)
43+
#endif
44+
{
45+
#if NETCOREAPP
46+
Options = options.Value;
47+
#else
48+
Options = new ZapierSettings(ConfigurationManager.AppSettings);
49+
#endif
50+
51+
_formService = formService;
52+
53+
_workflowService = workflowService;
54+
55+
_recordReaderService = recordReaderService;
56+
57+
_userValidationService = userValidationService;
58+
}
59+
60+
public List<Dictionary<string, string>> GetFormsData()
61+
{
62+
var formsData = new List<Dictionary<string, string>>();
63+
64+
string username = string.Empty;
65+
string password = string.Empty;
66+
67+
#if NETCOREAPP
68+
if (Request.Headers.TryGetValue(Constants.ZapierAppConfiguration.UsernameHeaderKey,
69+
out var usernameValues))
70+
username = usernameValues.First();
71+
if (Request.Headers.TryGetValue(Constants.ZapierAppConfiguration.PasswordHeaderKey,
72+
out var passwordValues))
73+
password = passwordValues.First();
74+
#else
75+
if (Request.Headers.TryGetValues(Constants.ZapierAppConfiguration.UsernameHeaderKey,
76+
out var usernameValues))
77+
username = usernameValues.First();
78+
if (Request.Headers.TryGetValues(Constants.ZapierAppConfiguration.PasswordHeaderKey,
79+
out var passwordValues))
80+
password = passwordValues.First();
81+
#endif
82+
83+
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return null;
84+
85+
var isAuthorized = _userValidationService.Validate(username, password, Options.UserGroup).GetAwaiter().GetResult();
86+
if (!isAuthorized) return null;
87+
88+
var zapierWorkflowId = new Guid("d05b95e5-86f8-4c31-99b8-4ec7fc62a787");
89+
90+
// 1. get forms
91+
var forms = _formService.Get();
92+
foreach (var form in forms)
93+
{
94+
#if NETCOREAPP
95+
var hasZapierWorkflow = _workflowService.Get(form).Any(p => p.WorkflowTypeId == zapierWorkflowId);
96+
#else
97+
var hasZapierWorkflow = form.WorkflowIds.Contains(zapierWorkflowId);
98+
#endif
99+
100+
if (hasZapierWorkflow)
101+
formsData.Add(new Dictionary<string, string>
102+
{
103+
{ Enum.GetName(typeof(StandardField), StandardField.FormId), form.Id.ToString() },
104+
{ Enum.GetName(typeof(StandardField), StandardField.FormName), form.Name },
105+
{ Enum.GetName(typeof(StandardField), StandardField.PageUrl), "/" },
106+
{ Enum.GetName(typeof(StandardField), StandardField.SubmissionDate), DateTime.Now.ToString() }
107+
});
108+
}
109+
110+
return formsData;
111+
}
112+
113+
}
114+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System;
2+
using System.Linq;
3+
using System.Net;
4+
using Umbraco.Forms.Core.Services;
5+
using Umbraco.Forms.Integrations.Automation.Zapier.Configuration;
6+
using Umbraco.Forms.Integrations.Automation.Zapier.Models.Dtos;
7+
using Umbraco.Forms.Integrations.Automation.Zapier.Services;
8+
9+
#if NETCOREAPP
10+
using Microsoft.AspNetCore.Mvc;
11+
using Microsoft.Extensions.Logging;
12+
using Microsoft.Extensions.Options;
13+
using Umbraco.Cms.Web.Common.Controllers;
14+
#else
15+
using System.Web.Http;
16+
using System.Configuration;
17+
using Umbraco.Web.WebApi;
18+
#endif
19+
20+
namespace Umbraco.Forms.Integrations.Automation.Zapier.Controllers
21+
{
22+
public class SubscriptionController : UmbracoApiController
23+
{
24+
private readonly ZapierSettings Options;
25+
26+
#if NETCOREAPP
27+
private readonly ILogger<SubscriptionController> _logger;
28+
29+
private readonly IWorkflowService _workflowService;
30+
#else
31+
private readonly IWorkflowServices _workflowServices;
32+
#endif
33+
34+
private readonly IFormService _formService;
35+
36+
private readonly IUserValidationService _userValidationService;
37+
38+
#if NETCOREAPP
39+
public SubscriptionController(IOptions<ZapierSettings> options, ILogger<SubscriptionController> logger, IFormService formService, IWorkflowService workflowService, IUserValidationService userValidationService)
40+
#else
41+
public SubscriptionController(IFormService formService, IWorkflowServices workflowServices, IUserValidationService userValidationService)
42+
#endif
43+
{
44+
#if NETCOREAPP
45+
Options = options.Value;
46+
47+
_logger = logger;
48+
#else
49+
Options = new ZapierSettings(ConfigurationManager.AppSettings);
50+
#endif
51+
_formService = formService;
52+
53+
#if NETCOREAPP
54+
_workflowService = workflowService;
55+
#else
56+
_workflowServices = workflowServices;
57+
#endif
58+
59+
_userValidationService = userValidationService;
60+
}
61+
62+
[HttpPost]
63+
public bool UpdatePreferences([FromBody] SubscriptionDto dto)
64+
{
65+
string username = string.Empty;
66+
string password = string.Empty;
67+
68+
#if NETCOREAPP
69+
if (Request.Headers.TryGetValue(Constants.ZapierAppConfiguration.UsernameHeaderKey,
70+
out var usernameValues))
71+
username = usernameValues.First();
72+
if (Request.Headers.TryGetValue(Constants.ZapierAppConfiguration.PasswordHeaderKey,
73+
out var passwordValues))
74+
password = passwordValues.First();
75+
#else
76+
if (Request.Headers.TryGetValues(Constants.ZapierAppConfiguration.UsernameHeaderKey,
77+
out var usernameValues))
78+
username = usernameValues.First();
79+
if (Request.Headers.TryGetValues(Constants.ZapierAppConfiguration.PasswordHeaderKey,
80+
out var passwordValues))
81+
password = passwordValues.First();
82+
#endif
83+
84+
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return false;
85+
86+
var isAuthorized = _userValidationService.Validate(username, password, Options.UserGroup).GetAwaiter().GetResult();
87+
if (!isAuthorized) return false;
88+
89+
if (dto == null) return false;
90+
91+
var zapierWorkflowTypeId = new Guid("d05b95e5-86f8-4c31-99b8-4ec7fc62a787");
92+
93+
try
94+
{
95+
// 1. get forms
96+
var forms = _formService.Get();
97+
foreach (var form in forms)
98+
{
99+
// 2. check if 'Trigger Zapier' workflow exists on the form
100+
#if NETCOREAPP
101+
var zapierWorkflows = _workflowService.Get(form).Where(p => p.WorkflowTypeId == zapierWorkflowTypeId).ToList();
102+
#else
103+
var zapierWorkflows = _workflowServices.Get(form)
104+
.Where(p => p.WorkflowTypeId == zapierWorkflowTypeId).ToList();
105+
#endif
106+
if (zapierWorkflows.Any())
107+
{
108+
foreach (var zapierWorkflow in zapierWorkflows)
109+
{
110+
// 3. check if request hook URL matches with the WebHookUri property of the workflow. If match found, set Active property.
111+
if (zapierWorkflow.Settings[nameof(ZapierWorkflow.WebHookUri)] == dto.HookUrl)
112+
{
113+
zapierWorkflow.Active = dto.Enable;
114+
115+
#if NETCOREAPP
116+
_workflowService.Update(zapierWorkflow);
117+
#else
118+
_workflowServices.Update(zapierWorkflow);
119+
#endif
120+
}
121+
}
122+
}
123+
}
124+
}
125+
catch (Exception e)
126+
{
127+
#if NETCOREAPP
128+
_logger.LogError(e.Message);
129+
#else
130+
Logger.Error(typeof(SubscriptionController), e);
131+
#endif
132+
return false;
133+
}
134+
135+
return true;
136+
}
137+
}
138+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Newtonsoft.Json;
2+
3+
namespace Umbraco.Forms.Integrations.Automation.Zapier.Models.Dtos
4+
{
5+
public class SubscriptionDto
6+
{
7+
[JsonProperty("hookUrl")]
8+
public string HookUrl { get; set; }
9+
10+
[JsonProperty("enable")]
11+
public bool Enable { get; set; }
12+
}
13+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Threading.Tasks;
2+
3+
namespace Umbraco.Forms.Integrations.Automation.Zapier.Services
4+
{
5+
public interface IUserValidationService
6+
{
7+
Task<bool> Validate(string username, string password, string userGroup);
8+
}
9+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System.Linq;
2+
using System.Threading.Tasks;
3+
4+
#if NETCOREAPP
5+
using Umbraco.Cms.Core.Security;
6+
using Umbraco.Cms.Core.Services;
7+
#else
8+
using Umbraco.Core.Services;
9+
using Umbraco.Web;
10+
#endif
11+
12+
namespace Umbraco.Forms.Integrations.Automation.Zapier.Services
13+
{
14+
public class UserValidationService : IUserValidationService
15+
{
16+
private readonly IUserService _userService;
17+
18+
19+
#if NETCOREAPP
20+
private readonly IBackOfficeUserManager _backOfficeUserManager;
21+
22+
public UserValidationService(IBackOfficeUserManager backOfficeUserManager, IUserService userService)
23+
{
24+
_backOfficeUserManager = backOfficeUserManager;
25+
}
26+
#else
27+
public UserValidationService(IUserService userService)
28+
{
29+
_userService = userService;
30+
}
31+
#endif
32+
33+
public async Task<bool> Validate(string username, string password, string userGroup)
34+
{
35+
#if NETCOREAPP
36+
var isUserValid =
37+
await _backOfficeUserManager.ValidateCredentialsAsync(username, password);
38+
#else
39+
var isUserValid = Umbraco.Web.Composing.Current.UmbracoContext.Security.ValidateBackOfficeCredentials(username, password);
40+
#endif
41+
42+
if (!isUserValid) return false;
43+
44+
if (!string.IsNullOrEmpty(userGroup))
45+
{
46+
var user = _userService.GetByUsername(username);
47+
48+
return user != null && user.Groups.Any(p => p.Name == userGroup);
49+
}
50+
51+
return true;
52+
}
53+
}
54+
}

src/Umbraco.Forms.Integrations.Automation.Zapier/ZapierComposer.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#else
99
using Umbraco.Core.Composing;
1010
#endif
11+
using Umbraco.Core;
12+
using Umbraco.Forms.Integrations.Automation.Zapier.Services;
1113

1214
namespace Umbraco.Forms.Integrations.Automation.Zapier
1315
{
@@ -21,11 +23,13 @@ public void Compose(IUmbracoBuilder builder)
2123
.Bind(builder.Config.GetSection(Constants.Configuration.Settings));
2224

2325
builder.WithCollectionBuilder<WorkflowCollectionBuilder>().Add<ZapierWorkflow>();
26+
27+
builder.Services.AddScoped<IUserValidationService, UserValidationService>();
2428
}
2529
#else
2630
public void Compose(Composition composition)
2731
{
28-
32+
composition.Register<IUserValidationService, UserValidationService>(Lifetime.Scope);
2933
}
3034
#endif
3135
}

src/Umbraco.Forms.Integrations.Automation.Zapier/ZapierWorkflow.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Umbraco.Forms.Integrations.Automation.Zapier.Validators;
1010

1111
#if NETCOREAPP
12+
using System.Threading.Tasks;
1213
using Microsoft.Extensions.Logging;
1314
using Umbraco.Cms.Core.Routing;
1415
using Umbraco.Cms.Core.Web;
@@ -78,8 +79,6 @@ public ZapierWorkflow(IUmbracoContextAccessor umbracoContextAccessor)
7879
// Access to the client within the class is via ClientFactory(), allowing us to mock the responses in tests.
7980
public static Func<HttpClient> ClientFactory = () => s_client;
8081

81-
82-
8382
#if NETCOREAPP
8483
public override WorkflowExecutionStatus Execute(WorkflowExecutionContext context)
8584
{

0 commit comments

Comments
 (0)