diff --git a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Dnn.PersonaBar.UI.csproj b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Dnn.PersonaBar.UI.csproj
index 6a53dbddb3c..31e0e352dd4 100644
--- a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Dnn.PersonaBar.UI.csproj
+++ b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Dnn.PersonaBar.UI.csproj
@@ -119,6 +119,7 @@
Code
+
diff --git a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Services/Dto/FrameworkQueryDTO.cs b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Services/Dto/FrameworkQueryDTO.cs
new file mode 100644
index 00000000000..12b5a2d51cf
--- /dev/null
+++ b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Services/Dto/FrameworkQueryDTO.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information
+
+namespace Dnn.PersonaBar.UI.Services.DTO
+{
+ using System;
+ using System.Runtime.Serialization;
+
+ [DataContract]
+ public class FrameworkQueryDTO
+ {
+ [DataMember(Name = "UpToDate")]
+ public bool UpToDate { get; set; } = true;
+
+ [DataMember(Name = "Version")]
+ public string Version { get; set; } = string.Empty;
+
+ [DataMember(Name = "Url")]
+ public string Url { get; set; } = string.Empty;
+
+ [DataMember(Name = "Critical")]
+ public bool IsCritical { get; set; } = false;
+
+ [DataMember(Name = "Published")]
+ public DateTime Published { get; set; }
+ }
+}
diff --git a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Services/ServerSummaryController.cs b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Services/ServerSummaryController.cs
index d93ed627a7c..564d51e507d 100644
--- a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Services/ServerSummaryController.cs
+++ b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/Services/ServerSummaryController.cs
@@ -4,18 +4,21 @@
namespace Dnn.PersonaBar.UI.Services
{
- using System;
+ using System;
+ using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
- using System.Text;
+ using System.Text;
+ using System.Text.RegularExpressions;
using System.Web;
using System.Web.Caching;
using System.Web.Http;
using Dnn.PersonaBar.Library;
- using Dnn.PersonaBar.Library.Attributes;
+ using Dnn.PersonaBar.Library.Attributes;
+ using Dnn.PersonaBar.UI.Services.DTO;
using DotNetNuke.Application;
using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
@@ -29,9 +32,6 @@ namespace Dnn.PersonaBar.UI.Services
[MenuPermission(Scope = ServiceScope.Regular)]
public class ServerSummaryController : PersonaBarApiController
{
- private const string CriticalUpdateHash = "e67b666fb40c4f304a41d1706d455c09017b7bcf4ec1e411450ebfcd2c8f12d0";
- private const string NormalUpdateHash = "df29e1cda367bb8fa8534b5fb2415406100252dec057138b8d63cbadb44fb8e7";
-
private enum UpdateType
{
None = 0,
@@ -56,7 +56,8 @@ public HttpResponseMessage GetServerInfo()
FrameworkVersion = isHost ? Globals.NETFrameworkVersion.ToString(2) : string.Empty,
ServerName = isHost ? Globals.ServerName : string.Empty,
LicenseVisible = isHost && this.GetVisibleSetting("LicenseVisible"),
- DocCenterVisible = this.GetVisibleSetting("DocCenterVisible"),
+ DocCenterVisible = this.GetVisibleSetting("DocCenterVisible"),
+ Update = this.UpdateInfo(),
};
return this.Request.CreateResponse(HttpStatusCode.OK, response);
@@ -68,87 +69,85 @@ public HttpResponseMessage GetServerInfo()
}
}
+ ///
+ /// Returns update information about current framework version.
+ ///
+ /// A serialized FrameworkQueryDTO object.
[HttpGet]
- public HttpResponseMessage GetUpdateLink()
- {
- UpdateType updateType;
- var url = this.NeedUpdate(out updateType) ? Upgrade.UpgradeRedirect() : string.Empty;
-
- return this.Request.CreateResponse(HttpStatusCode.OK, new { Url = url, Type = updateType });
- }
-
+ public HttpResponseMessage GetUpdateInfo()
+ {
+ return this.Request.CreateResponse(HttpStatusCode.OK, this.UpdateInfo());
+ }
+
private bool GetVisibleSetting(string settingName)
{
var portalSettings = PortalController.Instance.GetPortalSettings(this.PortalId);
return !portalSettings.ContainsKey(settingName)
|| string.IsNullOrEmpty(portalSettings[settingName])
|| portalSettings[settingName] == "true";
- }
-
- private bool NeedUpdate(out UpdateType updateType)
- {
- updateType = UpdateType.None;
-
- if (HttpContext.Current == null || !Host.CheckUpgrade || !this.UserInfo.IsSuperUser)
- {
- return false;
- }
-
- var version = DotNetNukeContext.Current.Application.Version;
- var request = HttpContext.Current.Request;
-
- var imageUrl = Upgrade.UpgradeIndicator(version, request.IsLocal, request.IsSecureConnection);
- imageUrl = Globals.AddHTTP(imageUrl.TrimStart('/'));
-
- try
- {
- string hash;
- const string cacheKey = "UpdateServiceUrlCacheKey";
- var cachedData = DataCache.GetCache(cacheKey) as string;
- if (cachedData != null)
- {
- hash = cachedData;
- }
- else
- {
- var webRequest = WebRequest.CreateHttp(imageUrl);
- webRequest.Timeout = Host.WebRequestTimeout;
- webRequest.UserAgent = request.UserAgent;
- webRequest.Referer = request.RawUrl;
-
- using (var stream = ((HttpWebResponse)webRequest.GetResponse()).GetResponseStream())
- {
- if (stream == null)
- {
- return false;
- }
-
- using (var sha256 = SHA256.Create())
- {
- hash =
- BitConverter.ToString(sha256.ComputeHash(stream)).Replace("-", string.Empty).ToLowerInvariant();
- DataCache.SetCache(cacheKey, hash, (DNNCacheDependency)null,
- Cache.NoAbsoluteExpiration, TimeSpan.FromDays(1), CacheItemPriority.Normal, null);
- }
- }
- }
-
- switch (hash)
- {
- case NormalUpdateHash:
- updateType = UpdateType.Normal;
- return true;
- case CriticalUpdateHash:
- updateType = UpdateType.Critical;
- return true;
- default:
- return false;
- }
- }
- catch (Exception)
- {
- return false;
- }
- }
+ }
+
+ private FrameworkQueryDTO UpdateInfo()
+ {
+ if (HttpContext.Current == null || !Host.CheckUpgrade || !this.UserInfo.IsSuperUser)
+ {
+ return new FrameworkQueryDTO();
+ }
+
+ return CBO.GetCachedObject(new CacheItemArgs("DnnUpdateUrl"), this.RetrieveUpdateUrl);
+ }
+
+ private FrameworkQueryDTO RetrieveUpdateUrl(CacheItemArgs args)
+ {
+ try
+ {
+ var url = $"{DotNetNukeContext.Current.Application.UpgradeUrl}/Update/FrameworkStatus";
+ url += "?core=" + Globals.FormatVersion(DotNetNukeContext.Current.Application.Version, "00", 3, string.Empty);
+ url += "&type=" + DotNetNukeContext.Current.Application.Type;
+ url += "&name=" + DotNetNukeContext.Current.Application.Name;
+ url += "&id=" + Host.GUID;
+ url += "&no=" + PortalController.Instance.GetPortals().Count;
+ url += "&os=" + Globals.FormatVersion(Globals.OperatingSystemVersion, "00", 2, string.Empty);
+ url += "&net=" + Globals.FormatVersion(Globals.NETFrameworkVersion, "00", 2, string.Empty);
+ url += "&db=" + Globals.FormatVersion(Globals.DatabaseEngineVersion, "00", 2, string.Empty);
+ var response = this.GetJsonObject(url);
+ if (response.Version.Length == 6)
+ {
+ response.Version = $"v. {response.Version.Substring(0, 2)}.{response.Version.Substring(2, 2)}.{response.Version.Substring(4, 2)}";
+ }
+
+ return response;
+ }
+ catch (Exception ex)
+ {
+ Exceptions.LogException(ex);
+ }
+
+ return new FrameworkQueryDTO();
+ }
+
+ private T GetJsonObject(string url)
+ {
+ var request = Globals.GetExternalRequest(url);
+ using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
+ {
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ var dataStream = response.GetResponseStream();
+ var reader = new StreamReader(dataStream);
+ var responseFromServer = reader.ReadToEnd();
+ return Newtonsoft.Json.JsonConvert.DeserializeObject(responseFromServer);
+ }
+ }
+
+ return default(T);
+ }
+
+ private string UpdateUrl()
+ {
+ var url = DotNetNukeContext.Current.Application.UpgradeUrl;
+
+ return url;
+ }
}
}
diff --git a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/App_LocalResources/PersonaBar.resx b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/App_LocalResources/PersonaBar.resx
index 5251f50e654..a17f0da1f84 100644
--- a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/App_LocalResources/PersonaBar.resx
+++ b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/App_LocalResources/PersonaBar.resx
@@ -297,8 +297,8 @@
OK
-
- [ Critical Update ]
+
+ Critical
[ New Update ]
@@ -321,4 +321,10 @@
Click to unlock Edit Mode.
+
+ Update
+
+
+ Latest Version
+
\ No newline at end of file
diff --git a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/css/main.css b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/css/main.css
index dd78ff01b3f..80bf7751d58 100644
--- a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/css/main.css
+++ b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/css/main.css
@@ -1,4 +1,4 @@
-@font-face {
+@font-face {
font-family: 'pb_regular';
src: url('open-sans.semibold.ttf') format('truetype');
font-weight: normal;
@@ -732,27 +732,42 @@ transform: rotate(180deg);
background-size: 32px auto;
position: relative;
border-bottom: 1px solid var(--dnn-color-pb-menu-divider);
+ text-align: center;
}
+ .personabar .personabarLogo.updateLogo {
+ background-position: center 14px;
+ }
.personabar .personabarLogo:hover {
background-color: var(--dnn-color-pb-menu-background-hover);
}
.personabar .personabarLogo a.update {
text-decoration: none;
text-transform: uppercase;
- font-size: 7px;
+ font-size: 10px;
font-family: pb_semibold;
display: none;
position: absolute;
bottom: 8px;
- width: 100%;
+ width: 64px;
text-align: center;
+ background-color: #21a3da;
+ border-radius: 3px;
+ color: #fff;
+ display: block;
+ padding: 2px;
+ margin-left: 5px;
}
+
+ .personabar .personabarLogo a.update.critical {
+ background-color: #D63333;
+ }
+
.personabar .personabarLogo a.update.normal-update {
color: #21A3DA;
display: block;
}
.personabar .personabarLogo a.update.critical-update {
- color: #D9577A;
+ color: #D63333;
display: block;
}
@@ -1943,7 +1958,13 @@ div.ui-dialog-titlebar > .ui-dialog-titlebar-close:hover {
color: #fff;
margin-top: 18px;
cursor: default;
+ padding-bottom: 6px;
}
+
+ .hoverSummaryMenu ul li.border {
+ border-bottom: 1px solid #868484;
+ }
+
.hoverSummaryMenu ul li span, .hoverSummaryMenu ul li label {
display: block;
line-height: 13px;
@@ -1956,8 +1977,7 @@ div.ui-dialog-titlebar > .ui-dialog-titlebar-close:hover {
.hoverSummaryMenu ul li label {
font-size: 12px;
color: var(--dnn-color-pb-menu-text-highlight);
- padding: 11px 0 18px 0;
- border-bottom: 1px solid var(--dnn-color-pb-menu-divider);
+ padding: 2px 0 5px 0;
text-transform: uppercase;
-moz-word-break: break-all;
-o-word-break: break-all;
@@ -1994,6 +2014,8 @@ div.ui-dialog-titlebar > .ui-dialog-titlebar-close:hover {
text-decoration: none;
cursor: pointer;
}
+
+ .server-summary li.update a:hover,
.server-summary li.doc-center a:hover,
.server-summary li.logout:hover {
color: #FFF;
@@ -2002,6 +2024,32 @@ div.ui-dialog-titlebar > .ui-dialog-titlebar-close:hover {
margin-top: 12px;
}
+.server-summary li.new-version-info.border {
+ border-color: #21a3da;
+}
+
+.server-summary li.new-version-info label {
+ color: #21a3da;
+}
+
+.server-summary li.new-version-info.border.critical {
+ border-color: #D63333;
+}
+
+.server-summary li.new-version-info.critical label {
+ color: #D63333;
+}
+
+.server-summary li.new-version-info span.update-critical {
+ font-size: 10px;
+ background-color: #D63333;
+ color: white;
+ text-transform: uppercase;
+ border-radius: 4px;
+ padding: 2px 4px;
+ float: right;
+}
+
/* Popup Style END */
/* Dropdown Style */
diff --git a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/index.html b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/index.html
index f3049db8b6a..d1fe93f3280 100644
--- a/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/index.html
+++ b/Dnn.AdminExperience/Library/Dnn.PersonaBar.UI/admin/personaBar/index.html
@@ -26,8 +26,8 @@