diff options
-rw-r--r-- | .gitignore | 7 | ||||
-rw-r--r-- | Module.Taskfile.yaml | 68 | ||||
-rw-r--r-- | README.md | 17 | ||||
-rw-r--r-- | Taskfile.yaml | 75 | ||||
-rw-r--r-- | plugins.essentials.build.sln | 54 | ||||
-rw-r--r-- | plugins/VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj | 2 | ||||
-rw-r--r-- | plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs | 7 | ||||
-rw-r--r-- | plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserMFAExtensions.cs | 15 | ||||
-rw-r--r-- | plugins/VNLib.Plugins.Essentials.Accounts/src/VNLib.Plugins.Essentials.Accounts.csproj | 2 |
9 files changed, 224 insertions, 23 deletions
@@ -472,11 +472,6 @@ FodyWeavers.xsd # Additional files built by Visual Studio # End of https://www.toptal.com/developers/gitignore/api/c,c++,visualstudio -/VNLib.Utils *.json -*.licenseheader -*.sln -*.ps1 -**/.task/ -*[Tt]askfile.*
\ No newline at end of file +*.licenseheader
\ No newline at end of file diff --git a/Module.Taskfile.yaml b/Module.Taskfile.yaml new file mode 100644 index 0000000..d729ea3 --- /dev/null +++ b/Module.Taskfile.yaml @@ -0,0 +1,68 @@ +# https://taskfile.dev + +#Called by the vnbuild system to produce builds for my website +#https://www.vaughnnugent.com/resources/software + +#This taskfile performs the build operations for a module, it handles +#git code updates, msbuild on solutions, and sleet NuGet feed pushes. + +#this file must be in the same directory as the solution file + +version: '3' + +vars: + INT_DIR: '{{.SCRATCH_DIR}}/obj/{{.MODULE_NAME}}/' + MS_ARGS: '/p:RunAnalyzersDuringBuild=false /p:IntermediateOutputPath="{{.INT_DIR}}" /p:UseCommonOutputDirectory=true /p:BuildInParallel=true /p:MultiProcessorCompilation=true' + PACK_OUT: '{{.OUTPUT_DIR}}/{{.HEAD_SHA}}/pkg' + +tasks: + +#called by build pipeline to sync repo + update: + cmds: + - git remote update + - git reset --hard + - git pull origin {{.BRANCH_NAME}} --verify-signatures + +#called by build pipeline to build module + build: + cmds: + - echo "building module {{.MODULE_NAME}}" + + #re-write semver after hard reset, before build + - dotnet-gitversion.exe /updateprojectfiles + + #build debug mode first + - task: build_debug + - task: build_release + + postbuild_success: + cmds: + #push packages to the sleet feed (feed path is vnbuild global) + - sleet push "{{.PACK_OUT}}/debug/" --source debug --config "{{.SLEET_CONFIG_PATH}}" --force + - sleet push "{{.PACK_OUT}}/release/" --source release --config "{{.SLEET_CONFIG_PATH}}" --force + + postbuild_failed: + cmds: + - echo "postbuild failed {{.MODULE_NAME}}" + +#called by build pipeline to clean module + clean: + cmds: + #clean solution + - dotnet clean /p:BuildInParallel=true /p:MultiProcessorCompilation=true + + +#Internal tasks + build_debug: + internal: true + cmds: + - dotnet publish -c debug {{.MS_ARGS}} + - dotnet pack -c debug {{.MS_ARGS}} -o "{{.PACK_OUT}}/debug/" + + build_release: + internal: true + cmds: + - dotnet publish -c release {{.MS_ARGS}} + - dotnet pack -c release {{.MS_ARGS}} -o "{{.PACK_OUT}}/release/" +
\ No newline at end of file @@ -1,11 +1,16 @@ -# Essentials +# Plugins.Essentials +This repository contains a collection of essential "Web Plugins" that are built to be loaded directly by a `ServiceStack` in your application, and conform to all required constrains for runtime loading. Some library packages my be consumed directly by your library/application to perform included functionality or provide a base class or set of classes to reduce complexity. Please see each package's readme.md file for further information. -This repository contains a collection of essential "Web Plugins" that are built to be loaded directly by a `ServiceStack` in your application, and conform to all required constrains for runtime loading. Some library packages my be consumed directly by your library/application to perform included functionality or provide a base class or set of classes to reduce complexity. Please see each package's readme.md file for further information. +This repo will be used a small "mono-repo" for essential runtime loadable plugins that provide essential web-site/api functionality. -This repo will be used a small "mono-repo" for essential runtime loadable plugins that provide essential web-site/api functionality. +## Builds +Debug build w/ symbols & xml docs, release builds, NuGet packages, and individually packaged source code are available on my website (link below). All tar-gzip (.tgz) files will have an associated .sha256 appended checksum of the desired download file. -These libraries are intended for web-server/web-site use and therefor are license to use by the following: +## Docs and Guides +Documentation, specifications, and setup guides are available on my website. + +[Docs and Articles](https://www.vaughnnugent.com/resources/software/articles?tags=docs,_plugins.essentials) +[Builds and Source](https://www.vaughnnugent.com/resources/software/modules/VNLib.Core) ## License -All source files in this repository is licensed under the GNU Affero General Public License (or any later version). -See the LICENSE files for more information.
\ No newline at end of file +The software in this repository is licensed under the GNU Affero General Public License (or any later version). See the LICENSE files for more information.
\ No newline at end of file diff --git a/Taskfile.yaml b/Taskfile.yaml new file mode 100644 index 0000000..b16b082 --- /dev/null +++ b/Taskfile.yaml @@ -0,0 +1,75 @@ +# https://taskfile.dev + +#Called by the vnbuild system to produce builds for my website +#https://www.vaughnnugent.com/resources/software + +#This taskfile is called from the root of a project that is being built +#and the purpose of this taskfile is to package up the output of a build +#from the solution file, and package it up into a tgz files for distribution + +version: '3' + +vars: + TARGET: '{{.USER_WORKING_DIR}}/bin' + RELEASE_DIR: "./bin/release/{{.TARGET_FRAMEWORK}}/publish" + SOURCE_OUT: "{{.USER_WORKING_DIR}}/bin/source" + +tasks: + + #when build succeeds, archive the output into a tgz + postbuild_success: + dir: '{{.USER_WORKING_DIR}}' + cmds: + #pack up source code + - task: packsource + + #run post in debug mode + - task: postbuild + vars: { BUILD_MODE: debug } + + #remove uncessary files from the release dir + - powershell -Command "Get-ChildItem -Recurse '{{.RELEASE_DIR}}/' -Include *.pdb,*.xml | Remove-Item" + + #run post in release mode + - task: postbuild + vars: { BUILD_MODE: release } + + + postbuild_failed: + dir: '{{.USER_WORKING_DIR}}' + cmds: + - echo "postbuild failed {{.PROJECT_NAME}}" + + + postbuild: + dir: '{{.USER_WORKING_DIR}}' + internal: true + vars: + #the build output directory + BUILD_OUT: "{{.USER_WORKING_DIR}}/bin/{{.BUILD_MODE}}/{{.TARGET_FRAMEWORK}}/publish" + + cmds: + + #copy license and readme to target + - cd .. && powershell -Command "Copy-Item -Path ./LICENSE.txt -Destination '{{.BUILD_OUT}}/license.txt'" + - cd .. && powershell -Command "Copy-Item -Path ./build.readme.md -Destination '{{.BUILD_OUT}}/readme.md'" + + #tar outputs + - cd "{{.BUILD_OUT}}" && tar -czf "{{.TARGET}}/{{.BUILD_MODE}}.tgz" . + + packsource: + dir: '{{.USER_WORKING_DIR}}' + internal: true + cmds: + #copy source code to target + - powershell -Command "Get-ChildItem -Include *.cs,*.csproj -Recurse | Where { \$_.FullName -notlike '*\obj\*' -and \$_.FullName -notlike '*\bin\*' } | Resolve-Path -Relative | tar --files-from - -czf '{{.TARGET}}/src.tgz'" + + +#Remove the output dirs on clean + clean: + dir: '{{.USER_WORKING_DIR}}' + cmds: + - cmd: powershell Remove-Item -Recurse './bin' + ignore_error: true + - cmd: powershell Remove-Item -Recurse './obj' + ignore_error: true diff --git a/plugins.essentials.build.sln b/plugins.essentials.build.sln new file mode 100644 index 0000000..dc80ba6 --- /dev/null +++ b/plugins.essentials.build.sln @@ -0,0 +1,54 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VNLib.Plugins.Essentials.Accounts", "plugins\VNLib.Plugins.Essentials.Accounts\src\VNLib.Plugins.Essentials.Accounts.csproj", "{56AA96E6-4AFE-4461-9BC0-3E1F63022474}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VNLib.Plugins.Essentials.Accounts.Registration", "plugins\VNLib.Plugins.Essentials.Accounts.Registration\src\VNLib.Plugins.Essentials.Accounts.Registration.csproj", "{13CE7998-447C-4552-B20F-AB40B1D17F74}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VNLib.Plugins.Essentials.Content.Routing", "plugins\VNLib.Plugins.Essentials.Content.Routing\src\VNLib.Plugins.Essentials.Content.Routing.csproj", "{384CA311-C442-44E4-A54F-D50F4C1270D7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VNLib.Plugins.Essentials.SocialOauth", "plugins\VNLib.Plugins.Essentials.SocialOauth\src\VNLib.Plugins.Essentials.SocialOauth.csproj", "{581E891A-C630-4329-9122-99ADE9FA7ADF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{481E5ABF-D132-46CA-A579-B99FAD82FA48}" + ProjectSection(SolutionItems) = preProject + .gitattributes = .gitattributes + .gitignore = .gitignore + .onedev-buildspec.yml = .onedev-buildspec.yml + LICENSE.txt = LICENSE.txt + Module.Taskfile.yaml = Module.Taskfile.yaml + README.md = README.md + Taskfile.yaml = Taskfile.yaml + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {56AA96E6-4AFE-4461-9BC0-3E1F63022474}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {56AA96E6-4AFE-4461-9BC0-3E1F63022474}.Debug|Any CPU.Build.0 = Debug|Any CPU + {56AA96E6-4AFE-4461-9BC0-3E1F63022474}.Release|Any CPU.ActiveCfg = Release|Any CPU + {56AA96E6-4AFE-4461-9BC0-3E1F63022474}.Release|Any CPU.Build.0 = Release|Any CPU + {13CE7998-447C-4552-B20F-AB40B1D17F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13CE7998-447C-4552-B20F-AB40B1D17F74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13CE7998-447C-4552-B20F-AB40B1D17F74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13CE7998-447C-4552-B20F-AB40B1D17F74}.Release|Any CPU.Build.0 = Release|Any CPU + {384CA311-C442-44E4-A54F-D50F4C1270D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {384CA311-C442-44E4-A54F-D50F4C1270D7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {384CA311-C442-44E4-A54F-D50F4C1270D7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {384CA311-C442-44E4-A54F-D50F4C1270D7}.Release|Any CPU.Build.0 = Release|Any CPU + {581E891A-C630-4329-9122-99ADE9FA7ADF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {581E891A-C630-4329-9122-99ADE9FA7ADF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {581E891A-C630-4329-9122-99ADE9FA7ADF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {581E891A-C630-4329-9122-99ADE9FA7ADF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BA2844FD-C565-4DB1-93B9-B110C6EEB3DC} + EndGlobalSection +EndGlobal diff --git a/plugins/VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj b/plugins/VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj index 5b254d3..ba91d90 100644 --- a/plugins/VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj +++ b/plugins/VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj @@ -34,7 +34,7 @@ <Deterministic>False</Deterministic> </PropertyGroup> <ItemGroup> - <PackageReference Include="FluentValidation" Version="11.5.2" /> + <PackageReference Include="FluentValidation" Version="11.6.0" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\..\..\..\core\lib\Plugins.Essentials\src\VNLib.Plugins.Essentials.csproj" /> diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs index 5b50cb2..0d10811 100644 --- a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs +++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs @@ -361,13 +361,8 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints //Valid, complete } break; - case MFAType.PGP: - { } - break; default: - { - webm.Result = MFA_ERROR_MESSAGE; - } + webm.Result = MFA_ERROR_MESSAGE; return; } diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserMFAExtensions.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserMFAExtensions.cs index e042799..0b52f54 100644 --- a/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserMFAExtensions.cs +++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserMFAExtensions.cs @@ -120,7 +120,10 @@ namespace VNLib.Plugins.Essentials.Accounts.MFA using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAlloc(base32Secret.Length, true); ERRNO count = VnEncoding.TryFromBase32Chars(base32Secret, buffer); //Verify the TOTP using the decrypted secret - return count && VerifyTOTP(code, buffer.AsSpan(0, count), config.TOTPConfig); + bool isValid = count && VerifyTOTP(code, buffer.AsSpan(0, count), config.TOTPConfig); + //Zero out the buffer + MemoryUtil.InitializeBlock(buffer.Span); + return isValid; } private static bool VerifyTOTP(uint totpCode, ReadOnlySpan<byte> userSecret, TOTPConfig config) @@ -227,6 +230,12 @@ namespace VNLib.Plugins.Essentials.Accounts.MFA public static void PKISetUserKey(this IUser user, IReadOnlyDictionary<string, string>? keyFields) { + if(keyFields == null) + { + user[USER_PKI_ENTRY] = null!; + return; + } + //Serialize the key data byte[] keyData = JsonSerializer.SerializeToUtf8Bytes(keyFields, Statics.SR_OPTIONS); @@ -294,7 +303,7 @@ namespace VNLib.Plugins.Essentials.Accounts.MFA /// <param name="upgradeJwtString">The signed JWT upgrade message</param> /// <param name="base32Secret">The stored base64 encoded signature from the session that requested an upgrade</param> /// <returns>True if the upgrade was verified, not expired, and was recovered from the signed message, false otherwise</returns> - public static MFAUpgrade? RecoverUpgrade(this MFAConfig config, string upgradeJwtString, string base32Secret) + internal static MFAUpgrade? RecoverUpgrade(this MFAConfig config, string upgradeJwtString, string base32Secret) { //Parse jwt using JsonWebToken jwt = JsonWebToken.Parse(upgradeJwtString); @@ -340,7 +349,7 @@ namespace VNLib.Plugins.Essentials.Accounts.MFA /// <param name="login">The message from the user requesting the login</param> /// <returns>A signed upgrade message the client will pass back to the server after the MFA verification</returns> /// <exception cref="InvalidOperationException"></exception> - public static MfaUpgradeMessage? MFAGetUpgradeIfEnabled(this IUser user, MFAConfig? conf, LoginMessage login) + internal static MfaUpgradeMessage? MFAGetUpgradeIfEnabled(this IUser user, MFAConfig? conf, LoginMessage login) { //Webauthn config diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/VNLib.Plugins.Essentials.Accounts.csproj b/plugins/VNLib.Plugins.Essentials.Accounts/src/VNLib.Plugins.Essentials.Accounts.csproj index c96900e..09423ed 100644 --- a/plugins/VNLib.Plugins.Essentials.Accounts/src/VNLib.Plugins.Essentials.Accounts.csproj +++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/VNLib.Plugins.Essentials.Accounts.csproj @@ -43,7 +43,7 @@ <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> - <PackageReference Include="FluentValidation" Version="11.5.2" /> + <PackageReference Include="FluentValidation" Version="11.6.0" /> </ItemGroup> <ItemGroup> |