Skip to content

Commit

Permalink
Merge branch 'containerization-to-deploy' into EngincanV/add-migratio…
Browse files Browse the repository at this point in the history
…n-logic
  • Loading branch information
skoc10 authored May 13, 2024
2 parents 3a04240 + 6528bf3 commit f38d3ac
Show file tree
Hide file tree
Showing 11 changed files with 500 additions and 2 deletions.
60 changes: 60 additions & 0 deletions .github/workflows/containerization-to-deploy_cms-kit-demo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# # Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# # More GitHub Actions for Azure: https://github.com/Azure/actions

# name: Build and deploy ASP.Net Core app to Azure Web App - cms-kit-demo

# on:
# push:
# branches:
# - containerization-to-deploy
# workflow_dispatch:

# jobs:
# build:
# runs-on: ubuntu-latest

# steps:
# - uses: actions/checkout@v2

# - name: Set up .NET Core
# uses: actions/setup-dotnet@v1
# with:
# dotnet-version: '7.x'
# include-prerelease: true

# - name: Build with dotnet
# run: dotnet build --configuration Release

# - name: dotnet publish
# run: dotnet publish -c Release -o ${{env.DOTNET_ROOT}}/myapp

# - name: Copy CmsKitDemo.db to publish directory
# run: cp src/CmsKitDemo.db ${{env.DOTNET_ROOT}}/myapp

# - name: Upload artifact for deployment job
# uses: actions/upload-artifact@v2
# with:
# name: .net-app
# path: ${{env.DOTNET_ROOT}}/myapp

# deploy:
# runs-on: ubuntu-latest
# needs: build
# environment:
# name: 'Production'
# url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}

# steps:
# - name: Download artifact from build job
# uses: actions/download-artifact@v2
# with:
# name: .net-app

# - name: Deploy to Azure Web App
# id: deploy-to-webapp
# uses: azure/webapps-deploy@v2
# with:
# app-name: 'cms-kit-demo'
# slot-name: 'Production'
# publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_B8EE580013C3409F9EA266AF29C41EAD }}
# package: .
4 changes: 3 additions & 1 deletion src/CmsKitDemo/CmsKitDemoModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
using Volo.Abp.IO;
using Volo.CmsKit.Reactions;
using Volo.CmsKit.Comments;
using Microsoft.EntityFrameworkCore.Query;

namespace CmsKitDemo;

Expand Down Expand Up @@ -318,7 +319,8 @@ private void ConfigureEfCore(ServiceConfigurationContext context)
{
options.Configure(configurationContext =>
{
configurationContext.UseSqlite();
configurationContext.UseSqlite()
.ReplaceService<IMethodCallTranslatorProvider, CmsKitDemoSqliteMethodCallTranslatorProvider>();
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.Sqlite.Query.Internal;
using System.Reflection;
using Volo.Abp;

namespace CmsKitDemo.Data
{
public class CmsKitDemoSqliteMethodCallTranslatorProvider : SqliteMethodCallTranslatorProvider
{
public CmsKitDemoSqliteMethodCallTranslatorProvider([NotNull] RelationalMethodCallTranslatorProviderDependencies dependencies)
: base(dependencies)
{
var sqlExpressionFactory = dependencies.SqlExpressionFactory;

AddTranslators(
new IMethodCallTranslator[]
{
new SqliteMathTranslator(sqlExpressionFactory),
new SqliteDateTimeAddTranslator(sqlExpressionFactory.As<SqliteSqlExpressionFactory>()),
new CmsKitDemoSqliteStringMethodTranslator(sqlExpressionFactory)
});
}
}

public class CmsKitDemoSqliteStringMethodTranslator : SqliteStringMethodTranslator
{
private static readonly MethodInfo _containsMethodInfo
= typeof(string).GetRuntimeMethod(nameof(string.Contains), new[] { typeof(string) });

private readonly ISqlExpressionFactory _sqlExpressionFactory;

public CmsKitDemoSqliteStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) : base(sqlExpressionFactory)
{
_sqlExpressionFactory = sqlExpressionFactory;
}

public override SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList<SqlExpression> arguments, IDiagnosticsLogger<DbLoggerCategory.Query> logger)
{
Check.NotNull(method, nameof(method));
Check.NotNull(arguments, nameof(arguments));

if (_containsMethodInfo.Equals(method))
{
var pattern = arguments[0];
var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, pattern);

instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping);
pattern = _sqlExpressionFactory.ApplyTypeMapping(pattern, stringTypeMapping);

// this basically changes query to "instr(upper(left_expression), upper(right_expression))"
return _sqlExpressionFactory.OrElse(
_sqlExpressionFactory.Equal(
pattern,
_sqlExpressionFactory.Constant(string.Empty, stringTypeMapping)),
_sqlExpressionFactory.GreaterThan(
_sqlExpressionFactory.Function(
"instr",
new[]
{
_sqlExpressionFactory.Function("upper", new[]{instance}, false, new []{ false }, typeof(string)),
_sqlExpressionFactory.Function("upper", new[]{pattern}, false, new []{ false }, typeof(string))
},
false,
new[] { false, false },
typeof(int)), _sqlExpressionFactory.Constant(0)));
}

return base.Translate(instance, method, arguments, logger);
}
}
}
155 changes: 155 additions & 0 deletions src/CmsKitDemo/DbMigrationMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
using Microsoft.Extensions.Options;
using System.Data.Common;
using System.Net;
using System.Text;
using System.Text.Unicode;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Threading;

namespace CmsKitDemo
{
public class DbMigrationMiddleware : IMiddleware, ITransientDependency
{
private readonly IConnectionStringResolver _connectionStringResolver;
private readonly IConfiguration _configuration;

public DbMigrationMiddleware(IConnectionStringResolver connectionStringResolver, IConfiguration configuration)
{
_connectionStringResolver = connectionStringResolver;
_configuration = configuration;
}

public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var connString = await _connectionStringResolver.ResolveAsync();

var dbBuilder = new DbConnectionStringBuilder
{
ConnectionString = connString
};


await next(context);
}
}

[Dependency(ReplaceServices = true)]
public class DemoConnectionStringResolver : DefaultConnectionStringResolver
{
public const string DemoUserCookieName = "CmsKitDemoUser";

private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IGuidGenerator _guidGenerator;
private readonly IConfiguration _configuration;

public DemoConnectionStringResolver(IOptionsMonitor<AbpDbConnectionOptions> options, IConfiguration configuration, IHttpContextAccessor httpContextAccessor, IGuidGenerator guidGenerator) : base(options)
{
_configuration = configuration;
_httpContextAccessor = httpContextAccessor;
_guidGenerator = guidGenerator;
}

[Obsolete("Use ResolveAsync method.")]
public override string Resolve(string connectionStringName)
{
return AsyncHelper.RunSync(() => ResolveInternalAsync(connectionStringName));
}

public async override Task<string> ResolveAsync(string connectionStringName)
{
return await ResolveInternalAsync(connectionStringName);
}

private async Task<string> ResolveInternalAsync(string connectionStringName)
{
var dbFolder = _configuration["App:SqliteDbFolder"]?.EnsureEndsWith(Path.DirectorySeparatorChar);
if (dbFolder.IsNullOrWhiteSpace())
{
return await base.ResolveAsync(connectionStringName);
}

//string demoUserId = _configuration["App:DefaultDbName"]!;
string demoUserId = GetDemoUserIdOrNull() ?? _configuration["App:DefaultDbName"]!;

var dbFilePath = $"{dbFolder}{demoUserId}.db";
var connString = $"Data Source={dbFilePath};Mode=ReadWriteCreate;";

if (ShouldCreateDemoDatabase(dbFilePath))
{
await CreateDemoDatabaseAsync(dbFilePath);
}

return connString;
}

public string GetDemoUserIdOrNull()
{
var httpContext = _httpContextAccessor.HttpContext;
if (httpContext == null)
{
return null;
}

var demoUserId = httpContext.Items[DemoUserCookieName] as string;
if (demoUserId != null)
{
return demoUserId;
}

demoUserId = httpContext.Request?.Cookies[DemoUserCookieName];
if (demoUserId == null)
{
demoUserId = _guidGenerator.Create().ToString();
}

SetDemoUserCookie(demoUserId);
httpContext.Items[DemoUserCookieName] = demoUserId;
return demoUserId;
}

private void SetDemoUserCookie(string value)
{
var option = new CookieOptions
{
Expires = DateTime.Now.AddMonths(12)
};

_httpContextAccessor.HttpContext?.Response.Cookies.Append(DemoUserCookieName, value, option);
}

private bool ShouldCreateDemoDatabase(string dbFilePath)
{
if (!File.Exists(dbFilePath))
{
return true;
}

return new FileInfo(dbFilePath!).Length <= 0;
}


private async Task CreateDemoDatabaseAsync(string newDbFilePath)
{
try
{
var defaultDbFilePath = GetDefaultDbFilePath();

//copy the existing db file to the target
File.Copy(defaultDbFilePath, newDbFilePath, overwrite: true);
}
catch (Exception ex)
{
//ignore
}
}

private string GetDefaultDbFilePath()
{
var dbFolder = _configuration["App:SqliteDbFolder"]?.EnsureEndsWith(Path.DirectorySeparatorChar);

return $"{dbFolder}{_configuration["App:DefaultDbName"]}.db";
}
}
}
4 changes: 3 additions & 1 deletion src/CmsKitDemo/Pages/Index.cshtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using CmsKitDemo.Localization
@using Volo.Abp.Data;
@inject IHtmlLocalizer<CmsKitDemoResource> L
@model CmsKitDemo.Pages.IndexModel
@inject IConnectionStringResolver ConnectionStringResolver

@section styles {
<abp-style src="/Pages/Index.cshtml.css" />
Expand Down Expand Up @@ -32,7 +34,7 @@
</div>
<div class="col-lg-9 col-md-7 col-12 d-flex align-items-center">
<div class="ps-md-3 text-center text-md-start">
<h6 class="mb-0">ABP Framework</h6>
<h6 class="mb-0">ABP Framework - @await ConnectionStringResolver.ResolveAsync()</h6>
<h1>CMS Kit Module</h1>
<p class="pd-title mb-4">This module provides CMS (Content Management System) capabilities for your application.</p>
<a href="https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Index" target="_blank" class="btn btn-primary btn-lg product-btn">Documentation</a>
Expand Down
Binary file added src/CmsKitDemo/sqliteDbs/CmsKitDemo.db
Binary file not shown.
7 changes: 7 additions & 0 deletions src/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
RUN apt-get update && apt-get install -y libgdiplus
WORKDIR /app
EXPOSE 80
COPY CmsKitDemo/bin/Release/publish .
COPY CmsKitDemo.db .
ENTRYPOINT ["dotnet", "CmsKitDemo.dll"]
19 changes: 19 additions & 0 deletions src/Dockerfile copy.azure
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS base
WORKDIR /src
COPY . .
RUN dotnet tool install -g Volo.Abp.Cli
ENV PATH="${PATH}:/root/.dotnet/tools"
WORKDIR /src/CmsKitDemo
RUN abp install-libs
RUN dotnet publish -c Release -o bin/Release/publish

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS final
RUN apt-get update && apt-get install -y libgdiplus
WORKDIR /app/sqliteDb
COPY --from=base /src/CmsKitDemo.db .
RUN chmod 666 CmsKitDemo.db
WORKDIR /app
EXPOSE 80
COPY --from=base /src/CmsKitDemo/bin/Release/publish .
ENV App__ConnectionStrings__Default="Data Source=/app/sqliteDb/CmsKitDemo.db;Version=3;"
ENTRYPOINT ["dotnet", "CmsKitDemo.dll"]
17 changes: 17 additions & 0 deletions src/Dockerfile.azure
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS base
WORKDIR /src
COPY . .
RUN dotnet tool install -g Volo.Abp.Cli --version 7.4.5
ENV PATH="${PATH}:/root/.dotnet/tools"
WORKDIR /src/CmsKitDemo
RUN abp install-libs
RUN dotnet publish -c Release -o bin/Release/publish

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS final
RUN apt-get update && apt-get install -y libgdiplus
WORKDIR /app
COPY --from=base /src/CmsKitDemo.db .
WORKDIR /app
EXPOSE 80
COPY --from=base /src/CmsKitDemo/bin/Release/publish .
ENTRYPOINT ["dotnet", "CmsKitDemo.dll"]
Loading

0 comments on commit f38d3ac

Please sign in to comment.