Skip to content

Commit a5803ed

Browse files
ArgoZhanggudufy
andauthored
feat(ITotpService): add ITotpService interface (#5900)
* refactor: 增加 IAuthenticatorService 接口 * doc: 增加示例 * refactor: 更改为 ITOTPService 服务 * refactor: 增加菜单 * doc: 增加源码映射 * feat: 增加 OtpInput 组件 * doc: 更新示例 * refactor: 增加空检查 * chore: 增加工程引用 * refactor: 代码格式化 * refactor: 增加模板 * refactor: 更新脚本错误 * doc: 更新样式 * Revert "refactor: 增加模板" This reverts commit c83b2de. * doc: 更新示例 * refactor: 增加样式文件扩展名 * feat: 增加 OtpInput 组件 * refactor: 增加样式文件扩展名 * refactor: 增加 Readonly 功能 * feat: 增加禁用只读功能 * doc: 增加示例 * chore: 更新字典 * feat: 增加 MaxLength 属性 * refactor: 增加脚本 * doc: 增加示例 * refactor: 更新示例 * refactor: 增加默认实现 * refactor: 增加默认服务逻辑 * chore: 更新字典 * test: 增加单元测试 * test: 增加单元测试 * chore: 更新字典 * refactor: 更新接口 * chore: bump version 9.5.11-beta04 * chore: bump version 9.5.11-beta02 Co-Authored-By: gudufy <[email protected]> --------- Co-authored-by: gudufy <[email protected]>
1 parent 27474e0 commit a5803ed

File tree

17 files changed

+435
-7
lines changed

17 files changed

+435
-7
lines changed

BootstrapBlazor.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{9BAF50BE
7878
EndProject
7979
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTest.Benchmarks", "tools\Benchmarks\UnitTest.Benchmarks.csproj", "{3E6D8D0E-5A36-4CFD-8612-7D64E3FFE7B1}"
8080
EndProject
81+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BootstrapBlazor.Authenticator", "..\BootstrapBlazor.Extensions\src\components\BootstrapBlazor.Authenticator\BootstrapBlazor.Authenticator.csproj", "{51641ADB-69FA-6DDF-F83F-FEA0C5AFFD88}"
82+
EndProject
8183
Global
8284
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8385
Debug|Any CPU = Debug|Any CPU
@@ -112,6 +114,10 @@ Global
112114
{3E6D8D0E-5A36-4CFD-8612-7D64E3FFE7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
113115
{3E6D8D0E-5A36-4CFD-8612-7D64E3FFE7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
114116
{3E6D8D0E-5A36-4CFD-8612-7D64E3FFE7B1}.Release|Any CPU.Build.0 = Release|Any CPU
117+
{51641ADB-69FA-6DDF-F83F-FEA0C5AFFD88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
118+
{51641ADB-69FA-6DDF-F83F-FEA0C5AFFD88}.Debug|Any CPU.Build.0 = Debug|Any CPU
119+
{51641ADB-69FA-6DDF-F83F-FEA0C5AFFD88}.Release|Any CPU.ActiveCfg = Release|Any CPU
120+
{51641ADB-69FA-6DDF-F83F-FEA0C5AFFD88}.Release|Any CPU.Build.0 = Release|Any CPU
115121
EndGlobalSection
116122
GlobalSection(SolutionProperties) = preSolution
117123
HideSolutionNode = FALSE
@@ -128,6 +134,7 @@ Global
128134
{D8AEAFE7-10AF-4A5B-BC67-FE740A2CA1DF} = {7C1D79F1-87BC-42C1-BD5A-CDE4044AC1BD}
129135
{C075C6C8-B9CB-4AC0-9BDF-B2002B4AB99C} = {EA765165-0542-41C8-93F2-85787FEDEDFF}
130136
{3E6D8D0E-5A36-4CFD-8612-7D64E3FFE7B1} = {9BAF50BE-141D-4429-93A9-942F373D1F68}
137+
{51641ADB-69FA-6DDF-F83F-FEA0C5AFFD88} = {A2182155-43ED-44C1-BF6F-1B70EBD2DFFE}
131138
EndGlobalSection
132139
GlobalSection(ExtensibilityGlobals) = postSolution
133140
SolutionGuid = {0DCB0756-34FA-4FD0-AE1D-D3F08B5B3A6B}

exclusion.dic

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,6 @@ iframe
111111
Sqlite
112112
maxlength
113113
inputmode
114+
Totp
115+
otpauth
116+
Hotp

src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
</ItemGroup>
7979

8080
<ItemGroup>
81+
<ProjectReference Include="..\..\..\BootstrapBlazor.Extensions\src\components\BootstrapBlazor.Authenticator\BootstrapBlazor.Authenticator.csproj" />
8182
<ProjectReference Include="..\BootstrapBlazor\BootstrapBlazor.csproj" />
8283
</ItemGroup>
8384

src/BootstrapBlazor.Server/Components/Components/Pre.razor.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ export function dispose(id) {
110110
EventHandler.off(el, 'click', '.btn-minus');
111111

112112
const { Pre } = window.BootstrapBlazor;
113-
Pre.dispose(id, () => {
114-
EventHandler.off(document, 'changed.bb.theme', updateTheme);
115-
});
113+
if (Pre) {
114+
Pre.dispose(id, () => {
115+
EventHandler.off(document, 'changed.bb.theme', updateTheme);
116+
});
117+
}
116118
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@page "/authenticator"
2+
3+
<HeadContent>
4+
<style>
5+
.qrcode {
6+
display: flex;
7+
justify-content: center;
8+
}
9+
10+
.progress {
11+
max-width: 500px;
12+
margin: 0 auto;
13+
}
14+
15+
.opt-progress-label {
16+
position: absolute;
17+
top: 50%;
18+
left: 50%;
19+
transform: translate(-50%, -50%);
20+
font-size: 0.75rem;
21+
color: var(--bs-body-color);
22+
}
23+
</style>
24+
</HeadContent>
25+
26+
<h3>@Localizer["Title"]</h3>
27+
28+
<h4>@Localizer["SubTitle"]</h4>
29+
30+
<PackageTips Name="BootstrapBlazor.Authenticator"></PackageTips>
31+
32+
<DemoBlock Title="@Localizer["BaseUsageText"]" Introduction="@Localizer["IntroText1"]" Name="Normal">
33+
<QRCode Content="@_content" Width="190" class="mb-3"></QRCode>
34+
<OtpInput Value="@_code" IsReadonly="true" class="text-center mb-3"></OtpInput>
35+
<div class="position-relative">
36+
<BootstrapBlazor.Components.Progress Value="@_progress" IsShowValue="false"></BootstrapBlazor.Components.Progress>
37+
<span class="opt-progress-label">@_remain</span>
38+
</div>
39+
</DemoBlock>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the Apache 2.0 License
3+
// See the LICENSE file in the project root for more information.
4+
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone
5+
6+
7+
namespace BootstrapBlazor.Server.Components.Samples;
8+
9+
/// <summary>
10+
/// Authenticators sample
11+
/// </summary>
12+
public partial class Authenticators
13+
{
14+
[Inject]
15+
[NotNull]
16+
private IStringLocalizer<Anchors>? Localizer { get; set; }
17+
18+
[Inject]
19+
[NotNull]
20+
private ITotpService? TotpService { get; set; }
21+
22+
private string _content = "";
23+
24+
private string? _code;
25+
26+
private double _progress = 0;
27+
28+
private int _remain = 0;
29+
30+
/// <summary>
31+
/// <inheritdoc/>
32+
/// </summary>
33+
protected override void OnInitialized()
34+
{
35+
base.OnInitialized();
36+
37+
_content = TotpService.GenerateOtpUri();
38+
_code = TotpService.Compute("OMM2LVLFX6QJHMYI");
39+
}
40+
41+
/// <summary>
42+
/// <inheritdoc/>
43+
/// </summary>
44+
/// <param name="firstRender"></param>
45+
/// <returns></returns>
46+
protected override async Task OnAfterRenderAsync(bool firstRender)
47+
{
48+
await base.OnAfterRenderAsync(firstRender);
49+
50+
await Task.Delay(1000);
51+
_code = TotpService.Compute("OMM2LVLFX6QJHMYI");
52+
_remain = TotpService.Instance.GetRemainingSeconds();
53+
_progress = (30d - _remain) * 100 / 30d;
54+
StateHasChanged();
55+
}
56+
}

src/BootstrapBlazor.Server/Extensions/ServiceCollectionSharedExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ public static IServiceCollection AddBootstrapBlazorServices(this IServiceCollect
3030
services.AddSingleton<MenuService>();
3131
services.AddScoped<FanControllerDataService>();
3232

33+
// 增加 Authenticator 服务
34+
services.AddBootstrapBlazorAuthenticator();
35+
3336
// 增加示例网站配置
3437
services.AddOptionsMonitor<WebsiteOptions>();
3538

src/BootstrapBlazor.Server/Locales/en-US.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4919,7 +4919,8 @@
49194919
"Typed": "Typed",
49204920
"UniverSheet": "UniverSheet",
49214921
"ShieldBadge": "ShieldBadge",
4922-
"OtpInput": "OtpInput"
4922+
"OtpInput": "OtpInput",
4923+
"Authenticator": "Authenticator"
49234924
},
49244925
"BootstrapBlazor.Server.Components.Samples.Table.TablesHeader": {
49254926
"TablesHeaderTitle": "Header grouping function",
@@ -7101,5 +7102,9 @@
71017102
"OtpInputsNormalIntro": "Control the password type or length by setting parameters such as <code>Type</code>",
71027103
"OtpInputsValidateFormTitle": "ValidateForm",
71037104
"OtpInputsValidateFormIntro": "When the password is not provided, click the Submit button, the password box will be displayed in red and it will be prompted that it cannot be empty."
7105+
},
7106+
"BootstrapBlazor.Server.Components.Samples.Authenticators": {
7107+
"Title": "Authenticator",
7108+
"SubTitle": "An implementation TOTP RFC 6238 and HOTP RFC 4226 Authenticator service."
71047109
}
71057110
}

src/BootstrapBlazor.Server/Locales/zh-CN.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4919,7 +4919,8 @@
49194919
"Typed": "打字机效果 Typed",
49204920
"UniverSheet": "表格组件 UniverSheet",
49214921
"ShieldBadge": "徽章组件 ShieldBadge",
4922-
"OtpInput": "验证码输入框 OtpInput"
4922+
"OtpInput": "验证码输入框 OtpInput",
4923+
"Authenticator": "密码验证服务 Authenticator"
49234924
},
49244925
"BootstrapBlazor.Server.Components.Samples.Table.TablesHeader": {
49254926
"TablesHeaderTitle": "表头分组功能",
@@ -7101,5 +7102,9 @@
71017102
"OtpInputsNormalIntro": "通过设置 <code>Type</code> 等参数控制密码类型或者长度",
71027103
"OtpInputsValidateFormTitle": "表单内使用",
71037104
"OtpInputsValidateFormIntro": "密码未提供值时,点击提交按钮,密码框显示为红色,并且提示不可为空"
7105+
},
7106+
"BootstrapBlazor.Server.Components.Samples.Authenticators": {
7107+
"Title": "Authenticator 密码验证服务",
7108+
"SubTitle": "实现 TOTP RFC 6238 和 HOTP RFC 4226 认证器服务"
71047109
}
71057110
}

src/BootstrapBlazor.Server/docs.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@
229229
"typed": "Typeds",
230230
"univer-sheet": "UniverSheets",
231231
"shield-badge": "ShieldBadges",
232-
"opt-input": "OtpInputs"
232+
"opt-input": "OtpInputs",
233+
"authenticator": "Authenticators"
233234
},
234235
"video": {
235236
"table": "BV1ap4y1x7Qn?p=1",

0 commit comments

Comments
 (0)