diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c54d7a7..e778438 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -50,6 +50,7 @@ jobs: - name: Save the SSH private key to a file run: | if [ ! -f ~/.ssh/id_rsa ]; then + echo "Save the SSH private key to a file" mkdir -p ~/.ssh echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa @@ -58,6 +59,7 @@ jobs: - name: Add remote server to known_hosts run: | if ! grep -q "${{ env.SSH_HOST }}" ~/.ssh/known_hosts; then + echo "Add remote server to known_hosts" ssh-keyscan ${{ env.SSH_HOST }} >> ~/.ssh/known_hosts fi diff --git a/src/MvcDemo/Data/DemoDbInitializer.cs b/src/MvcDemo/Data/DemoDbInitializer.cs deleted file mode 100644 index 722bb84..0000000 --- a/src/MvcDemo/Data/DemoDbInitializer.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Demo.Models; - -namespace Demo.Data -{ - public static class DemoDbInitializer - { - public const string AdminUserName = "demo"; - public const string AdminInitPassword = "demo@myvas.com"; - - public static async Task Initialize(IServiceProvider serviceProvider) - { - using var db = new DemoDbContext(serviceProvider.GetRequiredService>()); - await EnsureAdminUser(serviceProvider); - } - - private static async Task EnsureAdminUser(IServiceProvider serviceProvider) - { - var userManager = serviceProvider.GetRequiredService>(); - - var user = await userManager.FindByNameAsync(AdminUserName); - if (user == null) - { - user = new IdentityUser() - { - UserName = AdminUserName, - Email = "demo@myvas.com", - EmailConfirmed = true, - PhoneNumber = "13800138000", - PhoneNumberConfirmed = true, - }; - var result = await userManager.CreateAsync(user, AdminInitPassword); - if (!result.Succeeded) - { - throw new Exception(GetErrorMessage(result)); - } - } - } - - private static string GetErrorMessage(IdentityResult identityResult) - { - var result = ""; - - foreach (var error in identityResult.Errors) - { - result += $"[{error.Code}]{error.Description}" + Environment.NewLine; - } - return result; - } - - - } -} diff --git a/src/MvcDemo/Data/DemoDesignTimeDbContextFactory.cs b/src/MvcDemo/Data/DemoDesignTimeDbContextFactory.cs deleted file mode 100644 index 94d18b2..0000000 --- a/src/MvcDemo/Data/DemoDesignTimeDbContextFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; - -namespace Demo.Data -{ - public class DemoDesignTimeDbContextFactory : IDesignTimeDbContextFactory - { - public DemoDbContext CreateDbContext(string[] args) - { - var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlite("Data Source=demo.sqlite"); - - return new DemoDbContext(optionsBuilder.Options); - } - } -} diff --git a/src/MvcDemo/Data/HostDatabaseExtensions.cs b/src/MvcDemo/Data/HostDatabaseExtensions.cs deleted file mode 100644 index fdcfd03..0000000 --- a/src/MvcDemo/Data/HostDatabaseExtensions.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using System; - -namespace Demo.Data; - -public static class HostDatabaseExtensions -{ - public static WebApplication MigrateDatabase(this WebApplication host) - { - using (var scope = host.Services.CreateScope()) - { - var services = scope.ServiceProvider; - - try - { - var db = services.GetRequiredService(); - db.Database.Migrate(); - } - catch (Exception ex) - { - var logger = services.GetRequiredService>(); - logger.LogError(ex, "An error occurred while migrating the database."); - } - } - - return host; - } - - public static WebApplication SeedDatabase(this WebApplication host) - { - using (var scope = host.Services.CreateScope()) - { - var services = scope.ServiceProvider; - - try - { - DemoDbInitializer.Initialize(services).Wait(); - } - catch (Exception ex) - { - var logger = services.GetRequiredService>(); - logger.LogError(ex, "An error occurred while seeding the database."); - } - } - - return host; - } -} diff --git a/src/MvcDemo/Data/WebApplicationDatabaseExtensions.cs b/src/MvcDemo/Data/WebApplicationDatabaseExtensions.cs new file mode 100644 index 0000000..65f63be --- /dev/null +++ b/src/MvcDemo/Data/WebApplicationDatabaseExtensions.cs @@ -0,0 +1,90 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Demo.Data; + +public static class WebApplicationDatabaseExtensions +{ + public static WebApplication MigrateDatabase(this WebApplication app) + { + using (var scope = app.Services.CreateScope()) + { + var services = scope.ServiceProvider; + + try + { + var db = services.GetRequiredService(); + db.Database.Migrate(); + } + catch (Exception ex) + { + var logger = services.GetRequiredService>(); + logger.LogError(ex, "An error occurred while migrating the database."); + } + } + + return app; + } + + + public static WebApplication SeedDatabase(this WebApplication app, string adminUserName, string adminInitPassword) + { + using (var scope = app.Services.CreateScope()) + { + var services = scope.ServiceProvider; + + try + { + Task.Run(async () => + { + var userManager = services.GetRequiredService>(); + await EnsureAdminUser(userManager, adminUserName, adminInitPassword); + }); + } + catch (Exception ex) + { + var logger = services.GetRequiredService>(); + logger.LogError(ex, "An error occurred while seeding the database."); + } + } + + return app; + } + + private static async Task EnsureAdminUser(UserManager userManager, string adminUserName, string adminEmail) + { + var adminInitPassword = adminEmail; + + var user = await userManager.FindByNameAsync(adminUserName); + if (user == null) + { + user = new IdentityUser() + { + UserName = adminUserName, + Email = adminEmail, + EmailConfirmed = true, + }; + var result = await userManager.CreateAsync(user, adminInitPassword); + if (!result.Succeeded) + { + throw new Exception(GetErrorMessage(result)); + } + } + } + + private static string GetErrorMessage(IdentityResult identityResult) + { + var result = ""; + + foreach (var error in identityResult.Errors) + { + result += $"[{error.Code}]{error.Description}" + Environment.NewLine; + } + return result; + } +} \ No newline at end of file diff --git a/src/MvcDemo/Demo.csproj b/src/MvcDemo/Demo.csproj index 99dbc3f..edda96a 100644 --- a/src/MvcDemo/Demo.csproj +++ b/src/MvcDemo/Demo.csproj @@ -27,7 +27,7 @@ - + diff --git a/src/MvcDemo/HostExtensions.cs b/src/MvcDemo/HostExtensions.cs index 04219b7..81ac6ac 100644 --- a/src/MvcDemo/HostExtensions.cs +++ b/src/MvcDemo/HostExtensions.cs @@ -12,7 +12,7 @@ namespace Demo; public static class HostExtensions { - public static WebApplication ConfigureServices(this WebApplicationBuilder builder) + public static WebApplicationBuilder ConfigureServices(this WebApplicationBuilder builder) { var Configuration = builder.Configuration; @@ -91,6 +91,7 @@ public static WebApplication ConfigureServices(this WebApplicationBuilder builde { o.Configuration = Configuration.GetConnectionString("RedisConnection"); }) + .AddJsapiTicketRedisCacheProvider() .AddWeixinSite(o => { o.Debug = true; // for this demo for debugging @@ -105,7 +106,7 @@ public static WebApplication ConfigureServices(this WebApplicationBuilder builde }) .AddWeixinEventSink(); - return builder.Build(); + return builder; } public static WebApplication ConfigurePipeline(this WebApplication app) diff --git a/src/MvcDemo/Migrations/20250323190719_V2.Designer.cs b/src/MvcDemo/Migrations/20250325070817_V3.Designer.cs similarity index 99% rename from src/MvcDemo/Migrations/20250323190719_V2.Designer.cs rename to src/MvcDemo/Migrations/20250325070817_V3.Designer.cs index d342b94..c1b5614 100644 --- a/src/MvcDemo/Migrations/20250323190719_V2.Designer.cs +++ b/src/MvcDemo/Migrations/20250325070817_V3.Designer.cs @@ -11,8 +11,8 @@ namespace Demo.Migrations { [DbContext(typeof(DemoDbContext))] - [Migration("20250323190719_V2")] - partial class V2 + [Migration("20250325070817_V3")] + partial class V3 { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/src/MvcDemo/Migrations/20250323190719_V2.cs b/src/MvcDemo/Migrations/20250325070817_V3.cs similarity index 57% rename from src/MvcDemo/Migrations/20250323190719_V2.cs rename to src/MvcDemo/Migrations/20250325070817_V3.cs index ee8e147..83e2fc5 100644 --- a/src/MvcDemo/Migrations/20250323190719_V2.cs +++ b/src/MvcDemo/Migrations/20250325070817_V3.cs @@ -6,7 +6,7 @@ namespace Demo.Migrations { /// - public partial class V2 : Migration + public partial class V3 : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -23,42 +23,51 @@ protected override void Up(MigrationBuilder migrationBuilder) table: "WeixinSubscribers"); migrationBuilder.DropColumn( - name: "CreateUnixTime", + name: "RowVersion", table: "WeixinSubscribers"); migrationBuilder.DropColumn( - name: "RowVersion", - table: "WeixinSubscribers"); + name: "CreateUnixTime", + table: "WeixinReceivedMessages"); + + migrationBuilder.DropColumn( + name: "CreateUnixTime", + table: "WeixinReceivedEvents"); migrationBuilder.RenameColumn( - name: "Gender", + name: "UnsubscribedTime", table: "WeixinSubscribers", - newName: "Sex"); + newName: "SecurityStamp"); migrationBuilder.RenameColumn( - name: "NickName", + name: "Unsubscribed", table: "WeixinSubscribers", - newName: "Nickname"); + newName: "Subscribed"); migrationBuilder.RenameColumn( - name: "AvatorImageUrl", + name: "SubscribedTime", table: "WeixinSubscribers", newName: "HeadImgUrl"); - + migrationBuilder.RenameColumn( - name: "SubscribedTime", + name: "Gender", table: "WeixinSubscribers", - newName: "SubscribeTime"); + newName: "UnsubscribeTime"); migrationBuilder.RenameColumn( - name: "Unsubscribed", + name: "AvatorImageUrl", table: "WeixinSubscribers", - newName: "Subscribed"); - - migrationBuilder.RenameColumn( - name: "UnsubscribedTime", + newName: "ConcurrencyStamp"); + + migrationBuilder.AlterColumn( + name: "OpenId", table: "WeixinSubscribers", - newName: "UnsubscribeTime"); + type: "TEXT", + maxLength: 32, + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 32); migrationBuilder.AddColumn( name: "Id", @@ -67,23 +76,51 @@ protected override void Up(MigrationBuilder migrationBuilder) nullable: false, defaultValue: ""); - migrationBuilder.AddColumn( - name: "SecurityStamp", + migrationBuilder.AddColumn( + name: "Sex", table: "WeixinSubscribers", - type: "TEXT", + type: "INTEGER", nullable: true); - - migrationBuilder.AddColumn( - name: "ConcurrencyStamp", + + migrationBuilder.AddColumn( + name: "SubscribeTime", table: "WeixinSubscribers", - type: "TEXT", + type: "INTEGER", nullable: true); - - migrationBuilder.AddColumn( - name: "CreateTime", + + migrationBuilder.AlterColumn( + name: "ToUserName", + table: "WeixinReceivedMessages", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 32); + + migrationBuilder.AlterColumn( + name: "MsgType", + table: "WeixinReceivedMessages", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "MsgId", table: "WeixinReceivedMessages", type: "INTEGER", - nullable: true); + nullable: true, + oldClrType: typeof(long), + oldType: "INTEGER"); + + migrationBuilder.AlterColumn( + name: "FromUserName", + table: "WeixinReceivedMessages", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 32); migrationBuilder.AddColumn( name: "ConcurrencyStamp", @@ -93,16 +130,56 @@ protected override void Up(MigrationBuilder migrationBuilder) migrationBuilder.AddColumn( name: "CreateTime", - table: "WeixinReceivedEvents", + table: "WeixinReceivedMessages", type: "INTEGER", nullable: true); + migrationBuilder.AlterColumn( + name: "ToUserName", + table: "WeixinReceivedEvents", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 32); + + migrationBuilder.AlterColumn( + name: "MsgType", + table: "WeixinReceivedEvents", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT"); + + migrationBuilder.AlterColumn( + name: "FromUserName", + table: "WeixinReceivedEvents", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 32); + + migrationBuilder.AlterColumn( + name: "Event", + table: "WeixinReceivedEvents", + type: "TEXT", + nullable: true, + oldClrType: typeof(string), + oldType: "TEXT"); + migrationBuilder.AddColumn( name: "ConcurrencyStamp", table: "WeixinReceivedEvents", type: "TEXT", nullable: true); + migrationBuilder.AddColumn( + name: "CreateTime", + table: "WeixinReceivedEvents", + type: "INTEGER", + nullable: true); + migrationBuilder.AddPrimaryKey( name: "PK_WeixinSubscribers", table: "WeixinSubscribers", @@ -173,35 +250,71 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "PK_WeixinSubscribers", table: "WeixinSubscribers"); - migrationBuilder.RenameColumn( + migrationBuilder.DropColumn( + name: "Id", + table: "WeixinSubscribers"); + + migrationBuilder.DropColumn( name: "Sex", - table: "WeixinSubscribers", - newName: "Gender"); + table: "WeixinSubscribers"); - migrationBuilder.RenameColumn( + migrationBuilder.DropColumn( name: "SubscribeTime", - table: "WeixinSubscribers", - newName: "SubscribedTime"); + table: "WeixinSubscribers"); + + migrationBuilder.DropColumn( + name: "ConcurrencyStamp", + table: "WeixinReceivedMessages"); + + migrationBuilder.DropColumn( + name: "CreateTime", + table: "WeixinReceivedMessages"); + + migrationBuilder.DropColumn( + name: "ConcurrencyStamp", + table: "WeixinReceivedEvents"); + + migrationBuilder.DropColumn( + name: "CreateTime", + table: "WeixinReceivedEvents"); migrationBuilder.RenameColumn( name: "UnsubscribeTime", table: "WeixinSubscribers", - newName: "UnsubscribedTime"); + newName: "Gender"); migrationBuilder.RenameColumn( name: "Subscribed", table: "WeixinSubscribers", newName: "Unsubscribed"); - migrationBuilder.DropColumn( + migrationBuilder.RenameColumn( name: "SecurityStamp", - table: "WeixinSubscribers"); + table: "WeixinSubscribers", + newName: "UnsubscribedTime"); migrationBuilder.RenameColumn( name: "HeadImgUrl", table: "WeixinSubscribers", + newName: "SubscribedTime"); + + migrationBuilder.RenameColumn( + name: "ConcurrencyStamp", + table: "WeixinSubscribers", newName: "AvatorImageUrl"); + migrationBuilder.AlterColumn( + name: "OpenId", + table: "WeixinSubscribers", + type: "TEXT", + maxLength: 32, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "TEXT", + oldMaxLength: 32, + oldNullable: true); + migrationBuilder.AddColumn( name: "AppId", table: "WeixinSubscribers", @@ -215,6 +328,48 @@ protected override void Down(MigrationBuilder migrationBuilder) rowVersion: true, nullable: true); + migrationBuilder.AlterColumn( + name: "ToUserName", + table: "WeixinReceivedMessages", + type: "TEXT", + maxLength: 32, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "MsgType", + table: "WeixinReceivedMessages", + type: "TEXT", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "MsgId", + table: "WeixinReceivedMessages", + type: "INTEGER", + nullable: false, + defaultValue: 0L, + oldClrType: typeof(long), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "FromUserName", + table: "WeixinReceivedMessages", + type: "TEXT", + maxLength: 32, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + migrationBuilder.AddColumn( name: "CreateUnixTime", table: "WeixinReceivedMessages", @@ -222,6 +377,48 @@ protected override void Down(MigrationBuilder migrationBuilder) nullable: false, defaultValue: 0L); + migrationBuilder.AlterColumn( + name: "ToUserName", + table: "WeixinReceivedEvents", + type: "TEXT", + maxLength: 32, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "MsgType", + table: "WeixinReceivedEvents", + type: "TEXT", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "FromUserName", + table: "WeixinReceivedEvents", + type: "TEXT", + maxLength: 32, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Event", + table: "WeixinReceivedEvents", + type: "TEXT", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "TEXT", + oldNullable: true); + migrationBuilder.AddColumn( name: "CreateUnixTime", table: "WeixinReceivedEvents", diff --git a/src/MvcDemo/Program.cs b/src/MvcDemo/Program.cs index 292d50e..548c2ec 100644 --- a/src/MvcDemo/Program.cs +++ b/src/MvcDemo/Program.cs @@ -12,16 +12,17 @@ var assembly = typeof(Program).Assembly; var assemblyName = assembly.GetName().Name; -var assemblyVersion = assembly.GetCustomAttribute()?.InformationalVersion; -Log.Information($"{assemblyName} {assemblyVersion} starting up..."); +var assemblyVersion = assembly.GetName().Version?.ToString() + ?? assembly.GetCustomAttribute()?.InformationalVersion; +Log.Information($"{assemblyName} v{assemblyVersion} starting up..."); try { var builder = WebApplication.CreateBuilder(args); - var app = builder.ConfigureServices() + var app = builder.ConfigureServices().Build() .MigrateDatabase() - .SeedDatabase() + .SeedDatabase("demo", "demo@myvas.com") .ConfigurePipeline(); app.Run(); @@ -34,6 +35,6 @@ } finally { - Log.Information($"{assemblyName} {assemblyVersion} shutdown."); + Log.Information($"{assemblyName} v{assemblyVersion} shutdown."); Log.CloseAndFlush(); } diff --git a/src/MvcDemo/Views/Home/Index.cshtml b/src/MvcDemo/Views/Home/Index.cshtml index dec7fea..71e9c31 100644 --- a/src/MvcDemo/Views/Home/Index.cshtml +++ b/src/MvcDemo/Views/Home/Index.cshtml @@ -1,16 +1,17 @@ @using System.Reflection @{ - ViewData["Title"] = "Demo"; - var assembly = typeof(Program).Assembly; var assemblyName = assembly.GetName().Name; - var assemblyVersion = assembly.GetCustomAttribute()?.InformationalVersion - ?? assembly.GetName().Version.ToString(); + var assemblyVersion = assembly.GetName().Version?.ToString() + ?? assembly.GetCustomAttribute()?.InformationalVersion; + + ViewData["Title"] = assemblyName; } -

@ViewData["Title"] @(assemblyVersion)

+

@assemblyName v@assemblyVersion

-

这是一组github开源项目的演示网站。本网站源代码在此:Myvas.AspNetCore.Authentication.Demo

+

这是一组github开源项目的演示网站。本网站源代码在此:Myvas.AspNetCore.Authentication.Demo

  • WeixinOpen (open.weixin.qq.com)
  • WeixinAuth (mp.weixin.qq.com)
  • @@ -24,12 +25,14 @@

    触发身份验证

    (1)点击UserInfo触发Challenge进入登录页面。

    --- 或 ---

    -

    (2)点击这里展示一个网址二维码,用手机扫码进入。

    +

    (2)点击这里展示一个网址二维码,用手机扫码进入。

    --- 或 ---

    (3)直接扫码进入微信公众号测试,然后点击菜单[UserInfo]

    -

    (注:以上微信公众号的源码在Myvas.AspNetCore.Weixin,其Demo程序可以修改这些菜单)
    +
    (注:以上微信公众号的源码在Myvas.AspNetCore.Weixin,其Demo程序可以修改这些菜单)


    @@ -76,5 +79,6 @@ \ No newline at end of file