From 343f20980d09ec3c975e0311baba4e75415eeb8c Mon Sep 17 00:00:00 2001 From: Gary Sharp Date: Wed, 11 Dec 2024 15:13:26 +1100 Subject: [PATCH] qol: impove plugin installation/update api --- Disco.Services/Plugins/Plugins.cs | 14 +- Disco.Services/Plugins/UninstallPluginTask.cs | 2 +- Disco.Services/Plugins/UpdatePluginTask.cs | 25 +- .../UpdatePluginsAfterDiscoUpdateTask.cs | 2 +- .../Areas/API/Controllers/PluginController.cs | 64 +-- .../Areas/Config/Views/Plugins/Index.cshtml | 343 +++++++------- .../Config/Views/Plugins/Index.generated.cs | 439 +++++++++++------- .../Areas/Config/Views/Plugins/Install.cshtml | 15 +- .../Config/Views/Plugins/Install.generated.cs | 118 +++-- Disco.Web/ClientSource/Style/Config.css | 2 +- Disco.Web/ClientSource/Style/Config.less | 2 +- Disco.Web/ClientSource/Style/Config.min.css | 2 +- .../T4MVC/API.PluginController.generated.cs | 82 ++-- 13 files changed, 606 insertions(+), 504 deletions(-) diff --git a/Disco.Services/Plugins/Plugins.cs b/Disco.Services/Plugins/Plugins.cs index 7dab55e2..bbbd98ec 100644 --- a/Disco.Services/Plugins/Plugins.cs +++ b/Disco.Services/Plugins/Plugins.cs @@ -505,7 +505,7 @@ namespace Disco.Services.Plugins #region Restart App private static object _restartTimerLock = new object(); private static Timer _restartTimer; - internal static void RestartApp(int DelayMilliseconds) + internal static void RestartApp(TimeSpan delay) { lock (_restartTimerLock) { @@ -514,11 +514,15 @@ namespace Disco.Services.Plugins _restartTimer.Dispose(); } - _restartTimer = new Timer((state) => - { + if (delay == TimeSpan.Zero) HttpRuntime.UnloadAppDomain(); - //AppDomain.Unload(AppDomain.CurrentDomain); - }, null, DelayMilliseconds, Timeout.Infinite); + else + { + _restartTimer = new Timer((state) => + { + HttpRuntime.UnloadAppDomain(); + }, null, (int)delay.TotalMilliseconds, Timeout.Infinite); + } } } #endregion diff --git a/Disco.Services/Plugins/UninstallPluginTask.cs b/Disco.Services/Plugins/UninstallPluginTask.cs index 52a90d30..957e49a7 100644 --- a/Disco.Services/Plugins/UninstallPluginTask.cs +++ b/Disco.Services/Plugins/UninstallPluginTask.cs @@ -46,7 +46,7 @@ namespace Disco.Services.Plugins } Status.Finished("Restarting Disco ICT, please wait...", "/Config/Plugins"); - Plugins.RestartApp(2500); + Plugins.RestartApp(TimeSpan.FromSeconds(1)); } public static ScheduledTaskStatus UninstallPlugin(PluginManifest Manifest, bool UninstallData) diff --git a/Disco.Services/Plugins/UpdatePluginTask.cs b/Disco.Services/Plugins/UpdatePluginTask.cs index 3a5ec190..04bb4f27 100644 --- a/Disco.Services/Plugins/UpdatePluginTask.cs +++ b/Disco.Services/Plugins/UpdatePluginTask.cs @@ -18,8 +18,9 @@ namespace Disco.Services.Plugins protected override void ExecuteTask() { - string pluginId = (string)ExecutionContext.JobDetail.JobDataMap["PluginId"]; - string packageFilePath = (string)ExecutionContext.JobDetail.JobDataMap["PackageFilePath"]; + var pluginId = (string)ExecutionContext.JobDetail.JobDataMap["PluginId"]; + var packageFilePath = (string)ExecutionContext.JobDetail.JobDataMap["PackageFilePath"]; + var immediateRestart = (bool)ExecutionContext.JobDetail.JobDataMap["ImmediateRestart"]; PluginLibraryManifestV2 libraryManifest; PluginLibraryIncompatibility libraryIncompatibility; @@ -89,7 +90,7 @@ namespace Disco.Services.Plugins ExecuteTaskInternal(Status, pluginPackagesLocation, updatePlugins); Status.Finished("Restarting Disco ICT, please wait...", "/Config/Plugins"); - Plugins.RestartApp(2500); + Plugins.RestartApp(immediateRestart ? TimeSpan.Zero : TimeSpan.FromSeconds(1)); } public static List OfflineInstalledPlugins(DiscoDataContext Database) @@ -258,7 +259,7 @@ namespace Disco.Services.Plugins } } - private static ScheduledTaskStatus UpdateHelper(string PluginId = null, string PackageFilePath = null) + private static ScheduledTaskStatus UpdateHelper(string pluginId, string packageFilePath, bool immediateRestart) { if (ScheduledTasks.GetTaskStatuses(typeof(UpdatePluginTask)).Where(s => s.IsRunning).Count() > 0) throw new InvalidOperationException("A plugin is already being Updated"); @@ -267,24 +268,28 @@ namespace Disco.Services.Plugins if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0) throw new InvalidOperationException("A plugin is being Installed"); - JobDataMap taskData = new JobDataMap() { { "PluginId", PluginId }, { "PackageFilePath", PackageFilePath } }; + JobDataMap taskData = new JobDataMap() { + { "PluginId", pluginId }, + { "PackageFilePath", packageFilePath }, + { "ImmediateRestart", immediateRestart }, + }; var instance = new UpdatePluginTask(); return instance.ScheduleTask(taskData); } - public static ScheduledTaskStatus UpdateLocalPlugin(string PluginId, string PackageFilePath) + public static ScheduledTaskStatus UpdateLocalPlugin(string pluginId, string packageFilePath, bool immediateRestart = false) { - return UpdateHelper(PluginId, PackageFilePath); + return UpdateHelper(pluginId, packageFilePath, immediateRestart); } - public static ScheduledTaskStatus UpdatePlugin(string PluginId) + public static ScheduledTaskStatus UpdatePlugin(string pluginId, bool immediateRestart = false) { - return UpdateHelper(PluginId); + return UpdateHelper(pluginId, packageFilePath: null, immediateRestart); } public static ScheduledTaskStatus UpdateAllPlugins() { - return UpdateHelper(); + return UpdateHelper(pluginId: null, packageFilePath: null, immediateRestart: false); } } } diff --git a/Disco.Services/Plugins/UpdatePluginsAfterDiscoUpdateTask.cs b/Disco.Services/Plugins/UpdatePluginsAfterDiscoUpdateTask.cs index fdd2156d..f029fd23 100644 --- a/Disco.Services/Plugins/UpdatePluginsAfterDiscoUpdateTask.cs +++ b/Disco.Services/Plugins/UpdatePluginsAfterDiscoUpdateTask.cs @@ -34,7 +34,7 @@ namespace Disco.Services.Plugins // Restart Status.Finished("Restarting Disco ICT, please wait...", "/"); - Plugins.RestartApp(2500); + Plugins.RestartApp(TimeSpan.FromSeconds(1)); } public static ScheduledTaskStatus UpdateDiscoPlugins(bool ReturnExistingStatusIfRunning) diff --git a/Disco.Web/Areas/API/Controllers/PluginController.cs b/Disco.Web/Areas/API/Controllers/PluginController.cs index 636783cf..bcc46954 100644 --- a/Disco.Web/Areas/API/Controllers/PluginController.cs +++ b/Disco.Web/Areas/API/Controllers/PluginController.cs @@ -15,12 +15,12 @@ namespace Disco.Web.Areas.API.Controllers public partial class PluginController : AuthorizedDatabaseController { [DiscoAuthorize(Claims.Config.Plugin.Install)] - public virtual ActionResult UpdateLibraryManifest(bool TryWaitingForCompletion = false) + public virtual ActionResult UpdateLibraryManifest(bool tryWaitingForCompletion = false) { var status = PluginLibraryUpdateTask.ScheduleNow(); // If upload takes <= 2 seconds, return back to Plugin Install (rather than Task Status) - if (TryWaitingForCompletion && status.WaitUntilFinished(TimeSpan.FromSeconds(3)) && status.TaskException == null) + if (tryWaitingForCompletion && status.WaitUntilFinished(TimeSpan.FromSeconds(3)) && status.TaskException == null) { return RedirectToAction(MVC.Config.Plugins.Install()); } @@ -31,7 +31,7 @@ namespace Disco.Web.Areas.API.Controllers } } - [DiscoAuthorize(Claims.Config.Plugin.Install)] + [HttpPost, DiscoAuthorize(Claims.Config.Plugin.Install), ValidateAntiForgeryToken] public virtual ActionResult UpdateAll() { var status = UpdatePluginTask.UpdateAllPlugins(); @@ -39,63 +39,39 @@ namespace Disco.Web.Areas.API.Controllers return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId)); } - [DiscoAuthorize(Claims.Config.Plugin.Install)] - public virtual ActionResult Update(string PluginId) + [HttpPost, DiscoAuthorize(Claims.Config.Plugin.Install), ValidateAntiForgeryToken] + public virtual ActionResult Update(string pluginId) { - if (string.IsNullOrEmpty(PluginId)) + if (string.IsNullOrEmpty(pluginId)) throw new ArgumentNullException("PluginId"); - var status = UpdatePluginTask.UpdatePlugin(PluginId); + var status = UpdatePluginTask.UpdatePlugin(pluginId); return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId)); } - [DiscoAuthorizeAll(Claims.Config.Plugin.Install, Claims.Config.Plugin.InstallLocal)] - public virtual ActionResult UpdateLocal(string PluginId, HttpPostedFileBase Plugin) - { - if (string.IsNullOrEmpty(PluginId)) - throw new ArgumentNullException("PluginId"); - - if (Plugin == null || Plugin.ContentLength <= 0 || string.IsNullOrWhiteSpace(Plugin.FileName)) - throw new ArgumentException("A discoPlugin file must be uploaded", "Plugin"); - - var tempPluginLocation = Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, Path.GetFileName(Plugin.FileName)); - - if (!Directory.Exists(Database.DiscoConfiguration.PluginPackagesLocation)) - Directory.CreateDirectory(Database.DiscoConfiguration.PluginPackagesLocation); - - if (System.IO.File.Exists(tempPluginLocation)) - System.IO.File.Delete(tempPluginLocation); - - Plugin.SaveAs(tempPluginLocation); - - var status = UpdatePluginTask.UpdateLocalPlugin(PluginId, tempPluginLocation); - - return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId)); - } - - [DiscoAuthorize(Claims.Config.Plugin.Uninstall)] - public virtual ActionResult Uninstall(string id, bool UninstallData) + [HttpPost, DiscoAuthorize(Claims.Config.Plugin.Uninstall), ValidateAntiForgeryToken] + public virtual ActionResult Uninstall(string id, bool uninstallData) { if (string.IsNullOrEmpty(id)) throw new ArgumentNullException("id"); PluginManifest manifest = Plugins.GetPlugin(id); - var status = UninstallPluginTask.UninstallPlugin(manifest, UninstallData); + var status = UninstallPluginTask.UninstallPlugin(manifest, uninstallData); return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId)); } - [DiscoAuthorize(Claims.Config.Plugin.Install)] - public virtual ActionResult Install(string PluginId) + [HttpPost, DiscoAuthorize(Claims.Config.Plugin.Install), ValidateAntiForgeryToken] + public virtual ActionResult Install(string pluginId) { - if (string.IsNullOrEmpty(PluginId)) + if (string.IsNullOrEmpty(pluginId)) throw new ArgumentNullException("PluginId", "A PluginId must be supplied"); var library = PluginLibrary.LoadManifest(Database); var libraryIncompatibility = library.LoadIncompatibilityData(); - var libraryItem = library.Plugins.FirstOrDefault(p => p.Id.Equals(PluginId)); + var libraryItem = library.Plugins.FirstOrDefault(p => p.Id.Equals(pluginId)); if (libraryItem == null) throw new ArgumentNullException("PluginId", "Plugin not found in library"); @@ -116,13 +92,13 @@ namespace Disco.Web.Areas.API.Controllers return RedirectToAction(MVC.Config.Logging.TaskStatus(status.SessionId)); } - [DiscoAuthorizeAll(Claims.Config.Plugin.Install, Claims.Config.Plugin.InstallLocal)] - public virtual ActionResult InstallLocal(HttpPostedFileBase Plugin) + [HttpPost, DiscoAuthorizeAll(Claims.Config.Plugin.Install, Claims.Config.Plugin.InstallLocal), ValidateAntiForgeryToken] + public virtual ActionResult InstallLocal(HttpPostedFileBase plugin, bool immediateRestart = false) { - if (Plugin == null || Plugin.ContentLength <= 0 || string.IsNullOrWhiteSpace(Plugin.FileName)) + if (plugin == null || plugin.ContentLength <= 0 || string.IsNullOrWhiteSpace(plugin.FileName)) throw new ArgumentException("A discoPlugin file must be uploaded", "Plugin"); - var tempPluginLocation = Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, Path.GetFileName(Plugin.FileName)); + var tempPluginLocation = Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, Path.GetFileName(plugin.FileName)); if (!Directory.Exists(Database.DiscoConfiguration.PluginPackagesLocation)) Directory.CreateDirectory(Database.DiscoConfiguration.PluginPackagesLocation); @@ -130,7 +106,7 @@ namespace Disco.Web.Areas.API.Controllers if (System.IO.File.Exists(tempPluginLocation)) System.IO.File.Delete(tempPluginLocation); - Plugin.SaveAs(tempPluginLocation); + plugin.SaveAs(tempPluginLocation); // Check for Install/Update PluginManifest packageManifest; @@ -151,7 +127,7 @@ namespace Disco.Web.Areas.API.Controllers ScheduledTaskStatus status; if (Plugins.PluginInstalled(packageManifest.Id)) - status = UpdatePluginTask.UpdateLocalPlugin(packageManifest.Id, tempPluginLocation); + status = UpdatePluginTask.UpdateLocalPlugin(packageManifest.Id, tempPluginLocation, immediateRestart); else status = InstallPluginTask.InstallLocalPlugin(tempPluginLocation, true); diff --git a/Disco.Web/Areas/Config/Views/Plugins/Index.cshtml b/Disco.Web/Areas/Config/Views/Plugins/Index.cshtml index 42f86660..4326089e 100644 --- a/Disco.Web/Areas/Config/Views/Plugins/Index.cshtml +++ b/Disco.Web/Areas/Config/Views/Plugins/Index.cshtml @@ -11,10 +11,10 @@
@{ if (Model.PluginManifests.Count == 0) - { -
-

No Plugins are Installed

-
+ { +
+

No Plugins are Installed

+
} else { @@ -23,186 +23,191 @@ int itemsPerColumn = pluginGroups.Count / 3; var itemNextId = 0; - - - - @for (int i = 0; i < 3; i++) - { - \r\n"); +WriteLiteral(">\r\n \r\n"); #line 29 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - + #line default #line hidden #line 29 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - for (int i = 0; i < 3; i++) - { - - - #line default - #line hidden -WriteLiteral(" \r\n"); +WriteLiteral("\r\n \r\n"); #line 61 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - } + } #line default #line hidden -WriteLiteral(" \r\n \r\n"); +WriteLiteral(" \r\n \r\n"); #line 64 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - if (canUninstall) - { + if (canUninstall) + { #line default #line hidden -WriteLiteral(" \r\n
\r\n"); +WriteLiteral(" class=\"dialog\""); -WriteLiteral(" "); +WriteLiteral(">\r\n
\r\n"); + +WriteLiteral(" "); #line 68 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - Write(Html.DropDownList("uninstallPlugin", Model.PluginManifests.ToSelectListItems(null, true, "Select a Plugin to Uninstall"))); + Write(Html.DropDownList("uninstallPlugin", Model.PluginManifests.OrderBy(p => p.Name).ToSelectListItems(null, true, "Select a Plugin to Uninstall"))); #line default #line hidden -WriteLiteral("\r\n
\r\n
\r\n \r\n
\r\n " + +" Uninstall Plugin Data\r\n Uninstall Plugin Data\r\n \r\n \r\n \r\n \r\n Warning: Data will be permanently deleted\r\n " + -"

\r\n
\r\n
\r\n
\r\n"); +"

\r\n
\r\n \r\n " + +" \r\n"); -WriteLiteral(" \r\n \r\n \r\n \r\n \r\n \r\n Are you sure you want to uninstall this plugin?\r\n

\r\n " + -" Are you sure you want to uninstall this plugin?\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n Warning: Data will be permanently deleted\r\n " + -"

\r\n \r\n \r\n"); - -WriteLiteral(" \r\n"); + + #line 93 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + + + + #line default + #line hidden +WriteLiteral(" \r\n"); + +WriteLiteral(" \r\n"); + + + #line 96 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + } + + + #line default + #line hidden +WriteLiteral(" \r\n"); + +WriteLiteral(" \r\n"); #line 175 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - } - if (Model.PluginUpdates.Count > 0) - { + } + if (Model.PluginUpdates.Count > 0) + { #line default #line hidden -WriteLiteral(" \r\n \r\n \r\n
"); +WriteLiteral(">\r\n
"); #line 180 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - Write(Model.PluginUpdates.Count); + Write(Model.PluginUpdates.Count); #line default @@ -483,7 +548,7 @@ WriteLiteral(" plugin update"); #line 180 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - Write(Model.PluginUpdates.Count == 1 ? " is" : "s are"); + Write(Model.PluginUpdates.Count == 1 ? " is" : "s are"); #line default @@ -492,64 +557,82 @@ WriteLiteral(" available
\r\n"); #line 181 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - + #line default #line hidden #line 181 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - if (canInstall) - { - + if (canInstall) + { + using (Html.BeginForm(MVC.API.Plugin.UpdateAll())) + { + #line default #line hidden - #line 183 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - Write(Html.ActionLinkSmallButton("Update Now", MVC.API.Plugin.UpdateAll(), null, "alert")); + #line 185 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + Write(Html.AntiForgeryToken()); #line default #line hidden - #line 183 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - - } - else - { + #line 185 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + #line default #line hidden -WriteLiteral(" Update All\r\n"); + + + #line 187 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + } + } + else + { + + + #line default + #line hidden +WriteLiteral(" You do not have sufficient permission to install these updates.
\r\n"); - #line 188 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - } + #line 192 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + } #line default #line hidden -WriteLiteral(" \r\n"); +WriteLiteral(" \r\n"); -WriteLiteral(@" +WriteLiteral(@" "); - #line 199 "..\..\Areas\Config\Views\Plugins\Index.cshtml" - } + #line 203 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + + } } @@ -562,28 +645,28 @@ WriteLiteral(" class=\"actionBar\""); WriteLiteral(">\r\n"); - #line 204 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + #line 209 "..\..\Areas\Config\Views\Plugins\Index.cshtml" #line default #line hidden - #line 204 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + #line 209 "..\..\Areas\Config\Views\Plugins\Index.cshtml" if (canUninstall && Model.PluginManifests.Count > 0) - { + { #line default #line hidden - #line 206 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + #line 211 "..\..\Areas\Config\Views\Plugins\Index.cshtml" Write(Html.ActionLinkButton("Uninstall Plugins", MVC.Config.Plugins.Index(), "buttonUninstall")); #line default #line hidden - #line 206 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + #line 211 "..\..\Areas\Config\Views\Plugins\Index.cshtml" } @@ -593,7 +676,7 @@ WriteLiteral(">\r\n"); WriteLiteral(" "); - #line 208 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + #line 213 "..\..\Areas\Config\Views\Plugins\Index.cshtml" if (canInstall) { @@ -601,14 +684,14 @@ WriteLiteral(" "); #line default #line hidden - #line 210 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + #line 215 "..\..\Areas\Config\Views\Plugins\Index.cshtml" Write(Html.ActionLinkButton("Install Plugins", MVC.Config.Plugins.Install())); #line default #line hidden - #line 210 "..\..\Areas\Config\Views\Plugins\Index.cshtml" + #line 215 "..\..\Areas\Config\Views\Plugins\Index.cshtml" } diff --git a/Disco.Web/Areas/Config/Views/Plugins/Install.cshtml b/Disco.Web/Areas/Config/Views/Plugins/Install.cshtml index 5018a49f..98fdd605 100644 --- a/Disco.Web/Areas/Config/Views/Plugins/Install.cshtml +++ b/Disco.Web/Areas/Config/Views/Plugins/Install.cshtml @@ -65,7 +65,7 @@ } -
+

@@ -75,13 +75,18 @@ Only Install plugins from a trusted source.

+ @using (Html.BeginForm(MVC.API.Plugin.Install(), FormMethod.Post)) + { + @Html.AntiForgeryToken() + }
@if (canInstallLocal) { -
+
@using (Html.BeginForm(MVC.API.Plugin.InstallLocal(), FormMethod.Post, new { enctype = "multipart/form-data" })) { + @Html.AntiForgeryToken() } @@ -114,8 +119,10 @@ return; } $(this).dialog("disable"); - - window.location.href = $selectedPluginUrl; + $(this) + .find('form') + .attr('action', $selectedPluginUrl) + .submit(); }, Cancel: function () { $selectedPlugin = null; diff --git a/Disco.Web/Areas/Config/Views/Plugins/Install.generated.cs b/Disco.Web/Areas/Config/Views/Plugins/Install.generated.cs index dfc87048..925aff78 100644 --- a/Disco.Web/Areas/Config/Views/Plugins/Install.generated.cs +++ b/Disco.Web/Areas/Config/Views/Plugins/Install.generated.cs @@ -400,6 +400,8 @@ WriteLiteral(" id=\"dialogInstallPlugin\""); WriteLiteral(" title=\"Install this Plugin?\""); +WriteLiteral(" class=\"dialog\""); + WriteLiteral(">\r\n Warning: All plugins run with the same level of network pri" + "vileges as the Disco ICT Web App.
\r\n Only Install plugin" + -"s from a trusted source.\r\n

\r\n
\r\n
\r\n"); +"s from a trusted source.\r\n

\r\n
\r\n"); - #line 79 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + #line 78 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + + + #line default + #line hidden + + #line 78 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + using (Html.BeginForm(MVC.API.Plugin.Install(), FormMethod.Post)) + { + + + #line default + #line hidden + + #line 80 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + Write(Html.AntiForgeryToken()); + + + #line default + #line hidden + + #line 80 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + + } + + + #line default + #line hidden +WriteLiteral("\r\n"); + + + #line 83 "..\..\Areas\Config\Views\Plugins\Install.cshtml" if (canInstallLocal) { @@ -438,6 +471,8 @@ WriteLiteral(" id=\"dialogUploadPlugin\""); WriteLiteral(" title=\"Install Plugin Package\""); +WriteLiteral(" class=\"dialog\""); + WriteLiteral(">\r\n \r\n"); - #line 83 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + #line 87 "..\..\Areas\Config\Views\Plugins\Install.cshtml" #line default #line hidden - #line 83 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + #line 87 "..\..\Areas\Config\Views\Plugins\Install.cshtml" using (Html.BeginForm(MVC.API.Plugin.InstallLocal(), FormMethod.Post, new { enctype = "multipart/form-data" })) { + + + #line default + #line hidden + + #line 89 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + Write(Html.AntiForgeryToken()); + + + #line default + #line hidden + + #line 89 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + #line default @@ -477,7 +526,7 @@ WriteLiteral(" accept=\".discoPlugin\""); WriteLiteral(" />\r\n"); - #line 87 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + #line 92 "..\..\Areas\Config\Views\Plugins\Install.cshtml" } @@ -501,7 +550,7 @@ WriteLiteral(">Warning: All plugins run with the same level "iv>\r\n"); - #line 96 "..\..\Areas\Config\Views\Plugins\Install.cshtml" + #line 101 "..\..\Areas\Config\Views\Plugins\Install.cshtml" } @@ -515,35 +564,36 @@ WriteLiteral("