diff --git a/src/bielu.Umbraco.Cdn.Abstraction/Models/Provider.cs b/src/bielu.Umbraco.Cdn.Abstraction/Models/Provider.cs index a395c95..c697f3b 100644 --- a/src/bielu.Umbraco.Cdn.Abstraction/Models/Provider.cs +++ b/src/bielu.Umbraco.Cdn.Abstraction/Models/Provider.cs @@ -4,8 +4,9 @@ namespace bielu.Umbraco.Cdn.Models; public class Provider { + public bool Enabled { get; set; } public string? Id { get; set; } public string? Name { get; set; } public IList? SupportedHostnames { get; set; } - public int NodeId { get; set; } + public string Version { get; set; } } \ No newline at end of file diff --git a/src/bielu.Umbraco.Cdn.Aws.CloudFront/Extensions/BieluUmbracoCdnCloudflareExtensions.cs b/src/bielu.Umbraco.Cdn.Aws.CloudFront/Extensions/BieluUmbracoCdnCloudflareExtensions.cs index 65dc881..d6f21f1 100644 --- a/src/bielu.Umbraco.Cdn.Aws.CloudFront/Extensions/BieluUmbracoCdnCloudflareExtensions.cs +++ b/src/bielu.Umbraco.Cdn.Aws.CloudFront/Extensions/BieluUmbracoCdnCloudflareExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using bielu.Umbraco.Cdn.Aws.Services; using bielu.Umbraco.Cdn.Services; using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.DependencyInjection; @@ -19,7 +20,7 @@ public static IUmbracoBuilder AddAwsCloudFrontCdnProvider( .AddClasses(c => c.AssignableTo(typeof(ICdnService))) .AsImplementedInterfaces() .WithTransientLifetime()); - + builder.Services.AddSingleton(); return builder; } diff --git a/src/bielu.Umbraco.Cdn.Aws.CloudFront/bielu.Umbraco.Cdn.Aws.CloudFront.csproj b/src/bielu.Umbraco.Cdn.Aws.CloudFront/bielu.Umbraco.Cdn.Aws.CloudFront.csproj index f4dffcd..51195af 100644 --- a/src/bielu.Umbraco.Cdn.Aws.CloudFront/bielu.Umbraco.Cdn.Aws.CloudFront.csproj +++ b/src/bielu.Umbraco.Cdn.Aws.CloudFront/bielu.Umbraco.Cdn.Aws.CloudFront.csproj @@ -11,7 +11,7 @@ true - + diff --git a/src/bielu.Umbraco.Cdn.Azure.FrontDoor/Extensions/BieluUmbracoCdnAzureFrontDoorExtensions.cs b/src/bielu.Umbraco.Cdn.Azure.FrontDoor/Extensions/BieluUmbracoCdnAzureFrontDoorExtensions.cs new file mode 100644 index 0000000..3423a1c --- /dev/null +++ b/src/bielu.Umbraco.Cdn.Azure.FrontDoor/Extensions/BieluUmbracoCdnAzureFrontDoorExtensions.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using bielu.Umbraco.Cdn.Azure.Configuration; +using bielu.Umbraco.Cdn.Azure.Services; +using bielu.Umbraco.Cdn.Services; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Umbraco.Cms.Core.DependencyInjection; + +namespace bielu.Umbraco.Cdn.Azure.Extensions +{ + public static class BieluUmbracoCdnAzureFrontDoorExtensions + { + public static IUmbracoBuilder AddAzureFrontDoorCdnProvider( + this IUmbracoBuilder builder) + { + if (builder == null) + throw new ArgumentNullException(nameof(builder)); + builder.Services.Scan(s => + s.FromAssemblies(new List() { typeof(BieluUmbracoCdnAzureFrontDoorExtensions).Assembly }) + .AddClasses(c => c.AssignableTo(typeof(ICdnService))) + .AsImplementedInterfaces() + .WithTransientLifetime()); + builder.Services.AddSingleton(typeof(IFrontDoorClientFactory), typeof(FrontDoorClientFactory)); + builder.Services.AddSingleton(typeof(IArmClientFactory), typeof(ArmClientFactory)); + var positionOptions = new FrontDoorOptions(); + builder.Config.GetSection(FrontDoorOptions.SectionName).Bind(positionOptions); + builder.Services.AddOptions().BindConfiguration(FrontDoorOptions.SectionName); + return builder; + } + } +} \ No newline at end of file diff --git a/src/bielu.Umbraco.Cdn.Azure.FrontDoor/Services/FrontDoorClientFactory.cs b/src/bielu.Umbraco.Cdn.Azure.FrontDoor/Services/FrontDoorClientFactory.cs index c73dab1..1741f7f 100644 --- a/src/bielu.Umbraco.Cdn.Azure.FrontDoor/Services/FrontDoorClientFactory.cs +++ b/src/bielu.Umbraco.Cdn.Azure.FrontDoor/Services/FrontDoorClientFactory.cs @@ -20,6 +20,10 @@ public FrontDoorClientFactory(IArmClientFactory armClientFactory, IOptionsMonito public FrontDoorResource GetFrontDoorClient() { + if (_frontDoorOptions.CurrentValue.Disabled) + { + return null; + } var armClient = _armClientFactory.GetFrontDoorClient(); string resourceGroupName =_frontDoorOptions.CurrentValue.ResourceGroupName; SubscriptionResource subscription = armClient.GetSubscriptionResource(new ResourceIdentifier(_frontDoorOptions.CurrentValue.SubscriptionId)); diff --git a/src/bielu.Umbraco.Cdn.Azure.FrontDoor/bielu.Umbraco.Cdn.Azure.FrontDoor.csproj b/src/bielu.Umbraco.Cdn.Azure.FrontDoor/bielu.Umbraco.Cdn.Azure.FrontDoor.csproj index 728aed6..1107d13 100644 --- a/src/bielu.Umbraco.Cdn.Azure.FrontDoor/bielu.Umbraco.Cdn.Azure.FrontDoor.csproj +++ b/src/bielu.Umbraco.Cdn.Azure.FrontDoor/bielu.Umbraco.Cdn.Azure.FrontDoor.csproj @@ -11,7 +11,7 @@ true - + diff --git a/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Content/ContentEventsNotificationNotificationHandler.cs b/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Content/ContentEventsNotificationNotificationHandler.cs index 89e58bd..a435738 100644 --- a/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Content/ContentEventsNotificationNotificationHandler.cs +++ b/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Content/ContentEventsNotificationNotificationHandler.cs @@ -61,7 +61,7 @@ public async Task HandleAsync(ContentMovingNotification notification, Cancellati } //todo: optimize as now we dont valide which domains is valid for either of cdns - foreach (var cdnServices in _cdnServices) + foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled())) { var result = Task.Run(async () => { return await cdnServices.PurgePages(pages); }).Result; var errors = false; @@ -109,7 +109,7 @@ public async Task HandleAsync(ContentDeletingNotification notification, Cancella } //todo: optimize as now we dont valide which domains is valid for either of cdns - foreach (var cdnServices in _cdnServices) + foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled())) { try { @@ -220,7 +220,7 @@ public async Task HandleAsync(ContentPublishedNotification notification, Cancell try { //todo: optimize as now we dont valide which domains is valid for either of cdns - foreach (var cdnServices in _cdnServices) + foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled())) { var result = Task.Run(async () => { return await cdnServices.PurgePages(pages); }).Result; EventMessage message; @@ -330,7 +330,7 @@ public async Task HandleAsync(ContentSavedNotification notification, Cancellatio } } - foreach (var cdnServices in _cdnServices) + foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled())) { var result = Task.Run(async () => { return await cdnServices.PurgePages(pages); }).Result; EventMessage message; diff --git a/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Domain/DomainEventNotificationNotificationHandler.cs b/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Domain/DomainEventNotificationNotificationHandler.cs index 8332ccc..df6eac0 100644 --- a/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Domain/DomainEventNotificationNotificationHandler.cs +++ b/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Domain/DomainEventNotificationNotificationHandler.cs @@ -28,7 +28,7 @@ public DomainEventNotificationNotificationHandler(IUmbracoUrlDeliveryService umb public async Task HandleAsync(DomainSavedNotification notification, CancellationToken cancellationToken) { //todo: optimize as now we dont valide which domains is valid for either of cdns - foreach (var cdnServices in _cdnServices) + foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled())) { //todo: split on / as umbraco is dump to count / as part of domain var result = Task.Run(async () => @@ -52,7 +52,7 @@ public async Task HandleAsync(DomainSavedNotification notification, Cancellation public async Task HandleAsync(DomainDeletedNotification notification, CancellationToken cancellationToken) { //todo: optimize as now we dont valide which domains is valid for either of cdns - foreach (var cdnServices in _cdnServices) + foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled())) { //todo: split on / as umbraco is dump to count / as part of domain var result = Task.Run(async () => diff --git a/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Media/MediaEventsNotificationNotificationHandler.cs b/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Media/MediaEventsNotificationNotificationHandler.cs index 60db509..4ce83ac 100644 --- a/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Media/MediaEventsNotificationNotificationHandler.cs +++ b/src/bielu.Umbraco.Cdn.Core/NotitificationHandlers/Media/MediaEventsNotificationNotificationHandler.cs @@ -67,7 +67,7 @@ public async Task HandleAsync(MediaSavedNotification notification, CancellationT } //todo: optimize as now we dont valide which domains is valid for either of cdns - foreach (var cdnServices in _cdnServices) + foreach (var cdnServices in _cdnServices.Where(x=>x.IsEnabled())) { var result = Task.Run(async () => { diff --git a/src/bielu.Umbraco.Cdn.Core/Services/CdnManager.cs b/src/bielu.Umbraco.Cdn.Core/Services/CdnManager.cs index 85f4d71..9465670 100644 --- a/src/bielu.Umbraco.Cdn.Core/Services/CdnManager.cs +++ b/src/bielu.Umbraco.Cdn.Core/Services/CdnManager.cs @@ -12,36 +12,48 @@ public class CdnManager : ICdnManager { private readonly IEnumerable _services; private readonly IUmbracoContextFactory _contextFactory; - private readonly IEnumerable _providers; - public CdnManager(IEnumerable services, IUmbracoContextFactory contextFactory) + private IEnumerable _providers { - _services = services; - _contextFactory = contextFactory; - using (var contextReference = _contextFactory.EnsureUmbracoContext()) + get { - var umbracoDomains = contextReference.UmbracoContext.Domains.GetAll(false); - - _providers = umbracoDomains.SelectMany(domain => + using (var contextReference = _contextFactory.EnsureUmbracoContext()) { - return services.Select(x => new Provider() - { - Name = x.GetType().Name, - Id = x.GetType().Name, - NodeId = domain.ContentId, - SupportedHostnames = Task.Run(async () => + var umbracoDomains = contextReference.UmbracoContext.Domains.GetAll(false); + + + return _services.Select(x => new Provider() { - var supportedHostNames = await x.GetSupportedHostnames(); - return umbracoDomains.Where(domain => supportedHostNames.Contains(domain.Name)) - .Select(domain => domain.Name).ToList(); - }).Result - }); - }); + Name = x.GetType().Name, + Id = x.GetType().Name, + Version = x.GetType().Assembly.GetName().Version.ToString(), + Enabled = x.IsEnabled(), + SupportedHostnames = Task.Run(async () => + { + if (!x.IsEnabled()) + { + return null; + } + var supportedHostNames = await x.GetSupportedHostnames(); + return umbracoDomains.Where(domain => supportedHostNames.Any(zone=>domain.Name.Contains(zone))) + .Select(domain => domain.Name).ToList(); + }).Result + }); + } } } + public CdnManager(IEnumerable services, IUmbracoContextFactory contextFactory) + { + _services = services; + _contextFactory = contextFactory; + + } + + public async Task> GetProviders(int guid) { + return _providers; } diff --git a/src/bielu.Umbraco.TestProject/Startup.cs b/src/bielu.Umbraco.TestProject/Startup.cs index 4598120..9b204fb 100644 --- a/src/bielu.Umbraco.TestProject/Startup.cs +++ b/src/bielu.Umbraco.TestProject/Startup.cs @@ -51,8 +51,8 @@ public void ConfigureServices(IServiceCollection services) .AddComposers() .AddCloudflareCdnProvider() .AddAzureFrontDoorCdnProvider() - .AddAwsCloudFrontCdnProvider() - .AddAkamaiCdnProvider() + // .AddAwsCloudFrontCdnProvider() + //.AddAkamaiCdnProvider() .Build(); services.AddTransient(typeof(IClouflareAuthentication), typeof(TokenApiClouflareAuthentication)); diff --git a/src/bielu.Umbraco.TestProject/appsettings.json b/src/bielu.Umbraco.TestProject/appsettings.json index efd591d..99350b2 100644 --- a/src/bielu.Umbraco.TestProject/appsettings.json +++ b/src/bielu.Umbraco.TestProject/appsettings.json @@ -14,8 +14,9 @@ "umbracoDbDSN": "Data Source=|DataDirectory|/Umbraco.sqlite.db;Cache=Shared;Foreign Keys=True;Pooling=True", "umbracoDbDSN_ProviderName": "Microsoft.Data.SQLite" }, - "bielu": { - "cdn": { + "Bielu": { + "Cdn": { + "DevMode": true, "cloudflare": { "enabled": true, "token": "-- token - use secret.json --" diff --git a/src/bielu.Umbraco.TestProject/bielu.Umbraco.TestProject.csproj b/src/bielu.Umbraco.TestProject/bielu.Umbraco.TestProject.csproj index 4caea3d..cce0ad2 100644 --- a/src/bielu.Umbraco.TestProject/bielu.Umbraco.TestProject.csproj +++ b/src/bielu.Umbraco.TestProject/bielu.Umbraco.TestProject.csproj @@ -40,7 +40,7 @@ - + true diff --git a/src/bielu.Umbraco.TestProject/nswag.json b/src/bielu.Umbraco.TestProject/nswag.json index 39c9f58..57b612d 100644 --- a/src/bielu.Umbraco.TestProject/nswag.json +++ b/src/bielu.Umbraco.TestProject/nswag.json @@ -6,7 +6,7 @@ "msBuildProjectExtensionsPath": null, "configuration": null, "runtime": "", - "targetFramework": "net60", + "targetFramework": "net6.0", "noBuild": true, "verbose": true, "workingDirectory": null, diff --git a/src/bielu.cdn.ui/src/Services/umbraco/generated/api.generated.clients.ts b/src/bielu.cdn.ui/src/Services/umbraco/generated/api.generated.clients.ts index 0a5dbd1..fa37a22 100644 --- a/src/bielu.cdn.ui/src/Services/umbraco/generated/api.generated.clients.ts +++ b/src/bielu.cdn.ui/src/Services/umbraco/generated/api.generated.clients.ts @@ -16,7 +16,7 @@ export interface IManagementClient { getProviders(id?: number | undefined): Promise; - refreshForNode(id: number, providerId?: string | null | undefined, domain?: string | null | undefined): Promise; + refreshForNode(id: number, providerId?: string | undefined, domain?: string | undefined): Promise; } export class ManagementClient implements IManagementClient { @@ -117,15 +117,19 @@ export class ManagementClient implements IManagementClient { return Promise.resolve(null as any); } - refreshForNode(id: number, providerId?: string | null | undefined, domain?: string | null | undefined): Promise { + refreshForNode(id: number, providerId?: string | undefined, domain?: string | undefined): Promise { let url_ = this.baseUrl + "/cdn/api/management/RefreshForNode?"; if (id === undefined || id === null) throw new Error("The parameter 'id' must be defined and cannot be null."); else url_ += "id=" + encodeURIComponent("" + id) + "&"; - if (providerId !== undefined && providerId !== null) + if (providerId === null) + throw new Error("The parameter 'providerId' cannot be null."); + else if (providerId !== undefined) url_ += "providerId=" + encodeURIComponent("" + providerId) + "&"; - if (domain !== undefined && domain !== null) + if (domain === null) + throw new Error("The parameter 'domain' cannot be null."); + else if (domain !== undefined) url_ += "domain=" + encodeURIComponent("" + domain) + "&"; url_ = url_.replace(/[?&]$/, ""); @@ -212,10 +216,11 @@ export interface IAuditRecord { } export class Provider implements IProvider { + enabled!: boolean; id!: string | null; name!: string | null; supportedHostnames!: string[] | null; - nodeId!: number; + version!: string; constructor(data?: IProvider) { if (data) { @@ -228,6 +233,7 @@ export class Provider implements IProvider { init(_data?: any, _mappings?: any) { if (_data) { + this.enabled = _data["enabled"] !== undefined ? _data["enabled"] : null; this.id = _data["id"] !== undefined ? _data["id"] : null; this.name = _data["name"] !== undefined ? _data["name"] : null; if (Array.isArray(_data["supportedHostnames"])) { @@ -238,7 +244,7 @@ export class Provider implements IProvider { else { this.supportedHostnames = null; } - this.nodeId = _data["nodeId"] !== undefined ? _data["nodeId"] : null; + this.version = _data["version"] !== undefined ? _data["version"] : null; } } @@ -249,6 +255,7 @@ export class Provider implements IProvider { toJSON(data?: any) { data = typeof data === 'object' ? data : {}; + data["enabled"] = this.enabled !== undefined ? this.enabled : null; data["id"] = this.id !== undefined ? this.id : null; data["name"] = this.name !== undefined ? this.name : null; if (Array.isArray(this.supportedHostnames)) { @@ -256,23 +263,24 @@ export class Provider implements IProvider { for (let item of this.supportedHostnames) data["supportedHostnames"].push(item); } - data["nodeId"] = this.nodeId !== undefined ? this.nodeId : null; + data["version"] = this.version !== undefined ? this.version : null; return data; } } export interface IProvider { + enabled: boolean; id: string | null; name: string | null; supportedHostnames: string[] | null; - nodeId: number; + version: string; } export class Status implements IStatus { success!: boolean; message!: string | null; details!: string | null; - errors!: (Errors | null)[] | null; + errors!: Errors[] | null; exception!: Exception | null; messageType!: EventMessageType | null; @@ -328,7 +336,7 @@ export interface IStatus { success: boolean; message: string | null; details: string | null; - errors: (Errors | null)[] | null; + errors: Errors[] | null; exception: Exception | null; messageType: EventMessageType | null; } diff --git a/src/bielu.cdn.ui/src/components/CdnDashboard.vue b/src/bielu.cdn.ui/src/components/CdnDashboard.vue index 8d029d2..1e1b863 100644 --- a/src/bielu.cdn.ui/src/components/CdnDashboard.vue +++ b/src/bielu.cdn.ui/src/components/CdnDashboard.vue @@ -1,21 +1,47 @@ @@ -23,11 +49,74 @@ export default defineComponent({ \ No newline at end of file diff --git a/src/bielu.cdn.ui/tsconfig.json b/src/bielu.cdn.ui/tsconfig.json index 28e5b08..bb178be 100644 --- a/src/bielu.cdn.ui/tsconfig.json +++ b/src/bielu.cdn.ui/tsconfig.json @@ -1,24 +1,23 @@ { "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, "module": "ESNext", "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "allowJs": true, - /* Linting */ + "target": "ES2020", + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "./types", "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "Node", + "isolatedModules": true, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "forceConsistentCasingInFileNames": true, + "useDefineForClassFields": false, + "skipLibCheck": true }, "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"], diff --git a/src/bielu.cdn.ui/wwwroot/App_Plugins/bielu.cdn.ui/bielu.cdn.ui.angularController.js b/src/bielu.cdn.ui/wwwroot/App_Plugins/bielu.cdn.ui/bielu.cdn.ui.angularController.js index 5b2ad7b..746a575 100644 --- a/src/bielu.cdn.ui/wwwroot/App_Plugins/bielu.cdn.ui/bielu.cdn.ui.angularController.js +++ b/src/bielu.cdn.ui/wwwroot/App_Plugins/bielu.cdn.ui/bielu.cdn.ui.angularController.js @@ -1,5 +1,4 @@ -import RefreshNode from "../../../src/components/RefreshNode.vue"; - + angular.module('umbraco') .controller('bielu.cdn.ui.controller', function (