-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Azure Communication SMS Provider (#15539)
--------- Co-authored-by: Mike Alhayek <[email protected]>
- Loading branch information
1 parent
9931a00
commit 4f4bec4
Showing
30 changed files
with
601 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
145 changes: 145 additions & 0 deletions
145
src/OrchardCore.Modules/OrchardCore.Sms.Azure/Drivers/AzureSettingsDisplayDriver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.DataProtection; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.AspNetCore.Mvc.Localization; | ||
using Microsoft.AspNetCore.Mvc.ModelBinding; | ||
using Microsoft.Extensions.Localization; | ||
using OrchardCore.DisplayManagement.Entities; | ||
using OrchardCore.DisplayManagement.Handlers; | ||
using OrchardCore.DisplayManagement.Notify; | ||
using OrchardCore.DisplayManagement.Views; | ||
using OrchardCore.Entities; | ||
using OrchardCore.Environment.Shell; | ||
using OrchardCore.Mvc.ModelBinding; | ||
using OrchardCore.Settings; | ||
using OrchardCore.Sms.Azure.Models; | ||
using OrchardCore.Sms.Azure.Services; | ||
using OrchardCore.Sms.Azure.ViewModels; | ||
|
||
namespace OrchardCore.Sms.Azure.Drivers; | ||
|
||
public sealed class AzureSettingsDisplayDriver : SiteDisplayDriver<AzureSmsSettings> | ||
{ | ||
private readonly IShellReleaseManager _shellReleaseManager; | ||
private readonly IHttpContextAccessor _httpContextAccessor; | ||
private readonly IAuthorizationService _authorizationService; | ||
private readonly IPhoneFormatValidator _phoneFormatValidator; | ||
private readonly IDataProtectionProvider _dataProtectionProvider; | ||
private readonly INotifier _notifier; | ||
|
||
internal readonly IHtmlLocalizer H; | ||
internal readonly IStringLocalizer S; | ||
|
||
protected override string SettingsGroupId | ||
=> SmsSettings.GroupId; | ||
|
||
public AzureSettingsDisplayDriver( | ||
IShellReleaseManager shellReleaseManager, | ||
IHttpContextAccessor httpContextAccessor, | ||
IAuthorizationService authorizationService, | ||
IPhoneFormatValidator phoneFormatValidator, | ||
IDataProtectionProvider dataProtectionProvider, | ||
INotifier notifier, | ||
IHtmlLocalizer<AzureSettingsDisplayDriver> htmlLocalizer, | ||
IStringLocalizer<AzureSettingsDisplayDriver> stringLocalizer) | ||
{ | ||
_shellReleaseManager = shellReleaseManager; | ||
_httpContextAccessor = httpContextAccessor; | ||
_authorizationService = authorizationService; | ||
_phoneFormatValidator = phoneFormatValidator; | ||
_dataProtectionProvider = dataProtectionProvider; | ||
_notifier = notifier; | ||
H = htmlLocalizer; | ||
S = stringLocalizer; | ||
} | ||
|
||
public override IDisplayResult Edit(ISite site, AzureSmsSettings settings, BuildEditorContext c) | ||
{ | ||
return Initialize<AzureSettingsViewModel>("AzureSmsSettings_Edit", model => | ||
{ | ||
model.IsEnabled = settings.IsEnabled; | ||
model.PhoneNumber = settings.PhoneNumber; | ||
model.HasConnectionString = !string.IsNullOrEmpty(settings.ConnectionString); | ||
}).Location("Content:5#Azure Communication") | ||
.RenderWhen(() => _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext?.User, SmsPermissions.ManageSmsSettings)) | ||
.OnGroup(SettingsGroupId); | ||
} | ||
|
||
public override async Task<IDisplayResult> UpdateAsync(ISite site, AzureSmsSettings settings, UpdateEditorContext context) | ||
{ | ||
if (!await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, SmsPermissions.ManageSmsSettings)) | ||
{ | ||
return null; | ||
} | ||
|
||
var model = new AzureSettingsViewModel(); | ||
|
||
await context.Updater.TryUpdateModelAsync(model, Prefix); | ||
|
||
var smsSettings = site.As<SmsSettings>(); | ||
|
||
var hasChanges = settings.IsEnabled != model.IsEnabled; | ||
if (!model.IsEnabled) | ||
{ | ||
if (hasChanges && smsSettings.DefaultProviderName == AzureSmsProvider.TechnicalName) | ||
{ | ||
await _notifier.WarningAsync(H["You have successfully disabled the default SMS provider. The SMS service is now disable and will remain disabled until you designate a new default provider."]); | ||
|
||
smsSettings.DefaultProviderName = null; | ||
|
||
site.Put(smsSettings); | ||
} | ||
|
||
settings.IsEnabled = false; | ||
} | ||
else | ||
{ | ||
settings.IsEnabled = true; | ||
|
||
hasChanges |= model.PhoneNumber != settings.PhoneNumber; | ||
|
||
if (string.IsNullOrEmpty(model.PhoneNumber)) | ||
{ | ||
context.Updater.ModelState.AddModelError(Prefix, nameof(model.PhoneNumber), S["The phone number is a required."]); | ||
} | ||
else if (!_phoneFormatValidator.IsValid(model.PhoneNumber)) | ||
{ | ||
context.Updater.ModelState.AddModelError(Prefix, nameof(model.PhoneNumber), S["Invalid phone number."]); | ||
} | ||
|
||
settings.PhoneNumber = model.PhoneNumber; | ||
|
||
if (string.IsNullOrWhiteSpace(model.ConnectionString) && settings.ConnectionString is null) | ||
{ | ||
context.Updater.ModelState.AddModelError(Prefix, nameof(model.ConnectionString), S["Connection string is required."]); | ||
} | ||
else if (!string.IsNullOrWhiteSpace(model.ConnectionString)) | ||
{ | ||
var protector = _dataProtectionProvider.CreateProtector(AzureSmsOptionsConfiguration.ProtectorName); | ||
|
||
var protectedConnection = protector.Protect(model.ConnectionString); | ||
|
||
// Check if the connection string changed before setting it. | ||
hasChanges |= protectedConnection != settings.ConnectionString; | ||
|
||
settings.ConnectionString = protectedConnection; | ||
} | ||
} | ||
|
||
if (context.Updater.ModelState.IsValid && settings.IsEnabled && string.IsNullOrEmpty(smsSettings.DefaultProviderName)) | ||
{ | ||
// If we are enabling the only provider, set it as the default one. | ||
smsSettings.DefaultProviderName = AzureSmsProvider.TechnicalName; | ||
site.Put(smsSettings); | ||
|
||
hasChanges = true; | ||
} | ||
|
||
if (hasChanges) | ||
{ | ||
_shellReleaseManager.RequestRelease(); | ||
} | ||
|
||
return Edit(site, settings, context); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/OrchardCore.Modules/OrchardCore.Sms.Azure/Extensions/SmsProviderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Options; | ||
using OrchardCore.Sms.Azure.Models; | ||
using OrchardCore.Sms.Azure.Services; | ||
|
||
namespace OrchardCore.Sms.Azure; | ||
|
||
public static class SmsProviderExtensions | ||
{ | ||
public static IServiceCollection AddAzureSmsProvider(this IServiceCollection services) | ||
=> services.AddSmsProviderOptionsConfiguration<AzureSmsProviderOptionsConfigurations>() | ||
.AddTransient<IConfigureOptions<AzureSmsOptions>, AzureSmsOptionsConfiguration>(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using OrchardCore.Modules.Manifest; | ||
|
||
[assembly: Module( | ||
Author = ManifestConstants.OrchardCoreTeam, | ||
Website = ManifestConstants.OrchardCoreWebsite, | ||
Version = ManifestConstants.OrchardCoreVersion | ||
)] | ||
|
||
[assembly: Feature( | ||
Name = "Azure Communication SMS", | ||
Id = "OrchardCore.Sms.Azure", | ||
Description = "Enables the ability to send SMS messages through Azure Communication Services (ACS).", | ||
Dependencies = | ||
[ | ||
"OrchardCore.Sms", | ||
], | ||
Category = "SMS" | ||
)] |
14 changes: 14 additions & 0 deletions
14
src/OrchardCore.Modules/OrchardCore.Sms.Azure/Models/AzureSmsOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
namespace OrchardCore.Sms.Azure.Models; | ||
|
||
public class AzureSmsOptions | ||
{ | ||
public bool IsEnabled { get; set; } | ||
|
||
public string PhoneNumber { get; set; } | ||
|
||
public string ConnectionString { get; set; } | ||
|
||
public bool ConfigurationExists() | ||
=> !string.IsNullOrWhiteSpace(PhoneNumber) && | ||
!string.IsNullOrWhiteSpace(ConnectionString); | ||
} |
10 changes: 10 additions & 0 deletions
10
src/OrchardCore.Modules/OrchardCore.Sms.Azure/Models/AzureSmsSettings.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace OrchardCore.Sms.Azure.Models; | ||
|
||
public class AzureSmsSettings | ||
{ | ||
public bool IsEnabled { get; set; } | ||
|
||
public string ConnectionString { get; set; } | ||
|
||
public string PhoneNumber { get; set; } | ||
} |
5 changes: 5 additions & 0 deletions
5
src/OrchardCore.Modules/OrchardCore.Sms.Azure/Models/DefaultAzureSmsOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace OrchardCore.Sms.Azure.Models; | ||
|
||
public sealed class DefaultAzureSmsOptions : AzureSmsOptions | ||
{ | ||
} |
29 changes: 29 additions & 0 deletions
29
src/OrchardCore.Modules/OrchardCore.Sms.Azure/OrchardCore.Sms.Azure.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Razor"> | ||
|
||
<PropertyGroup> | ||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> | ||
<!-- NuGet properties--> | ||
<Title>OrchardCore Sms</Title> | ||
<Description> | ||
$(OCCMSDescription) | ||
|
||
The Azure Communication SMS feature enables sending SMS messages via Azure Communication Services (ACS). | ||
</Description> | ||
<PackageTags>$(PackageTags) OrchardCoreCMS</PackageTags> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<FrameworkReference Include="Microsoft.AspNetCore.App" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Azure.Communication.Sms" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\OrchardCore\OrchardCore.DisplayManagement\OrchardCore.DisplayManagement.csproj" /> | ||
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Module.Targets\OrchardCore.Module.Targets.csproj" /> | ||
<ProjectReference Include="..\..\OrchardCore\OrchardCore.ResourceManagement\OrchardCore.ResourceManagement.csproj" /> | ||
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Sms.Core\OrchardCore.Sms.Core.csproj" /> | ||
</ItemGroup> | ||
</Project> |
39 changes: 39 additions & 0 deletions
39
src/OrchardCore.Modules/OrchardCore.Sms.Azure/Services/AzureSmsOptionsConfiguration.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using Microsoft.AspNetCore.DataProtection; | ||
using Microsoft.Extensions.Options; | ||
using OrchardCore.Settings; | ||
using OrchardCore.Sms.Azure.Models; | ||
|
||
namespace OrchardCore.Sms.Azure.Services; | ||
|
||
public sealed class AzureSmsOptionsConfiguration : IConfigureOptions<AzureSmsOptions> | ||
{ | ||
public const string ProtectorName = "AzureSmsProtector"; | ||
|
||
private readonly ISiteService _siteService; | ||
private readonly IDataProtectionProvider _dataProtectionProvider; | ||
|
||
public AzureSmsOptionsConfiguration( | ||
ISiteService siteService, | ||
IDataProtectionProvider dataProtectionProvider) | ||
{ | ||
_siteService = siteService; | ||
_dataProtectionProvider = dataProtectionProvider; | ||
} | ||
|
||
public void Configure(AzureSmsOptions options) | ||
{ | ||
var settings = _siteService.GetSettingsAsync<AzureSmsSettings>() | ||
.GetAwaiter() | ||
.GetResult(); | ||
|
||
options.IsEnabled = settings.IsEnabled; | ||
options.PhoneNumber = settings.PhoneNumber; | ||
|
||
if (!string.IsNullOrEmpty(settings.ConnectionString)) | ||
{ | ||
var protector = _dataProtectionProvider.CreateProtector(ProtectorName); | ||
|
||
options.ConnectionString = protector.Unprotect(settings.ConnectionString); | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/OrchardCore.Modules/OrchardCore.Sms.Azure/Services/AzureSmsProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using Microsoft.Extensions.Localization; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
using OrchardCore.Sms.Azure.Models; | ||
|
||
namespace OrchardCore.Sms.Azure.Services; | ||
|
||
public sealed class AzureSmsProvider : AzureSmsProviderBase | ||
{ | ||
public const string TechnicalName = "Azure"; | ||
|
||
public AzureSmsProvider( | ||
IOptions<AzureSmsOptions> options, | ||
IPhoneFormatValidator phoneFormatValidator, | ||
ILogger<AzureSmsProvider> logger, | ||
IStringLocalizer<AzureSmsProvider> stringLocalizer) | ||
: base(options.Value, phoneFormatValidator, logger, stringLocalizer) | ||
{ | ||
} | ||
|
||
public override LocalizedString Name | ||
=> S["Azure Communication"]; | ||
} |
Oops, something went wrong.