2022-03-29 13:44:21 +02:00
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2022-05-09 09:39:46 +02:00
|
|
|
using System.Net;
|
2020-10-23 14:18:53 +11:00
|
|
|
using System.Text;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
2020-04-20 12:20:47 +02:00
|
|
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
2021-02-18 11:06:02 +01:00
|
|
|
using Umbraco.Cms.Core.Security;
|
|
|
|
|
using Umbraco.Cms.Core.Semver;
|
|
|
|
|
using Umbraco.Cms.Core.Serialization;
|
2020-04-20 12:20:47 +02:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
namespace Umbraco.Extensions;
|
|
|
|
|
|
|
|
|
|
public static class ViewDataExtensions
|
2020-04-20 12:20:47 +02:00
|
|
|
{
|
2022-05-09 09:39:46 +02:00
|
|
|
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)
|
2020-04-20 12:20:47 +02:00
|
|
|
{
|
2022-05-09 09:39:46 +02:00
|
|
|
if (tempData[token] == null)
|
2020-04-20 12:20:47 +02:00
|
|
|
{
|
2022-05-09 09:39:46 +02:00
|
|
|
return false;
|
2020-04-20 12:20:47 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
viewData[token] = tempData[token];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-10-23 14:18:53 +11:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
/// <summary>
|
|
|
|
|
/// Copies data from a request cookie to view data and then clears the cookie in the response
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// <para>
|
|
|
|
|
/// 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
|
|
|
|
|
/// </para>
|
|
|
|
|
/// </remarks>
|
|
|
|
|
public static bool FromBase64CookieData<T>(
|
|
|
|
|
this ViewDataDictionary viewData,
|
|
|
|
|
HttpContext? httpContext,
|
|
|
|
|
string cookieName,
|
|
|
|
|
IJsonSerializer serializer)
|
|
|
|
|
{
|
|
|
|
|
var hasCookie = httpContext?.Request.Cookies.ContainsKey(cookieName) ?? false;
|
|
|
|
|
if (!hasCookie)
|
2020-04-20 12:20:47 +02:00
|
|
|
{
|
2022-05-09 09:39:46 +02:00
|
|
|
return false;
|
2020-04-20 12:20:47 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
// get the cookie value
|
|
|
|
|
if (httpContext is null || !httpContext.Request.Cookies.TryGetValue(cookieName, out var cookieVal))
|
2020-04-20 12:20:47 +02:00
|
|
|
{
|
2022-05-09 09:39:46 +02:00
|
|
|
return false;
|
2020-04-20 12:20:47 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
// ensure the cookie is expired (must be done after reading the value)
|
|
|
|
|
httpContext.Response.Cookies.Delete(cookieName);
|
2020-04-20 12:20:47 +02:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
if (cookieVal.IsNullOrWhiteSpace())
|
2020-04-20 12:20:47 +02:00
|
|
|
{
|
2022-05-09 09:39:46 +02:00
|
|
|
return false;
|
2020-04-20 12:20:47 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
try
|
2020-04-20 12:20:47 +02:00
|
|
|
{
|
2022-05-09 09:39:46 +02:00
|
|
|
var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(WebUtility.UrlDecode(cookieVal)!));
|
2020-04-20 12:20:47 +02:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
// deserialize to T and store in viewdata
|
|
|
|
|
viewData[cookieName] = serializer.Deserialize<T>(decoded);
|
|
|
|
|
return true;
|
2020-04-20 12:20:47 +02:00
|
|
|
}
|
2022-05-09 09:39:46 +02:00
|
|
|
catch (Exception)
|
2020-05-05 14:28:01 +02:00
|
|
|
{
|
2022-05-09 09:39:46 +02:00
|
|
|
return false;
|
2020-05-05 14:28:01 +02:00
|
|
|
}
|
2022-05-09 09:39:46 +02:00
|
|
|
}
|
2020-05-05 14:28:01 +02:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
public static string? GetUmbracoPath(this ViewDataDictionary viewData) => (string?)viewData[TokenUmbracoPath];
|
2020-04-20 12:20:47 +02:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
public static void SetUmbracoPath(this ViewDataDictionary viewData, string value) =>
|
|
|
|
|
viewData[TokenUmbracoPath] = value;
|
2020-04-20 12:20:47 +02:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
public static string? GetInstallApiBaseUrl(this ViewDataDictionary viewData) =>
|
|
|
|
|
(string?)viewData[TokenInstallApiBaseUrl];
|
2020-04-20 12:20:47 +02:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
public static void SetInstallApiBaseUrl(this ViewDataDictionary viewData, string? value) =>
|
|
|
|
|
viewData[TokenInstallApiBaseUrl] = value;
|
2020-04-20 12:20:47 +02:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
public static string? GetUmbracoBaseFolder(this ViewDataDictionary viewData) =>
|
|
|
|
|
(string?)viewData[TokenUmbracoBaseFolder];
|
2022-01-21 13:10:34 +01:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
public static void SetUmbracoBaseFolder(this ViewDataDictionary viewData, string value) =>
|
|
|
|
|
viewData[TokenUmbracoBaseFolder] = value;
|
2022-01-21 13:10:34 +01:00
|
|
|
|
2022-05-09 09:39:46 +02:00
|
|
|
public static void SetUmbracoVersion(this ViewDataDictionary viewData, SemVersion version) =>
|
|
|
|
|
viewData[TokenUmbracoVersion] = version;
|
|
|
|
|
|
|
|
|
|
public static SemVersion? GetUmbracoVersion(this ViewDataDictionary viewData) =>
|
|
|
|
|
(SemVersion?)viewData[TokenUmbracoVersion];
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Used by the back office login screen to get any registered external login provider errors
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="viewData"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public static BackOfficeExternalLoginProviderErrors?
|
|
|
|
|
GetExternalSignInProviderErrors(this ViewDataDictionary viewData) =>
|
|
|
|
|
(BackOfficeExternalLoginProviderErrors?)viewData[TokenExternalSignInError];
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Used by the back office controller to register any external login provider errors
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="viewData"></param>
|
|
|
|
|
/// <param name="errors"></param>
|
|
|
|
|
public static void SetExternalSignInProviderErrors(
|
|
|
|
|
this ViewDataDictionary viewData,
|
|
|
|
|
BackOfficeExternalLoginProviderErrors errors) => viewData[TokenExternalSignInError] = errors;
|
|
|
|
|
|
|
|
|
|
public static string? GetPasswordResetCode(this ViewDataDictionary viewData) =>
|
|
|
|
|
(string?)viewData[TokenPasswordResetCode];
|
|
|
|
|
|
|
|
|
|
public static void SetPasswordResetCode(this ViewDataDictionary viewData, string value) =>
|
|
|
|
|
viewData[TokenPasswordResetCode] = value;
|
|
|
|
|
|
|
|
|
|
public static void SetTwoFactorProviderNames(this ViewDataDictionary viewData, IEnumerable<string> providerNames) =>
|
|
|
|
|
viewData[TokenTwoFactorRequired] = providerNames;
|
|
|
|
|
|
|
|
|
|
public static bool TryGetTwoFactorProviderNames(
|
|
|
|
|
this ViewDataDictionary viewData,
|
|
|
|
|
[MaybeNullWhen(false)] out IEnumerable<string> providerNames)
|
|
|
|
|
{
|
|
|
|
|
providerNames = viewData[TokenTwoFactorRequired] as IEnumerable<string>;
|
|
|
|
|
return providerNames is not null;
|
2020-04-20 12:20:47 +02:00
|
|
|
}
|
|
|
|
|
}
|