From 3358d9e32007e19690422166dbce514bb0680cee Mon Sep 17 00:00:00 2001
From: Gary Sharp
Date: Mon, 28 Jul 2014 15:02:33 +1000
Subject: [PATCH] Update: Disco ICT Online Services - Plugin Library
Migrate plugin library to https://services.discoict.com.au
---
.../PluginLibraryCompatibilityItem.cs | 16 -
.../PluginLibraryCompatibilityRequest.cs | 14 -
.../PluginLibraryCompatibilityResponse.cs | 15 -
.../BI/Interop/Community/PluginLibraryItem.cs | 23 --
.../Community/PluginLibraryUpdateRequest.cs | 14 -
.../Community/PluginLibraryUpdateResponse.cs | 14 -
Disco.Models/Disco.Models.csproj | 11 +-
.../DiscoServices/PluginIncompatibility.cs | 12 +
.../PluginLibraryIncompatibility.cs | 11 +
.../DiscoServices/PluginLibraryManifestV2.cs | 41 +++
Disco.Services/Disco.Services.csproj | 5 +-
.../Interop/DiscoServices/PluginLibrary.cs | 149 +++++++++
.../DiscoServices/PluginLibraryUpdateTask.cs | 63 ++++
.../PluginLibraryUpdateTask.cs | 218 -------------
Disco.Services/Plugins/InstallPluginTask.cs | 38 +--
Disco.Services/Plugins/Plugins.cs | 102 +-----
Disco.Services/Plugins/UpdatePluginTask.cs | 128 ++++----
.../UpdatePluginsAfterDiscoUpdateTask.cs | 16 +-
.../Areas/API/Controllers/PluginController.cs | 24 +-
.../Config/Controllers/PluginsController.cs | 11 +-
.../Config/Models/Plugins/IndexViewModel.cs | 32 +-
.../Config/Models/Plugins/InstallModel.cs | 24 +-
.../Plugins/PluginConfigurationViewModel.cs | 7 +-
.../Areas/Config/Views/Plugins/Install.cshtml | 101 +++---
.../Config/Views/Plugins/Install.generated.cs | 296 +++++++++---------
Disco.Web/ClientBin/.gitignore | 3 +-
Disco.Web/ClientSource/Style/BundleSite.css | 1 +
.../ClientSource/Style/BundleSite.min.css | 2 +-
Disco.Web/ClientSource/Style/Config.css | 33 +-
Disco.Web/ClientSource/Style/Config.less | 42 ++-
Disco.Web/ClientSource/Style/Config.min.css | 2 +-
Disco.Web/ClientSource/Style/Site.css | 1 +
Disco.Web/ClientSource/Style/Site.less | 1 +
Disco.Web/ClientSource/Style/Site.min.css | 2 +-
Disco.Web/Disco.Web.csproj | 1 +
.../T4MVC/API.PluginController.generated.cs | 18 +-
Disco.Web/Extensions/T4MVC/T4MVC.cs | 1 +
37 files changed, 729 insertions(+), 763 deletions(-)
delete mode 100644 Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityItem.cs
delete mode 100644 Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityRequest.cs
delete mode 100644 Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityResponse.cs
delete mode 100644 Disco.Models/BI/Interop/Community/PluginLibraryItem.cs
delete mode 100644 Disco.Models/BI/Interop/Community/PluginLibraryUpdateRequest.cs
delete mode 100644 Disco.Models/BI/Interop/Community/PluginLibraryUpdateResponse.cs
create mode 100644 Disco.Models/Services/Interop/DiscoServices/PluginIncompatibility.cs
create mode 100644 Disco.Models/Services/Interop/DiscoServices/PluginLibraryIncompatibility.cs
create mode 100644 Disco.Models/Services/Interop/DiscoServices/PluginLibraryManifestV2.cs
create mode 100644 Disco.Services/Interop/DiscoServices/PluginLibrary.cs
create mode 100644 Disco.Services/Interop/DiscoServices/PluginLibraryUpdateTask.cs
delete mode 100644 Disco.Services/Plugins/CommunityInterop/PluginLibraryUpdateTask.cs
diff --git a/Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityItem.cs b/Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityItem.cs
deleted file mode 100644
index 74ff740b..00000000
--- a/Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityItem.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Disco.Models.BI.Interop.Community
-{
- public class PluginLibraryCompatibilityItem
- {
- public string Id { get; set; }
- public string Version { get; set; }
- public bool Compatible { get; set; }
- public string Reason { get; set; }
- }
-}
diff --git a/Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityRequest.cs b/Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityRequest.cs
deleted file mode 100644
index 14fd0eaa..00000000
--- a/Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityRequest.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Disco.Models.BI.Interop.Community
-{
- public class PluginLibraryCompatibilityRequest
- {
- public string HostVersion { get; set; }
- public string DeploymentId { get; set; }
- }
-}
diff --git a/Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityResponse.cs b/Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityResponse.cs
deleted file mode 100644
index 9af50f48..00000000
--- a/Disco.Models/BI/Interop/Community/PluginLibraryCompatibilityResponse.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Disco.Models.BI.Interop.Community
-{
- public class PluginLibraryCompatibilityResponse
- {
- public string HostVersion { get; set; }
- public DateTime ResponseTimestamp { get; set; }
- public List Plugins { get; set; }
- }
-}
diff --git a/Disco.Models/BI/Interop/Community/PluginLibraryItem.cs b/Disco.Models/BI/Interop/Community/PluginLibraryItem.cs
deleted file mode 100644
index a8b7d117..00000000
--- a/Disco.Models/BI/Interop/Community/PluginLibraryItem.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Disco.Models.BI.Interop.Community
-{
- public class PluginLibraryItem
- {
- public string Id { get; set; }
- public string Name { get; set; }
- public string Author { get; set; }
- public string Url { get; set; }
- public string Blurb { get; set; }
-
- public string LatestVersion { get; set; }
- public string LatestChangeLog { get; set; }
- public string LatestHostVersionMin { get; set; }
- public string LatestHostVersionMax { get; set; }
- public string LatestDownloadUrl { get; set; }
- }
-}
diff --git a/Disco.Models/BI/Interop/Community/PluginLibraryUpdateRequest.cs b/Disco.Models/BI/Interop/Community/PluginLibraryUpdateRequest.cs
deleted file mode 100644
index 11199452..00000000
--- a/Disco.Models/BI/Interop/Community/PluginLibraryUpdateRequest.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Disco.Models.BI.Interop.Community
-{
- public class PluginLibraryUpdateRequest
- {
- public string HostVersion { get; set; }
- public string DeploymentId { get; set; }
- }
-}
diff --git a/Disco.Models/BI/Interop/Community/PluginLibraryUpdateResponse.cs b/Disco.Models/BI/Interop/Community/PluginLibraryUpdateResponse.cs
deleted file mode 100644
index 9905e483..00000000
--- a/Disco.Models/BI/Interop/Community/PluginLibraryUpdateResponse.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Disco.Models.BI.Interop.Community
-{
- public class PluginLibraryUpdateResponse
- {
- public DateTime ResponseTimestamp { get; set; }
- public List Plugins { get; set; }
- }
-}
diff --git a/Disco.Models/Disco.Models.csproj b/Disco.Models/Disco.Models.csproj
index 9382c795..6ece3428 100644
--- a/Disco.Models/Disco.Models.csproj
+++ b/Disco.Models/Disco.Models.csproj
@@ -57,12 +57,6 @@
-
-
-
-
-
-
@@ -109,6 +103,9 @@
+
+
+
@@ -182,7 +179,7 @@
-
+
diff --git a/Disco.Models/Services/Interop/DiscoServices/PluginIncompatibility.cs b/Disco.Models/Services/Interop/DiscoServices/PluginIncompatibility.cs
new file mode 100644
index 00000000..22615c68
--- /dev/null
+++ b/Disco.Models/Services/Interop/DiscoServices/PluginIncompatibility.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Disco.Models.Services.Interop.DiscoServices
+{
+ public class PluginIncompatibility
+ {
+ public string PluginId { get; set; }
+ public Version Version { get; set; }
+
+ public string Reason { get; set; }
+ }
+}
diff --git a/Disco.Models/Services/Interop/DiscoServices/PluginLibraryIncompatibility.cs b/Disco.Models/Services/Interop/DiscoServices/PluginLibraryIncompatibility.cs
new file mode 100644
index 00000000..b43912d6
--- /dev/null
+++ b/Disco.Models/Services/Interop/DiscoServices/PluginLibraryIncompatibility.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace Disco.Models.Services.Interop.DiscoServices
+{
+ public class PluginLibraryIncompatibility
+ {
+
+ public List IncompatiblePlugins { get; set; }
+
+ }
+}
diff --git a/Disco.Models/Services/Interop/DiscoServices/PluginLibraryManifestV2.cs b/Disco.Models/Services/Interop/DiscoServices/PluginLibraryManifestV2.cs
new file mode 100644
index 00000000..66554807
--- /dev/null
+++ b/Disco.Models/Services/Interop/DiscoServices/PluginLibraryManifestV2.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+
+namespace Disco.Models.Services.Interop.DiscoServices
+{
+ public class PluginLibraryManifestV2
+ {
+ public DateTime ManifestDate { get; set; }
+
+ public List Plugins { get; set; }
+ }
+
+ public class PluginLibraryItemV2
+ {
+ public string Id { get; set; }
+ public string Name { get; set; }
+ public string Author { get; set; }
+ public string InformationUrl { get; set; }
+
+ public string PrimaryFeatureCategory { get; set; }
+
+ public string Description { get; set; }
+
+ public List Releases { get; set; }
+ }
+
+ public class PluginLibraryItemReleaseV2
+ {
+ public string PluginId { get; set; }
+ public string Version { get; set; }
+
+ public string HostMinVersion { get; set; }
+ public string HostMaxVersion { get; set; }
+
+ public bool Blocked { get; set; }
+
+ public string Description { get; set; }
+
+ public string DownloadUrl { get; set; }
+ }
+}
diff --git a/Disco.Services/Disco.Services.csproj b/Disco.Services/Disco.Services.csproj
index d2b3af3e..898c57c4 100644
--- a/Disco.Services/Disco.Services.csproj
+++ b/Disco.Services/Disco.Services.csproj
@@ -248,6 +248,8 @@
+
+
@@ -275,7 +277,6 @@
-
@@ -379,7 +380,7 @@
-
+
diff --git a/Disco.Services/Interop/DiscoServices/PluginLibrary.cs b/Disco.Services/Interop/DiscoServices/PluginLibrary.cs
new file mode 100644
index 00000000..3b3c269c
--- /dev/null
+++ b/Disco.Services/Interop/DiscoServices/PluginLibrary.cs
@@ -0,0 +1,149 @@
+using Disco.Data.Repository;
+using Disco.Models.Services.Interop.DiscoServices;
+using Disco.Services.Tasks;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Web;
+
+namespace Disco.Services.Interop.DiscoServices
+{
+ public static class PluginLibrary
+ {
+ private static string UpdateUrl()
+ {
+ return string.Concat(DiscoServiceHelpers.ServicesUrl, "API/Plugins/Library/V2");
+ }
+
+ public static string InitialManifestFilename()
+ {
+ return HttpContext.Current.Server.MapPath("~/ClientBin/DiscoServices.InitialPluginLibraryManifest.json");
+ }
+
+ public static string ManifestFilename(DiscoDataContext Database)
+ {
+ return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "LibraryManifest.json");
+ }
+
+ public static PluginLibraryManifestV2 LoadManifest(DiscoDataContext Database)
+ {
+ var manifestFile = ManifestFilename(Database);
+
+ if (File.Exists(manifestFile))
+ {
+ return JsonConvert.DeserializeObject(File.ReadAllText(manifestFile));
+ }
+ else
+ {
+ // Use Initial Plugin Library Manifest
+ manifestFile = InitialManifestFilename();
+
+ if (File.Exists(manifestFile))
+ return JsonConvert.DeserializeObject(File.ReadAllText(manifestFile));
+
+ throw new FileNotFoundException("No plugin library manifest file was found", manifestFile);
+ }
+ }
+
+ public static PluginLibraryIncompatibility LoadIncompatibilityData(this PluginLibraryManifestV2 LibraryManifest)
+ {
+ var pluginAssembly = typeof(PluginLibrary).Assembly;
+ Version hostVersion = pluginAssembly.GetName().Version;
+
+ return new PluginLibraryIncompatibility()
+ {
+ IncompatiblePlugins = LibraryManifest.Plugins.SelectMany(p => p.Releases, (p, r) =>
+ {
+ var rVersion = Version.Parse(r.Version);
+
+ if (r.Blocked)
+ return new PluginIncompatibility() { PluginId = r.PluginId, Version = rVersion, Reason = "This plugin release is blocked by Disco ICT Online Services" };
+
+ if (r.HostMinVersion != null && hostVersion < Version.Parse(r.HostMinVersion))
+ return new PluginIncompatibility() { PluginId = r.PluginId, Version = rVersion, Reason = string.Format("This plugin requires v{0} or newer", r.HostMinVersion) };
+
+ if (r.HostMaxVersion != null && hostVersion > Version.Parse(r.HostMaxVersion))
+ return new PluginIncompatibility() { PluginId = r.PluginId, Version = rVersion, Reason = string.Format("This plugin requires v{0} or older", r.HostMaxVersion) };
+
+ return null;
+ }).Where(i => i != null).ToList()
+ };
+ }
+
+ public static PluginLibraryManifestV2 UpdateManifest(DiscoDataContext Database, IScheduledTaskStatus Status)
+ {
+ Status.UpdateStatus(10, "Sending Request");
+
+ PluginLibraryManifestV2 result;
+
+ var discoVersion = UpdateQuery.CurrentDiscoVersionFormatted();
+ var url = UpdateUrl();
+
+ using (var httpClient = new HttpClient())
+ {
+ using (var formData = new FormUrlEncodedContent(new KeyValuePair[] {
+ new KeyValuePair("DeploymentId", Database.DiscoConfiguration.DeploymentId),
+ new KeyValuePair("DiscoVersion", discoVersion)
+ }))
+ {
+ var response = httpClient.PostAsync(url, formData).Result;
+
+ response.EnsureSuccessStatusCode();
+
+ Status.UpdateStatus(50, "Waiting for Response");
+
+ var resultJson = response.Content.ReadAsStringAsync().Result;
+
+ Status.UpdateStatus(90, "Processing Response");
+
+ result = JsonConvert.DeserializeObject(resultJson);
+ }
+ }
+
+ var manifestJson = JsonConvert.SerializeObject(result);
+
+ var manifestFile = PluginLibrary.ManifestFilename(Database);
+
+ if (!Directory.Exists(Path.GetDirectoryName(manifestFile)))
+ Directory.CreateDirectory(Path.GetDirectoryName(manifestFile));
+
+ File.WriteAllText(manifestFile, manifestJson);
+
+ return result;
+ }
+
+ public static PluginLibraryItemReleaseV2 LatestCompatibleRelease(this PluginLibraryItemV2 LibraryItem, PluginLibraryIncompatibility Incompatibility)
+ {
+ return LibraryItem.Releases.OrderByDescending(r => Version.Parse(r.Version)).FirstOrDefault(r => Incompatibility.IsCompatible(r));
+ }
+
+ public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, PluginLibraryItemReleaseV2 Release)
+ {
+ PluginIncompatibility incompatibility;
+
+ return IsCompatible(IncompatibilityLibrary, Release, out incompatibility);
+ }
+
+ public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, PluginLibraryItemReleaseV2 Release, out PluginIncompatibility Incompatibility)
+ {
+ return IsCompatible(IncompatibilityLibrary, Release.PluginId, Version.Parse(Release.Version), out Incompatibility);
+ }
+
+ public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, string PluginId, Version Version)
+ {
+ PluginIncompatibility incompatibility;
+
+ return IsCompatible(IncompatibilityLibrary, PluginId, Version, out incompatibility);
+ }
+
+ public static bool IsCompatible(this PluginLibraryIncompatibility IncompatibilityLibrary, string PluginId, Version Version, out PluginIncompatibility Incompatibility)
+ {
+ Incompatibility = IncompatibilityLibrary.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(PluginId, StringComparison.OrdinalIgnoreCase) && i.Version == Version);
+
+ return Incompatibility == null;
+ }
+ }
+}
diff --git a/Disco.Services/Interop/DiscoServices/PluginLibraryUpdateTask.cs b/Disco.Services/Interop/DiscoServices/PluginLibraryUpdateTask.cs
new file mode 100644
index 00000000..8178f05b
--- /dev/null
+++ b/Disco.Services/Interop/DiscoServices/PluginLibraryUpdateTask.cs
@@ -0,0 +1,63 @@
+using Disco.Data.Repository;
+using Disco.Services.Tasks;
+using Newtonsoft.Json;
+using Quartz;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Disco.Services.Interop.DiscoServices
+{
+ public class PluginLibraryUpdateTask : ScheduledTask
+ {
+ public override string TaskName { get { return "Disco ICT - Update Plugin Library"; } }
+ public override bool SingleInstanceTask { get { return true; } }
+ public override bool CancelInitiallySupported { get { return false; } }
+
+ public override void InitalizeScheduledTask(DiscoDataContext Database)
+ {
+ // Random time between midday and midnight.
+ var rnd = new Random();
+
+ var rndHour = rnd.Next(12, 23);
+ var rndMinute = rnd.Next(0, 59);
+
+ TriggerBuilder triggerBuilder = TriggerBuilder.Create().
+ WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(rndHour, rndMinute));
+
+ this.ScheduleTask(triggerBuilder);
+ }
+
+ protected override void ExecuteTask()
+ {
+ using (DiscoDataContext database = new DiscoDataContext())
+ {
+ Status.UpdateStatus(1, "Updating Plugin Library Manifest", "Initializing");
+
+ var manifest = PluginLibrary.UpdateManifest(database, this.Status);
+
+ Status.SetFinishedMessage("The Plugin Library Manifest was updated successfully");
+ }
+ }
+
+ public static ScheduledTaskStatus ScheduleNow()
+ {
+ var taskStatus = RunningStatus;
+ if (taskStatus != null)
+ return taskStatus;
+ else
+ {
+ var task = new PluginLibraryUpdateTask();
+ return task.ScheduleTask();
+ }
+ }
+
+ public static ScheduledTaskStatus RunningStatus
+ {
+ get
+ {
+ return ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
+ }
+ }
+ }
+}
diff --git a/Disco.Services/Plugins/CommunityInterop/PluginLibraryUpdateTask.cs b/Disco.Services/Plugins/CommunityInterop/PluginLibraryUpdateTask.cs
deleted file mode 100644
index a86d0558..00000000
--- a/Disco.Services/Plugins/CommunityInterop/PluginLibraryUpdateTask.cs
+++ /dev/null
@@ -1,218 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Disco.Data.Repository;
-using Disco.Services.Plugins;
-using Disco.Services.Tasks;
-using Disco.Models.BI.Interop.Community;
-using System.Net;
-using System.Xml.Serialization;
-using System.IO;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Converters;
-using Quartz;
-using Disco.Services.Interop.DiscoServices;
-
-namespace Disco.Services.Plugins.CommunityInterop
-{
- public class PluginLibraryUpdateTask : ScheduledTask
- {
- public override string TaskName { get { return "Disco Community - Update Plugin Library"; } }
-
- public static string CurrentDiscoVersion()
- {
- var AssemblyVersion = typeof(PluginLibraryUpdateTask).Assembly.GetName().Version;
- return string.Format("{0}.{1}.{2:0000}.{3:0000}", AssemblyVersion.Major, AssemblyVersion.Minor, AssemblyVersion.Build, AssemblyVersion.Revision);
- }
-
- protected override void ExecuteTask()
- {
- ExecuteTaskInternal(this.Status);
- Status.SetFinishedMessage("The Plugin Library Catalogue was updated.");
- }
-
- internal static void ExecuteTaskInternal(ScheduledTaskStatus Status)
- {
- PluginLibraryUpdateRequest updateRequestBody;
- PluginLibraryUpdateResponse updateResult;
- string catalogueFile;
- PluginLibraryCompatibilityRequest compatRequestBody;
- PluginLibraryCompatibilityResponse compatResult;
- string compatibilityFile;
-
- var DiscoBIVersion = CurrentDiscoVersion();
- HttpWebRequest webRequest;
-
- #region Update
-
- Status.UpdateStatus(1, "Updating Plugin Library Catalogue", "Building Request");
-
- using (DiscoDataContext database = new DiscoDataContext())
- {
- catalogueFile = Plugins.CatalogueFile(database);
-
- updateRequestBody = new PluginLibraryUpdateRequest()
- {
- DeploymentId = database.DiscoConfiguration.DeploymentId,
- HostVersion = typeof(Plugins).Assembly.GetName().Version.ToString(4)
- };
- }
-
- Status.UpdateStatus(10, "Sending Request");
-
- webRequest = (HttpWebRequest)HttpWebRequest.Create(PluginLibraryUpdateUrl());
- webRequest.KeepAlive = false;
-
- webRequest.ContentType = "application/xml";
- webRequest.Method = WebRequestMethods.Http.Post;
- webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", DiscoBIVersion);
-
- using (var wrStream = webRequest.GetRequestStream())
- {
- XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryUpdateRequest));
- xml.Serialize(wrStream, updateRequestBody);
- }
-
- Status.UpdateStatus(20, "Waiting for Response");
-
- using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
- {
- if (webResponse.StatusCode == HttpStatusCode.OK)
- {
- Status.UpdateStatus(45, "Reading Response");
- using (var wResStream = webResponse.GetResponseStream())
- {
- XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryUpdateResponse));
- updateResult = (PluginLibraryUpdateResponse)xml.Deserialize(wResStream);
- }
- }
- else
- {
- Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
- return;
- }
- }
-
- if (!Directory.Exists(Path.GetDirectoryName(catalogueFile)))
- Directory.CreateDirectory(Path.GetDirectoryName(catalogueFile));
-
- using (FileStream fs = new FileStream(catalogueFile, FileMode.Create, FileAccess.Write, FileShare.None))
- {
- using (StreamWriter fsWriter = new StreamWriter(fs))
- {
- fsWriter.Write(JsonConvert.SerializeObject(updateResult));
- fsWriter.Flush();
- }
- }
- #endregion
-
- #region Compatibility
-
- Status.UpdateStatus(50, "Updating Plugin Library Compatibility", "Building Request");
-
- using (DiscoDataContext database = new DiscoDataContext())
- {
- compatibilityFile = Plugins.CompatibilityFile(database);
-
- compatRequestBody = new PluginLibraryCompatibilityRequest()
- {
- DeploymentId = database.DiscoConfiguration.DeploymentId,
- HostVersion = typeof(Plugins).Assembly.GetName().Version.ToString(4)
- };
- }
-
- Status.UpdateStatus(60, "Sending Request");
-
- webRequest = (HttpWebRequest)HttpWebRequest.Create(PluginLibraryCompatibilityUrl());
- webRequest.KeepAlive = false;
-
- webRequest.ContentType = "application/json";
- webRequest.Method = WebRequestMethods.Http.Post;
- webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", DiscoBIVersion);
-
- using (var wrStream = webRequest.GetRequestStream())
- {
- XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryCompatibilityRequest));
- xml.Serialize(wrStream, compatRequestBody);
- }
-
- Status.UpdateStatus(70, "Waiting for Response");
-
- using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
- {
- if (webResponse.StatusCode == HttpStatusCode.OK)
- {
- Status.UpdateStatus(95, "Reading Response");
- using (var wResStream = webResponse.GetResponseStream())
- {
- XmlSerializer xml = new XmlSerializer(typeof(PluginLibraryCompatibilityResponse));
- compatResult = (PluginLibraryCompatibilityResponse)xml.Deserialize(wResStream);
- }
- }
- else
- {
- Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
- return;
- }
- }
-
- if (!Directory.Exists(Path.GetDirectoryName(compatibilityFile)))
- Directory.CreateDirectory(Path.GetDirectoryName(compatibilityFile));
-
- using (FileStream fs = new FileStream(compatibilityFile, FileMode.Create, FileAccess.Write, FileShare.None))
- {
- using (StreamWriter fsWriter = new StreamWriter(fs))
- {
- fsWriter.Write(JsonConvert.SerializeObject(compatResult));
- fsWriter.Flush();
- }
- }
- #endregion
- }
-
- private static string PluginLibraryUpdateUrl()
- {
- return string.Concat(DiscoServiceHelpers.CommunityUrl(), "DiscoPluginLibrary/V1");
- }
- private static string PluginLibraryCompatibilityUrl()
- {
- return string.Concat(DiscoServiceHelpers.CommunityUrl(), "DiscoPluginLibrary/CompatibilityV1");
- }
-
- public static ScheduledTaskStatus ScheduleNow()
- {
-
- var taskStatus = ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
- if (taskStatus != null)
- return taskStatus;
- else
- {
- var t = new PluginLibraryUpdateTask();
- return t.ScheduleTask();
- }
- }
- public static ScheduledTaskStatus RunningStatus
- {
- get
- {
- return ScheduledTasks.GetTaskStatuses(typeof(PluginLibraryUpdateTask)).Where(ts => ts.IsRunning).FirstOrDefault();
- }
- }
-
- public override void InitalizeScheduledTask(DiscoDataContext Database)
- {
- // Random time between midday and midnight.
- var rnd = new Random();
-
- var rndHour = rnd.Next(12, 23);
- var rndMinute = rnd.Next(0, 59);
-
- TriggerBuilder triggerBuilder = TriggerBuilder.Create().
- WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(rndHour, rndMinute));
-
- this.ScheduleTask(triggerBuilder);
- }
- }
-}
diff --git a/Disco.Services/Plugins/InstallPluginTask.cs b/Disco.Services/Plugins/InstallPluginTask.cs
index 0b555d34..66c8d3c3 100644
--- a/Disco.Services/Plugins/InstallPluginTask.cs
+++ b/Disco.Services/Plugins/InstallPluginTask.cs
@@ -1,11 +1,13 @@
using Disco.Data.Repository;
+using Disco.Models.Services.Interop.DiscoServices;
+using Disco.Services.Interop.DiscoServices;
using Disco.Services.Tasks;
using Quartz;
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
-using System.Net;
+using System.Net.Http;
namespace Disco.Services.Plugins
{
@@ -33,31 +35,17 @@ namespace Disco.Services.Plugins
Directory.CreateDirectory(Path.GetDirectoryName(packageFilePath));
// Need to Download the Package
- HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(packageUrlPath);
- webRequest.KeepAlive = false;
-
- webRequest.ContentType = "application/xml";
- webRequest.Method = WebRequestMethods.Http.Get;
- webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", Disco.Services.Plugins.CommunityInterop.PluginLibraryUpdateTask.CurrentDiscoVersion());
-
- using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
+ using (HttpClient httpClient = new HttpClient())
{
- if (webResponse.StatusCode == HttpStatusCode.OK)
+ using (var httpResponse = httpClient.GetAsync(packageUrlPath).Result)
{
- Status.UpdateStatus(0, "Downloading...");
- using (var wResStream = webResponse.GetResponseStream())
+ httpResponse.EnsureSuccessStatusCode();
+
+ using (FileStream fsOut = new FileStream(packageFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
- using (FileStream fsOut = new FileStream(packageFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
- {
- wResStream.CopyTo(fsOut);
- }
+ httpResponse.Content.ReadAsStreamAsync().Result.CopyTo(fsOut);
}
}
- else
- {
- Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
- return;
- }
}
}
@@ -97,10 +85,10 @@ namespace Disco.Services.Plugins
string packagePath = Path.Combine(database.DiscoConfiguration.PluginsLocation, packageManifest.Id);
// Check for Compatibility
- var compatibilityData = Plugins.LoadCompatibilityData(database);
- var pluginCompatibility = compatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == Version.Parse(i.Version));
- if (pluginCompatibility != null && !pluginCompatibility.Compatible)
- throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginCompatibility.Reason));
+ var libraryIncompatibility = PluginLibrary.LoadManifest(database).LoadIncompatibilityData();
+ PluginIncompatibility incompatibility;
+ if (!libraryIncompatibility.IsCompatible(packageManifest.Id, packageManifest.Version, out incompatibility))
+ throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, incompatibility.Reason));
// Force Delete of Existing Folder
if (Directory.Exists(packagePath))
diff --git a/Disco.Services/Plugins/Plugins.cs b/Disco.Services/Plugins/Plugins.cs
index 48adbc77..2bce21dd 100644
--- a/Disco.Services/Plugins/Plugins.cs
+++ b/Disco.Services/Plugins/Plugins.cs
@@ -1,5 +1,6 @@
using Disco.Data.Repository;
-using Disco.Models.BI.Interop.Community;
+using Disco.Models.Services.Interop.DiscoServices;
+using Disco.Services.Interop.DiscoServices;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@@ -248,81 +249,6 @@ namespace Disco.Services.Plugins
throw new InvalidOperationException(string.Format("Unknown Plugin Feature Category Type: [{0}]", FeatureCategoryType.Name));
}
- public static string CatalogueFile(DiscoDataContext Database)
- {
- return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "Catalogue.json");
- }
- public static string CompatibilityFile(DiscoDataContext Database)
- {
- return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "Compatibility.json");
- }
-
- public static PluginLibraryUpdateResponse LoadCatalogue(DiscoDataContext Database)
- {
- var catalogueFile = CatalogueFile(Database);
-
- if (!File.Exists(catalogueFile))
- return null;
-
- return JsonConvert.DeserializeObject(File.ReadAllText(catalogueFile));
- }
-
- public static PluginLibraryCompatibilityResponse LoadCompatibilityData(DiscoDataContext Database)
- {
- var pluginAssembly = typeof(Plugins).Assembly;
- Version hostVersion = pluginAssembly.GetName().Version;
- PluginLibraryCompatibilityResponse Data = null;
- var localCompatFile = Path.Combine(Path.GetDirectoryName(pluginAssembly.Location), "ReleasePluginCompatibility.json");
- var serverCompatFile = CompatibilityFile(Database);
-
- if (File.Exists(localCompatFile))
- {
- Data = JsonConvert.DeserializeObject(File.ReadAllText(localCompatFile));
- Data.HostVersion = hostVersion.ToString(4);
- }
- if (File.Exists(serverCompatFile))
- {
- var serverData = JsonConvert.DeserializeObject(File.ReadAllText(serverCompatFile));
- if (Version.Parse(serverData.HostVersion) == hostVersion)
- {
- if (Data == null)
- {
- // No Local Compatibility File
- Data = serverData;
- }
- else
- {
- // Join Compatibility Files
- var localItems = Data.Plugins;
- var localItemVersions = localItems.ToDictionary(i => i, i => Version.Parse(i.Version));
- var joinedItems = localItems.ToList();
- Data.ResponseTimestamp = serverData.ResponseTimestamp;
- foreach (var serverItem in serverData.Plugins)
- {
- var serverItemVersion = Version.Parse(serverItem.Version);
- var localItem = localItems.FirstOrDefault(i => i.Id.Equals(serverItem.Id, StringComparison.OrdinalIgnoreCase) && serverItemVersion == localItemVersions[i]);
- if (localItem != null)
- joinedItems.Remove(localItem);
-
- joinedItems.Add(serverItem);
- }
- Data.Plugins = joinedItems;
- }
- }
- }
- if (Data == null)
- {
- Data = new PluginLibraryCompatibilityResponse()
- {
- HostVersion = hostVersion.ToString(4),
- Plugins = new List(),
- ResponseTimestamp = new DateTime(2011, 7, 1)
- };
- }
-
- return Data;
- }
-
public static void InitalizePlugins(DiscoDataContext Database)
{
if (_PluginManifests == null)
@@ -332,7 +258,7 @@ namespace Disco.Services.Plugins
if (_PluginManifests == null)
{
Version hostVersion = typeof(Plugins).Assembly.GetName().Version;
- var compatibilityData = new Lazy(() => LoadCompatibilityData(Database));
+ var compatibilityData = new Lazy(() => PluginLibrary.LoadManifest(Database).LoadIncompatibilityData());
Dictionary loadedPlugins = new Dictionary();
PluginPath = Database.DiscoConfiguration.PluginsLocation;
@@ -371,9 +297,9 @@ namespace Disco.Services.Plugins
if (pluginManifest != null)
{
// Check Version Compatibility
- var pluginCompatibility = compatibilityData.Value.Plugins.FirstOrDefault(i => i.Id.Equals(pluginManifest.Id, StringComparison.OrdinalIgnoreCase) && pluginManifest.Version == Version.Parse(i.Version));
- if (pluginCompatibility != null && !pluginCompatibility.Compatible)
- throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", pluginManifest.Id, pluginManifest.VersionFormatted, pluginCompatibility.Reason));
+ var pluginIncompatible = compatibilityData.Value.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(pluginManifest.Id, StringComparison.OrdinalIgnoreCase) && pluginManifest.Version == i.Version);
+ if (pluginIncompatible != null)
+ throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", pluginManifest.Id, pluginManifest.VersionFormatted, pluginIncompatible.Reason));
if (pluginManifest.HostVersionMin != null && pluginManifest.HostVersionMin > hostVersion)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] does not support this version of Disco (Requires v{2} or greater)", pluginManifest.Id, pluginManifest.VersionFormatted, pluginManifest.HostVersionMin.ToString()));
@@ -441,13 +367,13 @@ namespace Disco.Services.Plugins
_PluginAssemblyManifests = _PluginManifests.Values.ToDictionary(p => p.PluginAssembly, p => p);
}
- public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryCompatibilityResponse CompatibilityData = null)
+ public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryIncompatibility PluginLibraryIncompatibility = null)
{
PluginManifest updatedManifest;
using (var packageStream = File.OpenRead(UpdatePluginPackageFilePath))
{
- updatedManifest = UpdatePlugin(Database, ExistingManifest, packageStream, CompatibilityData);
+ updatedManifest = UpdatePlugin(Database, ExistingManifest, packageStream, PluginLibraryIncompatibility);
}
// Remove Update after processing
@@ -456,7 +382,7 @@ namespace Disco.Services.Plugins
return updatedManifest;
}
- public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryCompatibilityResponse CompatibilityData = null)
+ public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryIncompatibility PluginLibraryIncompatibility = null)
{
using (MemoryStream packageStream = new MemoryStream())
{
@@ -486,11 +412,11 @@ namespace Disco.Services.Plugins
}
// Check Compatibility
- if (CompatibilityData == null)
- CompatibilityData = LoadCompatibilityData(Database);
- var pluginCompatibility = CompatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == Version.Parse(i.Version));
- if (pluginCompatibility != null && !pluginCompatibility.Compatible)
- throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginCompatibility.Reason));
+ if (PluginLibraryIncompatibility == null)
+ PluginLibraryIncompatibility = PluginLibrary.LoadManifest(Database).LoadIncompatibilityData();
+ var pluginIncompatibility = PluginLibraryIncompatibility.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == i.Version);
+ if (pluginIncompatibility != null)
+ throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginIncompatibility.Reason));
string packagePath = Path.Combine(Database.DiscoConfiguration.PluginsLocation, packageManifest.Id);
diff --git a/Disco.Services/Plugins/UpdatePluginTask.cs b/Disco.Services/Plugins/UpdatePluginTask.cs
index 3fffc683..cb7020f2 100644
--- a/Disco.Services/Plugins/UpdatePluginTask.cs
+++ b/Disco.Services/Plugins/UpdatePluginTask.cs
@@ -1,17 +1,14 @@
-using System;
+using Disco.Data.Repository;
+using Disco.Models.Services.Interop.DiscoServices;
+using Disco.Services.Interop.DiscoServices;
+using Disco.Services.Tasks;
+using Quartz;
+using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
-using System.Net;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Web;
-using Disco.Data.Repository;
-using Disco.Models.BI.Interop.Community;
-using Disco.Services.Tasks;
-using Quartz;
+using System.Net.Http;
namespace Disco.Services.Plugins
{
@@ -24,17 +21,19 @@ namespace Disco.Services.Plugins
string pluginId = (string)this.ExecutionContext.JobDetail.JobDataMap["PluginId"];
string packageFilePath = (string)this.ExecutionContext.JobDetail.JobDataMap["PackageFilePath"];
- PluginLibraryUpdateResponse catalogue;
+ PluginLibraryManifestV2 libraryManifest;
+ PluginLibraryIncompatibility libraryIncompatibility;
string pluginPackagesLocation;
if (!Plugins.PluginsLoaded)
throw new InvalidOperationException("Plugins have not been initialized");
- List> updatePlugins;
+ List> updatePlugins;
using (DiscoDataContext database = new DiscoDataContext())
{
- catalogue = Plugins.LoadCatalogue(database);
+ libraryManifest = PluginLibrary.LoadManifest(database);
+ libraryIncompatibility = libraryManifest.LoadIncompatibilityData();
pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation;
}
@@ -44,30 +43,41 @@ namespace Disco.Services.Plugins
{
// Update Single from Catalogue
PluginManifest existingManifest = Plugins.GetPlugin(pluginId);
- var catalogueItem = catalogue.Plugins.FirstOrDefault(p => p.Id == existingManifest.Id);
+ var libraryItem = libraryManifest.Plugins.FirstOrDefault(p => p.Id == existingManifest.Id);
- if (catalogueItem == null)
- throw new InvalidOperationException("No updates are available for this Plugin");
- if (Version.Parse(catalogueItem.LatestVersion) <= existingManifest.Version)
+ if (libraryItem == null)
+ throw new InvalidOperationException("This item isn't in the plugin library manifest");
+
+ var libraryItemRelease = libraryItem.LatestCompatibleRelease(libraryIncompatibility);
+
+ if (Version.Parse(libraryItemRelease.Version) <= existingManifest.Version)
throw new InvalidOperationException("Only newer versions can be used to update a plugin");
- updatePlugins = new List>() {
- new Tuple(existingManifest, null, catalogueItem)
+ updatePlugins = new List>() {
+ Tuple.Create(existingManifest, (string)null, libraryItem, libraryItemRelease)
};
}
else
{
// Update Single from Local
PluginManifest existingManifest = Plugins.GetPlugin(pluginId);
- updatePlugins = new List>() {
- new Tuple(existingManifest, packageFilePath, null)
+ updatePlugins = new List>() {
+ Tuple.Create(existingManifest, packageFilePath, (PluginLibraryItemV2)null, (PluginLibraryItemReleaseV2)null)
};
}
}
else
{
// Update All
- updatePlugins = Plugins.GetPlugins().Join((IEnumerable)catalogue.Plugins, manifest => manifest.Id, update => update.Id, (manifest, update) => new Tuple(manifest, null, update)).Where(i => Version.Parse(i.Item3.LatestVersion) > i.Item1.Version).ToList();
+ updatePlugins = Plugins.GetPlugins()
+ .Join(
+ libraryManifest.Plugins,
+ manifest => manifest.Id,
+ libraryItem => libraryItem.Id,
+ (manifest, libraryItem) => Tuple.Create(manifest, (string)null, libraryItem, libraryItem.LatestCompatibleRelease(libraryIncompatibility)),
+ StringComparer.OrdinalIgnoreCase)
+ .Where(i => Version.Parse(i.Item4.Version) > i.Item1.Version)
+ .ToList();
}
if (updatePlugins == null || updatePlugins.Count == 0)
@@ -115,31 +125,40 @@ namespace Disco.Services.Plugins
internal static void UpdateOffline(ScheduledTaskStatus Status)
{
- PluginLibraryUpdateResponse pluginCatalogue = null;
+ PluginLibraryManifestV2 libraryManifest = null;
+ PluginLibraryIncompatibility libraryIncompatibility = null;
List installedPluginManifests;
string pluginPackagesLocation;
- List> updatePlugins = new List>();
+ List> updatePlugins =
+ new List>();
+
-
using (DiscoDataContext database = new DiscoDataContext())
{
pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation;
installedPluginManifests = OfflineInstalledPlugins(database);
- if (installedPluginManifests.Count > 0)
- pluginCatalogue = Plugins.LoadCatalogue(database);
+ if (installedPluginManifests.Count > 0){
+ libraryManifest = PluginLibrary.LoadManifest(database);
+ libraryIncompatibility = libraryManifest.LoadIncompatibilityData();
+ }
}
- if (pluginCatalogue != null && installedPluginManifests.Count > 0)
+ if (libraryManifest != null && installedPluginManifests.Count > 0)
{
foreach (var pluginManifest in installedPluginManifests)
{
// Check for Update
- var catalogueItem = pluginCatalogue.Plugins.FirstOrDefault(i => i.Id == pluginManifest.Id && Version.Parse(i.LatestVersion) > pluginManifest.Version);
+ var libraryItem = libraryManifest.Plugins.FirstOrDefault(i => i.Id == pluginManifest.Id);
- if (catalogueItem != null)
- { // Update Available
- updatePlugins.Add(new Tuple(pluginManifest, null, catalogueItem));
+ if (libraryItem != null)
+ {
+ var libraryItemRelease = libraryItem.LatestCompatibleRelease(libraryIncompatibility);
+
+ if (libraryItemRelease != null && Version.Parse(libraryItemRelease.Version) > pluginManifest.Version)
+ { // Update Available
+ updatePlugins.Add(Tuple.Create(pluginManifest, (string)null, libraryItem, libraryItemRelease));
+ }
}
}
}
@@ -150,18 +169,19 @@ namespace Disco.Services.Plugins
}
}
- internal static void ExecuteTaskInternal(ScheduledTaskStatus Status, string pluginPackagesLocation, List> UpdatePlugins)
+ internal static void ExecuteTaskInternal(ScheduledTaskStatus Status, string pluginPackagesLocation, List> UpdatePlugins)
{
while (UpdatePlugins.Count > 0)
{
var updatePlugin = UpdatePlugins[0];
var existingManifest = updatePlugin.Item1;
var packageTempFilePath = updatePlugin.Item2;
- var catalogueItem = updatePlugin.Item3;
+ var libraryItem = updatePlugin.Item3;
+ var libraryItemRelease = updatePlugin.Item4;
UpdatePlugins.Remove(updatePlugin);
- var pluginId = existingManifest != null ? existingManifest.Id : catalogueItem.Id;
- var pluginName = existingManifest != null ? existingManifest.Name : catalogueItem.Name;
+ var pluginId = existingManifest != null ? existingManifest.Id : libraryItemRelease.PluginId;
+ var pluginName = existingManifest != null ? existingManifest.Name : libraryItem.Name;
if (string.IsNullOrEmpty(packageTempFilePath))
{
@@ -176,31 +196,19 @@ namespace Disco.Services.Plugins
Directory.CreateDirectory(Path.GetDirectoryName(packageTempFilePath));
// Need to Download the Package
- HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(catalogueItem.LatestDownloadUrl);
- webRequest.KeepAlive = false;
-
- webRequest.ContentType = "application/xml";
- webRequest.Method = WebRequestMethods.Http.Get;
- webRequest.UserAgent = string.Format("Disco/{0} (PluginLibrary)", Disco.Services.Plugins.CommunityInterop.PluginLibraryUpdateTask.CurrentDiscoVersion());
-
- using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
+ using (HttpClient httpClient = new HttpClient())
{
- if (webResponse.StatusCode == HttpStatusCode.OK)
+ Status.UpdateStatus(0, "Downloading...");
+
+ using (var httpResponse = httpClient.GetAsync(libraryItemRelease.DownloadUrl).Result)
{
- Status.UpdateStatus(0, "Downloading...");
- using (var wResStream = webResponse.GetResponseStream())
+ httpResponse.EnsureSuccessStatusCode();
+
+ using (FileStream fsOut = new FileStream(packageTempFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
- using (FileStream fsOut = new FileStream(packageTempFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
- {
- wResStream.CopyTo(fsOut);
- }
+ httpResponse.Content.ReadAsStreamAsync().Result.CopyTo(fsOut);
}
}
- else
- {
- Status.SetTaskException(new WebException(string.Format("Server responded with: [{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription)));
- return;
- }
}
}
@@ -234,10 +242,10 @@ namespace Disco.Services.Plugins
using (DiscoDataContext database = new DiscoDataContext())
{
// Check for Compatibility
- var compatibilityData = Plugins.LoadCompatibilityData(database);
- var pluginCompatibility = compatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(updateManifest.Id, StringComparison.OrdinalIgnoreCase) && updateManifest.Version == Version.Parse(i.Version));
- if (pluginCompatibility != null && !pluginCompatibility.Compatible)
- throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", updateManifest.Id, updateManifest.VersionFormatted, pluginCompatibility.Reason));
+ var incompatibilityLibrary = PluginLibrary.LoadManifest(database).LoadIncompatibilityData();
+ PluginIncompatibility incompatibility;
+ if (!incompatibilityLibrary.IsCompatible(updateManifest.Id, updateManifest.Version, out incompatibility))
+ throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", updateManifest.Id, updateManifest.VersionFormatted, incompatibility.Reason));
var updatePluginPath = Path.Combine(database.DiscoConfiguration.PluginsLocation, string.Format("{0}.discoPlugin", updateManifest.Id));
File.Move(packageTempFilePath, updatePluginPath);
diff --git a/Disco.Services/Plugins/UpdatePluginsAfterDiscoUpdateTask.cs b/Disco.Services/Plugins/UpdatePluginsAfterDiscoUpdateTask.cs
index 097c428b..1b6b01e2 100644
--- a/Disco.Services/Plugins/UpdatePluginsAfterDiscoUpdateTask.cs
+++ b/Disco.Services/Plugins/UpdatePluginsAfterDiscoUpdateTask.cs
@@ -1,9 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using Disco.Data.Repository;
+using Disco.Services.Interop.DiscoServices;
using Disco.Services.Tasks;
+using System;
+using System.Linq;
namespace Disco.Services.Plugins
{
@@ -20,12 +19,15 @@ namespace Disco.Services.Plugins
// Wait for App to Load (10 Seconds)
for (int i = 0; i < 10; i++)
{
- this.Status.UpdateStatus(10 * i);
+ this.Status.UpdateStatus(10 * i);
System.Threading.Thread.Sleep(1000);
}
// Update Catalogue
- CommunityInterop.PluginLibraryUpdateTask.ExecuteTaskInternal(this.Status);
+ using (DiscoDataContext database = new DiscoDataContext())
+ {
+ PluginLibrary.UpdateManifest(database, this.Status);
+ }
// Update all Plugins
UpdatePluginTask.UpdateOffline(this.Status);
diff --git a/Disco.Web/Areas/API/Controllers/PluginController.cs b/Disco.Web/Areas/API/Controllers/PluginController.cs
index 06260a2c..636783cf 100644
--- a/Disco.Web/Areas/API/Controllers/PluginController.cs
+++ b/Disco.Web/Areas/API/Controllers/PluginController.cs
@@ -1,6 +1,6 @@
using Disco.Services.Authorization;
+using Disco.Services.Interop.DiscoServices;
using Disco.Services.Plugins;
-using Disco.Services.Plugins.CommunityInterop;
using Disco.Services.Tasks;
using Disco.Services.Web;
using System;
@@ -15,7 +15,7 @@ namespace Disco.Web.Areas.API.Controllers
public partial class PluginController : AuthorizedDatabaseController
{
[DiscoAuthorize(Claims.Config.Plugin.Install)]
- public virtual ActionResult UpdateLibraryCatalogue(bool TryWaitingForCompletion = false)
+ public virtual ActionResult UpdateLibraryManifest(bool TryWaitingForCompletion = false)
{
var status = PluginLibraryUpdateTask.ScheduleNow();
@@ -93,19 +93,25 @@ namespace Disco.Web.Areas.API.Controllers
if (string.IsNullOrEmpty(PluginId))
throw new ArgumentNullException("PluginId", "A PluginId must be supplied");
- var catalogue = Plugins.LoadCatalogue(Database);
- var plugin = catalogue.Plugins.FirstOrDefault(p => p.Id.Equals(PluginId));
+ var library = PluginLibrary.LoadManifest(Database);
+ var libraryIncompatibility = library.LoadIncompatibilityData();
+ var libraryItem = library.Plugins.FirstOrDefault(p => p.Id.Equals(PluginId));
- if (plugin == null)
- throw new ArgumentNullException("PluginId", "Plugin not found in catalogue");
+ if (libraryItem == null)
+ throw new ArgumentNullException("PluginId", "Plugin not found in library");
+
+ var libraryItemRelease = libraryItem.LatestCompatibleRelease(libraryIncompatibility);
+
+ if (libraryItemRelease == null)
+ throw new ArgumentNullException("PluginId", "No compatibility releases were found in library");
// Already Installed?
- if (Plugins.PluginInstalled(plugin.Id))
+ if (Plugins.PluginInstalled(libraryItem.Id))
throw new InvalidOperationException("This plugin is already installed");
- var tempPluginLocation = Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, string.Format("{0}.discoPlugin", plugin.Id));
+ var tempPluginLocation = Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, string.Format("{0}.discoPlugin", libraryItem.Id));
- var status = InstallPluginTask.InstallPlugin(plugin.LatestDownloadUrl, tempPluginLocation, true);
+ var status = InstallPluginTask.InstallPlugin(libraryItem.LatestCompatibleRelease(libraryIncompatibility).DownloadUrl, tempPluginLocation, true);
return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId));
}
diff --git a/Disco.Web/Areas/Config/Controllers/PluginsController.cs b/Disco.Web/Areas/Config/Controllers/PluginsController.cs
index da36119f..77fc9638 100644
--- a/Disco.Web/Areas/Config/Controllers/PluginsController.cs
+++ b/Disco.Web/Areas/Config/Controllers/PluginsController.cs
@@ -1,4 +1,5 @@
using Disco.Services.Authorization;
+using Disco.Services.Interop.DiscoServices;
using Disco.Services.Plugins;
using Disco.Services.Users;
using Disco.Services.Web;
@@ -16,7 +17,7 @@ namespace Disco.Web.Areas.Config.Controllers
Models.Plugins.IndexViewModel vm = new Models.Plugins.IndexViewModel()
{
PluginManifests = Plugins.GetPlugins(),
- Catalogue = Plugins.LoadCatalogue(Database)
+ PluginLibrary = PluginLibrary.LoadManifest(Database)
};
return View(vm);
}
@@ -70,18 +71,18 @@ namespace Disco.Web.Areas.Config.Controllers
public virtual ActionResult Install()
{
// Check for recent catalogue
- var catalogue = Plugins.LoadCatalogue(Database);
+ var library = PluginLibrary.LoadManifest(Database);
- if (catalogue == null || catalogue.ResponseTimestamp < DateTime.Now.AddHours(-1))
+ if (library == null || library.ManifestDate < DateTime.Now.AddHours(-1))
{
// Need to Update Catalogue (over 1 hour old)
- return RedirectToAction(MVC.API.Plugin.UpdateLibraryCatalogue(true));
+ return RedirectToAction(MVC.API.Plugin.UpdateLibraryManifest(true));
}
else
{
var model = new Models.Plugins.InstallModel()
{
- Catalogue = catalogue
+ Library = library
};
return View(model);
diff --git a/Disco.Web/Areas/Config/Models/Plugins/IndexViewModel.cs b/Disco.Web/Areas/Config/Models/Plugins/IndexViewModel.cs
index 7f726652..b083fb3a 100644
--- a/Disco.Web/Areas/Config/Models/Plugins/IndexViewModel.cs
+++ b/Disco.Web/Areas/Config/Models/Plugins/IndexViewModel.cs
@@ -1,33 +1,43 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using Disco.Models.BI.Interop.Community;
+using Disco.Models.Services.Interop.DiscoServices;
+using Disco.Services.Interop.DiscoServices;
using Disco.Services.Plugins;
using Disco.Services.Plugins.Features.Other;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace Disco.Web.Areas.Config.Models.Plugins
{
public class IndexViewModel
{
public List PluginManifests { get; set; }
- public PluginLibraryUpdateResponse Catalogue { get; set; }
+ public PluginLibraryManifestV2 PluginLibrary { get; set; }
- private Dictionary _PluginUpdates;
- public Dictionary PluginUpdates
+ private Dictionary> _PluginUpdates;
+ public Dictionary> PluginUpdates
{
get
{
if (_PluginUpdates == null)
{
- if (Catalogue == null || Catalogue.Plugins == null || Catalogue.Plugins.Count == 0 ||
+ if (PluginLibrary == null || PluginLibrary.Plugins == null || PluginLibrary.Plugins.Count == 0 ||
PluginManifests == null || PluginManifests.Count == 0)
{
- _PluginUpdates = new Dictionary(); // No Updates
+ _PluginUpdates = new Dictionary>(); // No Updates
}
else
{
- _PluginUpdates = PluginManifests.Join((IEnumerable)Catalogue.Plugins, manifest => manifest.Id, update => update.Id, (manifest, update) => new Tuple(manifest, update)).Where(i => Version.Parse(i.Item2.LatestVersion) > i.Item1.Version).ToDictionary(i => i.Item1, i => i.Item2);
+ var libraryIncompatibility = PluginLibrary.LoadIncompatibilityData();
+
+ _PluginUpdates = PluginManifests
+ .Join(
+ PluginLibrary.Plugins,
+ manifest => manifest.Id,
+ libraryItem => libraryItem.Id,
+ (manifest, libraryItem) => Tuple.Create(manifest, libraryItem, libraryItem.LatestCompatibleRelease(libraryIncompatibility)),
+ StringComparer.OrdinalIgnoreCase)
+ .Where(i => i.Item3 != null && Version.Parse(i.Item3.Version) > i.Item1.Version)
+ .ToDictionary(i => i.Item1, i => Tuple.Create(i.Item2, i.Item3));
}
}
return _PluginUpdates;
diff --git a/Disco.Web/Areas/Config/Models/Plugins/InstallModel.cs b/Disco.Web/Areas/Config/Models/Plugins/InstallModel.cs
index 8f59c960..31a99d4f 100644
--- a/Disco.Web/Areas/Config/Models/Plugins/InstallModel.cs
+++ b/Disco.Web/Areas/Config/Models/Plugins/InstallModel.cs
@@ -1,13 +1,29 @@
-using System;
+using Disco.Models.Services.Interop.DiscoServices;
+using Disco.Services.Interop.DiscoServices;
+using System;
using System.Collections.Generic;
using System.Linq;
-using System.Web;
-using Disco.Models.BI.Interop.Community;
namespace Disco.Web.Areas.Config.Models.Plugins
{
public class InstallModel
{
- public PluginLibraryUpdateResponse Catalogue { get; set; }
+ public PluginLibraryManifestV2 Library { get; set; }
+
+ public List>>> AvailablePlugins
+ {
+ get
+ {
+ var incompatibility = Library.LoadIncompatibilityData();
+
+ return Library.Plugins
+ .Select(p => Tuple.Create(p, p.LatestCompatibleRelease(incompatibility)))
+ .Where(p => p.Item2 != null)
+ .GroupBy(p => p.Item1.PrimaryFeatureCategory)
+ .Select(p => Tuple.Create(p.Key, p.OrderBy(r => r.Item1.Name).ToList()))
+ .OrderBy(g => g.Item1)
+ .ToList();
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Disco.Web/Areas/Config/Models/Plugins/PluginConfigurationViewModel.cs b/Disco.Web/Areas/Config/Models/Plugins/PluginConfigurationViewModel.cs
index 2576f8b1..c05b67f2 100644
--- a/Disco.Web/Areas/Config/Models/Plugins/PluginConfigurationViewModel.cs
+++ b/Disco.Web/Areas/Config/Models/Plugins/PluginConfigurationViewModel.cs
@@ -1,8 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using Disco.Services.Plugins;
+using Disco.Services.Plugins;
+using System;
namespace Disco.Web.Areas.Config.Models.Plugins
{
diff --git a/Disco.Web/Areas/Config/Views/Plugins/Install.cshtml b/Disco.Web/Areas/Config/Views/Plugins/Install.cshtml
index f31ee36c..b72c5e43 100644
--- a/Disco.Web/Areas/Config/Views/Plugins/Install.cshtml
+++ b/Disco.Web/Areas/Config/Views/Plugins/Install.cshtml
@@ -7,10 +7,9 @@
ViewBag.Title = Html.ToBreadcrumb("Configuration", MVC.Config.Config.Index(), "Plugins", MVC.Config.Plugins.Index(), "Install Plugin");
}
-
-
The plugin catalogue [https://discoict.com.au] was last updated @CommonHelpers.FriendlyDate((Model.Catalogue.ResponseTimestamp > DateTime.Now ? DateTime.Now : Model.Catalogue.ResponseTimestamp))
-
- @if (Model.Catalogue.Plugins.Count == 0)
+
+
The plugin library [https://discoict.com.au] was last updated @CommonHelpers.FriendlyDate((Model.Library.ManifestDate > DateTime.Now ? DateTime.Now : Model.Library.ManifestDate))
+ @if (Model.Library.Plugins.Count == 0)
{
No Plugins are Available
@@ -18,50 +17,50 @@
}
else
{
- var plugins = Model.Catalogue.Plugins;
- int itemsPerColumn = plugins.Count / 3;
- var itemNextId = 0;
-
+
+ }
+
+
}
@@ -98,6 +97,8 @@
var $selectedPlugin;
var $selectedPluginUrl;
+ $('#pluginLibraryHeading').appendTo('#layout_PageHeading');
+
// Install
var $dialogInstall = $('#dialogInstallPlugin').dialog({
resizable: false,
@@ -120,7 +121,7 @@
}
}
});
- $('#pageMenu').find('a.pluginInstallLink').click(function () {
+ $('#pluginLibraryGroups').find('a.pluginInstallLink').click(function () {
$this = $(this);
$selectedPlugin = $this.closest('.pluginItem');
@@ -134,7 +135,7 @@
return false;
});
- $('#pageMenu').find('a.pluginUpdateLink').click(function () {
+ $('#pluginLibraryGroups').find('a.pluginUpdateLink').click(function () {
$this = $(this);
$selectedPlugin = $this.closest('.pluginItem');
@@ -180,7 +181,7 @@
});
- @Html.ActionLinkButton("Update Catalogue", MVC.API.Plugin.UpdateLibraryCatalogue())
+ @Html.ActionLinkButton("Update Plugin Library", MVC.API.Plugin.UpdateLibraryManifest())
@if (canInstallLocal)
{
@Html.ActionLinkButton("Install Plugin Package", MVC.API.Plugin.InstallLocal(), "buttonUpload")
diff --git a/Disco.Web/Areas/Config/Views/Plugins/Install.generated.cs b/Disco.Web/Areas/Config/Views/Plugins/Install.generated.cs
index e8c8b97a..0c17860f 100644
--- a/Disco.Web/Areas/Config/Views/Plugins/Install.generated.cs
+++ b/Disco.Web/Areas/Config/Views/Plugins/Install.generated.cs
@@ -64,13 +64,13 @@ namespace Disco.Web.Areas.Config.Views.Plugins
#line hidden
WriteLiteral("\r\n
\r\n
The plugin catalogue [The plugin library [https://discoict.com.au] was last updated ");
#line 11 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
- Write(CommonHelpers.FriendlyDate((Model.Catalogue.ResponseTimestamp > DateTime.Now ? DateTime.Now : Model.Catalogue.ResponseTimestamp)));
+ Write(CommonHelpers.FriendlyDate((Model.Library.ManifestDate > DateTime.Now ? DateTime.Now : Model.Library.ManifestDate)));
#line default
#line hidden
-WriteLiteral("\r\n
\r\n");
+WriteLiteral("\r\n");
- #line 13 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ #line 12 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default
#line hidden
- #line 13 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
- if (Model.Catalogue.Plugins.Count == 0)
+ #line 12 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ if (Model.Library.Plugins.Count == 0)
{
@@ -108,73 +108,81 @@ WriteLiteral(" style=\"width: 450px; padding: 100px 0;\"");
WriteLiteral(">\r\n
No Plugins are Available
\r\n
\r\n");
- #line 18 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ #line 17 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
}
else
{
- var plugins = Model.Catalogue.Plugins;
- int itemsPerColumn = plugins.Count / 3;
- var itemNextId = 0;
+ var pluginGroups = Model.AvailablePlugins;
+
#line default
#line hidden
-WriteLiteral(" \r\n
\r\n");
- #line 65 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ #line 61 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ }
+
+
+ #line default
+ #line hidden
+WriteLiteral("
\r\n");
+
+
+ #line 63 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+
}
@@ -406,7 +417,7 @@ WriteLiteral(">Warning: All plugins run with the same level
"om a trusted source.\r\n
\r\n \r\n\r\n");
- #line 78 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ #line 77 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
if (canInstallLocal)
{
@@ -426,13 +437,13 @@ WriteLiteral(" style=\"padding-bottom: 10px;\"");
WriteLiteral(">\r\n");
- #line 82 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ #line 81 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
#line default
#line hidden
- #line 82 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ #line 81 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
using (Html.BeginForm(MVC.API.Plugin.InstallLocal(), FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@@ -456,7 +467,7 @@ WriteLiteral(" type=\"file\"");
WriteLiteral(" />\r\n");
- #line 86 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ #line 85 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
}
@@ -480,48 +491,49 @@ WriteLiteral(">Warning: All plugins run with the same level
"\n");
- #line 95 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
+ #line 94 "..\..\Areas\Config\Views\Plugins\Install.cshtml"
}
#line default
#line hidden
WriteLiteral("