src/identity/Contracts/Errors/Identity.codegen.cs (294 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Globalization;
using System.Resources;
using System.Text;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
// Specify that the fallback language is also inside a satellite assembly.
[assembly: NeutralResourcesLanguage("en", UltimateResourceFallbackLocation.Satellite)]
namespace Microsoft.Azure.CleanRoomSidecar.Identity.Errors
{
/// <summary>
/// Enumeration of display name to code.
/// </summary>
public enum IdentityErrorCode
{
InternalError = 500,
InvalidClientId = 501,
InvalidConfiguration = 502,
}
/// <summary>
/// Class definition.
/// </summary>
public partial class IdentityException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="IdentityException"/> class.
/// This constructor is used to create an instance of <see cref="IdentityException"/>
/// with an inner exception.
/// </summary>
/// <param name="exception">Instance of <see cref="IdentityException"/> from which
/// this exception is to be initialized.</param>
/// <param name="innerException">Inner exception to be associated with this instance.
/// </param>
public IdentityException(
IdentityException exception,
Exception innerException)
: base(string.Empty, innerException)
{
if (exception != null)
{
this.Id = exception.Id;
this.Parameters = exception.Parameters;
this.Initialize();
}
}
/// <summary>
/// Gets the ID associated with the error.
/// </summary>
[JsonInclude]
public IdentityErrorCode Id { get; private set; }
/// <summary>
/// Gets the parameters needed to form resource strings.
/// </summary>
[JsonInclude]
public Dictionary<string, string> Parameters { get; private set; }
/// <summary>
/// Gets the tags associated with the error.
/// </summary>
[JsonIgnore]
public Dictionary<string, string> Tags { get; private set; }
/// <summary>
/// Gets the error code associated with the error.
/// </summary>
[JsonIgnore]
public IdentityErrorCode ErrorCode => this.Id;
/// <summary>
/// Gets the error message. Use GetMessage if you want to specify culture.
/// </summary>
[JsonIgnore]
public override string Message => this.GetMessageSafe();
/// <summary>
/// Perform any custom initialization of the class properties here.
/// </summary>
internal void Initialize()
{
this.Data.Add("ErrorCode", this.Id);
this.Data.Add("Level", IdentityErrorCodeSeverityMap[this.Id]);
}
}
/// <summary>
/// Constructors (one per code) that take required parameters and return initialized object.
/// </summary>
public partial class IdentityException
{
/// <summary>
/// Initializes a new instance of the <see cref="IdentityException"/> class.
/// </summary>
internal IdentityException(
IdentityErrorCode id,
Dictionary<string, string> parameters,
Dictionary<string, string> tags)
{
this.Id = id;
this.Parameters = parameters;
this.Tags = tags;
this.Initialize();
}
/// <summary>
/// Initializes a new instance of the <see cref="IdentityException"/> class.
/// </summary>
/// <remarks>This constructor is used for JSON deserialization.</remarks>
[JsonConstructor]
protected IdentityException()
{
}
public static IdentityException InternalError()
{
return new IdentityException(
IdentityErrorCode.InternalError,
new System.Collections.Generic.Dictionary<string, string>()
{
},
new System.Collections.Generic.Dictionary<string, string>()
{
});
}
public static IdentityException InvalidClientId(string clientId)
{
return new IdentityException(
IdentityErrorCode.InvalidClientId,
new System.Collections.Generic.Dictionary<string, string>()
{
{ "ClientId", clientId },
},
new System.Collections.Generic.Dictionary<string, string>()
{
});
}
public static IdentityException InvalidConfiguration(string message)
{
return new IdentityException(
IdentityErrorCode.InvalidConfiguration,
new System.Collections.Generic.Dictionary<string, string>()
{
{ "Message", message },
},
new System.Collections.Generic.Dictionary<string, string>()
{
});
}
}
/// <summary>
/// Accessors for resource string that take culture as input and return localized string.
/// </summary>
public partial class IdentityException
{
public string GetMessage(string culture = null)
{
culture = culture ?? CultureInfo.InstalledUICulture.Name;
string resourceId = $"Error_{(int)this.Id}_Message";
return MessageFormatter.GetFormattedMessageString(
resourceId,
this.Parameters,
culture);
}
public string GetMessageSafe(string culture = null)
{
try
{
return this.GetMessage(culture);
}
catch (Exception)
{
return $"Unable to retrieve event message.";
}
}
public string GetPossibleCauses(string culture = null)
{
culture = culture ?? CultureInfo.InstalledUICulture.Name;
string resourceId = $"Error_{(int)this.Id}_PossibleCauses";
return MessageFormatter.GetFormattedMessageString(
resourceId,
this.Parameters,
culture);
}
public string GetPossibleCausesSafe(string culture = null)
{
try
{
return this.GetPossibleCauses(culture);
}
catch (Exception)
{
return $"Unable to retrieve event message.";
}
}
public string GetRecommendedAction(string culture = null)
{
culture = culture ?? CultureInfo.InstalledUICulture.Name;
string resourceId = $"Error_{(int)this.Id}_RecommendedAction";
return MessageFormatter.GetFormattedMessageString(
resourceId,
this.Parameters,
culture);
}
public string GetRecommendedActionSafe(string culture = null)
{
try
{
return this.GetRecommendedAction(culture);
}
catch (Exception)
{
return $"Unable to retrieve event message.";
}
}
/// <summary>
/// Message formatter class for creating messages in the requested culture.
/// </summary>
private class MessageFormatter
{
/// <summary>
/// If a message parameter is not passed, it will be replaced with this string.
/// </summary>
private const string NoParameterMarker = "";
/// <summary>
/// For having a % character in the message, its better to use %% in the message.
/// The %% in the message is replaced with this for safe parsing, and replaced back
/// with %.
/// </summary>
private const string ANSIIMarkerForPercent = "%";
/// <summary>
/// Regular expression for matching parameter names (e.g. %PrimaryCloudName;) in the
/// message.
/// </summary>
private static readonly Regex ParameterRegex = new Regex(
@"%[^%]*?;",
RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled);
/// <summary>
/// Resource manager instance for fetching the messages from the resource file.
/// </summary>
private static ResourceManager resourceManager;
/// <summary>
/// Initializes static members of the <see cref="MessageFormatter"/> class.
/// </summary>
static MessageFormatter()
{
resourceManager =
new ResourceManager(
"Microsoft.Azure.CleanRoomSidecar.Identity.Resources.Errors",
typeof(IdentityException).Assembly);
}
/// <summary>
/// Formats and returns the message string in the given locale.
/// </summary>
/// <param name="resourceId">The resource id.</param>
/// <param name="parameters">Collection of named parameters for creating message.
/// </param>
/// <param name="culture">The culture, in which the string is needed.</param>
/// <returns>
/// Formatted message in the given locale. Empty string if resource not found.
/// </returns>
public static string GetFormattedMessageString(
string resourceId,
IDictionary<string, string> parameters,
string culture)
{
string formatString = GetResourceString(resourceId, culture);
return FormatString(formatString, parameters);
}
/// <summary>
/// Get resource string for the specified resource id. Empty string if resource is
/// not found.
/// </summary>
/// <param name="resourceId">The resource id.</param>
/// <param name="culture">The culture, in which the string is needed.</param>
/// <returns>Resource string in the given locale. Null if resource not found.
/// </returns>
private static string GetResourceString(
string resourceId,
string culture)
{
CultureInfo cultureInfo = null;
try
{
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language
if (culture != null && culture.Contains(","))
{
culture = culture.Split(',')[0];
}
cultureInfo = new CultureInfo(culture ?? string.Empty);
}
catch (CultureNotFoundException)
{
// Client can send a locale which is valid on client system, but is not
// supported by the OS/.NET versions of the Gateway web/worker roles.
// Unsupported culture in OS/.NET will default to 'en-US'.
cultureInfo = new CultureInfo("en-US");
}
return resourceManager.GetString(resourceId, cultureInfo);
}
/// <summary>
/// Replace all the message parameters with that in the list of parameters passed.
/// </summary>
/// <param name="formatString">The formatted message in which the values need to be
/// replaced.</param>
/// <param name="parameters">A key value pair of message parameters and values.</param>
/// <returns>The string with all the parameters replaced.</returns>
private static string FormatString(
string formatString,
IDictionary<string, string> parameters)
{
if (string.IsNullOrWhiteSpace(formatString))
{
return string.Empty;
}
StringBuilder sb = new StringBuilder();
sb.Append(formatString);
// hide percentage escape characters using their ANSI marker
sb.Replace("%%", ANSIIMarkerForPercent);
foreach (Match param in MessageFormatter.ParameterRegex.Matches(formatString))
{
string key = param.Value.Substring(1, param.Length - 2);
string parameter;
if (parameters == null || !parameters.TryGetValue(key, out parameter))
{
parameter = MessageFormatter.NoParameterMarker;
}
sb.Replace(param.Value, parameter);
}
sb.Replace(ANSIIMarkerForPercent, "%");
return sb.ToString();
}
}
}
/// <summary>
/// Accessors for Severity.
/// </summary>
public partial class IdentityException
{
private static Dictionary<IdentityErrorCode, string> IdentityErrorCodeSeverityMap { get; } =
new Dictionary<IdentityErrorCode, string>
{
{ IdentityErrorCode.InternalError, "Error" },
{ IdentityErrorCode.InvalidClientId, "Error" },
{ IdentityErrorCode.InvalidConfiguration, "Error" },
};
public static string GetSeverity(IdentityErrorCode id)
{
return IdentityErrorCodeSeverityMap[id];
}
public static bool TryGetSeverity(IdentityErrorCode id, out string value)
{
return IdentityErrorCodeSeverityMap.TryGetValue(id, out value);
}
}
/// <summary>
/// Accessors for HttpStatusCode.
/// </summary>
public partial class IdentityException
{
private static Dictionary<IdentityErrorCode, string> IdentityErrorCodeHttpStatusCodeMap { get; } =
new Dictionary<IdentityErrorCode, string>
{
{ IdentityErrorCode.InternalError, "InternalServerError" },
{ IdentityErrorCode.InvalidClientId, "BadRequest" },
{ IdentityErrorCode.InvalidConfiguration, "InternalServerError" },
};
public static string GetHttpStatusCode(IdentityErrorCode id)
{
return IdentityErrorCodeHttpStatusCodeMap[id];
}
public static bool TryGetHttpStatusCode(IdentityErrorCode id, out string value)
{
return IdentityErrorCodeHttpStatusCodeMap.TryGetValue(id, out value);
}
}
}