Created
November 13, 2016 11:07
-
-
Save jstemerdink/8c6717ddd70ac09c1a82254e717dda46 to your computer and use it in GitHub Desktop.
A validation controller that uses the Moderation API from Microsoft Cognitive services to validate content
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CommentViewModel | |
{ | |
/// <summary>Gets the body content of the comment.</summary> | |
[Remote("IsSafeTextContent", "ModeratorValidation")] | |
public virtual string Body { get; set; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Configuration; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using System.Web.Mvc; | |
using System.Web.UI; | |
using EPiServer.Framework.Localization; | |
using EPiServer.Globalization; | |
using Microsoft.CognitiveServices.ContentModerator; | |
using Microsoft.CognitiveServices.ContentModerator.Contract.Text; | |
/// <summary> | |
/// Class ModeratorValidationController. | |
/// </summary> | |
/// <seealso cref="System.Web.Mvc.Controller" /> | |
/// <author>Jeroen Stemerdink</author> | |
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)] | |
public class ModeratorValidationController : Controller | |
{ | |
/// <summary> | |
/// The subscription key | |
/// </summary> | |
private static readonly string SubscriptionKey = | |
ConfigurationManager.AppSettings["contentmoderator:subscriptionkey"]; | |
/// <summary> | |
/// The moderator client | |
/// </summary> | |
private readonly ModeratorClient client; | |
/// <summary> | |
/// The localization service | |
/// </summary> | |
private readonly LocalizationService localizationService; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="ModeratorValidationController"/> class. | |
/// </summary> | |
/// <param name="localizationService">The localization service.</param> | |
public ModeratorValidationController(LocalizationService localizationService) | |
{ | |
this.client = new ModeratorClient(SubscriptionKey); | |
this.localizationService = localizationService; | |
} | |
/// <summary> | |
/// Determines whether [the specified body] [is safe text content]. | |
/// </summary> | |
/// <param name="body">The body.</param> | |
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns> | |
public JsonResult IsSafeTextContent(string body) | |
{ | |
return this.CheckContent(body, Constants.MediaType.Plain, false, false); | |
} | |
/// <summary> | |
/// Determines whether [is safe HTML content] [the specified body]. | |
/// </summary> | |
/// <param name="body">The body.</param> | |
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns> | |
public JsonResult IsSafeHtmlContent(string body) | |
{ | |
return this.CheckContent(body, Constants.MediaType.Html, false, false); | |
} | |
/// <summary> | |
/// Determines whether [is safe text content with urls] [the specified body]. | |
/// </summary> | |
/// <param name="body">The body.</param> | |
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns> | |
public JsonResult IsSafeTextContentWithUrls(string body) | |
{ | |
return this.CheckContent(body, Constants.MediaType.Plain, true, false); | |
} | |
/// <summary> | |
/// Determines whether [is safe HTML content with urls] [the specified body]. | |
/// </summary> | |
/// <param name="body">The body.</param> | |
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns> | |
public JsonResult IsSafeHtmlContentWithUrls(string body) | |
{ | |
return this.CheckContent(body, Constants.MediaType.Html, true, false); | |
} | |
/// <summary> | |
/// Determines whether [is safe text content with pii] [the specified body]. | |
/// </summary> | |
/// <param name="body">The body.</param> | |
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns> | |
public JsonResult IsSafeTextContentWithPii(string body) | |
{ | |
return this.CheckContent(body, Constants.MediaType.Plain, false, true); | |
} | |
/// <summary> | |
/// Determines whether [is safe HTML content with pii] [the specified body]. | |
/// </summary> | |
/// <param name="body">The body.</param> | |
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns> | |
public JsonResult IsSafeHtmlContentWithPii(string body) | |
{ | |
return this.CheckContent(body, Constants.MediaType.Html, false, true); | |
} | |
/// <summary> | |
/// Determines whether [is safe text content only text] [the specified body]. | |
/// </summary> | |
/// <param name="body">The body.</param> | |
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns> | |
public JsonResult IsSafeTextContentOnlyText(string body) | |
{ | |
return this.CheckContent(body, Constants.MediaType.Plain, true, true); | |
} | |
/// <summary> | |
/// Determines whether [is safe HTML content only text] [the specified body]. | |
/// </summary> | |
/// <param name="body">The body.</param> | |
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns> | |
public JsonResult IsSafeHtmlContentOnlyText(string body) | |
{ | |
return this.CheckContent(body, Constants.MediaType.Html, true, true); | |
} | |
/// <summary> | |
/// Checks the content. | |
/// </summary> | |
/// <param name="body">The body.</param> | |
/// <param name="mediaType">Type of the media.</param> | |
/// <param name="allowUrls">if set to <c>true</c> [allow urls].</param> | |
/// <param name="allowPii">if set to <c>true</c> [allow pii].</param> | |
/// <returns>A <see cref="JsonResult"/> with either true or an error message.</returns> | |
private JsonResult CheckContent(string body, Constants.MediaType mediaType, bool allowUrls, bool allowPii) | |
{ | |
Task<ScreenTextResult> moderate = this.client.ScreenTextAsync( | |
body, | |
mediaType, | |
ContentLanguage.PreferredCulture.Name, | |
true, | |
true, | |
true, | |
string.Empty); | |
ScreenTextResult result = moderate.Result; | |
if (!ResultSuccess(result)) | |
{ | |
return this.Json(this.Translate("/validation/moderatornotavailable"), JsonRequestBehavior.AllowGet); | |
} | |
bool safeText = IsSafeText(result); | |
bool safeUrl = allowUrls ? IsSafeUrl(result) : ContainsNoUrl(result); | |
bool safePii = allowPii ? IsSafePii(result) : ContainsNoPii(result); | |
bool noMisrepresentation = !IsMisrepresentation(result); | |
if (safeText && safeUrl && safePii && noMisrepresentation) | |
{ | |
return this.Json(true, JsonRequestBehavior.AllowGet); | |
} | |
return this.Json(this.Translate("/validation/moderation"), JsonRequestBehavior.AllowGet); | |
} | |
/// <summary> | |
/// Results the success. | |
/// </summary> | |
/// <param name="result">The result.</param> | |
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> | |
private static bool ResultSuccess(Result result) | |
{ | |
return (result.Status != null) && (result.Status.Code == "3000"); | |
} | |
/// <summary> | |
/// Determines whether the specified result is misrepresentation. | |
/// </summary> | |
/// <param name="result">The result.</param> | |
/// <returns><c>true</c> if the specified result is misrepresentation; otherwise, <c>false</c>.</returns> | |
private static bool IsMisrepresentation(ScreenTextResult result) | |
{ | |
return !string.IsNullOrWhiteSpace(result.Misrepresentation); | |
} | |
/// <summary> | |
/// Determines whether [is safe pii] [the specified result]. | |
/// </summary> | |
/// <param name="result">The result.</param> | |
/// <returns><c>true</c> if [is safe pii] [the specified result]; otherwise, <c>false</c>.</returns> | |
private static bool IsSafePii(ScreenTextResult result) | |
{ | |
if (result.PII == null) | |
{ | |
return true; | |
} | |
return (result.PII.Email == null) || (result.PII.Email.Count <= 0) | |
|| result.PII.Email.All(email => email.SubType.Equals("Regular", StringComparison.OrdinalIgnoreCase)); | |
} | |
/// <summary> | |
/// Determines whether [contains no pii] [the specified result]. | |
/// </summary> | |
/// <param name="result">The result.</param> | |
/// <returns><c>true</c> if [contains no pii] [the specified result]; otherwise, <c>false</c>.</returns> | |
private static bool ContainsNoPii(ScreenTextResult result) | |
{ | |
return result.PII == null; | |
} | |
/// <summary> | |
/// Determines whether [is safe text] [the specified result]. | |
/// </summary> | |
/// <param name="result">The result.</param> | |
/// <returns><c>true</c> if [is safe text] [the specified result]; otherwise, <c>false</c>.</returns> | |
private static bool IsSafeText(ScreenTextResult result) | |
{ | |
return (result.Terms == null) || (result.Terms.Length == 0); | |
} | |
/// <summary> | |
/// Determines whether [contains no URL] [the specified result]. | |
/// </summary> | |
/// <param name="result">The result.</param> | |
/// <returns><c>true</c> if [contains no URL] [the specified result]; otherwise, <c>false</c>.</returns> | |
private static bool ContainsNoUrl(ScreenTextResult result) | |
{ | |
return (result.Urls == null) || (result.Urls.Length == 0); | |
} | |
/// <summary> | |
/// Determines whether [is safe URL] [the specified result]. | |
/// </summary> | |
/// <param name="result">The result.</param> | |
/// <returns><c>true</c> if [is safe URL] [the specified result]; otherwise, <c>false</c>.</returns> | |
private static bool IsSafeUrl(ScreenTextResult result) | |
{ | |
bool safeUrl = true; | |
if ((result.Urls == null) || (result.Urls.Length == 0)) | |
{ | |
return true; | |
} | |
foreach (MatchUrl matchUrl in result.Urls) | |
{ | |
if (matchUrl.categories.Adult > 0.0) | |
{ | |
safeUrl = false; | |
} | |
if (matchUrl.categories.Malware > 0.0) | |
{ | |
safeUrl = false; | |
} | |
if (matchUrl.categories.Phishing > 0.0) | |
{ | |
safeUrl = false; | |
} | |
} | |
return safeUrl; | |
} | |
/// <summary> | |
/// Translates the specified resurce key. | |
/// </summary> | |
/// <param name="resurceKey">The resurce key.</param> | |
/// <returns>System.String.</returns> | |
private string Translate(string resurceKey) | |
{ | |
string value; | |
if (!this.localizationService.TryGetString(resurceKey, out value)) | |
{ | |
value = resurceKey; | |
} | |
return value; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment