using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Semver; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Web; using Umbraco.Cms.Web.Common.Attributes; using Umbraco.Extensions; using Constants = Umbraco.Cms.Core.Constants; namespace Umbraco.Cms.Web.BackOffice.Controllers { [PluginController(Constants.Web.Mvc.BackOfficeApiArea)] public class UpdateCheckController : UmbracoAuthorizedJsonController { private readonly IUpgradeService _upgradeService; private readonly IUmbracoVersion _umbracoVersion; private readonly ICookieManager _cookieManager; private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor; private readonly GlobalSettings _globalSettings; public UpdateCheckController( IUpgradeService upgradeService, IUmbracoVersion umbracoVersion, ICookieManager cookieManager, IBackOfficeSecurityAccessor backofficeSecurityAccessor, IOptions globalSettings) { _upgradeService = upgradeService ?? throw new ArgumentNullException(nameof(upgradeService)); _umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion)); _cookieManager = cookieManager ?? throw new ArgumentNullException(nameof(cookieManager)); _backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor)); _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); } [UpdateCheckResponseFilter] public async Task GetCheck() { var updChkCookie = _cookieManager.GetCookieValue("UMB_UPDCHK"); var updateCheckCookie = updChkCookie ?? string.Empty; if (_globalSettings.VersionCheckPeriod > 0 && string.IsNullOrEmpty(updateCheckCookie) && _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.IsAdmin()) { try { var version = new SemVersion(_umbracoVersion.Version.Major, _umbracoVersion.Version.Minor, _umbracoVersion.Version.Build, _umbracoVersion.Comment); var result = await _upgradeService.CheckUpgrade(version); return new UpgradeCheckResponse(result.UpgradeType, result.Comment, result.UpgradeUrl, _umbracoVersion); } catch { //We don't want to crash due to this return null; } } return null; } /// /// Adds the cookie response if it was successful /// /// /// A filter is required because we are returning an object from the get method and not an HttpResponseMessage /// /// internal class UpdateCheckResponseFilterAttribute : TypeFilterAttribute { public UpdateCheckResponseFilterAttribute() : base(typeof(UpdateCheckResponseFilter)) { } private class UpdateCheckResponseFilter : IActionFilter { private readonly GlobalSettings _globalSettings; public UpdateCheckResponseFilter(IOptions globalSettings) { _globalSettings = globalSettings.Value; } public void OnActionExecuted(ActionExecutedContext context) { if (context.HttpContext.Response == null) return; if (context.Result is ObjectResult objectContent) { if (objectContent.Value == null) return; context.HttpContext.Response.Cookies.Append("UMB_UPDCHK", "1", new CookieOptions() { Path = "/", Expires = DateTimeOffset.Now.AddDays(_globalSettings.VersionCheckPeriod), HttpOnly = true, Secure = _globalSettings.UseHttps }); } } public void OnActionExecuting(ActionExecutingContext context) { } } } } }