using System.Diagnostics.CodeAnalysis; using System.Net; using System.Text; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Semver; using Umbraco.Cms.Core.Serialization; namespace Umbraco.Extensions; public static class ViewDataExtensions { public const string TokenUmbracoPath = "UmbracoPath"; public const string TokenInstallApiBaseUrl = "InstallApiBaseUrl"; public const string TokenUmbracoBaseFolder = "UmbracoBaseFolder"; public const string TokenUmbracoVersion = "UmbracoVersion"; public const string TokenExternalSignInError = "ExternalSignInError"; public const string TokenPasswordResetCode = "PasswordResetCode"; public const string TokenTwoFactorRequired = "TwoFactorRequired"; public static bool FromTempData(this ViewDataDictionary viewData, ITempDataDictionary tempData, string token) { if (tempData?[token] is null) { return false; } viewData[token] = tempData[token]; return true; } /// /// Copies data from a request cookie to view data and then clears the cookie in the response /// /// /// /// /// This is similar to TempData but in some cases we cannot use TempData which relies on the temp data provider and /// session. /// The cookie value can either be a simple string value /// /// public static bool FromBase64CookieData( this ViewDataDictionary viewData, HttpContext? httpContext, string cookieName, IJsonSerializer serializer) { var hasCookie = httpContext?.Request.Cookies.ContainsKey(cookieName) ?? false; if (!hasCookie) { return false; } // get the cookie value if (httpContext is null || !httpContext.Request.Cookies.TryGetValue(cookieName, out var cookieVal)) { return false; } // ensure the cookie is expired (must be done after reading the value) httpContext.Response.Cookies.Delete(cookieName); if (cookieVal.IsNullOrWhiteSpace()) { return false; } try { var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(WebUtility.UrlDecode(cookieVal)!)); // deserialize to T and store in viewdata viewData[cookieName] = serializer.Deserialize(decoded); return true; } catch (Exception) { return false; } } public static string? GetUmbracoPath(this ViewDataDictionary viewData) => (string?)viewData[TokenUmbracoPath]; public static void SetUmbracoPath(this ViewDataDictionary viewData, string value) => viewData[TokenUmbracoPath] = value; public static string? GetInstallApiBaseUrl(this ViewDataDictionary viewData) => (string?)viewData[TokenInstallApiBaseUrl]; public static void SetInstallApiBaseUrl(this ViewDataDictionary viewData, string? value) => viewData[TokenInstallApiBaseUrl] = value; public static string? GetUmbracoBaseFolder(this ViewDataDictionary viewData) => (string?)viewData[TokenUmbracoBaseFolder]; public static void SetUmbracoBaseFolder(this ViewDataDictionary viewData, string value) => viewData[TokenUmbracoBaseFolder] = value; public static void SetUmbracoVersion(this ViewDataDictionary viewData, SemVersion version) => viewData[TokenUmbracoVersion] = version; public static SemVersion? GetUmbracoVersion(this ViewDataDictionary viewData) => (SemVersion?)viewData[TokenUmbracoVersion]; /// /// Used by the back office login screen to get any registered external login provider errors /// /// /// public static BackOfficeExternalLoginProviderErrors? GetExternalSignInProviderErrors(this ViewDataDictionary viewData) => (BackOfficeExternalLoginProviderErrors?)viewData[TokenExternalSignInError]; /// /// Used by the back office controller to register any external login provider errors /// /// /// public static void SetExternalSignInProviderErrors( this ViewDataDictionary viewData, BackOfficeExternalLoginProviderErrors errors) => viewData[TokenExternalSignInError] = errors; public static void SetTwoFactorProviderNames(this ViewDataDictionary viewData, IEnumerable providerNames) => viewData[TokenTwoFactorRequired] = providerNames; public static bool TryGetTwoFactorProviderNames( this ViewDataDictionary viewData, [MaybeNullWhen(false)] out IEnumerable providerNames) { providerNames = viewData[TokenTwoFactorRequired] as IEnumerable; return providerNames is not null; } }