diff --git a/.vscode/launch.json b/.vscode/launch.json index a2be02b..cfb2a71 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,15 +4,26 @@ // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md "version": "0.2.0", "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/bin/Debug//", + "args": [], + "cwd": "${workspaceFolder}", + "stopAtEntry": false, + "console": "internalConsole" + }, { "name": ".NET Core Launch (web)", "type": "coreclr", "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/src/Host/IdentityServer.Dapper.Test/bin/Debug/netcoreapp2.1/IdentityServer.Dapper.Test.dll", + "program": "${workspaceFolder}/src/Host/IdentityServer4.Dapper.Host/bin/Debug/netcoreapp3.1/IdentityServer4.Dapper.Host.dll", "args": [], - "cwd": "${workspaceFolder}/src/Host/IdentityServer.Dapper.Test", + "cwd": "${workspaceFolder}/src/Host/IdentityServer4.Dapper.Host", "stopAtEntry": false, "internalConsoleOptions": "openOnSessionStart", "launchBrowser": { diff --git a/src/Host/IdentityServer4.Dapper.Host/IdentityServer4.Dapper.Host.csproj b/src/Host/IdentityServer4.Dapper.Host/IdentityServer4.Dapper.Host.csproj index 6ab44b3..46093ac 100644 --- a/src/Host/IdentityServer4.Dapper.Host/IdentityServer4.Dapper.Host.csproj +++ b/src/Host/IdentityServer4.Dapper.Host/IdentityServer4.Dapper.Host.csproj @@ -1,7 +1,7 @@ - netcoreapp2.2 + netcoreapp3.1 true Latest false @@ -10,8 +10,7 @@ - - + @@ -26,6 +25,7 @@ + diff --git a/src/Host/IdentityServer4.Dapper.Host/Startup.cs b/src/Host/IdentityServer4.Dapper.Host/Startup.cs index 7d771a8..e0f84fc 100644 --- a/src/Host/IdentityServer4.Dapper.Host/Startup.cs +++ b/src/Host/IdentityServer4.Dapper.Host/Startup.cs @@ -1,10 +1,12 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.SpaServices; +using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer; using IdentityServer4.Dapper.Extensions.MySql; +using IdentityServer4.Dapper.Extensions.PostgreSQL; using IdentityServer4.Dapper.Extensions; namespace IdentityServer4.Dapper.Host @@ -33,9 +35,10 @@ public void ConfigureServices(IServiceCollection services) }); services.AddIdentityServer() .AddDeveloperSigningCredential() - .AddMySQLProvider(option => + .AddPostgreSQLProvider(option => { - option.ConnectionString = "server=.;uid=darinhan;pwd=darinhan;database=identityserver4;SslMode=None;"; + //option.ConnectionString = "server=.;uid=darinhan;pwd=darinhan;database=identityserver4;SslMode=None;"; + option.ConnectionString = "Host=localhost;Port=32676;Username=postgresadmin;Password=admin123;Database=postgresdb;Minimum Pool Size=5;Search Path=identityserver"; }) .AddConfigurationStore() .AddOperationalStore(option => @@ -44,7 +47,9 @@ public void ConfigureServices(IServiceCollection services) option.TokenCleanupInterval = 10; }); - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + services.AddMvc(options => { + options.EnableEndpointRouting = false; + }); // In production, the React files will be served from this directory services.AddSpaStaticFiles(configuration => @@ -54,9 +59,9 @@ public void ConfigureServices(IServiceCollection services) } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { - if (env.IsDevelopment()) + if (env.EnvironmentName.Equals("Development")) { app.UseDeveloperExceptionPage(); } @@ -81,10 +86,10 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) { spa.Options.SourcePath = "ClientApp"; - spa.UseProxyToSpaDevelopmentServer("http://localhost:7012"); + //spa.UseProxyToSpaDevelopmentServer("http://localhost:7012"); //if (env.IsDevelopment()) //{ - // spa.UseReactDevelopmentServer(npmScript: "start"); + spa.UseReactDevelopmentServer(npmScript: "start"); //} }); } diff --git "a/src/Host/IdentityServer4.Dapper.Host/c:\\www.log\\IdentityServer4.Dapper.Host\\internal-nlog.txt" "b/src/Host/IdentityServer4.Dapper.Host/c:\\www.log\\IdentityServer4.Dapper.Host\\internal-nlog.txt" new file mode 100644 index 0000000..e16caaf --- /dev/null +++ "b/src/Host/IdentityServer4.Dapper.Host/c:\\www.log\\IdentityServer4.Dapper.Host\\internal-nlog.txt" @@ -0,0 +1,18 @@ +2020-09-23 16:07:10.0701 Info Message Template Auto Format enabled +2020-09-23 16:07:10.0917 Info Loading assembly: NLog.Web.AspNetCore +2020-09-23 16:07:10.1533 Info Adding target File Target[allfile] +2020-09-23 16:07:10.1686 Info Adding target File Target[ownFile-web] +2020-09-23 16:07:10.1741 Info Configured from an XML element in /Users/henry/Develop/IdentityServer4.Dapper/src/Host/IdentityServer4.Dapper.Host/bin/Debug/netcoreapp3.1/nlog.config... +2020-09-23 16:07:10.1870 Info Found 47 configuration items +2020-09-23 16:07:49.6776 Info Message Template Auto Format enabled +2020-09-23 16:07:49.6988 Info Loading assembly: NLog.Web.AspNetCore +2020-09-23 16:07:49.7595 Info Adding target File Target[allfile] +2020-09-23 16:07:49.7691 Info Adding target File Target[ownFile-web] +2020-09-23 16:07:49.7747 Info Configured from an XML element in /Users/henry/Develop/IdentityServer4.Dapper/src/Host/IdentityServer4.Dapper.Host/bin/Debug/netcoreapp3.1/nlog.config... +2020-09-23 16:07:49.7860 Info Found 47 configuration items +2020-09-23 16:15:27.0388 Info Message Template Auto Format enabled +2020-09-23 16:15:27.0683 Info Loading assembly: NLog.Web.AspNetCore +2020-09-23 16:15:27.1527 Info Adding target File Target[allfile] +2020-09-23 16:15:27.1661 Info Adding target File Target[ownFile-web] +2020-09-23 16:15:27.1728 Info Configured from an XML element in /Users/henry/Develop/IdentityServer4.Dapper/src/Host/IdentityServer4.Dapper.Host/bin/Debug/netcoreapp3.1/nlog.config... +2020-09-23 16:15:27.1870 Info Found 47 configuration items diff --git a/src/IdentityServer.Dapper.xUnitTest/IdentityServer.Dapper.xUnitTest.csproj b/src/IdentityServer.Dapper.xUnitTest/IdentityServer.Dapper.xUnitTest.csproj index e5faa96..895d56f 100644 --- a/src/IdentityServer.Dapper.xUnitTest/IdentityServer.Dapper.xUnitTest.csproj +++ b/src/IdentityServer.Dapper.xUnitTest/IdentityServer.Dapper.xUnitTest.csproj @@ -1,7 +1,7 @@  - netcoreapp2.2 + netcoreapp3.1 false @@ -9,7 +9,7 @@ - + @@ -17,6 +17,7 @@ + diff --git a/src/IdentityServer.Dapper.xUnitTest/xTestBase.cs b/src/IdentityServer.Dapper.xUnitTest/xTestBase.cs index 9569205..73865eb 100644 --- a/src/IdentityServer.Dapper.xUnitTest/xTestBase.cs +++ b/src/IdentityServer.Dapper.xUnitTest/xTestBase.cs @@ -1,5 +1,6 @@ using MySqlN = IdentityServer4.Dapper.Extensions.MySql; using MSSqlN = IdentityServer4.Dapper.Extensions.MSSql; +using PostgreSqlN = IdentityServer4.Dapper.Extensions.PostgreSQL; using IdentityServer4.Dapper.Options; using System; using System.Collections.Generic; @@ -14,6 +15,7 @@ class xTestBase { public const string MSSQL = "MSSQL"; public const string MySQL = "MySQL"; + public const string PostgreSQL = "PostgreSQL"; public static DBProviderOptions GetDBProviderOptions(string type) { @@ -21,12 +23,19 @@ public static DBProviderOptions GetDBProviderOptions(string type) if (type == MySQL) { options = MySqlN.IdentityServerDapperDBExtensions.GetDefaultOptions(); - options.ConnectionString = "server=10.40.0.190;uid=changyin.han;pwd=fjfhhan07;database=identityserver4dev;SslMode=None;"; + //options.ConnectionString = "server=10.40.0.190;uid=changyin.han;pwd=fjfhhan07;database=identityserver4dev;SslMode=None;"; + options.ConnectionString = "server=localhost;uid=idadmin;pwd=admin123;database=identityserver;SslMode=None;"; } else if (type == MSSQL) { options = MSSqlN.IdentityServerDapperDBExtensions.GetDefaultOptions(); - options.ConnectionString = "server=10.40.0.190;uid=sa;pwd=Onesmart190;database=identityserver4;"; + //options.ConnectionString = "server=10.40.0.190;uid=sa;pwd=Onesmart190;database=identityserver4;"; + options.ConnectionString = "server=localhost;uid=sa;pwd=Saiahcsep2020@;database=identityserver;"; + } + else if (type == PostgreSQL) + { + options = PostgreSqlN.IdentityServerDapperDBExtensions.GetDefaultOptions(); + options.ConnectionString = "Host=localhost;Port=32676;Username=postgresadmin;Password=admin123;Database=postgresdb;Minimum Pool Size=5;Search Path=identityserver"; } return options; diff --git a/src/IdentityServer.Dapper.xUnitTest/xTestDefaultApiResourceProvider.cs b/src/IdentityServer.Dapper.xUnitTest/xTestDefaultApiResourceProvider.cs index bce0033..6dabc4b 100644 --- a/src/IdentityServer.Dapper.xUnitTest/xTestDefaultApiResourceProvider.cs +++ b/src/IdentityServer.Dapper.xUnitTest/xTestDefaultApiResourceProvider.cs @@ -23,6 +23,7 @@ private DefaultApiResourceProvider GetDefaultApiResourceProvider(string sqltype) [Theory] [InlineData(xTestBase.MSSQL)] [InlineData(xTestBase.MySQL)] + [InlineData(xTestBase.PostgreSQL)] public void TestAddFind(string sqltype) { var provider = GetDefaultApiResourceProvider(sqltype); @@ -47,6 +48,7 @@ public void TestAddFind(string sqltype) [Theory] [InlineData(xTestBase.MSSQL)] [InlineData(xTestBase.MySQL)] + [InlineData(xTestBase.PostgreSQL)] public void TestRemove(string sqltype) { var provider = GetDefaultApiResourceProvider(sqltype); @@ -99,6 +101,7 @@ public void TestRemove(string sqltype) [Theory] [InlineData(xTestBase.MSSQL)] [InlineData(xTestBase.MySQL)] + [InlineData(xTestBase.PostgreSQL)] public void TestUpdate(string sqltype) { var provider = GetDefaultApiResourceProvider(sqltype); @@ -187,6 +190,7 @@ public void TestUpdate(string sqltype) [Theory] [InlineData(xTestBase.MSSQL)] [InlineData(xTestBase.MySQL)] + [InlineData(xTestBase.PostgreSQL)] public void TestFindAll(string sqltype) { var provider = GetDefaultApiResourceProvider(sqltype); @@ -209,6 +213,7 @@ public void TestFindAll(string sqltype) [Theory] [InlineData(xTestBase.MSSQL)] [InlineData(xTestBase.MySQL)] + [InlineData(xTestBase.PostgreSQL)] public void TestFindApiResourcesByScope(string sqltype) { var provider = GetDefaultApiResourceProvider(sqltype); @@ -240,6 +245,7 @@ public void TestFindApiResourcesByScope(string sqltype) [Theory] [InlineData(xTestBase.MSSQL)] [InlineData(xTestBase.MySQL)] + [InlineData(xTestBase.PostgreSQL)] public void TestSearch(string sqltype) { var provider = GetDefaultApiResourceProvider(sqltype); diff --git a/src/IdentityServer.Dapper.xUnitTest/xTestPostgreSQL.cs b/src/IdentityServer.Dapper.xUnitTest/xTestPostgreSQL.cs new file mode 100644 index 0000000..87dd0bd --- /dev/null +++ b/src/IdentityServer.Dapper.xUnitTest/xTestPostgreSQL.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; +using Dapper; + +namespace IdentityServer.Dapper.xUnitTest +{ + public class xTestPostgreSQL + { + [Fact] + public void TestGetPageQuerySQL() + { + var options = xTestBase.GetDBProviderOptions(xTestBase.PostgreSQL); + int pageIndex = 1; + int pageSize = 10; + int totalCount = 499; + string orderby = "order by id"; + DynamicParameters dynamicParameters = new DynamicParameters(); + + string pagedsql = options.GetPageQuerySQL("select * from ApiResources where 1 = 1", pageIndex, pageSize, totalCount, orderby, dynamicParameters); + + Assert.False(string.IsNullOrEmpty(pagedsql)); + Assert.Equal("select * from ApiResources where 1 = 1 order by id limit @size offset @start", pagedsql); + } + } +} diff --git a/src/IdentityServer4.Dapper.MSSql/IdentityServerDapperExtensions.cs b/src/IdentityServer4.Dapper.MSSql/IdentityServerDapperExtensions.cs index 5ec6c68..6dba27f 100644 --- a/src/IdentityServer4.Dapper.MSSql/IdentityServerDapperExtensions.cs +++ b/src/IdentityServer4.Dapper.MSSql/IdentityServerDapperExtensions.cs @@ -25,6 +25,8 @@ public static DBProviderOptions GetDefaultOptions() options.ColumnProtect = new System.Collections.Generic.Dictionary(); options.ColumnProtect.Add("left", "["); options.ColumnProtect.Add("right", "]"); + options.GetInArray = " in "; + options.GetPageQuerySQL = (input, pageindex, pagesize, totalcount, orderby, pairs) => { int pagestart = 0; diff --git a/src/IdentityServer4.Dapper.Mysql/IdentityServer4.Dapper.Mysql.csproj b/src/IdentityServer4.Dapper.Mysql/IdentityServer4.Dapper.Mysql.csproj index 738891a..92062da 100644 --- a/src/IdentityServer4.Dapper.Mysql/IdentityServer4.Dapper.Mysql.csproj +++ b/src/IdentityServer4.Dapper.Mysql/IdentityServer4.Dapper.Mysql.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/IdentityServer4.Dapper.Mysql/IdentityServerDapperExtensions.cs b/src/IdentityServer4.Dapper.Mysql/IdentityServerDapperExtensions.cs index 5540be9..7d99883 100644 --- a/src/IdentityServer4.Dapper.Mysql/IdentityServerDapperExtensions.cs +++ b/src/IdentityServer4.Dapper.Mysql/IdentityServerDapperExtensions.cs @@ -28,6 +28,7 @@ public static DBProviderOptions GetDefaultOptions() options.ColumnProtect = new System.Collections.Generic.Dictionary(); options.ColumnProtect.Add("left", "`"); options.ColumnProtect.Add("right", "`"); + options.GetInArray = " in "; //add singgleton options.GetPageQuerySQL = (input, pageindex, pagesize, totalcount, orderby, pairs) => { diff --git a/src/IdentityServer4.Dapper.PostgreSQL/IdentityServer4.Dapper.PostgreSQL.csproj b/src/IdentityServer4.Dapper.PostgreSQL/IdentityServer4.Dapper.PostgreSQL.csproj new file mode 100644 index 0000000..feb2a8e --- /dev/null +++ b/src/IdentityServer4.Dapper.PostgreSQL/IdentityServer4.Dapper.PostgreSQL.csproj @@ -0,0 +1,19 @@ + + + + netstandard2.0 + Darin.IdentityServer4.Dapper.PostgreSQL + Darin Han + IdentityServer4.Dapper.PostgreSQL + 1.0.5 + + + + + + + + + + + diff --git a/src/IdentityServer4.Dapper.PostgreSQL/IdentityServerDapperExtensions.cs b/src/IdentityServer4.Dapper.PostgreSQL/IdentityServerDapperExtensions.cs new file mode 100644 index 0000000..cf51628 --- /dev/null +++ b/src/IdentityServer4.Dapper.PostgreSQL/IdentityServerDapperExtensions.cs @@ -0,0 +1,63 @@ +using IdentityServer4.Dapper.Options; +using Microsoft.Extensions.DependencyInjection; +using System; +using Npgsql; +using System.Linq; + +namespace IdentityServer4.Dapper.Extensions.PostgreSQL +{ + public static class IdentityServerDapperDBExtensions + { + public static IIdentityServerBuilder AddPostgreSQLProvider(this IIdentityServerBuilder builder, Action dbProviderOptionsAction = null) + { + var options = GetDefaultOptions(); + dbProviderOptionsAction?.Invoke(options); + builder.Services.AddSingleton(options); + return builder; + } + + public static DBProviderOptions GetDefaultOptions() + { + //config mysql + var options = new DBProviderOptions(); + options.DbProviderFactory = NpgsqlFactory.Instance; + //get last insert id for insert actions + options.GetLastInsertID = "select LASTVAL();"; + //config the ColumnName protect string, postgresql using "" + options.ColumnProtect = new System.Collections.Generic.Dictionary(); + options.ColumnProtect.Add("left", ""); + options.ColumnProtect.Add("right", ""); + options.GetInArray = " = ANY "; + //add singgleton + options.GetPageQuerySQL = (input, pageindex, pagesize, totalcount, orderby, pairs) => + { + string limitsql = string.Empty; + if (pagesize > 0) + { + if (pagesize > totalcount) + { + pagesize = totalcount; + } + pairs.Add("start", (pageindex - 1) * pagesize); + pairs.Add("size", pagesize); + limitsql = "limit @size offset @start"; + } + + if (input.IndexOf("order by", StringComparison.CurrentCultureIgnoreCase) >= 0) + { + orderby = ""; + } + else + { + if (!string.IsNullOrWhiteSpace(orderby) && orderby.IndexOf("order by", StringComparison.CurrentCultureIgnoreCase) < 0) + { + orderby = "order by " + orderby; + } + } + + return $"{input} {orderby} {limitsql}"; + }; + return options; + } + } +} diff --git a/src/IdentityServer4.Dapper.sln b/src/IdentityServer4.Dapper.sln index 06e6305..03232e4 100644 --- a/src/IdentityServer4.Dapper.sln +++ b/src/IdentityServer4.Dapper.sln @@ -31,6 +31,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mysql", "Mysql", "{5E826446 SQL\Mysql\PersistedGrantDb.txt = SQL\Mysql\PersistedGrantDb.txt EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdentityServer4.Dapper.PostgreSQL", "IdentityServer4.Dapper.PostgreSQL\IdentityServer4.Dapper.PostgreSQL.csproj", "{B3AD41DE-295F-481A-8CB1-1CA13D3B963D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +59,10 @@ Global {3AABE11E-5D02-4C0A-B6B8-C1A4EE48563A}.Debug|Any CPU.Build.0 = Debug|Any CPU {3AABE11E-5D02-4C0A-B6B8-C1A4EE48563A}.Release|Any CPU.ActiveCfg = Release|Any CPU {3AABE11E-5D02-4C0A-B6B8-C1A4EE48563A}.Release|Any CPU.Build.0 = Release|Any CPU + {B3AD41DE-295F-481A-8CB1-1CA13D3B963D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B3AD41DE-295F-481A-8CB1-1CA13D3B963D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3AD41DE-295F-481A-8CB1-1CA13D3B963D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B3AD41DE-295F-481A-8CB1-1CA13D3B963D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/IdentityServer4.Dapper/DefaultProviders/DefaultApiResourceProvider.cs b/src/IdentityServer4.Dapper/DefaultProviders/DefaultApiResourceProvider.cs index e4ce3fd..2a98622 100644 --- a/src/IdentityServer4.Dapper/DefaultProviders/DefaultApiResourceProvider.cs +++ b/src/IdentityServer4.Dapper/DefaultProviders/DefaultApiResourceProvider.cs @@ -19,6 +19,7 @@ public class DefaultApiResourceProvider : IApiResourceProvider private readonly ILogger _logger; private string left; private string right; + private string inArray; private readonly IDistributedCache _cache; private static volatile object locker = new object(); @@ -29,6 +30,7 @@ public DefaultApiResourceProvider(DBProviderOptions dBProviderOptions, ILogger FindApiResourcesAll() + public IList FindApiResourcesAll() { using (var connection = _options.DbProviderFactory.CreateConnection()) { @@ -147,7 +149,7 @@ public IEnumerable FindApiResourcesAll() } } - return apilist.Select(c => c.ToModel()); + return apilist.Select(c => c.ToModel()).ToList(); } } #endregion @@ -259,7 +261,7 @@ public void Remove(string name) #endregion #region Search - public IEnumerable Search(string keywords, int pageIndex, int pageSize, out int totalCount) + public IList Search(string keywords, int pageIndex, int pageSize, out int totalCount) { using (var connection = _options.DbProviderFactory.CreateConnection()) { @@ -279,7 +281,7 @@ public IEnumerable Search(string keywords, int pageIndex, int pageS var apis = connection.Query(_options.GetPageQuerySQL("select * from ApiResources where Name like @keywords or DisplayName like @keywords or Description like @keywords", pageIndex, pageSize, totalCount, "", pairs), pairs, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text); if (apis != null) { - return apis.Select(c => c.ToModel()); + return apis.Select(c => c.ToModel()).ToList(); } return null; } @@ -330,7 +332,7 @@ public void Update(ApiResource apiResource) #region 子属性 #region ApiScope - public IEnumerable GetScopesByApiResourceId(int apiresourceid) + public IList GetScopesByApiResourceId(int apiresourceid) { using (var con = _options.DbProviderFactory.CreateConnection()) { @@ -339,9 +341,9 @@ public void Update(ApiResource apiResource) } } - public IEnumerable GetScopesByApiResourceId(int apiresourceid, IDbConnection con, IDbTransaction t) + public IList GetScopesByApiResourceId(int apiresourceid, IDbConnection con, IDbTransaction t) { - var scopes = con.Query("select * from ApiScopes where ApiResourceId = @ApiResourceId", new { ApiResourceId = apiresourceid }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t); + var scopes = con.Query("select * from ApiScopes where ApiResourceId = @ApiResourceId", new { ApiResourceId = apiresourceid }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t).ToList(); if (scopes != null && scopes.Count() > 0) { var scopeclaims = con.Query("select ApiScopeClaims.* from ApiScopes inner join ApiScopeClaims on ApiScopes.id = ApiScopeClaims.ApiScopeId where ApiResourceId = @ApiResourceId", new { ApiResourceId = apiresourceid }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t); @@ -356,7 +358,7 @@ public void Update(ApiResource apiResource) return scopes; } - public IEnumerable FindApiResourcesByScope(IEnumerable scopeNames) + public IList FindApiResourcesByScope(IList scopeNames) { if (scopeNames == null || scopeNames.Count() == 0) { @@ -365,7 +367,7 @@ public IEnumerable FindApiResourcesByScope(IEnumerable scop var names = scopeNames.ToArray(); var lstall = FindApiResourcesAll(); - return lstall.Where(c => c.Scopes.Where(s => names.Contains(s.Name)).Any()).AsEnumerable(); + return lstall.Where(c => c.Scopes.Where(s => names.Contains(s.Name)).Any()).ToList(); } public void UpdateScopesByApiResourceId(ApiResource apiResource) @@ -395,7 +397,7 @@ public void UpdateScopesByApiResourceId(ApiResource apiResource) } } } - private void InsertApiScopeByApiResourceId(IEnumerable apiScopes, int apiResourceId, IDbConnection con, IDbTransaction t) + private void InsertApiScopeByApiResourceId(IList apiScopes, int apiResourceId, IDbConnection con, IDbTransaction t) { if (apiScopes.IsEmpty()) { @@ -440,20 +442,25 @@ private void RemoveApiScopeByApiResourceId(int apiResourceId, IDbConnection con, ApiResourceId = apiResourceId }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t); } - private void RemoveApiScopes(IEnumerable apiScopes, IDbConnection con, IDbTransaction t) + private void RemoveApiScopes(IList apiScopes, IDbConnection con, IDbTransaction t) { - con.Execute($"delete from ApiScopeClaims where ApiScopeId in (@ApiScopeIds);", new + if ( apiScopes.IsEmpty() ) { - ApiScopeIds = apiScopes.Select(c => c.Id) + return; + } + + con.Execute($"delete from ApiScopeClaims where ApiScopeId {inArray}(@ApiScopeIds);", new + { + ApiScopeIds = apiScopes.Select(c => c.Id).ToList() }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t); - con.Execute($"delete from ApiScopes where id in (@ApiResourceIds);", new + con.Execute($"delete from ApiScopes where id {inArray}(@ApiResourceIds);", new { - ApiResourceIds = apiScopes.Select(c => c.Id) + ApiResourceIds = apiScopes.Select(c => c.Id).ToList() }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t); } - private void UpdateScopesByApiResourceId(IEnumerable apiScopes, int apiId, IDbConnection con, IDbTransaction t) + private void UpdateScopesByApiResourceId(IList apiScopes, int apiId, IDbConnection con, IDbTransaction t) { if (apiScopes.IsEmpty()) { @@ -467,13 +474,13 @@ private void UpdateScopesByApiResourceId(IEnumerable apiScope } //find deleted - var deleteds = dbitems.Where(c => !apiScopes.ToList().Exists(d => d.Name == c.Name)); + var deleteds = dbitems.Where(c => !apiScopes.ToList().Exists(d => d.Name == c.Name)).ToList(); RemoveApiScopes(deleteds, con, t); //find new - var addeds = apiScopes?.Where(c => !dbitems.ToList().Exists(d => d.Name == c.Name)); + var addeds = apiScopes?.Where(c => !dbitems.ToList().Exists(d => d.Name == c.Name)).ToList(); InsertApiScopeByApiResourceId(addeds, apiId, con, t); //find updated - var updateds = dbitems.Where(c => apiScopes.ToList().Exists(d => d.Name == c.Name)); + var updateds = dbitems.Where(c => apiScopes.ToList().Exists(d => d.Name == c.Name)).ToList(); if (updateds.IsEmpty()) { return; @@ -527,7 +534,7 @@ private void UpdateScopesByApiResourceId(IEnumerable apiScope #endregion #region Claim - public IEnumerable GetClaimsByAPIID(int apiresourceid) + public IList GetClaimsByAPIID(int apiresourceid) { using (var con = _options.DbProviderFactory.CreateConnection()) { @@ -536,9 +543,9 @@ private void UpdateScopesByApiResourceId(IEnumerable apiScope } } - public IEnumerable GetClaimsByAPIID(int apiresourceid, IDbConnection con, IDbTransaction t) + public IList GetClaimsByAPIID(int apiresourceid, IDbConnection con, IDbTransaction t) { - return con.Query("select * from ApiClaims where ApiResourceId = @ApiResourceId", new { ApiResourceId = apiresourceid }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t); + return con.Query("select * from ApiClaims where ApiResourceId = @ApiResourceId", new { ApiResourceId = apiresourceid }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t).ToList(); } private void InsertApiResourceClaim(Entities.ApiResourceClaim item, int apiresourceid, IDbConnection con, IDbTransaction t) @@ -554,7 +561,7 @@ private void InsertApiResourceClaim(Entities.ApiResourceClaim item, int apiresou } } - public void UpdateClaimsByApiResourceId(IEnumerable apiResourceClaims, int apiresourceid, IDbConnection con, IDbTransaction t) + public void UpdateClaimsByApiResourceId(IList apiResourceClaims, int apiresourceid, IDbConnection con, IDbTransaction t) { var dbitems = GetClaimsByAPIID(apiresourceid, con, t); if (dbitems != null) @@ -576,7 +583,7 @@ public void UpdateClaimsByApiResourceId(IEnumerable a { return; } - foreach (var item in apiResourceClaims.Where(c => !dbitems.ToList().Exists(d => d.Type == c.Type))) + foreach (var item in apiResourceClaims.Where(c => !dbitems.ToList().Exists(d => d.Type == c.Type)).ToList()) { InsertApiResourceClaim(item, apiresourceid, con, t); } @@ -612,7 +619,7 @@ public void UpdateClaimsByApiResourceId(ApiResource apiResource) #endregion #region ApiSecrets - public IEnumerable GetSecretByApiResourceId(int apiresourceid) + public IList GetSecretByApiResourceId(int apiresourceid) { using (var con = _options.DbProviderFactory.CreateConnection()) { @@ -622,9 +629,9 @@ public void UpdateClaimsByApiResourceId(ApiResource apiResource) } } - private IEnumerable GetSecretByApiResourceId(int apiresourceid, IDbConnection con, IDbTransaction t) + private IList GetSecretByApiResourceId(int apiresourceid, IDbConnection con, IDbTransaction t) { - return con.Query("select * from apisecrets where ApiResourceId = @ApiResourceId", new { ApiResourceId = apiresourceid }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t); + return con.Query("select * from ApiSecrets where ApiResourceId = @ApiResourceId", new { ApiResourceId = apiresourceid }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text, transaction: t).ToList(); } @@ -645,7 +652,7 @@ private void InsertApiSecretsByApiResourceId(Entities.ApiSecret item, int apires } - public void UpdateApiSecretsByApiResourceId(IEnumerable apiSecrets, int apiresourceid, IDbConnection con, IDbTransaction t) + public void UpdateApiSecretsByApiResourceId(IList apiSecrets, int apiresourceid, IDbConnection con, IDbTransaction t) { var dbitems = GetSecretByApiResourceId(apiresourceid); if (dbitems != null) @@ -679,7 +686,7 @@ public void UpdateApiSecretsByApiResourceId(IEnumerable apiS } if (!apiSecrets.IsEmpty()) { - foreach (var item in apiSecrets.Where(c => !dbitems.ToList().Exists(d => d.Type == c.Type && d.Value == c.Value))) + foreach (var item in apiSecrets.Where(c => !dbitems.ToList().Exists(d => d.Type == c.Type && d.Value == c.Value)).ToList()) { InsertApiSecretsByApiResourceId(item, apiresourceid, con, t); } diff --git a/src/IdentityServer4.Dapper/DefaultProviders/DefaultPersistedGrantProvider.cs b/src/IdentityServer4.Dapper/DefaultProviders/DefaultPersistedGrantProvider.cs index 7ea4347..864bef1 100644 --- a/src/IdentityServer4.Dapper/DefaultProviders/DefaultPersistedGrantProvider.cs +++ b/src/IdentityServer4.Dapper/DefaultProviders/DefaultPersistedGrantProvider.cs @@ -65,7 +65,7 @@ public PersistedGrant Get(string key) { connection.ConnectionString = _options.ConnectionString; - persistedGrant = connection.QueryFirstOrDefault($"select * from persistedgrants where {left}Key{right} = @Key", new { Key = key }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text); + persistedGrant = connection.QueryFirstOrDefault($"select * from PersistedGrants where {left}Key{right} = @Key", new { Key = key }, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text); } return persistedGrant?.ToModel(); } @@ -263,7 +263,7 @@ public IEnumerable Search(string keywords, int pageIndex, int pa DynamicParameters pairs = new DynamicParameters(); pairs.Add("keywords", "%" + keywords + "%"); - var countsql = $"select count(1) from persistedgrants where {left}Key{right} like @keywords or ClientId like @keywords or SubjectId like @keywords OR {left}Type{right} like @keywords"; + var countsql = $"select count(1) from PersistedGrants where {left}Key{right} like @keywords or ClientId like @keywords or SubjectId like @keywords OR {left}Type{right} like @keywords"; totalCount = connection.ExecuteScalar(countsql, pairs, commandType: CommandType.Text); if (totalCount == 0) @@ -271,7 +271,7 @@ public IEnumerable Search(string keywords, int pageIndex, int pa return null; } - var clients = connection.Query(_options.GetPageQuerySQL($"select * from persistedgrants where {left}Key{right} like @keywords or ClientId like @keywords or SubjectId like @keywords OR {left}Type{right} like @keywords", pageIndex, pageSize, totalCount, $"order by {left}Key{right}", pairs), pairs, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text); + var clients = connection.Query(_options.GetPageQuerySQL($"select * from PersistedGrants where {left}Key{right} like @keywords or ClientId like @keywords or SubjectId like @keywords OR {left}Type{right} like @keywords", pageIndex, pageSize, totalCount, $"order by {left}Key{right}", pairs), pairs, commandTimeout: _options.CommandTimeOut, commandType: CommandType.Text); if (clients != null) { return clients.Select(c => c.ToModel()); diff --git a/src/IdentityServer4.Dapper/Interfaces/IApiResourceProvider.cs b/src/IdentityServer4.Dapper/Interfaces/IApiResourceProvider.cs index ad9da66..021b6ca 100644 --- a/src/IdentityServer4.Dapper/Interfaces/IApiResourceProvider.cs +++ b/src/IdentityServer4.Dapper/Interfaces/IApiResourceProvider.cs @@ -9,9 +9,9 @@ public interface IApiResourceProvider { ApiResource FindApiResource(string name); - IEnumerable FindApiResourcesByScope(IEnumerable scopeNames); + IList FindApiResourcesByScope(IList scopeNames); - IEnumerable FindApiResourcesAll(); + IList FindApiResourcesAll(); void Add(ApiResource apiResource); /// @@ -37,7 +37,7 @@ public interface IApiResourceProvider void Remove(string name); - IEnumerable Search(string keywords, int pageIndex, int pageSize, out int totalCount); + IList Search(string keywords, int pageIndex, int pageSize, out int totalCount); } } diff --git a/src/IdentityServer4.Dapper/Options/DBProviderOptions.cs b/src/IdentityServer4.Dapper/Options/DBProviderOptions.cs index 41c7a18..cb3d331 100644 --- a/src/IdentityServer4.Dapper/Options/DBProviderOptions.cs +++ b/src/IdentityServer4.Dapper/Options/DBProviderOptions.cs @@ -45,5 +45,12 @@ public class DBProviderOptions /// string:paged sql returned /// public Func GetPageQuerySQL { get; set; } + + + /// + /// Get SQL For in array. + /// + public string GetInArray { get; set; } + } } diff --git a/src/IdentityServer4.Dapper/Stores/ResourceStore.cs b/src/IdentityServer4.Dapper/Stores/ResourceStore.cs index a7fde27..9bfcc8a 100644 --- a/src/IdentityServer4.Dapper/Stores/ResourceStore.cs +++ b/src/IdentityServer4.Dapper/Stores/ResourceStore.cs @@ -43,7 +43,7 @@ public Task FindApiResourceAsync(string name) public Task> FindApiResourcesByScopeAsync(IEnumerable scopeNames) { - var models = _apiResource.FindApiResourcesByScope(scopeNames).AsEnumerable(); + var models = _apiResource.FindApiResourcesByScope(scopeNames.ToList()).AsEnumerable(); _logger.LogDebug("Found {scopes} API scopes in database", models.SelectMany(x => x.Scopes).Select(x => x.Name)); return Task.FromResult(models); } diff --git a/src/SQL/PostgreSQL/ConfigurationDb.txt b/src/SQL/PostgreSQL/ConfigurationDb.txt new file mode 100644 index 0000000..4692531 --- /dev/null +++ b/src/SQL/PostgreSQL/ConfigurationDb.txt @@ -0,0 +1,175 @@ +-- for mysql + +CREATE TABLE ApiResources ( + Id SERIAL PRIMARY KEY, + Description varchar(1000) NULL, + DisplayName varchar(200) NULL, + Enabled bool NOT NULL, + Name varchar(200) NOT NULL +); + + +CREATE TABLE Clients ( + Id SERIAL primary key, + AbsoluteRefreshTokenLifetime int NOT NULL, + AccessTokenLifetime int NOT NULL, + AccessTokenType int NOT NULL, + AllowAccessTokensViaBrowser bool NOT NULL, + AllowOfflineAccess bool NOT NULL, + AllowPlainTextPkce bool NOT NULL, + AllowRememberConsent bool NOT NULL, + AlwaysIncludeUserClaimsInIdToken bool NOT NULL, + AlwaysSendClientClaims bool NOT NULL, + AuthorizationCodeLifetime int NOT NULL, + BackChannelLogoutSessionRequired bool NOT NULL, + BackChannelLogoutUri varchar(2000) NULL, + ClientClaimsPrefix varchar(200) NULL, + ClientId varchar(200) NOT NULL, + ClientName varchar(200) NULL, + ClientUri varchar(2000) NULL, + ConsentLifetime int NULL, + Description varchar(1000) NULL, + EnableLocalLogin bool NOT NULL, + Enabled bool NOT NULL, + FrontChannelLogoutSessionRequired bool NOT NULL, + FrontChannelLogoutUri varchar(2000) NULL, + IdentityTokenLifetime int NOT NULL, + IncludeJwtId bool NOT NULL, + LogoUri varchar(2000) NULL, + PairWiseSubjectSalt varchar(200) NULL, + ProtocolType varchar(200) NOT NULL, + RefreshTokenExpiration int NOT NULL, + RefreshTokenUsage int NOT NULL, + RequireClientSecret bool NOT NULL, + RequireConsent bool NOT NULL, + RequirePkce bool NOT NULL, + SlidingRefreshTokenLifetime int NOT NULL, + UpdateAccessTokenClaimsOnRefresh bool NOT NULL +); + +CREATE TABLE IdentityResources ( + Id SERIAL primary key, + Description varchar(1000) NULL, + DisplayName varchar(200) NULL, + Emphasize bool NOT NULL, + Enabled bool NOT NULL, + Name varchar(200) NOT NULL, + Required bool NOT NULL, + ShowInDiscoveryDocument bool NOT NULL +); + +CREATE TABLE ApiClaims ( + Id SERIAL primary key, + ApiResourceId int NOT NULL, + Type varchar(200) NOT NULL +); + +CREATE TABLE ApiScopes ( + Id SERIAL primary key, + ApiResourceId int NOT NULL, + Description varchar(1000) NULL, + DisplayName varchar(200) NULL, + Emphasize bool NOT NULL, + Name varchar(200) NOT NULL, + Required bool NOT NULL, + ShowInDiscoveryDocument bool NOT NULL +); + +CREATE TABLE ApiSecrets ( + Id SERIAL primary key, + ApiResourceId int NOT NULL, + Description varchar(1000) NULL, + Expiration timestamp NULL, + Type varchar(250) NULL, + Value varchar(2000) NULL +); + +CREATE TABLE ClientClaims ( + Id SERIAL primary key, + ClientId int NOT NULL, + Type varchar(250) NOT NULL, + Value varchar(250) NOT NULL +); + + +CREATE TABLE ClientCorsOrigins ( + Id SERIAL primary key, + ClientId int NOT NULL, + Origin varchar(150) NOT NULL +); + + + +CREATE TABLE ClientGrantTypes ( + Id SERIAL primary key, + ClientId int NOT NULL, + GrantType varchar(250) NOT NULL +); + + + +CREATE TABLE ClientIdPRestrictions ( + Id SERIAL primary key, + ClientId int NOT NULL, + Provider varchar(200) NOT NULL +); + + +CREATE TABLE ClientPostLogoutRedirectUris ( + Id SERIAL primary key, + ClientId int NOT NULL, + PostLogoutRedirectUri varchar(2000) NOT NULL +); + + + +CREATE TABLE ClientProperties ( + Id SERIAL primary key, + ClientId int NOT NULL, + Key varchar(250) NOT NULL, + Value varchar(2000) NOT NULL +); + + + +CREATE TABLE ClientRedirectUris ( + Id SERIAL primary key, + ClientId int NOT NULL, + RedirectUri varchar(2000) NOT NULL +); + + + +CREATE TABLE ClientScopes ( + Id SERIAL primary key, + ClientId int NOT NULL, + Scope varchar(200) NOT NULL +); + + + +CREATE TABLE ClientSecrets ( + Id SERIAL primary key, + ClientId int NOT NULL, + Description varchar(2000) NULL, + Expiration timestamp NULL, + Type varchar(250) NULL, + Value varchar(2000) NOT NULL +); + + + +CREATE TABLE IdentityClaims ( + Id SERIAL primary key, + IdentityResourceId int NOT NULL, + Type varchar(200) NOT NULL +); + + + +CREATE TABLE ApiScopeClaims ( + Id SERIAL primary key, + ApiScopeId int NOT NULL, + Type varchar(200) NOT NULL +); + diff --git a/src/SQL/PostgreSQL/PersistedGrantDb.txt b/src/SQL/PostgreSQL/PersistedGrantDb.txt new file mode 100644 index 0000000..ad92f86 --- /dev/null +++ b/src/SQL/PostgreSQL/PersistedGrantDb.txt @@ -0,0 +1,11 @@ + +CREATE TABLE PersistedGrants ( + Key varchar(200) NOT NULL, + ClientId varchar(200) NOT NULL, + CreationTime timestamp NOT NULL, + Data varchar(8000) NOT NULL, + Expiration timestamp NULL, + SubjectId varchar(200) NULL, + Type varchar(50) NOT NULL, + CONSTRAINT PK_PersistedGrants PRIMARY KEY (Key) +); \ No newline at end of file