Skip to content

Commit d0f4df0

Browse files
authored
Merge pull request #12 from umbraco/feature/zapier-subscriptions
Subscription and Polling endpoints
2 parents f95b4d6 + 3ed1258 commit d0f4df0

File tree

8 files changed

+355
-7
lines changed

8 files changed

+355
-7
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,17 @@ namespace Umbraco.Forms.Integrations.Automation.Zapier
33
{
44
public class Constants
55
{
6+
public const string ZapierWorkflowTypeId = "d05b95e5-86f8-4c31-99b8-4ec7fc62a787";
7+
68
public const string UmbracoFormsIntegrationsAutomationZapierUserGroup = "Umbraco.Forms.Integrations.Automation.Zapier.UserGroup";
79

10+
public static class ZapierAppConfiguration
11+
{
12+
public const string UsernameHeaderKey = "X-USERNAME";
13+
14+
public const string PasswordHeaderKey = "X-PASSWORD";
15+
}
16+
817
public static class Configuration
918
{
1019
public const string Settings = "Umbraco:Forms:Integrations:Automation:Zapier:Settings";
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
using System.Linq;
5+
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+
#else
16+
using System.Configuration;
17+
18+
using Umbraco.Forms.Core.Data.Storage;
19+
using Umbraco.Web.WebApi;
20+
#endif
21+
22+
namespace Umbraco.Forms.Integrations.Automation.Zapier.Controllers
23+
{
24+
public class PollingController : UmbracoApiController
25+
{
26+
private readonly ZapierSettings Options;
27+
28+
private readonly IUserValidationService _userValidationService;
29+
30+
#if NETCOREAPP
31+
private readonly IFormService _formService;
32+
33+
private readonly IWorkflowService _workflowService;
34+
35+
public PollingController(IOptions<ZapierSettings> options, IFormService formService, IWorkflowService workflowService, IUserValidationService userValidationService)
36+
#else
37+
private readonly IWorkflowServices _workflowServices;
38+
39+
private readonly IFormStorage _formStorage;
40+
41+
public PollingController(IWorkflowServices workflowServices,
42+
IFormStorage formStorage, IUserValidationService userValidationService)
43+
#endif
44+
{
45+
#if NETCOREAPP
46+
Options = options.Value;
47+
48+
_workflowService = workflowService;
49+
#else
50+
Options = new ZapierSettings(ConfigurationManager.AppSettings);
51+
52+
_workflowServices = workflowServices;
53+
54+
_formStorage = formStorage;
55+
#endif
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+
// 1. get forms
89+
#if NETCOREAPP
90+
var forms = _formService.Get();
91+
#else
92+
var forms = _formStorage.GetAll();
93+
#endif
94+
foreach (var form in forms)
95+
{
96+
#if NETCOREAPP
97+
var hasZapierWorkflow = _workflowService.Get(form).Any(p => p.WorkflowTypeId == new Guid(Constants.ZapierWorkflowTypeId));
98+
#else
99+
var hasZapierWorkflow = _workflowServices.Get(form)
100+
.Any(p => p.WorkflowTypeId == new Guid(Constants.ZapierWorkflowTypeId));
101+
#endif
102+
103+
if (hasZapierWorkflow)
104+
formsData.Add(new Dictionary<string, string>
105+
{
106+
{ Enum.GetName(typeof(StandardField), StandardField.FormId), form.Id.ToString() },
107+
{ Enum.GetName(typeof(StandardField), StandardField.FormName), form.Name },
108+
{ Enum.GetName(typeof(StandardField), StandardField.PageUrl), "/" },
109+
{ Enum.GetName(typeof(StandardField), StandardField.SubmissionDate), DateTime.Now.ToString() }
110+
});
111+
}
112+
113+
return formsData;
114+
}
115+
116+
}
117+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
using System;
2+
using System.Linq;
3+
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.Forms.Core.Data.Storage;
18+
using Umbraco.Web.WebApi;
19+
#endif
20+
21+
namespace Umbraco.Forms.Integrations.Automation.Zapier.Controllers
22+
{
23+
public class SubscriptionController : UmbracoApiController
24+
{
25+
private readonly ZapierSettings Options;
26+
27+
#if NETCOREAPP
28+
private readonly ILogger<SubscriptionController> _logger;
29+
30+
private readonly IWorkflowService _workflowService;
31+
32+
private readonly IFormService _formService;
33+
#else
34+
private readonly IWorkflowServices _workflowServices;
35+
36+
private readonly IFormStorage _formStorage;
37+
#endif
38+
39+
private readonly IUserValidationService _userValidationService;
40+
41+
#if NETCOREAPP
42+
public SubscriptionController(IOptions<ZapierSettings> options, ILogger<SubscriptionController> logger, IFormService formService,
43+
IWorkflowService workflowService, IUserValidationService userValidationService)
44+
#else
45+
public SubscriptionController(IWorkflowServices workflowServices, IFormStorage formStorage, IUserValidationService userValidationService)
46+
#endif
47+
{
48+
#if NETCOREAPP
49+
Options = options.Value;
50+
51+
_logger = logger;
52+
53+
_workflowService = workflowService;
54+
55+
_formService = formService;
56+
#else
57+
Options = new ZapierSettings(ConfigurationManager.AppSettings);
58+
59+
_workflowServices = workflowServices;
60+
61+
_formStorage = formStorage;
62+
#endif
63+
64+
_userValidationService = userValidationService;
65+
}
66+
67+
[HttpPost]
68+
public bool UpdatePreferences([FromBody] SubscriptionDto dto)
69+
{
70+
string username = string.Empty;
71+
string password = string.Empty;
72+
73+
#if NETCOREAPP
74+
if (Request.Headers.TryGetValue(Constants.ZapierAppConfiguration.UsernameHeaderKey,
75+
out var usernameValues))
76+
username = usernameValues.First();
77+
if (Request.Headers.TryGetValue(Constants.ZapierAppConfiguration.PasswordHeaderKey,
78+
out var passwordValues))
79+
password = passwordValues.First();
80+
#else
81+
if (Request.Headers.TryGetValues(Constants.ZapierAppConfiguration.UsernameHeaderKey,
82+
out var usernameValues))
83+
username = usernameValues.First();
84+
if (Request.Headers.TryGetValues(Constants.ZapierAppConfiguration.PasswordHeaderKey,
85+
out var passwordValues))
86+
password = passwordValues.First();
87+
#endif
88+
89+
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return false;
90+
91+
var isAuthorized = _userValidationService.Validate(username, password, Options.UserGroup).GetAwaiter().GetResult();
92+
if (!isAuthorized) return false;
93+
94+
if (dto == null) return false;
95+
96+
try
97+
{
98+
// 1. get forms
99+
#if NETCOREAPP
100+
var forms = _formService.Get();
101+
#else
102+
var forms = _formStorage.GetAll();
103+
#endif
104+
foreach (var form in forms)
105+
{
106+
// 2. check if 'Trigger Zapier' workflow exists on the form
107+
#if NETCOREAPP
108+
var zapierWorkflows = _workflowService.Get(form)
109+
.Where(p => p.WorkflowTypeId == new Guid(Constants.ZapierWorkflowTypeId)).ToList();
110+
#else
111+
var zapierWorkflows = _workflowServices.Get(form)
112+
.Where(p => p.WorkflowTypeId == new Guid(Constants.ZapierWorkflowTypeId)).ToList();
113+
#endif
114+
if (zapierWorkflows.Any())
115+
{
116+
foreach (var zapierWorkflow in zapierWorkflows)
117+
{
118+
// 3. check if request hook URL matches with the WebHookUri property of the workflow. If match found, set Active property.
119+
if (zapierWorkflow.Settings[nameof(ZapierWorkflow.WebHookUri)] == dto.HookUrl)
120+
{
121+
zapierWorkflow.Active = dto.Enable;
122+
123+
#if NETCOREAPP
124+
_workflowService.Update(zapierWorkflow);
125+
#else
126+
_workflowServices.Update(zapierWorkflow);
127+
#endif
128+
}
129+
}
130+
}
131+
}
132+
}
133+
catch (Exception e)
134+
{
135+
#if NETCOREAPP
136+
_logger.LogError(e.Message);
137+
#else
138+
Logger.Error(typeof(SubscriptionController), e);
139+
#endif
140+
return false;
141+
}
142+
143+
return true;
144+
}
145+
}
146+
}
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
}

0 commit comments

Comments
 (0)