From 95dec3636a637670cf7c75df4a650319acf28a7b Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Thu, 28 May 2026 22:18:26 +0100 Subject: [PATCH] Use InMemory db driver at testing --- Directory.Packages.old.props | 65 +++++++++ Directory.Packages.props | 74 ++++++----- src/Api/Api.csproj | 3 +- .../Controllers/Business/BillingController.cs | 4 +- .../accounting/AccountController.cs | 5 +- src/PostIt/App.axaml | 12 ++ src/PostIt/App.axaml.cs | 23 ++++ src/PostIt/MainWindow.axaml | 27 ++++ src/PostIt/MainWindow.axaml.cs | 12 ++ src/PostIt/PostIt.csproj | 21 +++ src/PostIt/Program.cs | 24 ++++ src/PostIt/app.manifest | 18 +++ src/Yavsc.Abstract/Yavsc.Abstract.csproj | 3 +- src/Yavsc.Blogs/Yavsc.Blogs.csproj | 3 +- src/Yavsc.Org/Extensions/HostingExtensions.cs | 49 ++++++- src/Yavsc.Org/Yavsc.Org.csproj | 5 +- src/Yavsc.Server/Helpers/FileSystemHelpers.cs | 123 ++++++++++-------- src/Yavsc.Server/Yavsc.Server.csproj | 5 +- src/Yavsc.Web/Yavsc.Web.csproj | 2 +- src/cli/cli.csproj | 3 +- test/yavscTests/WebServerFixture.cs | 30 +---- test/yavscTests/appsettings.json | 4 +- test/yavscTests/yavscTests.csproj | 9 +- yavsc.sln | 89 ++++++++++++- 24 files changed, 474 insertions(+), 139 deletions(-) create mode 100644 Directory.Packages.old.props create mode 100644 src/PostIt/App.axaml create mode 100644 src/PostIt/App.axaml.cs create mode 100644 src/PostIt/MainWindow.axaml create mode 100644 src/PostIt/MainWindow.axaml.cs create mode 100644 src/PostIt/PostIt.csproj create mode 100644 src/PostIt/Program.cs create mode 100644 src/PostIt/app.manifest diff --git a/Directory.Packages.old.props b/Directory.Packages.old.props new file mode 100644 index 00000000..8c40e048 --- /dev/null +++ b/Directory.Packages.old.props @@ -0,0 +1,65 @@ + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index 3b2164c8..d5911bb0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,10 +5,16 @@ + + + + + + - - - + + + @@ -17,47 +23,51 @@ - - - - - - + + + + + + + - - - + + + + - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - + - + - + - + + \ No newline at end of file diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj index e8d8bf71..580b110f 100644 --- a/src/Api/Api.csproj +++ b/src/Api/Api.csproj @@ -4,9 +4,10 @@ enable 1c73094f-959f-4211-b1a1-6a69b236c283 Yavsc.Api + true - + \ No newline at end of file diff --git a/src/Api/Controllers/Business/BillingController.cs b/src/Api/Controllers/Business/BillingController.cs index ad39a8e7..25844955 100644 --- a/src/Api/Controllers/Business/BillingController.cs +++ b/src/Api/Controllers/Business/BillingController.cs @@ -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 }); diff --git a/src/Api/Controllers/accounting/AccountController.cs b/src/Api/Controllers/accounting/AccountController.cs index 617916af..aff71013 100644 --- a/src/Api/Controllers/accounting/AccountController.cs +++ b/src/Api/Controllers/accounting/AccountController.cs @@ -66,12 +66,15 @@ namespace Yavsc.WebApi.Controllers /// Updates the avatar /// /// - [HttpPost("~/api/setavatar")] + [HttpPost("~/api/set-avatar")] public async Task 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); diff --git a/src/PostIt/App.axaml b/src/PostIt/App.axaml new file mode 100644 index 00000000..aac65f24 --- /dev/null +++ b/src/PostIt/App.axaml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/PostIt/App.axaml.cs b/src/PostIt/App.axaml.cs new file mode 100644 index 00000000..b75a7f30 --- /dev/null +++ b/src/PostIt/App.axaml.cs @@ -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(); + } +} \ No newline at end of file diff --git a/src/PostIt/MainWindow.axaml b/src/PostIt/MainWindow.axaml new file mode 100644 index 00000000..e4c0f9ff --- /dev/null +++ b/src/PostIt/MainWindow.axaml @@ -0,0 +1,27 @@ + + + + + + + + + + + + diff --git a/src/PostIt/MainWindow.axaml.cs b/src/PostIt/MainWindow.axaml.cs new file mode 100644 index 00000000..b2d99200 --- /dev/null +++ b/src/PostIt/MainWindow.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace PostIt; + +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + this.Greeting.Content="Hello Joe!"; + } +} \ No newline at end of file diff --git a/src/PostIt/PostIt.csproj b/src/PostIt/PostIt.csproj new file mode 100644 index 00000000..11c18962 --- /dev/null +++ b/src/PostIt/PostIt.csproj @@ -0,0 +1,21 @@ + + + WinExe + net10.0 + enable + app.manifest + true + + + + + + + + + None + All + + + + \ No newline at end of file diff --git a/src/PostIt/Program.cs b/src/PostIt/Program.cs new file mode 100644 index 00000000..f65042f4 --- /dev/null +++ b/src/PostIt/Program.cs @@ -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() + .UsePlatformDetect() +#if DEBUG + .WithDeveloperTools() +#endif + .WithInterFont() + .LogToTrace(); +} diff --git a/src/PostIt/app.manifest b/src/PostIt/app.manifest new file mode 100644 index 00000000..d65125d1 --- /dev/null +++ b/src/PostIt/app.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/src/Yavsc.Abstract/Yavsc.Abstract.csproj b/src/Yavsc.Abstract/Yavsc.Abstract.csproj index e851194a..fbc32624 100644 --- a/src/Yavsc.Abstract/Yavsc.Abstract.csproj +++ b/src/Yavsc.Abstract/Yavsc.Abstract.csproj @@ -6,8 +6,9 @@ Yavsc.Abstract https://github.com/pazof/yavsc + true - + \ No newline at end of file diff --git a/src/Yavsc.Blogs/Yavsc.Blogs.csproj b/src/Yavsc.Blogs/Yavsc.Blogs.csproj index acfc5b76..58654f7e 100644 --- a/src/Yavsc.Blogs/Yavsc.Blogs.csproj +++ b/src/Yavsc.Blogs/Yavsc.Blogs.csproj @@ -5,9 +5,10 @@ 1c73094f-959f-4211-b1a1-6a69b236c283 Yavsc.Api https://github.com/pazof/yavsc + true - + \ No newline at end of file diff --git a/src/Yavsc.Org/Extensions/HostingExtensions.cs b/src/Yavsc.Org/Extensions/HostingExtensions.cs index 06b7d4bd..fe218612 100644 --- a/src/Yavsc.Org/Extensions/HostingExtensions.cs +++ b/src/Yavsc.Org/Extensions/HostingExtensions.cs @@ -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(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( @@ -285,14 +294,35 @@ public static class HostingExtensions .AddResourceStore() .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 EnsureDefaultApplicationScopes() { return (context, _) => diff --git a/src/Yavsc.Org/Yavsc.Org.csproj b/src/Yavsc.Org/Yavsc.Org.csproj index b260d5a2..87e99f72 100644 --- a/src/Yavsc.Org/Yavsc.Org.csproj +++ b/src/Yavsc.Org/Yavsc.Org.csproj @@ -5,7 +5,7 @@ WTFPL 76e56fc2-1619-40d8-8393-365258b7a21d Yavsc - + true https://github.com/pazof/yavsc @@ -21,7 +21,6 @@ - @@ -33,6 +32,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + @@ -44,7 +44,6 @@ - diff --git a/src/Yavsc.Server/Helpers/FileSystemHelpers.cs b/src/Yavsc.Server/Helpers/FileSystemHelpers.cs index 89c76af7..ccdf7a1f 100644 --- a/src/Yavsc.Server/Helpers/FileSystemHelpers.cs +++ b/src/Yavsc.Server/Helpers/FileSystemHelpers.cs @@ -7,38 +7,34 @@ 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 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 ReceiveProSignatureAsync(this ClaimsPrincipal user, string billingCode, long estimateId, IFormFile formFile, string signType) { var item = new FileReceivedInfo( - Config.SiteSetup.Bills, + Config.SiteSetup.Bills, AbstractFileSystemHelpers.SignFileNameFormat("pro", billingCode, estimateId)); 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,67 +72,70 @@ 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; } - + public static FsOperationInfo DeleteUserDirOrFile(this ApplicationUser user, string dirName) { 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"} ; + if (string.IsNullOrEmpty(dirName)) + 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 }; } - + public static FsOperationInfo MoveUserDir(this ApplicationUser user, string fromDirName, string toDirName) { 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 "} ; + if (string.IsNullOrEmpty(fromDirName)) + 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 = "."; var destPath = Path.Combine(root, toDirName); 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); + di.MoveTo(destPath); return new FsOperationInfo { Done = true }; } public static FsOperationInfo MoveUserFileToDir(this ApplicationUser user, string fileNameFrom, string fileNameDest) { 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; } @@ -170,7 +169,7 @@ namespace Yavsc.Server.Helpers { return ReceiveUserFile(user, root, f.OpenReadStream(), destFileName ?? ParseFileNameFromDisposition(f.ContentDisposition), f.ContentType, CancellationToken.None); } - + /// /// Modifies the user's disk usage /// @@ -203,7 +202,7 @@ namespace Yavsc.Server.Helpers { item.Overridden = true; usage -= fi.Length; - } + } using (var dest = fi.OpenWrite()) { using (inputStream) @@ -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; @@ -231,15 +231,15 @@ 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}" ); + return new HtmlString( + $"{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}"; } diff --git a/src/Yavsc.Server/Yavsc.Server.csproj b/src/Yavsc.Server/Yavsc.Server.csproj index 0aeac22d..66b41ba5 100644 --- a/src/Yavsc.Server/Yavsc.Server.csproj +++ b/src/Yavsc.Server/Yavsc.Server.csproj @@ -4,10 +4,12 @@ enable 53bd70e8-ff81-497a-847f-a15fd8ea7a09 Yavsc.Server + true https://github.com/pazof/yavsc + @@ -22,7 +24,6 @@ - @@ -31,4 +32,4 @@ - + \ No newline at end of file diff --git a/src/Yavsc.Web/Yavsc.Web.csproj b/src/Yavsc.Web/Yavsc.Web.csproj index 86f61a85..51270671 100644 --- a/src/Yavsc.Web/Yavsc.Web.csproj +++ b/src/Yavsc.Web/Yavsc.Web.csproj @@ -15,4 +15,4 @@ PreserveNewest - + \ No newline at end of file diff --git a/src/cli/cli.csproj b/src/cli/cli.csproj index c35b5e1e..1e6fff4f 100644 --- a/src/cli/cli.csproj +++ b/src/cli/cli.csproj @@ -4,6 +4,7 @@ net10.0 enable Yavsc.cli + true @@ -18,4 +19,4 @@ - + \ No newline at end of file diff --git a/test/yavscTests/WebServerFixture.cs b/test/yavscTests/WebServerFixture.cs index a569b29f..8a1714bc 100644 --- a/test/yavscTests/WebServerFixture.cs +++ b/test/yavscTests/WebServerFixture.cs @@ -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 + { + [$"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>().Value; - String cxStr = config.GetConnectionString(Constants.YavscConnectionStringName) ?? throw new InvalidOperationException("DefaultConnection string is not configured."); using (var migrationScope = _app.Services.CreateScope()) { diff --git a/test/yavscTests/appsettings.json b/test/yavscTests/appsettings.json index 107dae86..aca65802 100644 --- a/test/yavscTests/appsettings.json +++ b/test/yavscTests/appsettings.json @@ -39,7 +39,7 @@ } }, "ConnectionStrings": { - "YavscConnection": "Server=localhost;Port=5432;Database=testingYavsc;Username=lame-Username;Password=lame-dbPassword;" + "YavscConnection": "InMemory" }, "DataProtection": { "Keys": { @@ -64,4 +64,4 @@ "Password": "f/\\kePassw0rd" } } -} \ No newline at end of file +} diff --git a/test/yavscTests/yavscTests.csproj b/test/yavscTests/yavscTests.csproj index 6fd4a752..9f745dff 100644 --- a/test/yavscTests/yavscTests.csproj +++ b/test/yavscTests/yavscTests.csproj @@ -1,4 +1,4 @@ - + net10.0 enable @@ -6,6 +6,7 @@ false Yavsc.Tests 78a4efec-68dc-4745-ba06-d8545ef9ee91 + true @@ -43,5 +44,7 @@ - - + + + + \ No newline at end of file diff --git a/yavsc.sln b/yavsc.sln index 3658046c..280fe44f 100644 --- a/yavsc.sln +++ b/yavsc.sln @@ -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