Use InMemory db driver at testing

This commit is contained in:
Paul Schneider 2026-05-28 22:18:26 +01:00
commit 95dec3636a
24 changed files with 474 additions and 139 deletions

View file

@ -0,0 +1,65 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AsciiDocSharp" Version="0.2.0" />
<PackageVersion Include="AsciiDocSharp.Converters.Html" Version="0.2.0" />
<PackageVersion Include="bootstrap" Version="5.3.8" />
<PackageVersion Include="coverlet.collector" Version="10.0.1" />
<PackageVersion Include="Google.Apis.Calendar.v3" Version="1.74.0.4154" />
<PackageVersion Include="Google.Apis.Compute.v1" Version="1.74.0.4138" />
<PackageVersion Include="HigginsSoft.IdentityServer8" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.AspNetIdentity" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.EntityFramework" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.EntityFramework.Storage" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.Security" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.Storage" Version="8.0.5-preview-net9" />
<PackageVersion Include="IdentityModel.AspNetCore" Version="4.3.0" />
<PackageVersion Include="IdentityModel.OidcClient" Version="6.0.0" />
<PackageVersion Include="MailKit" Version="4.17.0" />
<PackageVersion Include="Microsoft.AspNetCore.Antiforgery" Version="2.3.10" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Hosting" Version="2.3.10" />
<PackageVersion Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Razor" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.36" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR" Version="1.2.10" />
<PackageVersion Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.6" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
<PackageVersion Include="Microsoft.Playwright" Version="1.60.0" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="10.0.2" />
<PackageVersion Include="MimeKit" Version="4.16.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.1" />
<PackageVersion Include="PayPalMerchantSDK" Version="2.16.250" />
<PackageVersion Include="pazof.rules" Version="1.1.3" />
<PackageVersion Include="popper.js" Version="1.16.1" />
<PackageVersion Include="RazorEngine.NetCore" Version="3.1.1" />
<PackageVersion Include="Selenium.WebDriver" Version="4.44.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.1.7" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="10.0.8" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.8" />
</ItemGroup>
</Project>

View file

@ -5,10 +5,16 @@
<ItemGroup>
<PackageVersion Include="AsciiDocSharp" Version="0.2.0" />
<PackageVersion Include="AsciiDocSharp.Converters.Html" Version="0.2.0" />
<PackageVersion Include="Avalonia" Version="12.0.4" />
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="12.0.0" />
<PackageVersion Include="Avalonia.Desktop" Version="12.0.4" />
<PackageVersion Include="Avalonia.Fonts.Inter" Version="12.0.4" />
<PackageVersion Include="Avalonia.Themes.Fluent" Version="12.0.4" />
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.1" />
<PackageVersion Include="bootstrap" Version="5.3.8" />
<PackageVersion Include="coverlet.collector" Version="10.0.0" />
<PackageVersion Include="Google.Apis.Calendar.v3" Version="1.73.0.4073" />
<PackageVersion Include="Google.Apis.Compute.v1" Version="1.73.0.4107" />
<PackageVersion Include="coverlet.collector" Version="10.0.1" />
<PackageVersion Include="Google.Apis.Calendar.v3" Version="1.74.0.4154" />
<PackageVersion Include="Google.Apis.Compute.v1" Version="1.74.0.4138" />
<PackageVersion Include="HigginsSoft.IdentityServer8" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.AspNetIdentity" Version="8.0.5-preview-net9" />
<PackageVersion Include="HigginsSoft.IdentityServer8.EntityFramework" Version="8.0.5-preview-net9" />
@ -17,47 +23,51 @@
<PackageVersion Include="HigginsSoft.IdentityServer8.Storage" Version="8.0.5-preview-net9" />
<PackageVersion Include="IdentityModel.AspNetCore" Version="4.3.0" />
<PackageVersion Include="IdentityModel.OidcClient" Version="6.0.0" />
<PackageVersion Include="MailKit" Version="4.16.0" />
<PackageVersion Include="Microsoft.AspNetCore.Antiforgery" Version="2.3.9" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Hosting" Version="2.3.9" />
<PackageVersion Include="Magick.NET-Q8-AnyCPU" Version="14.13.1" />
<PackageVersion Include="MailKit" Version="4.17.0" />
<PackageVersion Include="Microsoft.AspNetCore.Antiforgery" Version="2.3.10" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Hosting" Version="2.3.10" />
<PackageVersion Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.6" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Razor" Version="2.3.0" />
<PackageVersion Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.36" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR" Version="1.2.9" />
<PackageVersion Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.6" />
<PackageVersion Include="Microsoft.AspNetCore.SignalR" Version="1.2.10" />
<PackageVersion Include="Microsoft.AspNetCore.StaticFiles" Version="2.3.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.6" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.4.0" />
<PackageVersion Include="Microsoft.Playwright" Version="1.59.0" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageVersion Include="MimeKit" Version="4.16.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.8" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.8" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
<PackageVersion Include="Microsoft.Playwright" Version="1.60.0" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="10.0.2" />
<PackageVersion Include="MimeKit" Version="4.17.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.2" />
<PackageVersion Include="PayPalMerchantSDK" Version="2.16.250" />
<PackageVersion Include="pazof.rules" Version="1.1.3" />
<PackageVersion Include="popper.js" Version="1.16.1" />
<PackageVersion Include="RazorEngine.NetCore" Version="3.1.1" />
<PackageVersion Include="Selenium.WebDriver" Version="4.43.0" />
<PackageVersion Include="Selenium.WebDriver" Version="4.44.0" />
<PackageVersion Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.12" />
<PackageVersion Include="SixLabors.ImageSharp" Version="4.0.0" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.1.7" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="10.0.6" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="10.0.8" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
<PackageVersion Include="Yavsc.Abstract" Version="1.0.6-rc18" />
</ItemGroup>
</Project>

View file

@ -4,6 +4,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>1c73094f-959f-4211-b1a1-6a69b236c283</UserSecretsId>
<RootNamespace>Yavsc.Api</RootNamespace>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />

View file

@ -115,7 +115,7 @@ namespace Yavsc.ApiControllers
}
if (Request.Form.Files.Count!=1)
return new BadRequestResult();
User.ReceiveProSignature(billingCode,id,Request.Form.Files[0],"pro");
await User.ReceiveProSignatureAsync(billingCode,id,Request.Form.Files[0],"pro");
estimate.ProviderValidationDate = DateTime.Now;
dbContext.SaveChanges(User.GetUserId());
// Notify the client
@ -160,7 +160,7 @@ namespace Yavsc.ApiControllers
}
if (Request.Form.Files.Count!=1)
return new BadRequestResult();
User.ReceiveProSignature(billingCode,id,Request.Form.Files[0],"cli");
await User.ReceiveProSignatureAsync(billingCode,id,Request.Form.Files[0],"cli");
estimate.ClientValidationDate = DateTime.Now;
dbContext.SaveChanges(User.GetUserId());
return Ok (new { ClientValidationDate = estimate.ClientValidationDate });

View file

@ -66,12 +66,15 @@ namespace Yavsc.WebApi.Controllers
/// Updates the avatar
/// </summary>
/// <returns></returns>
[HttpPost("~/api/setavatar")]
[HttpPost("~/api/set-avatar")]
public async Task<IActionResult> SetAvatar()
{
var user = await GetUserData(User.GetUserId());
if (Request.Form.Files.Count!=1)
return new BadRequestResult();
if (!Request.Form.Files[0].ContentType.StartsWith("image/png"))
return new BadRequestResult();
var info = user.ReceiveAvatar(Request.Form.Files[0]);
await _dbContext.SaveChangesAsync();
return Ok(info);

12
src/PostIt/App.axaml Normal file
View file

@ -0,0 +1,12 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="PostIt.App"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://AvaloniaEdit/Themes/Fluent/AvaloniaEdit.xaml" />
</Application.Styles>
</Application>

23
src/PostIt/App.axaml.cs Normal file
View file

@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace PostIt;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
}
base.OnFrameworkInitializationCompleted();
}
}

View file

@ -0,0 +1,27 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:AvaloniaEdit="clr-namespace:AvaloniaEdit;assembly=AvaloniaEdit"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="PostIt.MainWindow"
Title="PostIt">
<Window.Content>
<StackPanel>
<Label>Welcome to Avalonia !!!</Label>
<Label x:Name="Greeting">
Hello !
</Label>
<AvaloniaEdit:TextEditor
ShowLineNumbers="True"
FontFamily="Cascadia Code,Consolas,Menlo,Monospace"
Background="AliceBlue"
Foreground="Black"
Watermark="Hit me strong!"
/>
</StackPanel>
</Window.Content>
</Window>

View file

@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace PostIt;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Greeting.Content="Hello Joe!";
}
}

21
src/PostIt/PostIt.csproj Normal file
View file

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" />
<PackageReference Include="Avalonia.AvaloniaEdit" />
<PackageReference Include="Avalonia.Desktop" />
<PackageReference Include="Avalonia.Themes.Fluent" />
<PackageReference Include="Avalonia.Fonts.Inter" />
<PackageReference Include="AvaloniaUI.DiagnosticsSupport">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="Yavsc.Abstract" />
</ItemGroup>
</Project>

24
src/PostIt/Program.cs Normal file
View file

@ -0,0 +1,24 @@
using Avalonia;
using System;
namespace PostIt;
class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
#if DEBUG
.WithDeveloperTools()
#endif
.WithInterFont()
.LogToTrace();
}

18
src/PostIt/app.manifest Normal file
View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="PostIt.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>

View file

@ -6,6 +6,7 @@
</Description>
<RootNamespace>Yavsc.Abstract</RootNamespace>
<RepositoryUrl>https://github.com/pazof/yavsc</RepositoryUrl>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />

View file

@ -5,6 +5,7 @@
<UserSecretsId>1c73094f-959f-4211-b1a1-6a69b236c283</UserSecretsId>
<RootNamespace>Yavsc.Api</RootNamespace>
<RepositoryUrl>https://github.com/pazof/yavsc</RepositoryUrl>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />

View file

@ -37,6 +37,7 @@ namespace Yavsc.Extensions;
public static class HostingExtensions
{
private const string InMemoryProviderName = "InMemory";
public static WebApplication ConfigureWebAppServices(this WebApplicationBuilder builder)
{
@ -140,11 +141,19 @@ public static class HostingExtensions
public static IdentityBuilder AddIdentityDBAndStores(this WebApplicationBuilder builder)
{
IServiceCollection services = builder.Services;
var connectionString = builder.Configuration.GetConnectionString(Constants.YavscConnectionStringName);
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseNpgsql(builder.Configuration.GetConnectionString(Constants.YavscConnectionStringName),
options => options.MigrationsAssembly(typeof(Program).Assembly));
if (UsesInMemoryProvider(connectionString))
{
options.UseInMemoryDatabase(connectionString);
}
else
{
options.UseNpgsql(connectionString,
options => options.MigrationsAssembly(typeof(Program).Assembly));
}
});
var identityBuilder = services.AddIdentity<ApplicationUser, IdentityRole>(
@ -285,14 +294,35 @@ public static class HostingExtensions
.AddResourceStore<ResourceStore>()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly))
.UseSeeding(EnsureDefaultApplicationScopes());
options.ConfigureDbContext = b =>
{
if (UsesInMemoryProvider(connectionString))
{
b.UseInMemoryDatabase(connectionString);
}
else
{
b.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
}
b.UseSeeding(EnsureDefaultApplicationScopes());
};
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b => b.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
options.ConfigureDbContext = b =>
{
if (UsesInMemoryProvider(connectionString))
{
b.UseInMemoryDatabase(connectionString);
}
else
{
b.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
}
};
});
@ -303,6 +333,11 @@ public static class HostingExtensions
return identityServerBuilder;
}
private static bool UsesInMemoryProvider(string connectionString)
{
return string.Equals(connectionString, InMemoryProviderName, StringComparison.OrdinalIgnoreCase);
}
private static Action<DbContext, bool> EnsureDefaultApplicationScopes()
{
return (context, _) =>

View file

@ -5,7 +5,7 @@
<PackageLicenseExpression>WTFPL</PackageLicenseExpression>
<UserSecretsId>76e56fc2-1619-40d8-8393-365258b7a21d</UserSecretsId>
<RootNamespace>Yavsc</RootNamespace>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<RepositoryUrl>https://github.com/pazof/yavsc</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
@ -21,7 +21,6 @@
<PackageReference Include="HigginsSoft.IdentityServer8.EntityFramework.Storage" />
<PackageReference Include="HigginsSoft.IdentityServer8.Security" />
<PackageReference Include="HigginsSoft.IdentityServer8.Storage" />
<PackageReference Include="Serilog.AspNetCore" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" />
@ -33,6 +32,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
<PackageReference Include="Google.Apis.Compute.v1" />
@ -44,7 +44,6 @@
<PackageReference Include="Swashbuckle.AspNetCore" />
<PackageReference Include="AsciiDocSharp" />
<PackageReference Include="AsciiDocSharp.Converters.Html" />
<PackageReference Include="SixLabors.ImageSharp" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" />
<PackageReference Include="Microsoft.Extensions.Logging" />
</ItemGroup>

View file

@ -7,25 +7,26 @@ using Yavsc.Models;
using Yavsc.Models.FileSystem;
using Yavsc.Models.Streaming;
using Yavsc.ViewModels;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using Microsoft.AspNetCore.Http;
using Yavsc.Exceptions;
using Yavsc.Helpers;
using Yavsc.Abstract.Helpers;
using ImageMagick;
namespace Yavsc.Server.Helpers
{
public static class FileSystemHelpers
{
public static async Task SaveAsAsync(this IFormFile formFile, string path)
{
if (formFile.Length > 0) {
using (Stream fileStream = new FileStream(path, FileMode.Create)) {
if (formFile.Length > 0)
{
using (Stream fileStream = new FileStream(path, FileMode.Create))
{
await formFile.CopyToAsync(fileStream);
}
}
}
public static FileReceivedInfo ReceiveProSignature(this ClaimsPrincipal user, string billingCode, long estimateId, IFormFile formFile, string signType)
public static async Task<FileReceivedInfo> ReceiveProSignatureAsync(this ClaimsPrincipal user, string billingCode, long estimateId, IFormFile formFile, string signType)
{
var item = new FileReceivedInfo(
Config.SiteSetup.Bills,
@ -33,12 +34,7 @@ namespace Yavsc.Server.Helpers
var fi = new FileInfo(item.FullName);
if (fi.Exists) item.Overridden = true;
using (var org = formFile.OpenReadStream())
{
using Image image = Image.Load(org);
image.Save(fi.FullName);
}
await formFile.SaveAsAsync(fi.FullName);
return item;
}
@ -76,7 +72,7 @@ namespace Yavsc.Server.Helpers
{
var root = Path.Combine(AbstractFileSystemHelpers.UserFilesDirName, user.UserName);
var fi = new FileInfo(Path.Combine(root, fileName));
if (!fi.Exists) return ;
if (!fi.Exists) return;
fi.Delete();
user.DiskUsage -= fi.Length;
}
@ -85,18 +81,20 @@ namespace Yavsc.Server.Helpers
{
var root = Path.Combine(AbstractFileSystemHelpers.UserFilesDirName, user.UserName);
if (string.IsNullOrEmpty(dirName))
return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "specify a directory or file name"} ;
return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "specify a directory or file name" };
var di = new DirectoryInfo(Path.Combine(root, dirName));
if (!di.Exists) {
if (!di.Exists)
{
var fi = new FileInfo(Path.Combine(root, dirName));
if (!fi.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.NotFound, ErrorMessage = "non existent"} ;
if (!fi.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.NotFound, ErrorMessage = "non existent" };
fi.Delete();
user.DiskUsage -= fi.Length;
}
else {
if (di.GetDirectories().Length>0 || di.GetFiles().Length>0)
return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "dir is not empty, refusing to remove it"} ;
else
{
if (di.GetDirectories().Length > 0 || di.GetFiles().Length > 0)
return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "dir is not empty, refusing to remove it" };
di.Delete();
}
return new FsOperationInfo { Done = true };
@ -106,10 +104,10 @@ namespace Yavsc.Server.Helpers
{
var root = Path.Combine(AbstractFileSystemHelpers.UserFilesDirName, user.UserName);
if (string.IsNullOrEmpty(fromDirName))
return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest , ErrorMessage = "specify a dir name "} ;
return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "specify a dir name " };
var di = new DirectoryInfo(Path.Combine(root, fromDirName));
if (!di.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.NotFound, ErrorMessage = "fromDirName: non existent"} ;
if (!di.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.NotFound, ErrorMessage = "fromDirName: non existent" };
if (string.IsNullOrEmpty(toDirName)) toDirName = ".";
@ -117,12 +115,13 @@ namespace Yavsc.Server.Helpers
var fout = new FileInfo(destPath);
if (fout.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "destination is a regular file" } ;
if (fout.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.InvalidRequest, ErrorMessage = "destination is a regular file" };
var dout = new DirectoryInfo(destPath);
if (dout.Exists) {
destPath = Path.Combine(destPath, dout.Name);
var dOut = new DirectoryInfo(destPath);
if (dOut.Exists)
{
destPath = Path.Combine(destPath, dOut.Name);
}
di.MoveTo(destPath);
return new FsOperationInfo { Done = true };
@ -131,12 +130,12 @@ namespace Yavsc.Server.Helpers
{
var root = Path.Combine(AbstractFileSystemHelpers.UserFilesDirName, user.UserName);
var fi = new FileInfo(Path.Combine(root, fileNameFrom));
if (!fi.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.NotFound, ErrorMessage = "no file to move" } ;
if (!fi.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.NotFound, ErrorMessage = "no file to move" };
string dest;
if (!string.IsNullOrEmpty(fileNameDest)) dest = Path.Combine(root, fileNameDest);
else dest = root;
var fo = new FileInfo(dest);
if (fo.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.DestExists , ErrorMessage = "destination file name is an existing file" } ;
if (fo.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.DestExists, ErrorMessage = "destination file name is an existing file" };
var dout = new DirectoryInfo(dest);
if (!dout.Exists) dout.Create();
fi.MoveTo(Path.Combine(dout.FullName, fi.Name));
@ -146,9 +145,9 @@ namespace Yavsc.Server.Helpers
{
var root = Path.Combine(AbstractFileSystemHelpers.UserFilesDirName, user.UserName);
var fi = new FileInfo(Path.Combine(root, fileNameFrom));
if (!fi.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.NotFound, ErrorMessage = "no file to move" } ;
if (!fi.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.NotFound, ErrorMessage = "no file to move" };
var fo = new FileInfo(Path.Combine(root, fileNameDest));
if (fo.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.DestExists , ErrorMessage = "destination file name is an existing file" } ;
if (fo.Exists) return new FsOperationInfo { ErrorCode = ErrorCode.DestExists, ErrorMessage = "destination file name is an existing file" };
fi.MoveTo(fo.FullName);
return new FsOperationInfo { Done = true };
}
@ -158,7 +157,7 @@ namespace Yavsc.Server.Helpers
// form-data_ name=_file__ filename=_Constants.Private.cs_
var parts = disposition.Split(' ');
var filename = parts[2].Split('=')[1];
filename = filename.Substring(1,filename.Length-2);
filename = filename.Substring(1, filename.Length - 2);
return filename;
}
@ -211,7 +210,7 @@ namespace Yavsc.Server.Helpers
const int blen = 1024;
byte[] buffer = new byte[blen];
int len = 0;
while (!token.IsCancellationRequested && (len=inputStream.Read(buffer, 0, blen))>0)
while (!token.IsCancellationRequested && (len = inputStream.Read(buffer, 0, blen)) > 0)
{
dest.Write(buffer, 0, len);
usage += len;
@ -222,7 +221,8 @@ namespace Yavsc.Server.Helpers
inputStream.Close();
}
}
if (usage >= user.DiskQuota) {
if (usage >= user.DiskQuota)
{
item.QuotaOffense = true;
}
user.DiskUsage = usage;
@ -232,14 +232,14 @@ namespace Yavsc.Server.Helpers
public static HtmlString FileLink(this RemoteFileInfo info, string username, string subpath)
{
return new HtmlString(
$"{Config.UserFilesOptions.RequestPath}/{username}/{subpath}/{info.Name}" );
$"{Config.UserFilesOptions.RequestPath}/{username}/{subpath}/{info.Name}");
}
public static RemoteFileInfo FileInfo(this ApplicationUser user, string path)
{
IFileInfo info = Config.UserFilesOptions.FileProvider.GetFileInfo($"{user.UserName}/{path}");
if (!info.Exists) return null;
return new RemoteFileInfo{ Name = info.Name, Size = info.Length, LastModified = info.LastModified.UtcDateTime };
return new RemoteFileInfo { Name = info.Name, Size = info.Length, LastModified = info.LastModified.UtcDateTime };
}
@ -248,32 +248,43 @@ namespace Yavsc.Server.Helpers
var item = new FileReceivedInfo
(Config.AvatarsOptions.RequestPath.ToUriComponent(),
user.UserName + ".png");
using (var org = formFile.OpenReadStream())
{
using Image image = Image.Load(org);
image.Mutate(x=>x.Resize(128,128));
image.Save(Path.Combine(Config.SiteSetup.Avatars,item.FileName));
image.Mutate(x=>x.Resize(64,64));
image.Save(Path.Combine(Config.SiteSetup.Avatars,user.UserName + ".s.png"));
image.Mutate(x=>x.Resize(32,32));
image.Save(Path.Combine(Config.SiteSetup.Avatars,user.UserName + ".xs.png"));
var size = new MagickGeometry(128, 128);
size.IgnoreAspectRatio = false;
using var image = new MagickImage(org);
image.Resize(size);
image.Write(Path.Combine(Config.SiteSetup.Avatars, item.FileName));
size.X = 64;
size.Y = 64;
image.Resize(size);
image.Write(Path.Combine(Config.SiteSetup.Avatars, user.UserName + ".s.png"));
size.X = 32;
size.Y = 32;
image.Resize(size);
image.Write(Path.Combine(Config.SiteSetup.Avatars, user.UserName + ".xs.png"));
}
user.Avatar = $"{item.DestDir}/{item.FileName}";
return item;
}
public static string GetFileUrl (this LiveFlow flow)
public static string GetFileUrl(this LiveFlow flow)
{
// no server-side backup for this stream
return $"{Config.UserFilesOptions.RequestPath}/{flow.Owner.UserName}/live/"+GetFileName(flow);
return $"{Config.UserFilesOptions.RequestPath}/{flow.Owner.UserName}/live/" + GetFileName(flow);
}
public static string GetFileName (this LiveFlow flow)
public static string GetFileName(this LiveFlow flow)
{
var fileInfo = new FileInfo(flow.DifferedFileName);
var ext = fileInfo.Extension;
var namelen = flow.DifferedFileName.Length - ext.Length;
var basename = flow.DifferedFileName.Substring(0,namelen);
var basename = flow.DifferedFileName.Substring(0, namelen);
return $"{basename}-{flow.SequenceNumber}{ext}";
}

View file

@ -4,10 +4,12 @@
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>53bd70e8-ff81-497a-847f-a15fd8ea7a09</UserSecretsId>
<RootNamespace>Yavsc.Server</RootNamespace>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<RepositoryUrl>https://github.com/pazof/yavsc</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HigginsSoft.IdentityServer8.EntityFramework" />
<PackageReference Include="Magick.NET-Q8-AnyCPU" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
<PackageReference Include="HigginsSoft.IdentityServer8" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
@ -22,7 +24,6 @@
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" />
<PackageReference Include="Google.Apis.Calendar.v3" />
<PackageReference Include="PayPalMerchantSDK" />
<PackageReference Include="SixLabors.ImageSharp" />
<PackageReference Include="RazorEngine.NetCore" />
<PackageReference Include="MailKit" />
<PackageReference Include="MimeKit" />

View file

@ -4,6 +4,7 @@
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>Yavsc.cli</RootNamespace>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Razor" />

View file

@ -12,9 +12,6 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;
using System.Net;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
@ -116,22 +113,7 @@ namespace isnd.tests
TestingUserPassword = _sharedTestingUserPassword;
TestingUserEmail = _sharedTestingUserEmail;
}
void ConfigureLogger() => Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
.Enrich.FromLogContext()
// uncomment to write to Azure diagnostics stream
//.WriteTo.File(
// @"D:\home\LogFiles\Application\identityserver.txt",
// fileSizeLimitBytes: 1_000_000,
// rollOnFileSizeLimit: true,
// shared: true,
// flushToDiskInterval: TimeSpan.FromSeconds(1))
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code)
.CreateLogger();
public async Task SetupHost()
{
@ -142,11 +124,14 @@ namespace isnd.tests
var yavscOrgPath = Path.GetFullPath(Path.Combine(testAssemblyLocation, "../../src/Yavsc.Org"));
builder.Environment.ContentRootPath = yavscOrgPath;
ConfigureLogger();
var config = builder.Configuration
builder.Configuration
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: false, reloadOnChange: false)
.AddEnvironmentVariables().Build();
.AddEnvironmentVariables()
.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"ConnectionStrings:{Constants.YavscConnectionStringName}"] = "InMemory"
});
// Configure Kestrel for HTTPS with self-signed certificate on a dynamic port
builder.WebHost.ConfigureKestrel(options =>
@ -162,7 +147,6 @@ namespace isnd.tests
_app = builder.ConfigureWebAppServices();
Services = _app.Services;
SiteSettings = _app.Services.GetRequiredService<IOptions<SiteSettings>>().Value;
String cxStr = config.GetConnectionString(Constants.YavscConnectionStringName) ?? throw new InvalidOperationException("DefaultConnection string is not configured.");
using (var migrationScope = _app.Services.CreateScope())
{

View file

@ -39,7 +39,7 @@
}
},
"ConnectionStrings": {
"YavscConnection": "Server=localhost;Port=5432;Database=testingYavsc;Username=lame-Username;Password=lame-dbPassword;"
"YavscConnection": "InMemory"
},
"DataProtection": {
"Keys": {

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
@ -6,6 +6,7 @@
<IsPackable>false</IsPackable>
<RootNamespace>Yavsc.Tests</RootNamespace>
<UserSecretsId>78a4efec-68dc-4745-ba06-d8545ef9ee91</UserSecretsId>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" />
@ -43,5 +44,7 @@
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
</ItemGroup>
</Project>

View file

@ -23,47 +23,129 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "yavscTests", "test\yavscTes
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yavsc.Blogs", "src\Yavsc.Blogs\Yavsc.Blogs.csproj", "{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostIt", "src\PostIt\PostIt.csproj", "{342F9C7A-C72A-47F6-A2A7-442A524D10CE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Debug|x64.ActiveCfg = Debug|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Debug|x64.Build.0 = Debug|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Debug|x86.ActiveCfg = Debug|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Debug|x86.Build.0 = Debug|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Release|Any CPU.Build.0 = Release|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Release|x64.ActiveCfg = Release|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Release|x64.Build.0 = Release|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Release|x86.ActiveCfg = Release|Any CPU
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC}.Release|x86.Build.0 = Release|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Debug|x64.ActiveCfg = Debug|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Debug|x64.Build.0 = Debug|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Debug|x86.ActiveCfg = Debug|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Debug|x86.Build.0 = Debug|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Release|Any CPU.Build.0 = Release|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Release|x64.ActiveCfg = Release|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Release|x64.Build.0 = Release|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Release|x86.ActiveCfg = Release|Any CPU
{4F852616-39EE-4075-B6F9-BE1E2DDB877B}.Release|x86.Build.0 = Release|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Debug|x64.ActiveCfg = Debug|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Debug|x64.Build.0 = Debug|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Debug|x86.ActiveCfg = Debug|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Debug|x86.Build.0 = Debug|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Release|Any CPU.Build.0 = Release|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Release|x64.ActiveCfg = Release|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Release|x64.Build.0 = Release|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Release|x86.ActiveCfg = Release|Any CPU
{88142EC2-FEB2-4D69-AD3A-74F3364360F0}.Release|x86.Build.0 = Release|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Debug|x64.ActiveCfg = Debug|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Debug|x64.Build.0 = Debug|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Debug|x86.ActiveCfg = Debug|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Debug|x86.Build.0 = Debug|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Release|Any CPU.Build.0 = Release|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Release|x64.ActiveCfg = Release|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Release|x64.Build.0 = Release|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Release|x86.ActiveCfg = Release|Any CPU
{1F594222-C5CB-4D4A-94A1-C5AEB4990B59}.Release|x86.Build.0 = Release|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Debug|x64.ActiveCfg = Debug|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Debug|x64.Build.0 = Debug|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Debug|x86.ActiveCfg = Debug|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Debug|x86.Build.0 = Debug|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Release|Any CPU.Build.0 = Release|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Release|x64.ActiveCfg = Release|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Release|x64.Build.0 = Release|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Release|x86.ActiveCfg = Release|Any CPU
{95DAD2B5-4324-4E89-A337-5703E45CFBE8}.Release|x86.Build.0 = Release|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Debug|x64.ActiveCfg = Debug|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Debug|x64.Build.0 = Debug|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Debug|x86.ActiveCfg = Debug|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Debug|x86.Build.0 = Debug|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Release|Any CPU.Build.0 = Release|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Release|x64.ActiveCfg = Release|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Release|x64.Build.0 = Release|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Release|x86.ActiveCfg = Release|Any CPU
{27DA6CEC-4266-4F78-BB32-8388F9A401D0}.Release|x86.Build.0 = Release|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Debug|x64.ActiveCfg = Debug|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Debug|x64.Build.0 = Debug|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Debug|x86.ActiveCfg = Debug|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Debug|x86.Build.0 = Debug|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Release|Any CPU.Build.0 = Release|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Release|x64.ActiveCfg = Release|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Release|x64.Build.0 = Release|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Release|x86.ActiveCfg = Release|Any CPU
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1}.Release|x86.Build.0 = Release|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Debug|x64.ActiveCfg = Debug|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Debug|x64.Build.0 = Debug|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Debug|x86.ActiveCfg = Debug|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Debug|x86.Build.0 = Debug|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Release|Any CPU.Build.0 = Release|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Release|x64.ActiveCfg = Release|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Release|x64.Build.0 = Release|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Release|x86.ActiveCfg = Release|Any CPU
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C}.Release|x86.Build.0 = Release|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Debug|x64.ActiveCfg = Debug|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Debug|x64.Build.0 = Debug|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Debug|x86.ActiveCfg = Debug|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Debug|x86.Build.0 = Debug|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Release|Any CPU.Build.0 = Release|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Release|x64.ActiveCfg = Release|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Release|x64.Build.0 = Release|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Release|x86.ActiveCfg = Release|Any CPU
{342F9C7A-C72A-47F6-A2A7-442A524D10CE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{8AD551DA-AFB7-4C2A-BB33-9418E38659BC} = {CDB1BDB5-53F9-4B43-864F-60F2E74F44E2}
@ -74,5 +156,6 @@ Global
{27DA6CEC-4266-4F78-BB32-8388F9A401D0} = {CDB1BDB5-53F9-4B43-864F-60F2E74F44E2}
{CDCF676A-2037-472E-8C8B-67C5E4FDFEA1} = {76A7FBA6-B7EC-4864-85C0-1F470794BA0F}
{5D9E161F-3CB3-4854-9D07-3DF6882EA66C} = {CDB1BDB5-53F9-4B43-864F-60F2E74F44E2}
{342F9C7A-C72A-47F6-A2A7-442A524D10CE} = {CDB1BDB5-53F9-4B43-864F-60F2E74F44E2}
EndGlobalSection
EndGlobal