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, Formatting.Indented); 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; } } }