Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Bring back update notification #4695

Merged
merged 8 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Services\Dto\FrameworkQueryDTO.cs" />
<Compile Include="Services\Dto\SuggestionDto.cs" />
<Compile Include="Services\Dto\RoleGroupDto.cs" />
<Compile Include="Services\ServerSummaryController.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -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; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -68,87 +69,85 @@ public HttpResponseMessage GetServerInfo()
}
}

/// <summary>
/// Returns update information about current framework version.
/// </summary>
/// <returns>A serialized FrameworkQueryDTO object.</returns>
[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<FrameworkQueryDTO>(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<FrameworkQueryDTO>(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<T>(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<T>(responseFromServer);
}
}

return default(T);
}

private string UpdateUrl()
{
var url = DotNetNukeContext.Current.Application.UpgradeUrl;

return url;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@
<data name="btn_CloseDialog.Text" xml:space="preserve">
<value>OK</value>
</data>
<data name="CriticalUpdate.Text" xml:space="preserve">
<value>[ Critical Update ]</value>
<data name="Critical.Text" xml:space="preserve">
<value>Critical</value>
</data>
<data name="NormalUpdate.Text" xml:space="preserve">
<value>[ New Update ]</value>
Expand All @@ -321,4 +321,10 @@
<data name="UnlockEditMode.Text" xml:space="preserve">
<value>Click to unlock Edit Mode.</value>
</data>
<data name="Update.Text" xml:space="preserve">
<value>Update</value>
</data>
<data name="LatestVersion.Text" xml:space="preserve">
<value>Latest Version</value>
</data>
</root>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@font-face {
@font-face {
font-family: 'pb_regular';
src: url('open-sans.semibold.ttf') format('truetype');
font-weight: normal;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
<body>
<div id="personabar-wrap">
<div class="personabar" id="personabar">
<div class="personabarLogo">
<a class="update" target="_blank" data-bind="attr: {'href': updateLink}, html: updateText, css: {'normal-update': updateType() === 1, 'critical-update': updateType() === 2}"></a>
<div class="personabarLogo" data-bind="css: { 'updateLogo': !upToDate() }">
<a class="update" target="_blank" data-bind="visible: !upToDate(), attr: {'href': updateLink}, html: updateText, css: { 'critical': updateCritical() }"></a>
</div>
<div id="topLevelMenu">
<ul class="personabarnav">
Expand Down
Loading