Skip to content

Commit

Permalink
Add a recaptcha-script tag helper, which is responsible for adding a …
Browse files Browse the repository at this point in the history
…script tag to load the recaptcha javascript api.
  • Loading branch information
jooni91 committed Feb 16, 2020
1 parent dc4d6fd commit 3c8b3bc
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 4 deletions.
12 changes: 12 additions & 0 deletions src/ReCaptcha/Enums/Render.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace GSoftware.AspNetCore.ReCaptcha.TagHelpers
{
/// <summary>
/// Rechaptcha rendering options for the <see cref="RecaptchaScriptTagHelper"/>.
/// </summary>
public enum Render
{
Explicit,
Onload,
V3
}
}
5 changes: 1 addition & 4 deletions src/ReCaptcha/ReCaptcha.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="2.2.0" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand All @@ -47,8 +48,4 @@
</EmbeddedResource>
</ItemGroup>

<ItemGroup>
<Folder Include="TagHelpers\" />
</ItemGroup>

</Project>
82 changes: 82 additions & 0 deletions src/ReCaptcha/TagHelpers/RecaptchaScriptTagHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using GSoftware.AspNetCore.ReCaptcha.Configuration;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Options;

namespace GSoftware.AspNetCore.ReCaptcha.TagHelpers
{
/// <summary>
/// Adds a script tag, which will load the required reCAPTCHA JavaScript API. Can be added
/// anywhere on your HTML page, but if you use a onload callback function you must place this
/// after that callback to avoid race conditions.
/// </summary>
public class RecaptchaScriptTagHelper : TagHelper
{
private const string RecaptchaScriptEndpoint = "https://www.google.com/recaptcha/api.js";

private readonly RecaptchaSettings _settings;

public RecaptchaScriptTagHelper(IOptionsMonitor<RecaptchaSettings> settings)
{
_ = settings ?? throw new ArgumentNullException(nameof(settings));

_settings = settings.CurrentValue;
}

/// <summary>
/// Set the rendering mode for the script.
/// </summary>
public Render Render { get; set; } = Render.Onload;

/// <summary>
/// Set a callback function that will be called when reCAPTCHA has finished loading.
/// </summary>
public string? OnloadCallback { get; set; }

/// <summary>
/// Set a language code to force reCAPTCHA loading in the specified language. If not set language
/// will be detected automatically by reCAPTCHA. For a list of valid language codes visit:
/// https://developers.google.com/recaptcha/docs/language
/// </summary>
public string? Language { get; set; }

/// <inheritdoc/>
public override void Process(TagHelperContext context, TagHelperOutput output)
{
_ = output ?? throw new ArgumentNullException(nameof(output));

output.TagName = "script";

if (Render == Render.V3)
{
output.Attributes.Add("src", $"{RecaptchaScriptEndpoint}?render={_settings.SiteKey}");
}
else
{
var queryCollection = new Dictionary<string, string>();

if (!string.IsNullOrEmpty(OnloadCallback))
{
queryCollection.Add("onload", OnloadCallback);
}

if (Render == Render.Explicit)
{
queryCollection.Add("render", Render.ToString().ToLowerInvariant());
}

if (!string.IsNullOrEmpty(Language))
{
queryCollection.Add("hl", Language);
}

output.Attributes.Add("src", QueryHelpers.AddQueryString(RecaptchaScriptEndpoint, queryCollection));
}

output.Attributes.Add("async", null);
output.Attributes.Add("defer", null);
}
}
}

0 comments on commit 3c8b3bc

Please sign in to comment.