diff --git a/.gitignore b/.gitignore index 9d3c3957aa..a6f0dac3dd 100644 --- a/.gitignore +++ b/.gitignore @@ -267,7 +267,7 @@ framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Logs/*.* modules/blog/app/Volo.BlogTestApp/Logs/*.* modules/blogging/app/Volo.BloggingTestApp/Logs/*.* modules/blogging/app/Volo.BloggingTestApp/wwwroot/files/*.* -modules/docs/app/Volo.DocsTestApp/Logs/*.* +modules/docs/app/VoloDocs.Web/Logs/*.* samples/BookStore/src/Acme.BookStore.Web/Logs/*.* templates/module/app/MyCompanyName.MyProjectName.DemoApp/Logs/*.* templates/mvc/src/MyCompanyName.MyProjectName.Web/Logs/*.* diff --git a/abp_io/Volo.AbpWebSite.sln b/abp_io/Volo.AbpWebSite.sln index 0621f570a1..cc597fb6ae 100644 --- a/abp_io/Volo.AbpWebSite.sln +++ b/abp_io/Volo.AbpWebSite.sln @@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.AbpWebSite.Application EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.AbpWebSite.EntityFrameworkCore", "src\Volo.AbpWebSite.EntityFrameworkCore\Volo.AbpWebSite.EntityFrameworkCore.csproj", "{028C05DB-61BF-41EF-B9AD-614A43CD0A7F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Utils.SolutionTemplating", "src\Volo.Utils.SolutionTemplating\Volo.Utils.SolutionTemplating.csproj", "{742FCDDD-537C-42CC-AF16-A92C094D4B1D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Utils.SolutionTemplating", "src\Volo.Utils.SolutionTemplating\Volo.Utils.SolutionTemplating.csproj", "{742FCDDD-537C-42CC-AF16-A92C094D4B1D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/abp_io/src/Volo.AbpWebSite.Web/Pages/Index.cshtml b/abp_io/src/Volo.AbpWebSite.Web/Pages/Index.cshtml index 010209c690..8b04426273 100644 --- a/abp_io/src/Volo.AbpWebSite.Web/Pages/Index.cshtml +++ b/abp_io/src/Volo.AbpWebSite.Web/Pages/Index.cshtml @@ -1,5 +1,4 @@ @page -@using Volo.AbpWebSite @model Volo.AbpWebSite.Pages.IndexModel @{ Layout = "~/Pages/Shared/HomePageLayout.cshtml"; diff --git a/abp_io/src/Volo.AbpWebSite.Web/Volo.AbpWebSite.Web.csproj b/abp_io/src/Volo.AbpWebSite.Web/Volo.AbpWebSite.Web.csproj index b434646d99..9496a6db71 100644 --- a/abp_io/src/Volo.AbpWebSite.Web/Volo.AbpWebSite.Web.csproj +++ b/abp_io/src/Volo.AbpWebSite.Web/Volo.AbpWebSite.Web.csproj @@ -54,6 +54,7 @@ + diff --git a/abp_io/src/Volo.AbpWebSite.Web/compilerconfig.json b/abp_io/src/Volo.AbpWebSite.Web/compilerconfig.json index 1e74c37e28..87e801ce53 100644 --- a/abp_io/src/Volo.AbpWebSite.Web/compilerconfig.json +++ b/abp_io/src/Volo.AbpWebSite.Web/compilerconfig.json @@ -2,5 +2,9 @@ { "outputFile": "wwwroot/scss/vs.css", "inputFile": "wwwroot/scss/vs.scss" + }, + { + "outputFile": "Pages/Applications.css", + "inputFile": "Pages/Applications.scss" } ] \ No newline at end of file diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.css index ad4f5adca0..2ab1da238e 100644 --- a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.css +++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.css @@ -694,3 +694,6 @@ span.code-arrow { body { background-size: cover; } + +.applications-container .card-body p { + min-height: 7em; } diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.min.css b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.min.css index 524731f0ff..b9a963774e 100644 --- a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.min.css +++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.min.css @@ -1 +1 @@ -body{position:relative;font-family:'PT Sans',sans-serif;background:url(../assets/tools/bg.jpg) center center no-repeat;background-attachment:fixed;}h1,h2,h3,h4,h5,h6{font-family:'PT Sans Caption',sans-serif;}h1{font-size:2.25em;margin:1.5rem 0 .75rem;}h2{font-size:1.75em;margin:1.5rem 0 .75rem;}h3{font-size:1.5em;margin:1.5rem 0 .75rem;}h4{font-size:1.25em;margin:1.5rem 0 .75rem;}h5{font-size:1em;margin:1.5rem 0 .75rem;}h6{font-size:1em;margin:1.5rem 0 .75rem;}img{max-width:100%;}.navbar{padding:1.75rem 2rem;}.nav-link{padding-left:1rem !important;padding-right:1rem !important;}.navbar-dark .navbar-nav .nav-link{color:#fff;}.text-success{color:#e90052 !important;}a.text-success:hover,a.text-success:focus{color:#e90052 !important;}.bg-success,.btn-success,.badge-success{background-color:#e90052 !important;border-color:#e90052 !important;}.bg-success{background-color:rgba(233,0,82,.8) !important;}.bg-blue,.btn-blue,.badge-blue{background-color:#03abed !important;border-color:#03abed !important;color:#fff;}.bg-blue:hover,.btn-blue:hover,.badge-blue:hover{background-color:#0095d0 !important;border-color:#0095d0 !important;color:#fff !important;}.btn:focus,.btn:active,.btn:visited,a:focus,a:active,a:visited{outline:none !important;box-shadow:none;}.text-primary{color:#38003c !important;}.bg-primary,.btn-primary,.badge-primary{background-color:#38003c !important;border-color:#38003c !important;}.bg-primary{background-color:rgba(56,0,60,.9) !important;}.btn-outline-primary{color:#38003c !important;border-color:#38003c !important;}.btn-outline-primary:hover{background-color:#38003c !important;color:#fff !important;}.dropdown-menu{padding:1rem 0;border-radius:.15rem;border:none;box-shadow:5px 5px 40px rgba(0,0,0,.3);}.dropdown-menu .dropdown-item{padding:.75rem 1.5rem;}#index-video{position:fixed;right:0;bottom:0;min-width:100%;min-height:100%;z-index:-1;}.bg-gradient-horizontal{background:#fff;}@media(min-width:480px){.bg-gradient-horizontal{background:#fff;background:-moz-linear-gradient(left,#fff 50%,#f2f2f2 50%);background:-webkit-linear-gradient(left,#fff 50%,#f2f2f2 50%);background:linear-gradient(to right,#fff 50%,#f2f2f2 50%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#f2f2f2',GradientType=1);}}.bg-transparency{background:rgba(255,255,255,.9);}.bg-light{background:#eee;}.for-mobile{display:none;}.for-desktop{display:inline-block;}.breadcrumb{background:none;font-size:.85em;border-radius:0;border-bottom:1px solid #f5f5f5;margin:0 -15px;padding:.5rem 0;text-align:center;display:block;}.breadcrumb .breadcrumb-item+.breadcrumb-item{padding-left:.2rem;}.breadcrumb .breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.4rem;color:#eee;content:"|";}.breadcrumb .breadcrumb-item{color:#eee;display:inline-block;}.breadcrumb .breadcrumb-item a{color:#aaa;}.close{font-weight:300;}hr{margin-top:2rem;margin-bottom:2.5rem;border-top:1px solid rgba(0,0,0,.05);}span.with-br-name{font-size:.75em;}span.br-name{display:block;font-size:1.25em;}span.br-name-1{display:block;font-size:1em;}.btn-fifty{display:flex;}.btn-fifty .btn{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%;}.p-responsive{padding:120px 0;}.global-header{display:none;}.global-header .navbar{background:rgba(255,255,255,.2);}.global-header .navbar .products-link{border:1px solid rgba(255,255,255,.75);border-radius:.2rem;margin:0 10px;padding-top:.36rem;padding-bottom:.36rem;}.global-header .navbar .search-item{position:relative;}.global-header .navbar .search-item input.form-control{background:none;border:1px solid rgba(255,255,255,.25);border-radius:.2rem;color:#fff;padding-left:2.5rem;min-width:280px;}.global-header .navbar .search-item input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.25) !important;}.global-header .navbar .search-item input.form-control:-moz-placeholder{color:rgba(255,255,255,.25) !important;}.global-header .navbar .search-item input.form-control::-moz-placeholder{color:rgba(255,255,255,.25) !important;}.global-header .navbar .search-item input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.25) !important;}.global-header .navbar .search-item .btn-search{position:absolute;top:-2px;left:-1px;background:none;}header .btn{background:#fff;}header .btn.btn-login,header .btn.btn-logout{border:2px solid #fff;color:#fff;background:transparent;margin-right:6px;}header .btn.btn-login:hover,header .btn.btn-logout:hover{background:#fff;color:#e90052;}.product-header{font-size:1.1rem;}.product-header .navbar-brand{font-size:1.75rem;}.home-logo{width:120px;}.jumbotron-logo{width:240px;margin-bottom:40px;}.forkme{position:fixed;bottom:0;right:0;}.footer-logo{width:140px;}.jumbotron{background:#006bf0;background:-moz-linear-gradient(left,#006bf0 0%,#40ffb0 100%);background:-webkit-linear-gradient(left,#006bf0 0%,#40ffb0 100%);background:linear-gradient(to right,rgba(56,0,60,.9) 0%,rgba(185,0,74,.78) 100%);margin-top:-120px;border-radius:0;margin-bottom:0;height:90vh;}.jumbotron.jumbocover{padding:120px 0 20px;height:auto;}.jumbotron>.row{height:calc(90vh - 120px);}.jumbotron .abp-version{position:absolute;font-size:11px;right:1px;top:-2px;padding:1px 4px 0;display:inline-block;color:#fff;background:rgba(233,3,82,.7);border-radius:3px;opacity:.8;}.jumbotron .desc-span{font-size:1.4em;font-style:italic;opacity:.7;}.section-with-logos img{margin:25px;max-height:50px;transition:.4s;opacity:.6;-webkit-filter:grayscale(60%);filter:grayscale(60%);}.section-with-logos img:hover{opacity:1;-webkit-filter:grayscale(0%);filter:grayscale(0%);}img.subsection-icon{width:64px;height:64px;}.toggle-row{display:none;}.btn-toggle .lessText{display:none;}.btn-toggle .moreText{display:block;}.btn-toggle.less .lessText{display:block;}.btn-toggle.less .moreText{display:none;}.abp-browser{margin:3rem 0 1rem;text-align:left;border-radius:6px;overflow:hidden;}.abp-browser .browser-container{border:1px solid #eee;}.abp-browser .browser-row{padding:4px 10px;background:#e5e5e5;}.abp-browser .browser-row:after{content:"";display:table;clear:both;}.abp-browser .browser-dot{margin-top:2px;margin-right:2px;height:12px;width:12px;background-color:#bbb;border-radius:50%;display:inline-block;}.abp-browser .abp-browser input[type=text]{width:100%;border-radius:3px;border:none;background-color:#fff;margin-top:-8px;height:25px;color:#666;padding:5px;}.abp-browser .browser-bar{width:17px;height:3px;background-color:#aaa;margin:3px 0;display:block;}.abp-browser .browser-content{padding:2rem;background:#f5f5f5;}.abp-browser .bg-primary,.abp-browser .btn-primary,.abp-browser .badge-primary{background-color:#007bff !important;border-color:#007bff !important;}.abp-browser .btn-outline-primary{color:#007bff !important;border-color:#007bff !important;}.abp-browser .btn-outline-primary:hover{background-color:#007bff !important;color:#fff !important;}span.code-arrow{padding:52px 0 18px;display:block;font-size:40px;}.docs-page{background:#f5f7f9;}.docs-page .docs-sidebar{background:#f5f7f9;padding-right:1.5rem;position:relative;width:270px;}.docs-page .docs-sidebar .docs-sidebar-wrapper{width:270px;top:0;position:fixed;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{height:calc(100vh - 190px);overflow:hidden;overflow-y:auto;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search{position:relative;padding:0 0 1.25rem 1.5rem;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search input.form-control{background:none;border-radius:.2rem;padding-left:2.5rem;width:100%;background:#eeeff2;border:0;font-size:.85em;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search .btn-search{position:absolute;top:-5px;left:22px;background:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul{font-size:.913em;list-style:none;padding:0 0 0 20px;margin:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li{margin-left:0;padding-left:24px;display:block;width:100%;position:relative;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li label{margin:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li label.tree-toggle{transition:.3s;display:inline-block;width:18px;height:18px;text-align:center;padding:0;line-height:normal;border-radius:50%;margin-right:4px;position:absolute;left:0;top:8px;cursor:pointer;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li label.tree-toggle img{width:14px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li label.tree-toggle:not(.last-link).opened{transform:rotate(180deg);}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#101010;font-weight:700;padding:7px 0;display:block;border-bottom:1px solid #eeeff3;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li label.tree-toggle{top:6px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li a{font-weight:400;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul li a{font-weight:300;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#38003c;font-weight:bold;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:2rem;font-weight:700;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand .docs-logo{width:130px;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand strong{font-weight:300;font-size:1.2rem;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:.85em;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc strong{display:block;}.docs-page .docs-content .docs-text-field{padding:3rem;}.docs-page .docs-page-index{position:relative;}.docs-page .docs-page-index .docs-inner-anchors{position:fixed;top:0;max-width:270px;padding:10px;font-size:.9em;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills{font-size:.95em;margin-left:18px;border-left:1px solid #e5e5e5;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link{padding:.2rem 0 .2rem 1rem;color:#aaa;line-height:1.1;position:relative;border-left:3px solid transparent;border-radius:0;margin-left:-2px;margin-top:2px;margin-bottom:2px;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link.active{background:none;color:#38003b;border-color:#38003b;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-link.active{color:#38003b;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-pills .nav-link.active{color:#38003b;}.docs-page .docs-page-index .docs-inner-anchors>.navbar{margin-left:-18px;}.docs-page .docs-page-index .docs-inner-anchors .docs-anchors-wrapper{max-width:300px;float:left;}.docs-page .docs-page-index .docs-inner-anchors .inner-title{padding-left:18px;}.docs-page .docs-page-index .scroll-top-btn{display:none;font-size:.85em;color:#aaa;text-decoration:underline;padding-left:18px;}.docs-page .docs-page-index .scroll-top-btn.showup{display:block;}@media(min-width:1200px){.container{max-width:1180px;}}@media(min-width:1366px){.container{max-width:1340px;}}@media(min-width:1440px){.container{max-width:1400px;}}@media(max-width:767px){.docs-page{background:#f5f7f9;}.docs-page>.container-fluid{display:block;}.docs-page>.container-fluid>.row{display:block;}.docs-page .docs-sidebar{position:fixed;max-width:100%;width:100%;display:block;padding:0 !important;top:0;left:0;z-index:100;right:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper{max-width:100%;width:100%;top:0;position:relative;margin:0 !important;height:72px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{padding:.5rem 1.5rem 2rem 1.5rem;height:calc(100vh - 72px);overflow:hidden;overflow-y:auto;position:fixed;top:72px;font-size:17px;left:0;width:100%;z-index:100;background:#f5f7f9;display:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search{position:relative;padding:0 0 1rem !important;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search .btn-search{top:-14px;left:-2px;}.docs-page .docs-sidebar .docs-top .navbar-logo{padding:0;padding-top:.3rem;display:block;text-align:center;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:2rem;font-weight:700;display:block;margin-right:0;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand .docs-logo{width:110px;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:1em;display:none;}.docs-page .docs-sidebar .docs-top .open-dmenu{position:absolute;top:10px;left:20px;}.docs-page .docs-content{padding-top:72px;max-width:100%;display:block !important;}.docs-page .docs-content .docs-text-field{padding:1rem 1.5rem;}.docs-page .docs-page-index{display:none;}}@media(max-width:992px){body{font-size:14px;}.for-mobile{display:inline-block;}.for-desktop{display:none;}.close-mmenu,.close-dmenu{position:absolute;top:-78px;left:25px;color:#fff;font-size:68px;background:#fff;opacity:0;}.navbar{padding:.5rem 1.75rem;}.navbar .navbar-collapse{background:#38003d;position:fixed;top:86px;left:0;width:100%;height:100vh;height:calc(100vh - 86px);z-index:100 !important;}.navbar .navbar-collapse .navbar-nav{height:100vh;padding:20px 30px;overflow:auto;}.navbar .navbar-collapse .navbar-nav .nav-link{padding:1.2rem !important;}.navbar .navbar-toggler{padding:.5rem .75rem;font-size:1.5rem;line-height:1;background-color:transparent;border:0;border-radius:.25rem;color:#fff !important;margin-left:-1rem;}.jumbotron .btn,footer .btn{display:block;margin-bottom:10px;}.multi-tenancy{text-align:center !important;}.section-with-logos img{margin:15px;opacity:1;-webkit-filter:grayscale(0%);filter:grayscale(0%);}.jumbotron{padding-top:160px;margin-top:-160px;border-radius:0;padding-bottom:40px;margin-bottom:0;font-size:.85em;padding-left:45px;padding-right:45px;}span.code-arrow{padding:0 0 0;display:block;transform:rotate(90deg);font-size:2em;}.mb-5,.my-5{margin-bottom:2rem !important;}.jumbotron{height:calc(100vh + 120px);}.jumbotron.jumbocover{height:auto;padding:160px 0 20px;}.jumbotron hr{display:none;}.jumbotron .btn{margin-bottom:0 !important;}.jumbotron .jumbotron-logo{margin-bottom:0;width:180px;height:62px;margin-top:-30px;}.jumbotron .jlogo-wrapper{height:62px;}}.vs-blog{margin-top:-88px !important;}.abp-account-container{max-width:400px;margin:0 auto;margin-top:-88px !important;}body{background-size:cover;} \ No newline at end of file +body{position:relative;font-family:'PT Sans',sans-serif;background:url(../assets/tools/bg.jpg) center center no-repeat;background-attachment:fixed;}h1,h2,h3,h4,h5,h6{font-family:'PT Sans Caption',sans-serif;}h1{font-size:2.25em;margin:1.5rem 0 .75rem;}h2{font-size:1.75em;margin:1.5rem 0 .75rem;}h3{font-size:1.5em;margin:1.5rem 0 .75rem;}h4{font-size:1.25em;margin:1.5rem 0 .75rem;}h5{font-size:1em;margin:1.5rem 0 .75rem;}h6{font-size:1em;margin:1.5rem 0 .75rem;}img{max-width:100%;}.navbar{padding:1.75rem 2rem;}.nav-link{padding-left:1rem !important;padding-right:1rem !important;}.navbar-dark .navbar-nav .nav-link{color:#fff;}.text-success{color:#e90052 !important;}a.text-success:hover,a.text-success:focus{color:#e90052 !important;}.bg-success,.btn-success,.badge-success{background-color:#e90052 !important;border-color:#e90052 !important;}.bg-success{background-color:rgba(233,0,82,.8) !important;}.bg-blue,.btn-blue,.badge-blue{background-color:#03abed !important;border-color:#03abed !important;color:#fff;}.bg-blue:hover,.btn-blue:hover,.badge-blue:hover{background-color:#0095d0 !important;border-color:#0095d0 !important;color:#fff !important;}.btn:focus,.btn:active,.btn:visited,a:focus,a:active,a:visited{outline:none !important;box-shadow:none;}.text-primary{color:#38003c !important;}.bg-primary,.btn-primary,.badge-primary{background-color:#38003c !important;border-color:#38003c !important;}.bg-primary{background-color:rgba(56,0,60,.9) !important;}.btn-outline-primary{color:#38003c !important;border-color:#38003c !important;}.btn-outline-primary:hover{background-color:#38003c !important;color:#fff !important;}.dropdown-menu{padding:1rem 0;border-radius:.15rem;border:none;box-shadow:5px 5px 40px rgba(0,0,0,.3);}.dropdown-menu .dropdown-item{padding:.75rem 1.5rem;}#index-video{position:fixed;right:0;bottom:0;min-width:100%;min-height:100%;z-index:-1;}.bg-gradient-horizontal{background:#fff;}@media(min-width:480px){.bg-gradient-horizontal{background:#fff;background:-moz-linear-gradient(left,#fff 50%,#f2f2f2 50%);background:-webkit-linear-gradient(left,#fff 50%,#f2f2f2 50%);background:linear-gradient(to right,#fff 50%,#f2f2f2 50%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#f2f2f2',GradientType=1);}}.bg-transparency{background:rgba(255,255,255,.9);}.bg-light{background:#eee;}.for-mobile{display:none;}.for-desktop{display:inline-block;}.breadcrumb{background:none;font-size:.85em;border-radius:0;border-bottom:1px solid #f5f5f5;margin:0 -15px;padding:.5rem 0;text-align:center;display:block;}.breadcrumb .breadcrumb-item+.breadcrumb-item{padding-left:.2rem;}.breadcrumb .breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.4rem;color:#eee;content:"|";}.breadcrumb .breadcrumb-item{color:#eee;display:inline-block;}.breadcrumb .breadcrumb-item a{color:#aaa;}.close{font-weight:300;}hr{margin-top:2rem;margin-bottom:2.5rem;border-top:1px solid rgba(0,0,0,.05);}span.with-br-name{font-size:.75em;}span.br-name{display:block;font-size:1.25em;}span.br-name-1{display:block;font-size:1em;}.btn-fifty{display:flex;}.btn-fifty .btn{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%;}.p-responsive{padding:120px 0;}.global-header{display:none;}.global-header .navbar{background:rgba(255,255,255,.2);}.global-header .navbar .products-link{border:1px solid rgba(255,255,255,.75);border-radius:.2rem;margin:0 10px;padding-top:.36rem;padding-bottom:.36rem;}.global-header .navbar .search-item{position:relative;}.global-header .navbar .search-item input.form-control{background:none;border:1px solid rgba(255,255,255,.25);border-radius:.2rem;color:#fff;padding-left:2.5rem;min-width:280px;}.global-header .navbar .search-item input.form-control::-webkit-input-placeholder{color:rgba(255,255,255,.25) !important;}.global-header .navbar .search-item input.form-control:-moz-placeholder{color:rgba(255,255,255,.25) !important;}.global-header .navbar .search-item input.form-control::-moz-placeholder{color:rgba(255,255,255,.25) !important;}.global-header .navbar .search-item input.form-control:-ms-input-placeholder{color:rgba(255,255,255,.25) !important;}.global-header .navbar .search-item .btn-search{position:absolute;top:-2px;left:-1px;background:none;}header .btn{background:#fff;}header .btn.btn-login,header .btn.btn-logout{border:2px solid #fff;color:#fff;background:transparent;margin-right:6px;}header .btn.btn-login:hover,header .btn.btn-logout:hover{background:#fff;color:#e90052;}.product-header{font-size:1.1rem;}.product-header .navbar-brand{font-size:1.75rem;}.home-logo{width:120px;}.jumbotron-logo{width:240px;margin-bottom:40px;}.forkme{position:fixed;bottom:0;right:0;}.footer-logo{width:140px;}.jumbotron{background:#006bf0;background:-moz-linear-gradient(left,#006bf0 0%,#40ffb0 100%);background:-webkit-linear-gradient(left,#006bf0 0%,#40ffb0 100%);background:linear-gradient(to right,rgba(56,0,60,.9) 0%,rgba(185,0,74,.78) 100%);margin-top:-120px;border-radius:0;margin-bottom:0;height:90vh;}.jumbotron.jumbocover{padding:120px 0 20px;height:auto;}.jumbotron>.row{height:calc(90vh - 120px);}.jumbotron .abp-version{position:absolute;font-size:11px;right:1px;top:-2px;padding:1px 4px 0;display:inline-block;color:#fff;background:rgba(233,3,82,.7);border-radius:3px;opacity:.8;}.jumbotron .desc-span{font-size:1.4em;font-style:italic;opacity:.7;}.section-with-logos img{margin:25px;max-height:50px;transition:.4s;opacity:.6;-webkit-filter:grayscale(60%);filter:grayscale(60%);}.section-with-logos img:hover{opacity:1;-webkit-filter:grayscale(0%);filter:grayscale(0%);}img.subsection-icon{width:64px;height:64px;}.toggle-row{display:none;}.btn-toggle .lessText{display:none;}.btn-toggle .moreText{display:block;}.btn-toggle.less .lessText{display:block;}.btn-toggle.less .moreText{display:none;}.abp-browser{margin:3rem 0 1rem;text-align:left;border-radius:6px;overflow:hidden;}.abp-browser .browser-container{border:1px solid #eee;}.abp-browser .browser-row{padding:4px 10px;background:#e5e5e5;}.abp-browser .browser-row:after{content:"";display:table;clear:both;}.abp-browser .browser-dot{margin-top:2px;margin-right:2px;height:12px;width:12px;background-color:#bbb;border-radius:50%;display:inline-block;}.abp-browser .abp-browser input[type=text]{width:100%;border-radius:3px;border:none;background-color:#fff;margin-top:-8px;height:25px;color:#666;padding:5px;}.abp-browser .browser-bar{width:17px;height:3px;background-color:#aaa;margin:3px 0;display:block;}.abp-browser .browser-content{padding:2rem;background:#f5f5f5;}.abp-browser .bg-primary,.abp-browser .btn-primary,.abp-browser .badge-primary{background-color:#007bff !important;border-color:#007bff !important;}.abp-browser .btn-outline-primary{color:#007bff !important;border-color:#007bff !important;}.abp-browser .btn-outline-primary:hover{background-color:#007bff !important;color:#fff !important;}span.code-arrow{padding:52px 0 18px;display:block;font-size:40px;}.docs-page{background:#f5f7f9;}.docs-page .docs-sidebar{background:#f5f7f9;padding-right:1.5rem;position:relative;width:270px;}.docs-page .docs-sidebar .docs-sidebar-wrapper{width:270px;top:0;position:fixed;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{height:calc(100vh - 190px);overflow:hidden;overflow-y:auto;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search{position:relative;padding:0 0 1.25rem 1.5rem;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search input.form-control{background:none;border-radius:.2rem;padding-left:2.5rem;width:100%;background:#eeeff2;border:0;font-size:.85em;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search .btn-search{position:absolute;top:-5px;left:22px;background:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul{font-size:.913em;list-style:none;padding:0 0 0 20px;margin:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li{margin-left:0;padding-left:24px;display:block;width:100%;position:relative;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li label{margin:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li label.tree-toggle{transition:.3s;display:inline-block;width:18px;height:18px;text-align:center;padding:0;line-height:normal;border-radius:50%;margin-right:4px;position:absolute;left:0;top:8px;cursor:pointer;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li label.tree-toggle img{width:14px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li label.tree-toggle:not(.last-link).opened{transform:rotate(180deg);}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#101010;font-weight:700;padding:7px 0;display:block;border-bottom:1px solid #eeeff3;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li label.tree-toggle{top:6px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li a{font-weight:400;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul li a{font-weight:300;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#38003c;font-weight:bold;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:2rem;font-weight:700;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand .docs-logo{width:130px;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand strong{font-weight:300;font-size:1.2rem;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:.85em;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc strong{display:block;}.docs-page .docs-content .docs-text-field{padding:3rem;}.docs-page .docs-page-index{position:relative;}.docs-page .docs-page-index .docs-inner-anchors{position:fixed;top:0;max-width:270px;padding:10px;font-size:.9em;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills{font-size:.95em;margin-left:18px;border-left:1px solid #e5e5e5;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link{padding:.2rem 0 .2rem 1rem;color:#aaa;line-height:1.1;position:relative;border-left:3px solid transparent;border-radius:0;margin-left:-2px;margin-top:2px;margin-bottom:2px;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link.active{background:none;color:#38003b;border-color:#38003b;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-link.active{color:#38003b;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-pills .nav-link.active{color:#38003b;}.docs-page .docs-page-index .docs-inner-anchors>.navbar{margin-left:-18px;}.docs-page .docs-page-index .docs-inner-anchors .docs-anchors-wrapper{max-width:300px;float:left;}.docs-page .docs-page-index .docs-inner-anchors .inner-title{padding-left:18px;}.docs-page .docs-page-index .scroll-top-btn{display:none;font-size:.85em;color:#aaa;text-decoration:underline;padding-left:18px;}.docs-page .docs-page-index .scroll-top-btn.showup{display:block;}@media(min-width:1200px){.container{max-width:1180px;}}@media(min-width:1366px){.container{max-width:1340px;}}@media(min-width:1440px){.container{max-width:1400px;}}@media(max-width:767px){.docs-page{background:#f5f7f9;}.docs-page>.container-fluid{display:block;}.docs-page>.container-fluid>.row{display:block;}.docs-page .docs-sidebar{position:fixed;max-width:100%;width:100%;display:block;padding:0 !important;top:0;left:0;z-index:100;right:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper{max-width:100%;width:100%;top:0;position:relative;margin:0 !important;height:72px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{padding:.5rem 1.5rem 2rem 1.5rem;height:calc(100vh - 72px);overflow:hidden;overflow-y:auto;position:fixed;top:72px;font-size:17px;left:0;width:100%;z-index:100;background:#f5f7f9;display:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search{position:relative;padding:0 0 1rem !important;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-search .btn-search{top:-14px;left:-2px;}.docs-page .docs-sidebar .docs-top .navbar-logo{padding:0;padding-top:.3rem;display:block;text-align:center;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:2rem;font-weight:700;display:block;margin-right:0;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand .docs-logo{width:110px;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:1em;display:none;}.docs-page .docs-sidebar .docs-top .open-dmenu{position:absolute;top:10px;left:20px;}.docs-page .docs-content{padding-top:72px;max-width:100%;display:block !important;}.docs-page .docs-content .docs-text-field{padding:1rem 1.5rem;}.docs-page .docs-page-index{display:none;}}@media(max-width:992px){body{font-size:14px;}.for-mobile{display:inline-block;}.for-desktop{display:none;}.close-mmenu,.close-dmenu{position:absolute;top:-78px;left:25px;color:#fff;font-size:68px;background:#fff;opacity:0;}.navbar{padding:.5rem 1.75rem;}.navbar .navbar-collapse{background:#38003d;position:fixed;top:86px;left:0;width:100%;height:100vh;height:calc(100vh - 86px);z-index:100 !important;}.navbar .navbar-collapse .navbar-nav{height:100vh;padding:20px 30px;overflow:auto;}.navbar .navbar-collapse .navbar-nav .nav-link{padding:1.2rem !important;}.navbar .navbar-toggler{padding:.5rem .75rem;font-size:1.5rem;line-height:1;background-color:transparent;border:0;border-radius:.25rem;color:#fff !important;margin-left:-1rem;}.jumbotron .btn,footer .btn{display:block;margin-bottom:10px;}.multi-tenancy{text-align:center !important;}.section-with-logos img{margin:15px;opacity:1;-webkit-filter:grayscale(0%);filter:grayscale(0%);}.jumbotron{padding-top:160px;margin-top:-160px;border-radius:0;padding-bottom:40px;margin-bottom:0;font-size:.85em;padding-left:45px;padding-right:45px;}span.code-arrow{padding:0 0 0;display:block;transform:rotate(90deg);font-size:2em;}.mb-5,.my-5{margin-bottom:2rem !important;}.jumbotron{height:calc(100vh + 120px);}.jumbotron.jumbocover{height:auto;padding:160px 0 20px;}.jumbotron hr{display:none;}.jumbotron .btn{margin-bottom:0 !important;}.jumbotron .jumbotron-logo{margin-bottom:0;width:180px;height:62px;margin-top:-30px;}.jumbotron .jlogo-wrapper{height:62px;}}.vs-blog{margin-top:-88px !important;}.abp-account-container{max-width:400px;margin:0 auto;margin-top:-88px !important;}body{background-size:cover;}.applications-container .card-body p{min-height:7em;} \ No newline at end of file diff --git a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.scss b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.scss index 4d9cb4a995..6ff04112b4 100644 --- a/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.scss +++ b/abp_io/src/Volo.AbpWebSite.Web/wwwroot/scss/vs.scss @@ -19,4 +19,12 @@ body { background-size: cover; -} \ No newline at end of file +} + +.applications-container { + .card-body { + p { + min-height: 7em; + } + } +} diff --git a/common.props b/common.props index 0e6a922473..dce50d895e 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ latest - 0.15.0 + 0.16.0 $(NoWarn);CS1591 https://abp.io/assets/abp_nupkg.png https://abp.io diff --git a/docs/en/Apps/VoloDocs.md b/docs/en/Apps/VoloDocs.md new file mode 100644 index 0000000000..936f7f10d4 --- /dev/null +++ b/docs/en/Apps/VoloDocs.md @@ -0,0 +1,170 @@ +# VoloDocs + +## What is VoloDocs? + +VoloDocs is a cross-platform web application that allows you to easily create beautiful documentation and build developer communities. It simplifies software documentation with the help of GitHub integration. You use the power of GitHub for versioning, hosting of your docs. You let your users to edit a document. + +## Main Features + +- Serves documents from your GitHub repository. +- Supports Markdown / HTML document formatting. +- Supports versioning (integrated to GitHub releases). +- Supports multiple projects. +- Allows users to edit a document on GitHub. +- Cross-platform; deployable to Windows / Linux / macOS. + +## GitHub Repository + +It's free & open-source. You can browse VoloDocs source-code and contribute on GitHub: + +https://github.com/abpframework/abp/tree/master/modules/docs + +## Download + +You can download the VoloDocs release from the following link: + +http://apps.abp.io/VoloDocs/VoloDocs.zip *(will be ready soon...)* + +## Folder Structure + +When you extract the `VoloDocs.zip` file, you will see a `Web` folder and a `Migrator` folder. `Web` folder contains the website files and `Migrator` contains the application to build your database. Before publishing your website, you need to create a new database or update your existing database to the latest. If this is the first time you install VoloDocs, `Migrator` will create a new database for you, otherwise it updates to the latest version. The only setting you need to configure, is the `ConnectionString` which is located in the `appsettings.json` file. See the next section to learn how to configure your VoloDocs application. + +## Steps by Step Deployment + +- ### Database Migration + + To update your existing database or create your initial database, go to `Migrator` folder in your VoloDocs directory. + + Open `appsettings.json` in your text editor and set your database connection string. If you don't know how to write the connection string for your database system, you can check out https://www.connectionstrings.com/. + + After you set your connection string, run `Migrate.bat` for Windows platform and `VoloDocs.Migrator` for other operating systems. That's it now configure your website. + +- ### Configuring Website + + Go to `Web` folder in your VoloDocs directory. Open `appsettings.json` in your text editor. Set your connection string (same as in the `Migrator`'s `appsettings.json`). Set `title` of your website. This will be written on the left-upper corner of your website. That's it! Now you can publish your website. + + If you want to run + +- ### Publishing Website + + In the previous step, you created or updated your database. Ensure that your database exists on the specified connection string. + + - #### Publishing to IIS + + - Move `Web` folder to your `wwwroot ` folder. + - Rename `Web` folder to `VoloDocs` (Now you have `C:\inetpub\wwwroot\VoloDocs`).![Add IIS Website](../images/volodocs-iis-add-website.png) + - The `VoloDocs` application pool is being created automatically. Open **Application Pools** and double click `VoloDocs` application pool and set + - **.NET CLR version**: `No Managed Code` + - **Managed pipeline mode**: `Integrated` + + ![Add IIS Website](../images/volodocs-iis-application-pool.png) + + + + - If you get the below error, it means don't have the hosting bundle installed on the server. See [this document](https://docs.microsoft.com/aspnet/core/host-and-deploy/iis/#install-the-net-core-hosting-bundle) to learn how to install it or [download Hosting Bundle](https://www.microsoft.com/net/permalink/dotnetcore-current-windows-runtime-bundle-installer) and run on your server. + + ``` + Handler "aspNetCore" has a bad module "AspNetCoreModuleV2" in its module list using IIS + ``` + + - Further information about hosting VoloDocs check out [Microsoft's official document for hosting ASP.NET Core application on IIS](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis). + + - #### Publishing to Azure + + Microsoft has a good document on how to deploy your ASP.NET Core web app to Azure App Service. We recommend you to read this document https://docs.microsoft.com/en-us/azure/app-service/app-service-web-get-started-dotnet. + + - #### Running the Application From Command Line + + Alternatively you can run the application from command line, navigate to `VoloDocs\Web` folder and run the below command in your command line for Windows: + + ```powershell + dotnet VoloDocs.Web.dll + ``` + +- ### First Run + + To start the website, navigate to your address (as configured in the previous section). + + When you first open the website, you need to create a project. + + #### Creating a Project + + Go to the following address to create project + + - `http:///Account/Login?returnUrl=/Docs/Admin/Projects` + + ##### Default credentials + + To login the admin side, use the following credentials: + + * **Username**: `admin` + + * **Password**: `1q2w3E*` + + ##### An example project definition + + Here's a sample project information that uses GitHub source. + + We will configure the VoloDocs to show ABP Framework's documentation that's stored in GitHub. + + Here's the link to ABP Framework GitHub docs folder: + + https://github.com/abpframework/abp/tree/master/docs/en + + + + * **Name**: `ABP Framework` + + * **Short name**: `abp` + + * **Format**: `markdown` + + * **Default document name**: `Index` + + * **Navigation document name**: `docs-nav.json` ([see the sample navigation](https://github.com/abpframework/abp/blob/master/docs/en/docs-nav.json)) + + * **Minimum version**: *leave empty* *(hides the previous versions)* + + * **Main web site URL**: `/` + + * **Latest version branch name**: leave empty () + + * **GitHub root URL**: `https://github.com/abpframework/abp/tree/{version}/docs/en/` + + * **GitHub access token**: [see how to retrieve GitHub access token](#retrieving-github-access-token) + + * **GitHub user agent**: [see how to learn your GitHub username](#learn-your-github-username) + + ![Creating a new project](../images/docs-create-project.jpg) + + ##### Retrieving GitHub Access Token + + To create a personal access token in GitHub, you need to visit the **Settings** of the user account and under **Developer settings** you will find **Personal access tokens**. Select **Generate new token**, enter in a name as the Token description and enable the repo checkbox. Alternatively, to enter generate new token, browse to https://github.com/settings/tokens/new. + + ###### Generate Token for Public Repositories + + To access public repositories, check `public_repo` under the `repo` section. This will enable VoloDocs to access your public GitHub repositories. Click `Generate Token` button on the bottom of the page. + + ![Retrieve GitHub Access Token for Public Repo](../images/github-access-token-public-repo.jpg) + + ###### Generate Token for Private Repositories + + To access public repositories, check all items under the `repo` section. This will enable VoloDocs to access your private GitHub repositories. Click `Generate Token` button on the bottom of the page. + + ![Retrieve GitHub Access Token for Private Repo](../images/github-access-token-private-repo.jpg) + + ###### Learn Your GitHub Username + + To learn your GitHub username, click on your profile picture on the top-right corner of the GitHub page. You will see your username right after the text "Signed in as ..." + + ![Your GitHub Username](../images/github-myusername.jpg) + + + +After you save the project, go to root website address and you will see your documentation. + +`http:///documents` + + + + diff --git a/docs/en/AspNetCore/Auto-API-Controllers.md b/docs/en/AspNetCore/Auto-API-Controllers.md index 48567b6919..db7fb63642 100644 --- a/docs/en/AspNetCore/Auto-API-Controllers.md +++ b/docs/en/AspNetCore/Auto-API-Controllers.md @@ -80,7 +80,7 @@ Then the route for getting a book will be '**/api/volosoft/book-store/book/{id}* * Removing '**Async**' postfix. If the method name is 'GetPhonesAsync' then it becomes 'GetPhones'. * Removing **HTTP method prefix**. 'GetList', 'GetAll', 'Get', 'Put', 'Update', 'Delete', 'Remove', 'Create', 'Add', 'Insert', 'Post' and 'Patch' prefixes are removed based on the selected HTTP method. So, 'GetPhones' becomes 'Phones' since 'Get' prefix is a duplicate for a GET request. * Converting the result to **camelCase**. - * If the resulting action name is **empty** then it's not added to the route. If it's not empty, it's added to the route (like '/phones'). For 'GetAllAsync' method name it will be empty, for 'GetPhonesAsync' method name is will be 'phones'. + * If the resulting action name is **empty** then it's not added to the route. If it's not empty, it's added to the route (like '/phones'). For 'GetAllAsync' method name it will be empty, for 'GetPhonesAsync' method name it will be 'phones'. * Normalization can be customized by setting the `UrlActionNameNormalizer` option. It's an action delegate that is called for every method. * If there is another parameter with 'Id' postfix, then it's also added to the route as the final route segment (like '/phoneId'). @@ -135,4 +135,4 @@ public class PersonAppService : ApplicationService } ```` -Disabled `IsMetadataEnabled` which hides this service from API explorer and it will not be discoverable. However, it still can be usable for the clients know the exact API path/route. \ No newline at end of file +Disabled `IsMetadataEnabled` which hides this service from API explorer and it will not be discoverable. However, it still can be usable for the clients know the exact API path/route. diff --git a/docs/en/AspNetCore/Bundling-Minification.md b/docs/en/AspNetCore/Bundling-Minification.md index 7170690ef3..220562935d 100644 --- a/docs/en/AspNetCore/Bundling-Minification.md +++ b/docs/en/AspNetCore/Bundling-Minification.md @@ -194,7 +194,7 @@ services.Configure(options => options .ScriptBundles .Configure("MyGlobalBundle", bundle => { - bundle.AddContributors(typeof(MyExtensionStyleBundleContributor)); + bundle.AddContributors(typeof(MyExtensionGlobalStyleContributor)); }); }); ```` @@ -279,9 +279,9 @@ public class MyExtensionStyleBundleContributor : BundleContributor Using the built-in contributors for standard packages; -* Prevents you typing **invalid the resource paths**. +* Prevents you typing **the invalid resource paths**. * Prevents changing your contributor if the resource **path changes** (the dependant contributor will handle it). -* Prevents multiple modules adding the **duplicate the files**. +* Prevents multiple modules adding the **duplicate files**. * Manages **dependencies recursively** (adds dependencies of dependencies, if necessary). #### Volo.Abp.AspNetCore.Mvc.UI.Packages Package diff --git a/docs/en/Modules/Docs.md b/docs/en/Modules/Docs.md index 1aa81621f5..ac85978740 100644 --- a/docs/en/Modules/Docs.md +++ b/docs/en/Modules/Docs.md @@ -472,4 +472,9 @@ The upper sample `JSON` file renders the below navigation menu as `HTML`. -Finally a new Docs Module is added to your project which is feeded with GitHub. \ No newline at end of file +Finally a new Docs Module is added to your project which is feeded with GitHub. + +## Next + +Docs Module is also available as a standalone application. Check out [VoloDocs](../Apps/VoloDocs). + diff --git a/docs/en/Nightly-Builds.md b/docs/en/Nightly-Builds.md new file mode 100644 index 0000000000..e7ebe0f33b --- /dev/null +++ b/docs/en/Nightly-Builds.md @@ -0,0 +1,26 @@ +# Nightly Builds + +All framework & module packages are deployed to MyGet every night in weekdays. So, you can use or test the latest code without waiting the next release. + +## Configure Visual Studio + +> Requires Visual Studio 2017+ + +1. Go to `Tools > Options > NuGet Package Manager > Package Source`. +2. Click the green `+` icon. +3. Set `ABP Nightly` as *Name* and `https://www.myget.org/F/abp-nightly/api/v3/index.json` as the *Source* as shown below: + ![night-build-add-nuget-source](images/night-build-add-nuget-source.png) +4. Click the `Update` button. +5. Click the `OK` button to save changes. + +## Install Package + +Now, you can install preview / nightly packages to your project from Nuget Browser or Package Manager Console. + +![night-build-add-nuget-package](images/night-build-add-nuget-package.png) + +1. In the nuget browser, select "Include prereleases". +2. Change package source to "All". +3. Search a package. You will see prereleases of the package formatted as `(VERSION)-preview(DATE)` (like *v0.16.0-preview20190401* in this sample). +4. You can click to the `Install` button to add package to your project. + diff --git a/docs/en/Samples/Microservice-Demo.md b/docs/en/Samples/Microservice-Demo.md index 55a60dca89..4edebfbe03 100644 --- a/docs/en/Samples/Microservice-Demo.md +++ b/docs/en/Samples/Microservice-Demo.md @@ -116,11 +116,29 @@ To be able to run the solution from source code, following tools should be insta * Run `dotnet restore` from the command line inside the `samples\MicroserviceDemo` folder. * Build the solution in Visual Studio. -#### Restore Databases +#### Create Databases -Open `MsDemo_Identity.zip` and `MsDemo_ProductManagement.zip` inside the `samples\MicroserviceDemo\databases` folder and restore to the SQL Server. +MongoDB database is created dynamically, however you need to create database schemas for SQL server databases. The solution is configured to use Entity Core Code First migrations, so you can easily create databases. -> Notice that: These databases have EF Core migrations in the solution, however they don't have seed data, especially required for IdentityServer4 configuration. So, restoring the databases is much more easier. +There are two SQL server databases in this solution. + +##### MsDemo_Identity Database + +* Right click to the `AuthServer.Host` project and click to the `Set as startup project`. +* Open the **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console) +* Select `AuthServer.Host` as the **Default project**. +* Run `Update-Database` command. + +![microservice-sample-update-database-authserver](../images/microservice-sample-update-database-authserver.png) + +##### MsDemo_ProductManagement + +- Right click to the `ProductService.Host` project and click to the `Set as startup project`. +- Open the **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console) +- Select `ProductService.Host` as the **Default project**. +- Run `Update-Database` command. + +![microservice-sample-update-database-products](../images/microservice-sample-update-database-products.png) #### Run Projects @@ -136,6 +154,8 @@ Run the projects with the following order (right click to each project, set as s * BackendAdminApp.Host * PublicWebSite.Host +When you run projects, they will add some initial demo data to their databases. + ## A Brief Overview of the Solution The Visual Studio solution consists of multiple projects each have different roles in the system: diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 905821c73a..396b92afd3 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -276,6 +276,10 @@ { "text": "Testing" }, + { + "text": "Nightly Builds", + "path": "Nightly-Builds.md" + }, { "text": "Contribution Guide", "path": "Contribution/Index.md" diff --git a/docs/en/images/docs-create-project.jpg b/docs/en/images/docs-create-project.jpg new file mode 100644 index 0000000000..742f5e307f Binary files /dev/null and b/docs/en/images/docs-create-project.jpg differ diff --git a/docs/en/images/github-access-token-private-repo.jpg b/docs/en/images/github-access-token-private-repo.jpg new file mode 100644 index 0000000000..5bc53cc63d Binary files /dev/null and b/docs/en/images/github-access-token-private-repo.jpg differ diff --git a/docs/en/images/github-access-token-public-repo.jpg b/docs/en/images/github-access-token-public-repo.jpg new file mode 100644 index 0000000000..b909c2cfe5 Binary files /dev/null and b/docs/en/images/github-access-token-public-repo.jpg differ diff --git a/docs/en/images/github-myusername.jpg b/docs/en/images/github-myusername.jpg new file mode 100644 index 0000000000..4ac57eeed4 Binary files /dev/null and b/docs/en/images/github-myusername.jpg differ diff --git a/docs/en/images/microservice-sample-update-database-authserver.png b/docs/en/images/microservice-sample-update-database-authserver.png new file mode 100644 index 0000000000..689019b587 Binary files /dev/null and b/docs/en/images/microservice-sample-update-database-authserver.png differ diff --git a/docs/en/images/microservice-sample-update-database-products.png b/docs/en/images/microservice-sample-update-database-products.png new file mode 100644 index 0000000000..b49c2a8f8e Binary files /dev/null and b/docs/en/images/microservice-sample-update-database-products.png differ diff --git a/docs/en/images/night-build-add-nuget-package.png b/docs/en/images/night-build-add-nuget-package.png new file mode 100644 index 0000000000..c3621ef7d9 Binary files /dev/null and b/docs/en/images/night-build-add-nuget-package.png differ diff --git a/docs/en/images/night-build-add-nuget-source.png b/docs/en/images/night-build-add-nuget-source.png new file mode 100644 index 0000000000..8fd4b9365a Binary files /dev/null and b/docs/en/images/night-build-add-nuget-source.png differ diff --git a/docs/en/images/volodocs-iis-add-website.png b/docs/en/images/volodocs-iis-add-website.png new file mode 100644 index 0000000000..878b3e8f0c Binary files /dev/null and b/docs/en/images/volodocs-iis-add-website.png differ diff --git a/docs/en/images/volodocs-iis-application-pool.png b/docs/en/images/volodocs-iis-application-pool.png new file mode 100644 index 0000000000..cc5186f50b Binary files /dev/null and b/docs/en/images/volodocs-iis-application-pool.png differ diff --git a/docs/zh-Hans/AspNetCore/Bundling-Minification.md b/docs/zh-Hans/AspNetCore/Bundling-Minification.md index 7454bd3c17..b7c8c0a1b1 100644 --- a/docs/zh-Hans/AspNetCore/Bundling-Minification.md +++ b/docs/zh-Hans/AspNetCore/Bundling-Minification.md @@ -196,7 +196,7 @@ services.Configure(options => options .ScriptBundles .Configure("MyGlobalBundle", bundle => { - bundle.AddContributors(typeof(MyExtensionStyleBundleContributor)); + bundle.AddContributors(typeof(MyExtensionGlobalStyleContributor)); }); }); ```` @@ -214,7 +214,7 @@ services.Configure(options => `abp-style`和`abp-script`标签可以使用`type`属性(而不是`src`属性), 如本示例所示. 添加bundle贡献者时, 其依赖关系也会自动添加到bundle中. -#### Contributor Dependencies +#### 贡献者依赖关系 bundle贡献者可以与其他贡献者具有一个或多个依赖关系. 例如: @@ -227,9 +227,39 @@ public class MyExtensionStyleBundleContributor : BundleContributor } ```` -添加bundle贡献者时,其依赖关系将 **自动并递归** 添加. **依赖顺序** 通过阻止 **重复** 添加的依赖关系. 即使它们处于分离的束中,也会阻止重复. ABP在页面中组织所有bundle并消除重复. +添加bundle贡献者时,其依赖关系将 **自动并递归** 添加. **依赖顺序** 通过阻止 **重复** 添加的依赖关系. 即使它们处于分离的bundle中,也会阻止重复. ABP在页面中组织所有bundle并消除重复. -创建贡献者和定义依赖关系是一种跨不同模块组织包创建的方法. +创建贡献者和定义依赖关系是一种跨不同模块组织bundle创建的方法. + + +#### 贡献者扩展 + +在某些高级应用场景中, 当用到一个bundle贡献者时,你可能想做一些额外的配置. 贡献者扩展可以和被扩展的贡献者无缝衔接. + +下面的示例为 prism.js 脚本库添加一些样式: + +````csharp +public class MyPrismjsStyleExtension : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.AddIfNotContains("/libs/prismjs/plugins/toolbar/prism-toolbar.css"); + } +} +```` + +然后你可以配置 `BundleContributorOptions` 去扩展已存在的 `PrismjsStyleBundleContributor`. + +````csharp +Configure(options => +{ + options + .Extensions() + .Add(); +}); +```` + +任何时候当 `PrismjsStyleBundleContributor` 被添加到bundle中时, `MyPrismjsStyleExtension` 也会被自动添加. #### 访问 IServiceProvider @@ -239,7 +269,7 @@ public class MyExtensionStyleBundleContributor : BundleContributor 将特定的NPM包资源(js,css文件)添加到包中对于该包非常简单. 例如, 你总是为bootstrap NPM包添加`bootstrap.css`文件. -所有[标准NPM包](Client-Side-Package-Management.md)都有内置的贡献者. 例如,如果你的贡献者依赖于引导程序,你可以声明它,而不是自己添加bootstrap.css. +所有[标准NPM包](Client-Side-Package-Management.md)都有内置的贡献者. 例如,如果你的贡献者依赖于bootstrap,你可以声明它,而不是自己添加bootstrap.css. ````C# [DependsOn(typeof(BootstrapStyleContributor))] //Define the bootstrap style dependency @@ -261,7 +291,7 @@ public class MyExtensionStyleBundleContributor : BundleContributor > 默认情况下已在启动模板安装此软件包. 大多数情况下,你不需要手动安装它. 标准包贡献者在`Volo.Abp.AspNetCore.Mvc.UI.Packages` NuGet包中定义. -安装到你的项目中: +将它安装到你的项目中: ```` install-package Volo.Abp.AspNetCore.Mvc.UI.Packages @@ -283,9 +313,9 @@ namespace MyCompany.MyProject } ```` -#### Bundle Inheritance +#### Bundle 继承 -在某些特定情况下, 可能需要从其他bundle创建一个 **新** bundle **继承**, 从bundle继承(递归)继承该bundle的所有文件/贡献者. 然后派生的bundle可以添加或修改文件/贡献者**而无需修改**原始包. +在某些特定情况下, 可能需要从其他bundle创建一个 **新** bundle **继承**, 从bundle继承(递归)会继承该bundle的所有文件/贡献者. 然后派生的bundle可以添加或修改文件/贡献者**而无需修改**原始bundle. 例如: ````c# diff --git a/docs/zh-Hans/Nightly-Builds.md b/docs/zh-Hans/Nightly-Builds.md new file mode 100644 index 0000000000..c37c9af9bc --- /dev/null +++ b/docs/zh-Hans/Nightly-Builds.md @@ -0,0 +1,25 @@ + # 每日构建 + +所有框架和模块包都每晚都部署到MyGet. 因此你可以使用或测试最新的代码,而无需等待下一个版本. + +## 在Visual Studio配置 + +> 需要Visual Studio 2017以上 + +1. 在VS中打开: `工具 > 选项 > NuGet 包管理器 > 程序包源` +2. 单击绿色的`+`图标 +3. 在底部输入名称(ABP Nightly)和并粘贴URL(`https://www.myget.org/F/abp-nightly/api/v3/index.json`)到源上. + ![night-build-add-nuget-source](images/night-build-add-nuget-source.png) +3. 单击`更新`按钮 +4. 点击`确定`按钮保存 + +## 安装包 + +现在, 你可以从**管理NuGet包** 或 **程序包管理器控制台** 将预览/夜间程序包安装到你的项目中. + +![night-build-add-nuget-package](images/night-build-add-nuget-package.png) + +1. 在nuget浏览中,选择"包括预发行版". +2. 将包源更改为`全部`. +3. 搜索nuget包. 你将看到包的预发布格式为`(VERSION)-preview(DATE)` (如本示例中的**v0.16.0-preview20190401**). +4. 你可以单击`安装`按钮将包添加到项目中. diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 56575a4755..6b98655e85 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -278,6 +278,10 @@ { "text": "测试" }, + { + "text": "每日构建", + "path": "Nightly-Builds.md" + }, { "text": "贡献指南", "path": "Contribution/Index.md" diff --git a/docs/zh-Hans/images/night-build-add-nuget-package.png b/docs/zh-Hans/images/night-build-add-nuget-package.png new file mode 100644 index 0000000000..c3621ef7d9 Binary files /dev/null and b/docs/zh-Hans/images/night-build-add-nuget-package.png differ diff --git a/docs/zh-Hans/images/night-build-add-nuget-source.png b/docs/zh-Hans/images/night-build-add-nuget-source.png new file mode 100644 index 0000000000..8fd4b9365a Binary files /dev/null and b/docs/zh-Hans/images/night-build-add-nuget-source.png differ diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptionsExtensions.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptionsExtensions.cs index a162f1750e..4b473cbf38 100644 --- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptionsExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/MultiTenancy/MultiTenancyOptionsExtensions.cs @@ -8,7 +8,7 @@ namespace Volo.Abp.MultiTenancy public static void AddDomainTenantResolver(this TenantResolveOptions options, string domainFormat) { options.TenantResolvers.InsertAfter( - r => r is CurrentClaimsPrincipalTenantResolveContributor, + r => r is CurrentUserTenantResolveContributor, new DomainTenantResolveContributor(domainFormat) ); } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs index 5a095d561c..cd3294d66f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs @@ -124,8 +124,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form return GetLabelAsHtmlUsingTagHelper(context, output) + GetRequiredSymbol(context, output); } - - + protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output) { if (!TagHelper.DisplayRequiredSymbol) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json index 3c1cb1f82d..2acb0a275b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json @@ -1,9 +1,11 @@ { "culture": "pt-BR", "texts": { - "GivenTenantIsNotAvailable": "Tenant não está disponível: {0}", - "SwitchTenant": "Trocar tenant", + "GivenTenantIsNotAvailable": "Inquilino não está disponível: {0}", + "Tenant": "Inquilino", + "Switch": "trocar", "Name": "Nome", - "SwitchTenantHint": "Deixe o campo de nome em branco para alternar para o lado do host." + "SwitchTenantHint": "Deixe o campo de nome em branco para alternar para o lado do host.", + "NotSelected": "Não selecionado" } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json index 36886a6318..6ab8929f95 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/zh-Hans.json @@ -4,6 +4,9 @@ "GivenTenantIsNotAvailable": "给定的租户不可用: {0}", "SwitchTenant": "切换租户", "Name": "名称", - "SwitchTenantHint": "将name字段留空以切换到宿主端." + "SwitchTenantHint": "将name字段留空以切换到宿主端.", + "Tenant": "租户", + "Switch": "切换", + "NotSelected": "未选中" } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js index e327bd79ed..5d55837b84 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js @@ -69,6 +69,10 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f //TODO: data-ajaxForm comparison seems wrong! if (_$form.attr('data-ajaxForm') === undefined || _$form.attr('data-ajaxForm') === false) { _$form.abpAjaxForm(); + } + + if (_$form.attr('data-check-form-on-close') === undefined || _$form.attr('data-check-form-on-close') != 'false') { + _$form.needConfirmationOnUnsavedClose(_$modal); } _$form.on('abp-ajax-success', diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js index 52ef81d536..c9d11b5fac 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js @@ -3,6 +3,10 @@ return; } + var localize = function (key) { + return abp.localization.getResource('AbpUi')(key); + }; + /* A simple jQuery plug-in to make a button busy. */ $.fn.buttonBusy = function (isBusy) { return $(this).each(function () { @@ -127,4 +131,30 @@ }); }; + $.fn.needConfirmationOnUnsavedClose = function ($modal) { + var $form = $(this); + var formSaved = false; + var unEditedForm = JSON.stringify($form.serializeFormToObject()); + + $modal.on("hide.bs.modal", function (e) { + var currentForm = JSON.stringify($form.serializeFormToObject()); + var thereAreUnsavedChanges = currentForm !== unEditedForm; + + if (!formSaved && thereAreUnsavedChanges) { + e.preventDefault(); + abp.message.confirm(localize('AreYouSureYouWantToCancelEditingWarningMessage'), + function (result) { + if (result) { + formSaved = true; + $modal.modal('hide'); + } + }); + } + }); + + $(this).on('abp-ajax-success',function () { + formSaved = true; + }); + }; + })(jQuery); \ No newline at end of file diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs index a008190fbd..314e88411a 100644 --- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs +++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Permissions/RolePermissionValueProvider.cs @@ -19,6 +19,7 @@ namespace Volo.Abp.Authorization.Permissions public override async Task CheckAsync(PermissionValueCheckContext context) { var roles = context.Principal?.FindAll(AbpClaimTypes.Role).Select(c => c.Value).ToArray(); + if (roles == null || !roles.Any()) { return PermissionGrantResult.Undefined; diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs index 0a86870bb2..36c4780672 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AsyncCrudAppService.cs @@ -34,10 +34,8 @@ namespace Volo.Abp.Application.Services public abstract class AsyncCrudAppService : AsyncCrudAppService - where TGetAllInput : IPagedAndSortedResultRequest where TEntity : class, IEntity where TEntityDto : IEntityDto - where TCreateInput : IEntityDto { protected AsyncCrudAppService(IRepository repository) : base(repository) diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs index 936bcd5fd3..1a79d4308a 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs @@ -225,7 +225,11 @@ namespace Volo.Abp.Http.Client.DynamicProxying } //TODO: Is that the way we want? Couldn't send the culture (not ui culture) - requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(CultureInfo.CurrentUICulture.Name)); + var currentCulture = CultureInfo.CurrentUICulture.Name ?? CultureInfo.CurrentCulture.Name; + if (!currentCulture.IsNullOrEmpty()) + { + requestMessage.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(currentCulture)); + } } private string GetConfiguredApiVersion() diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs deleted file mode 100644 index 0f213ea1d7..0000000000 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentClaimsPrincipalTenantResolveContributor.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Security.Claims; - -namespace Volo.Abp.MultiTenancy -{ - public class CurrentClaimsPrincipalTenantResolveContributor : TenantResolveContributorBase - { - public const string ContributorName = "CurrentClaims"; - - public override string Name => ContributorName; - - public override void Resolve(ITenantResolveContext context) - { - var principal = context.ServiceProvider.GetRequiredService().Principal; - if (principal?.Identity?.IsAuthenticated != true) - { - return; - } - - context.Handled = true; - context.TenantIdOrName = principal - .Claims - .FirstOrDefault(c => c.Type == AbpClaimTypes.TenantId) - ?.Value; - } - } -} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentUserTenantResolveContributor.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentUserTenantResolveContributor.cs new file mode 100644 index 0000000000..d326421682 --- /dev/null +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/CurrentUserTenantResolveContributor.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Users; + +namespace Volo.Abp.MultiTenancy +{ + public class CurrentUserTenantResolveContributor : TenantResolveContributorBase + { + public const string ContributorName = "CurrentUser"; + + public override string Name => ContributorName; + + public override void Resolve(ITenantResolveContext context) + { + var currentUser = context.ServiceProvider.GetRequiredService(); + if (currentUser.IsAuthenticated != true) + { + return; + } + + context.Handled = true; + context.TenantIdOrName = currentUser.TenantId?.ToString(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs index 9d12f2b0b6..b431aaa6d3 100644 --- a/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs +++ b/framework/src/Volo.Abp.MultiTenancy/Volo/Abp/MultiTenancy/TenantResolveOptions.cs @@ -12,7 +12,7 @@ namespace Volo.Abp.MultiTenancy { TenantResolvers = new List { - new CurrentClaimsPrincipalTenantResolveContributor() + new CurrentUserTenantResolveContributor() }; } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json index 9eb47477f4..7aafe07612 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json @@ -45,6 +45,7 @@ "PagerShowMenuEntries": "Show _MENU_ entries", "DatatableActionDropdownDefaultText": "Actions", "ChangePassword": "Change password", - "PersonalInfo": "My profile" + "PersonalInfo": "My profile", + "AreYouSureYouWantToCancelEditingWarningMessage": "You have unsaved changes." } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json index d08ecb4525..54c573857a 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json @@ -26,16 +26,25 @@ "Edit": "Editar", "Refresh": "Refrescar", "ProcessingWithThreeDot": "Processando...", + "LoadingWithThreeDot": "Carregando...", + "Welcome": "Bem Vindo", "Login": "Entrar", - "Register": "cadastrar", + "Register": "Registrar-se", "Logout": "Sair", "Submit": "Enviar", "Back": "Voltar", + "PagerSearch": "Pesquisar", "PagerNext": "Próximo", "PagerPrevious": "Anterior", - "PagerInfo": "Mostrando _START_ até _END_ de _TOTAL_ registros.", + "PagerFirst": "Primeira", + "PagerLast": "Última", + "PagerInfo": "Mostrando _START_ até _END_ de _TOTAL_ registros", + "PagerInfoEmpty": "Mostrando 0 até 0 de 0 registros", + "PagerInfoFiltered": "(filtrado de um total de _MAX_ registros)", + "NoDataAvailableInDatatable": "Nenhum dado disponível", + "PagerShowMenuEntries": "Mostrando _MENU_ registros", "DatatableActionDropdownDefaultText": "Ações", - "ChangePassword": "Alterar senha", + "ChangePassword": "Alterar Senha", "PersonalInfo": "Perfil" } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json index d45c353878..5b236f8954 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json @@ -45,6 +45,7 @@ "PagerShowMenuEntries": "Sayfada _MENU_ kayıt göster.", "DatatableActionDropdownDefaultText": "İşlemler", "ChangePassword": "Şifre değiştir", - "PersonalInfo": "Profilim" + "PersonalInfo": "Profilim", + "AreYouSureYouWantToCancelEditingWarningMessage": "Kaydedilmemiş değişiklikler var." } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pt-BR.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pt-BR.json index c7b60f9ca1..c4d8bbf554 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pt-BR.json +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/pt-BR.json @@ -1,6 +1,7 @@ { "culture": "pt-BR", "texts": { - "BirthDate": "Aniversário" + "BirthDate": "Aniversário", + "Value1": "Valor Um" } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/zh-Hans.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/zh-Hans.json new file mode 100644 index 0000000000..8f064e1acb --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "culture": "zh-Hans", + "texts": { + "BirthDate": "生日", + "Value1": "Value One" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json index 0fafc3ee42..ead8fc2af8 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/en.json @@ -1,6 +1,7 @@ { "culture": "en", "texts": { - "USA": "United States of America" + "USA": "United States of America", + "Brazil": "Brasil" } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pt-BR.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pt-BR.json index 39122588cd..03c90ee9fd 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pt-BR.json +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/pt-BR.json @@ -4,4 +4,4 @@ "USA": "Estados Unidos da América", "Brazil": "Brasil" } -} +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/zh-Hans.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/zh-Hans.json new file mode 100644 index 0000000000..21989358c8 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "culture": "zh-Hans", + "texts": { + "USA": "美国", + "Brazil": "巴西" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json index d30db38152..45ccaf0d7b 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json @@ -4,4 +4,4 @@ "ThisFieldIsRequired": "Este campo é obrigatório", "MaxLenghtErrorMessage": "Este campo pode ser no máximo de '{0}' caracteres" } -} +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/zh-Hans.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/zh-Hans.json new file mode 100644 index 0000000000..452560bd98 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "culture": "zh-Hans", + "texts": { + "ThisFieldIsRequired": "此字段是必填字段", + "MaxLenghtErrorMessage": "该字段最多可包含'{0}'个字符" + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json index 65b1f69a03..4423681d76 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json @@ -5,6 +5,7 @@ "Car": "Carro", "CarPlural": "Carros", "MaxLenghtErrorMessage": "O comprimento deste campo pode ser no máximo de '{0}' caracteres", - "Universe": "Universo" + "Universe": "Universo", + "FortyTwo": "Quarenta e Dois" } -} +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/zh-Hans.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/zh-Hans.json new file mode 100644 index 0000000000..c0852faaf7 --- /dev/null +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/zh-Hans.json @@ -0,0 +1,11 @@ +{ + "culture": "zh-Hans", + "texts": { + "Hello {0}.": "你好 {0}.", + "Car": "汽车", + "CarPlural": "汽车", + "MaxLenghtErrorMessage": "此字段的长度最多为'{0}'个字符", + "Universe": "宇宙", + "FortyTwo": "四十二" + } +} \ No newline at end of file diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogRepository_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogRepository_Tests.cs new file mode 100644 index 0000000000..4f626c3636 --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AuditLogRepository_Tests.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.AuditLogging.EntityFrameworkCore +{ + public class AuditLogRepository_Tests : AuditLogRepository_Tests + { + + } +} diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogRepository_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogRepository_Tests.cs new file mode 100644 index 0000000000..ffcc2094ab --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo/Abp/AuditLogging/MongoDB/AuditLogRepository_Tests.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.AuditLogging.MongoDB +{ + public class AuditLogRepository_Tests : AuditLogRepository_Tests + { + + } +} diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogRepository_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogRepository_Tests.cs new file mode 100644 index 0000000000..27ab36f48e --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogRepository_Tests.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Auditing; +using Volo.Abp.Guids; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.AuditLogging +{ + public abstract class AuditLogRepository_Tests : AuditLoggingTestBase + where TStartupModule : IAbpModule + { + protected IAuditLogRepository AuditLogRepository { get; } + protected IGuidGenerator GuidGenerator { get; } + + protected AuditLogRepository_Tests() + { + AuditLogRepository = GetRequiredService(); + GuidGenerator = GetRequiredService(); + } + + [Fact] + public async Task GetListAsync() + { + // Arrange + var userId = new Guid("4456fb0d-74cc-4807-9eee-23e551e6cb06"); + var userId2 = new Guid("4456fb0d-74cc-4807-9eee-23e551e6cb06"); + var ipAddress = "153.1.7.61"; + var firstComment = "first Comment"; + + var log1 = new AuditLogInfo + { + UserId = userId, + ImpersonatorUserId = Guid.NewGuid(), + ImpersonatorTenantId = Guid.NewGuid(), + ExecutionTime = DateTime.Today, + ExecutionDuration = 42, + ClientIpAddress = ipAddress, + ClientName = "MyDesktop", + BrowserInfo = "Chrome", + Comments = new List { firstComment, "Second Comment" }, + UserName = "Douglas", + EntityChanges = { + new EntityChangeInfo + { + EntityId = Guid.NewGuid().ToString(), + EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity", + ChangeType = EntityChangeType.Created, + ChangeTime = DateTime.Now, + PropertyChanges = new List + { + new EntityPropertyChangeInfo + { + PropertyTypeFullName = typeof(string).FullName, + PropertyName = "Name", + NewValue = "New value", + OriginalValue = null + } + } + }, + new EntityChangeInfo + { + EntityId = Guid.NewGuid().ToString(), + EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity", + ChangeType = EntityChangeType.Created, + ChangeTime = DateTime.Now, + PropertyChanges = new List + { + new EntityPropertyChangeInfo + { + PropertyTypeFullName = typeof(string).FullName, + PropertyName = "Name", + NewValue = "New value", + OriginalValue = null + } + } + } + + } + }; + + var log2 = new AuditLogInfo + { + UserId = userId2, + ImpersonatorUserId = Guid.NewGuid(), + ImpersonatorTenantId = Guid.NewGuid(), + ExecutionTime = DateTime.Today, + ExecutionDuration = 42, + ClientIpAddress = ipAddress, + ClientName = "MyDesktop", + BrowserInfo = "Chrome", + Comments = new List { firstComment, "Second Comment" }, + HttpStatusCode = (int?)HttpStatusCode.BadGateway, + EntityChanges = { + new EntityChangeInfo + { + EntityId = Guid.NewGuid().ToString(), + EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity", + ChangeType = EntityChangeType.Created, + ChangeTime = DateTime.Now, + PropertyChanges = new List + { + new EntityPropertyChangeInfo + { + PropertyTypeFullName = typeof(string).FullName, + PropertyName = "Name", + NewValue = "New value", + OriginalValue = null + } + } + } + + } + }; + + AuditLogRepository.Insert(new AuditLog(GuidGenerator, log1)); + AuditLogRepository.Insert(new AuditLog(GuidGenerator, log2)); + + //Assert + var logs = await AuditLogRepository.GetListAsync(); + logs.ShouldNotBeNull(); + logs.ShouldContain(x => x.UserId == userId); + logs.ShouldContain(x => x.UserId == userId2); + } + + [Fact] + public async Task GetCountAsync() + { + // Arrange + var userId = new Guid("4456fb0d-74cc-4807-9eee-23e551e6cb06"); + var userId2 = new Guid("4456fb0d-74cc-4807-9eee-23e551e6cb06"); + var ipAddress = "153.1.7.61"; + var firstComment = "first Comment"; + + var log1 = new AuditLogInfo + { + UserId = userId, + ImpersonatorUserId = Guid.NewGuid(), + ImpersonatorTenantId = Guid.NewGuid(), + ExecutionTime = DateTime.Today, + ExecutionDuration = 42, + ClientIpAddress = ipAddress, + ClientName = "MyDesktop", + BrowserInfo = "Chrome", + Comments = new List { firstComment, "Second Comment" }, + UserName = "Douglas", + EntityChanges = { + new EntityChangeInfo + { + EntityId = Guid.NewGuid().ToString(), + EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity", + ChangeType = EntityChangeType.Created, + ChangeTime = DateTime.Now, + PropertyChanges = new List + { + new EntityPropertyChangeInfo + { + PropertyTypeFullName = typeof(string).FullName, + PropertyName = "Name", + NewValue = "New value", + OriginalValue = null + } + } + }, + new EntityChangeInfo + { + EntityId = Guid.NewGuid().ToString(), + EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity", + ChangeType = EntityChangeType.Created, + ChangeTime = DateTime.Now, + PropertyChanges = new List + { + new EntityPropertyChangeInfo + { + PropertyTypeFullName = typeof(string).FullName, + PropertyName = "Name", + NewValue = "New value", + OriginalValue = null + } + } + } + + } + }; + + var log2 = new AuditLogInfo + { + UserId = userId2, + ImpersonatorUserId = Guid.NewGuid(), + ImpersonatorTenantId = Guid.NewGuid(), + ExecutionTime = DateTime.Today, + ExecutionDuration = 42, + ClientIpAddress = ipAddress, + ClientName = "MyDesktop", + BrowserInfo = "Chrome", + Comments = new List { firstComment, "Second Comment" }, + HttpStatusCode = (int?)HttpStatusCode.BadGateway, + EntityChanges = { + new EntityChangeInfo + { + EntityId = Guid.NewGuid().ToString(), + EntityTypeFullName = "Volo.Abp.AuditLogging.TestEntity", + ChangeType = EntityChangeType.Created, + ChangeTime = DateTime.Now, + PropertyChanges = new List + { + new EntityPropertyChangeInfo + { + PropertyTypeFullName = typeof(string).FullName, + PropertyName = "Name", + NewValue = "New value", + OriginalValue = null + } + } + } + + } + }; + + AuditLogRepository.Insert(new AuditLog(GuidGenerator, log1)); + AuditLogRepository.Insert(new AuditLog(GuidGenerator, log2)); + + //Assert + var logs = await AuditLogRepository.GetCountAsync(); + logs.ShouldBe(2); + } + } +} diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogging_Repository_Resolve_Tests.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogging_Repository_Resolve_Tests.cs new file mode 100644 index 0000000000..340e3c7f3c --- /dev/null +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo/Abp/AuditLogging/AuditLogging_Repository_Resolve_Tests.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Volo.Abp.Modularity; + +namespace Volo.Abp.AuditLogging +{ + public class AuditLogging_Repository_Resolve_Tests : AuditLoggingTestBase + where TStartupModule : IAbpModule + { + + } +} diff --git a/modules/blogging/Volo.Blogging.sln b/modules/blogging/Volo.Blogging.sln index 05982d4524..1c4ac401bb 100644 --- a/modules/blogging/Volo.Blogging.sln +++ b/modules/blogging/Volo.Blogging.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.2026 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.Domain.Shared", "src\Volo.Blogging.Domain.Shared\Volo.Blogging.Domain.Shared.csproj", "{F1D954AD-001A-4533-A8CC-94DDCF70B552}" EndProject @@ -35,9 +35,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.EntityFramewo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.Application.Tests", "test\Volo.Blogging.Application.Tests\Volo.Blogging.Application.Tests.csproj", "{C949B953-80B3-4B36-B535-1AD74A34FEAC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Blogging.MongoDB", "src\Volo.Blogging.MongoDB\Volo.Blogging.MongoDB.csproj", "{98C2D36A-F874-405D-8565-9CE59438E879}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.MongoDB", "src\Volo.Blogging.MongoDB\Volo.Blogging.MongoDB.csproj", "{98C2D36A-F874-405D-8565-9CE59438E879}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.BloggingTestApp.MongoDb", "app\Volo.BloggingTestApp.MongoDb\Volo.BloggingTestApp.MongoDb.csproj", "{4C818374-2DE8-422F-8585-975E8366DB26}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.BloggingTestApp.MongoDb", "app\Volo.BloggingTestApp.MongoDb\Volo.BloggingTestApp.MongoDb.csproj", "{4C818374-2DE8-422F-8585-975E8366DB26}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Blogging.MongoDB.Tests", "test\Volo.Blogging.MongoDB.Tests\Volo.Blogging.MongoDB.Tests.csproj", "{0A29F64C-11F1-40B6-8E6D-91E86823775E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Blogging.Domain.Tests", "test\Volo.Blogging.Domain.Tests\Volo.Blogging.Domain.Tests.csproj", "{B6D7EF20-9921-490A-AA95-47E3E174DC9B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -105,6 +109,14 @@ Global {4C818374-2DE8-422F-8585-975E8366DB26}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C818374-2DE8-422F-8585-975E8366DB26}.Release|Any CPU.ActiveCfg = Release|Any CPU {4C818374-2DE8-422F-8585-975E8366DB26}.Release|Any CPU.Build.0 = Release|Any CPU + {0A29F64C-11F1-40B6-8E6D-91E86823775E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0A29F64C-11F1-40B6-8E6D-91E86823775E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0A29F64C-11F1-40B6-8E6D-91E86823775E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0A29F64C-11F1-40B6-8E6D-91E86823775E}.Release|Any CPU.Build.0 = Release|Any CPU + {B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6D7EF20-9921-490A-AA95-47E3E174DC9B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -125,6 +137,8 @@ Global {C949B953-80B3-4B36-B535-1AD74A34FEAC} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B} {98C2D36A-F874-405D-8565-9CE59438E879} = {42BF26EF-B8C7-42DC-9FFB-3653109B7776} {4C818374-2DE8-422F-8585-975E8366DB26} = {EB4FB44A-FE39-4245-9DAD-D6437BCE3870} + {0A29F64C-11F1-40B6-8E6D-91E86823775E} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B} + {B6D7EF20-9921-490A-AA95-47E3E174DC9B} = {25B3A516-5C0D-42E3-9294-E8A9346CEE4B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F2BAE819-78D4-407A-9201-22473B2850B0} diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs index 6ed5d57c2a..08dde7e019 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/PostWithDetailsDto.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using JetBrains.Annotations; using Volo.Abp.Application.Dtos; using Volo.Blogging.Tagging.Dtos; @@ -21,6 +22,7 @@ namespace Volo.Blogging.Posts public int CommentCount { get; set; } + [CanBeNull] public BlogUserDto Writer { get; set; } public List Tags { get; set; } diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs index 916455bc47..6787718a21 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs @@ -156,7 +156,6 @@ namespace Volo.Blogging.Posts var post = new Post( id: GuidGenerator.Create(), blogId: input.BlogId, - creatorId: CurrentUser.GetId(), title: input.Title, coverImage: input.CoverImage, url: input.Url diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Blogs/IBlogRepository.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Blogs/IBlogRepository.cs index 27e01a0262..ade8d1be0e 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Blogs/IBlogRepository.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Blogs/IBlogRepository.cs @@ -7,7 +7,5 @@ namespace Volo.Blogging.Blogs public interface IBlogRepository : IBasicRepository { Task FindByShortNameAsync(string shortName); - - Task GetTotalCount(); } } diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs index 8e4a898ce4..ee44e7e029 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/Post.cs @@ -23,7 +23,6 @@ namespace Volo.Blogging.Posts [CanBeNull] public virtual string Content { get; set; } - [CanBeNull] public virtual int ReadCount { get; protected set; } public virtual Collection Tags { get; protected set; } @@ -33,10 +32,9 @@ namespace Volo.Blogging.Posts } - public Post(Guid id, Guid blogId, Guid creatorId, [NotNull] string title, [NotNull] string coverImage, [NotNull] string url) + public Post(Guid id, Guid blogId, [NotNull] string title, [NotNull] string coverImage, [NotNull] string url) { Id = id; - CreatorId = creatorId; BlogId = blogId; Title = Check.NotNullOrWhiteSpace(title, nameof(title)); Url = Check.NotNullOrWhiteSpace(url, nameof(url)); diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs index f89d5f981f..28d14d885d 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Tagging/Tag.cs @@ -44,6 +44,13 @@ namespace Volo.Blogging.Tagging { return; } + + if (UsageCount - number <= 0) + { + UsageCount = 0; + return; + } + UsageCount -= number; } diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs index 5c9b43e8ed..604f7ca8b5 100644 --- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs +++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Blogs/EfCoreBlogRepository.cs @@ -19,10 +19,5 @@ namespace Volo.Blogging.Blogs { return await DbSet.FirstOrDefaultAsync(p => p.ShortName == shortName); } - - public async Task GetTotalCount() - { - return await DbSet.CountAsync(); - } } } diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs index 8a3b759730..b1c7b5d319 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Blogs/MongoBlogRepository.cs @@ -17,10 +17,5 @@ namespace Volo.Blogging.Blogs { return await GetMongoQueryable().FirstOrDefaultAsync(p => p.ShortName == shortName); } - - public async Task GetTotalCount() - { - return await GetMongoQueryable().CountAsync(); - } } } diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs index 1dedad184b..e2fcdca96c 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Tagging/MongoTagRepository.cs @@ -44,6 +44,7 @@ namespace Volo.Blogging.Tagging foreach (var tag in tags) { tag.DecreaseUsageCount(); + Update(tag); } } } diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml index 8dc8845982..f604ef40a7 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml @@ -46,11 +46,18 @@
-
- @if (Model.Post.Tags.Count > 0) - { -
-
@L["TagsInThisArticle"]
- @foreach (var tag in Model.Post.Tags) +
+ @if (Model.Post.Tags.Count > 0) { - @tag.Name +
+
@L["TagsInThisArticle"]
+ @foreach (var tag in Model.Post.Tags) + { + @tag.Name + } +
} -
- } - @if (Model.CommentsWithReplies.Count > 0) - { - - -

@L["CommentWithCount", @Model.CommentCount]

- @if (hasCommentingPermission) - { - @L["LeaveComment"] - } - else - { - @L["LeaveComment"] - } -
-
- } - -
- @foreach (var commentWithRepliesDto in Model.CommentsWithReplies) - { -
- -
-
- @(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName) - @ConvertDatetimeToTimeAgo(commentWithRepliesDto.Comment.CreationTime) -
-

- @commentWithRepliesDto.Comment.Text -

-
- + @if (Model.CommentsWithReplies.Count > 0) + { + + +

@L["CommentWithCount", @Model.CommentCount]

@if (hasCommentingPermission) { - - @L["Reply"] - + @L["LeaveComment"] } - - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete)) + else { - | - - @L["Delete"] - + @L["LeaveComment"] } +
+
+ } - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { - | - - @L["Edit"] - - } -
+
+ @foreach (var commentWithRepliesDto in Model.CommentsWithReplies) + { +
+ +
+
+ @(commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName) + @ConvertDatetimeToTimeAgo(commentWithRepliesDto.Comment.CreationTime) +
+

+ @commentWithRepliesDto.Comment.Text +

+
- @if (hasCommentingPermission) - { -
-
-

- @L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName] + @if (hasCommentingPermission) + { + + @L["Reply"] + + } -

-
-
- - + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete)) + { + | + + @L["Delete"] + + } -
- + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { + | + + @L["Edit"] + + } +
+ + @if (hasCommentingPermission) + { +
+
+

+ @L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName] + +

+
+ + + + +
+ +
+ + +
- - - +
-
-
- } - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { -
-
-
-
- -
- + } + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { +
+
+
+ + +
+ +
+ + +
- - - +
-
-
- } + } - @foreach (var reply in commentWithRepliesDto.Replies) - { -
- -
-
- @(reply.Writer == null ? "" : reply.Writer.UserName) - @ConvertDatetimeToTimeAgo(reply.CreationTime) -
-

- @reply.Text -

-
+ @foreach (var reply in commentWithRepliesDto.Replies) + { +
+ +
+
+ @(reply.Writer == null ? "" : reply.Writer.UserName) + @ConvertDatetimeToTimeAgo(reply.CreationTime) +
+

+ @reply.Text +

+
- @if (hasCommentingPermission) - { - - @L["Reply"] - - } - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { - | - - @L["Delete"] - - } + @if (hasCommentingPermission) + { + + @L["Reply"] + + } + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Delete) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { + | + + @L["Delete"] + + } - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { - | - - @L["Edit"] - - } -
+ @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { + | + + @L["Edit"] + + } +
- @if (hasCommentingPermission) - { -
-
-

- @L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName] -

-
-
- - -
- + @if (hasCommentingPermission) + { +
+
+

+ @L["ReplyTo", commentWithRepliesDto.Comment.Writer == null ? "" : commentWithRepliesDto.Comment.Writer.UserName] +

+
+ + + +
+ +
+ + +
- - - +
-
-
- } - @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) - { -
-
-
-
- -
- + } + @if (await Authorization.IsGrantedAsync(BloggingPermissions.Comments.Update) || (CurrentUser.Id == commentWithRepliesDto.Comment.CreatorId)) + { +
+
+
+ + +
+ +
+ + +
- - - +
-
+ }
- } -
+
+ }
- } -
+
+ }
- } -
- @if (hasCommentingPermission) - { -
-
-

@L["LeaveComment"]

-
-
-
-
- - -
- + @if (hasCommentingPermission) + { +
+
+

@L["LeaveComment"]

+
+
+
+ + + +
+ +
+ +
- - +
-
+ } + else + { + @L["LeaveComment"] + }
- } - else - { - @L["LeaveComment"] - } -
diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml index 32a8016d38..c9b8f8e549 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Index.cshtml @@ -81,26 +81,29 @@ @L["ContinueReading"]
-
- } @@ -137,7 +140,12 @@ @@ -196,7 +204,12 @@ - @post.Writer.UserName, @ConvertDatetimeToTimeAgo(post.CreationTime) + @if (post.Writer != null) + { + @(post.Writer.UserName), + } + + @ConvertDatetimeToTimeAgo(post.CreationTime) | diff --git a/modules/blogging/test/Volo.Blogging.Application.Tests/Volo.Blogging.Application.Tests.csproj b/modules/blogging/test/Volo.Blogging.Application.Tests/Volo.Blogging.Application.Tests.csproj index aa2837f443..a36f95ac50 100644 --- a/modules/blogging/test/Volo.Blogging.Application.Tests/Volo.Blogging.Application.Tests.csproj +++ b/modules/blogging/test/Volo.Blogging.Application.Tests/Volo.Blogging.Application.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo.Blogging.Domain.Tests.csproj b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo.Blogging.Domain.Tests.csproj new file mode 100644 index 0000000000..b2911bddee --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo.Blogging.Domain.Tests.csproj @@ -0,0 +1,18 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + diff --git a/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestBase.cs b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestBase.cs new file mode 100644 index 0000000000..7d758ee699 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestBase.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Blogging +{ + public abstract class BloggingDomainTestBase : BloggingTestBase + { + + } +} diff --git a/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestModule.cs b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestModule.cs new file mode 100644 index 0000000000..01ab4b07c7 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/BloggingDomainTestModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Modularity; + +namespace Volo.Blogging +{ + [DependsOn( + typeof(BloggingEntityFrameworkCoreTestModule), + typeof(BloggingTestBaseModule) + )] + public class BloggingDomainTestModule : AbpModule + { + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Blogs/Blog_Tests.cs b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Blogs/Blog_Tests.cs new file mode 100644 index 0000000000..6c44885dde --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Blogs/Blog_Tests.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Shouldly; +using Volo.Blogging.Blogs; +using Xunit; + +namespace Volo.Blogging +{ + public class Blog_Tests + { + [Theory] + [InlineData("aaa")] + [InlineData("bbb")] + public void SetName(string name) + { + var blog = new Blog(Guid.NewGuid(), "test blog", "test"); + blog.SetName(name); + blog.Name.ShouldBe(name); + } + + [Theory] + [InlineData("aaa")] + [InlineData("bbb")] + public void SetShortName(string name) + { + var blog = new Blog(Guid.NewGuid(), "test blog", "test"); + blog.SetShortName(name); + blog.ShortName.ShouldBe(name); + } + } +} diff --git a/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Comments/Comment_Tests.cs b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Comments/Comment_Tests.cs new file mode 100644 index 0000000000..34195d5f81 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Comments/Comment_Tests.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Shouldly; +using Volo.Blogging.Comments; +using Xunit; + +namespace Volo.Blogging +{ + public class Comment_Tests + { + [Theory] + [InlineData("aaa")] + [InlineData("bbb")] + public void SetText(string text) + { + var comment = new Comment(Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), "good"); + comment.SetText(text); + comment.Text.ShouldBe(text); + } + } +} diff --git a/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Posts/Post_Tests.cs b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Posts/Post_Tests.cs new file mode 100644 index 0000000000..2fb96d6b2c --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Posts/Post_Tests.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Shouldly; +using Volo.Blogging.Comments; +using Volo.Blogging.Posts; +using Xunit; + +namespace Volo.Blogging +{ + public class Post_Tests + { + [Fact] + public void IncreaseReadCount() + { + var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io"); + post.IncreaseReadCount(); + post.ReadCount.ShouldBe(1); + } + + [Theory] + [InlineData("aaa")] + [InlineData("bbb")] + public void SetTitle(string title) + { + var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io"); + post.SetTitle(title); + post.Title.ShouldBe(title); + } + + [Theory] + [InlineData("aaa")] + [InlineData("bbb")] + public void SetUrl(string url) + { + var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io"); + post.SetUrl(url); + post.Url.ShouldBe(url); + } + + [Fact] + public void AddTag() + { + var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io"); + var tagId = Guid.NewGuid(); + post.AddTag(tagId); + post.Tags.ShouldContain(x => x.TagId == tagId); + } + + + [Fact] + public void RemoveTag() + { + var post = new Post(Guid.NewGuid(), Guid.NewGuid(), "abp", "⊙o⊙", "abp.io"); + var tagId = Guid.NewGuid(); + post.AddTag(tagId); + + post.Tags.ShouldContain(x => x.TagId == tagId); + + post.RemoveTag(tagId); + post.Tags.ShouldNotContain(x => x.TagId == tagId); + } + + } +} diff --git a/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Tagging/Tag_Tests.cs b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Tagging/Tag_Tests.cs new file mode 100644 index 0000000000..a4368a6341 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Tagging/Tag_Tests.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Shouldly; +using Volo.Blogging.Tagging; +using Xunit; + +namespace Volo.Blogging +{ + public class Tag_Tests + { + [Theory] + [InlineData("aaa")] + [InlineData("bbb")] + public void SetName(string name) + { + var tag = new Tag(Guid.NewGuid(), "abp", 0, "abp tag"); + tag.SetName(name); + tag.Name.ShouldBe(name); + } + + [Theory] + [InlineData(1)] + [InlineData(2)] + [InlineData(3)] + public void IncreaseUsageCount(int number) + { + var tag = new Tag(Guid.NewGuid(), "abp", 0, "abp tag"); + tag.IncreaseUsageCount(number); + tag.UsageCount.ShouldBe(number); + } + + [Theory] + [InlineData(1)] + [InlineData(2)] + [InlineData(3)] + public void DecreaseUsageCount(int number) + { + var tag = new Tag(Guid.NewGuid(), "abp", 10, "abp tag"); + tag.DecreaseUsageCount(number); + tag.UsageCount.ShouldBe(10 - number); + } + + [Fact] + public void DecreaseUsageCount_Should_Greater_ThanOrEqual_Zero() + { + var tag = new Tag(Guid.NewGuid(), "abp", 10, "abp tag"); + tag.DecreaseUsageCount(100); + tag.UsageCount.ShouldBe(0); + } + + [Theory] + [InlineData("aaa")] + [InlineData("bbb")] + public void SetDescription(string description) + { + var tag = new Tag(Guid.NewGuid(), "abp", 0, "abp tag"); + tag.SetDescription(description); + tag.Description.ShouldBe(description); + } + + + } +} diff --git a/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Users/BlogUser_Test.cs b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Users/BlogUser_Test.cs new file mode 100644 index 0000000000..e407d6f3f0 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.Domain.Tests/Volo/Abp/Blogging/Users/BlogUser_Test.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text; +using Shouldly; +using Volo.Abp.Users; +using Volo.Blogging.Users; +using Xunit; + +namespace Volo.Blogging +{ + public class BlogUser_Test + { + [Fact] + public void Update() + { + var userId = Guid.NewGuid(); + var tenantId = Guid.NewGuid(); + var blogUser = new BlogUser(new UserData(userId, "bob lee", "boblee@volosoft.com", "lee", "bob", true, + "123456", true, tenantId)); + var userData = new UserData(userId, "lee bob", "leebob@volosoft.com", "bob", "lee", false, + "654321", false, tenantId); + + blogUser.Update(userData); + + blogUser.Equals(new BlogUser(userData)).ShouldBeTrue(); + } + + [Fact] + public void Update_User_Id_Must_Equals() + { + var userId = Guid.NewGuid(); + var tenantId = Guid.NewGuid(); + var blogUser = new BlogUser(new UserData(userId, "bob lee", "boblee@volosoft.com", "lee", "bob", true, + "123456", true, tenantId)); + + var userData = new UserData(Guid.NewGuid(), "lee bob", "leebob@volosoft.com", "bob", "lee", false, + "654321", false, tenantId); + + Assert.Throws(() => blogUser.Update(userData)); + } + + [Fact] + public void Update_Tenant_Id_Must_Equals() + { + var userId = Guid.NewGuid(); + var tenantId = Guid.NewGuid(); + var blogUser = new BlogUser(new UserData(userId, "bob lee", "boblee@volosoft.com", "lee", "bob", true, + "123456", true, tenantId)); + + var userData = new UserData(userId, "lee bob", "leebob@volosoft.com", "bob", "lee", false, + "654321", false, Guid.NewGuid()); + + Assert.Throws(() => blogUser.Update(userData)); + } + + [Fact] + public void BlogUserEquals() + { + var userId = Guid.NewGuid(); + var tenantId = Guid.NewGuid(); + var blogUser = new BlogUser(new UserData(userId, "bob lee", "john@volosoft.com", "lee", "bob", true, + "123456", true, tenantId)); + + var blogUser2= new BlogUser(new UserData(userId, "bob lee", "john@volosoft.com", "lee", "bob", true, + "123456", true, tenantId)); + + blogUser.Equals(blogUser2).ShouldBeTrue(); + } + } +} diff --git a/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs index b86945418c..4735926cc2 100644 --- a/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs +++ b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs @@ -1,9 +1,8 @@ -using Volo.Blogging.EntityFrameworkCore; +using Volo.Blogging.Blogs; -namespace Volo.Blogging.Blogs +namespace Volo.Blogging { public class BlogRepository_Tests : BlogRepository_Tests { - } -} +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs new file mode 100644 index 0000000000..5013e633fb --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs @@ -0,0 +1,8 @@ +using Volo.Blogging.Comments; + +namespace Volo.Blogging +{ + public class CommentRepository_Tests : CommentRepository_Tests + { + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/EntityFrameworkCore/BloggingEntityFrameworkCoreTestModule.cs b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/EntityFrameworkCore/BloggingEntityFrameworkCoreTestModule.cs index 67c5f7ce8b..59f0be4a24 100644 --- a/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/EntityFrameworkCore/BloggingEntityFrameworkCoreTestModule.cs +++ b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/EntityFrameworkCore/BloggingEntityFrameworkCoreTestModule.cs @@ -2,12 +2,12 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.Extensions.DependencyInjection; using Volo.Abp; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.Modularity; +using Volo.Blogging.EntityFrameworkCore; -namespace Volo.Blogging.EntityFrameworkCore +namespace Volo.Blogging { [DependsOn( typeof(BloggingEntityFrameworkCoreModule), @@ -49,4 +49,4 @@ namespace Volo.Blogging.EntityFrameworkCore _sqliteConnection.Dispose(); } } -} +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs new file mode 100644 index 0000000000..e23247de86 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs @@ -0,0 +1,8 @@ +using Volo.Blogging.Posts; + +namespace Volo.Blogging +{ + public class PostRepository_Tests : PostRepository_Tests + { + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs new file mode 100644 index 0000000000..5de23c7665 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.EntityFrameworkCore.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs @@ -0,0 +1,8 @@ +using Volo.Blogging.Tagging; + +namespace Volo.Blogging +{ + public class TagRepository_Tests : TagRepository_Tests + { + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj new file mode 100644 index 0000000000..093113db66 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + + diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs new file mode 100644 index 0000000000..333746f0f0 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Blogs/BlogRepository_Tests.cs @@ -0,0 +1,8 @@ +using Volo.Blogging.Blogs; + +namespace Volo.Blogging +{ + public class BlogRepository_Tests : BlogRepository_Tests + { + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs new file mode 100644 index 0000000000..353d22d3ee --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Comments/CommentRepository_Tests.cs @@ -0,0 +1,8 @@ +using Volo.Blogging.Comments; + +namespace Volo.Blogging +{ + public class CommentRepository_Tests : CommentRepository_Tests + { + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/BloggingMongoDBTestModule.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/BloggingMongoDBTestModule.cs new file mode 100644 index 0000000000..dc2c1cd47d --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/MongoDB/BloggingMongoDBTestModule.cs @@ -0,0 +1,32 @@ +using Mongo2Go; +using Volo.Abp; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Blogging.MongoDB; + +namespace Volo.Blogging +{ + [DependsOn( + typeof(BloggingTestBaseModule), + typeof(BloggingMongoDbModule) + )] + public class BloggingMongoDBTestModule : AbpModule + { + private MongoDbRunner _mongoDbRunner; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + _mongoDbRunner = MongoDbRunner.Start(); + + Configure(options => + { + options.ConnectionStrings.Default = _mongoDbRunner.ConnectionString; + }); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + _mongoDbRunner.Dispose(); + } + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs new file mode 100644 index 0000000000..6fbaed0768 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Posts/PostRepository_Tests.cs @@ -0,0 +1,8 @@ +using Volo.Blogging.Posts; + +namespace Volo.Blogging +{ + public class PostRepository_Tests : PostRepository_Tests + { + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs new file mode 100644 index 0000000000..c727ef00b3 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo/Blogging/Tagging/TagRepository_Tests.cs @@ -0,0 +1,8 @@ +using Volo.Blogging.Tagging; + +namespace Volo.Blogging +{ + public class TagRepository_Tests : TagRepository_Tests + { + } +} \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestData.cs b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestData.cs index 72910fb6ca..9666201719 100644 --- a/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestData.cs +++ b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestData.cs @@ -9,6 +9,8 @@ namespace Volo.Blogging public Guid Blog1Post1Id { get; } = Guid.NewGuid(); public Guid Blog1Post2Id { get; } = Guid.NewGuid(); public Guid Blog1Post1Comment1Id { get; } = Guid.NewGuid(); + public Guid Blog1Post1Comment2Id { get; } = Guid.NewGuid(); public string Tag1Name { get; } = "Tag1Name"; + public string Tag2Name { get; } = "Tag2Name"; } } \ No newline at end of file diff --git a/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestDataBuilder.cs b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestDataBuilder.cs index b830887fdd..67d8049a06 100644 --- a/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestDataBuilder.cs +++ b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/BloggingTestDataBuilder.cs @@ -39,10 +39,13 @@ namespace Volo.Blogging public async Task BuildAsync() { await _blogRepository.InsertAsync(new Blog(_testData.Blog1Id, "The First Blog", "blog-1")); - await _postRepository.InsertAsync(new Post(_testData.Blog1Post1Id, _testData.Blog1Id, Guid.Empty, "title", "coverImage", "url")); - await _postRepository.InsertAsync(new Post(_testData.Blog1Post2Id, _testData.Blog1Id, Guid.Empty, "title", "coverImage", "url")); + await _postRepository.InsertAsync(new Post(_testData.Blog1Post1Id, _testData.Blog1Id, "title", "coverImage", "url")); + await _postRepository.InsertAsync(new Post(_testData.Blog1Post2Id, _testData.Blog1Id, "title2", "coverImage2", "url2")); await _commentRepository.InsertAsync(new Comment(_testData.Blog1Post1Comment1Id,_testData.Blog1Post1Id,null,"text")); - await _tagRepository.InsertAsync(new Tag(_testData.Blog1Id, _testData.Tag1Name)); + await _commentRepository.InsertAsync(new Comment(_testData.Blog1Post1Comment2Id, _testData.Blog1Post1Id, _testData.Blog1Post1Comment1Id, "text")); + await _tagRepository.InsertAsync(new Tag(_testData.Blog1Id, _testData.Tag1Name, 10)); + await _tagRepository.InsertAsync(new Tag(_testData.Blog1Id, _testData.Tag2Name)); + } } } diff --git a/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Comments/CommentRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Comments/CommentRepository_Tests.cs new file mode 100644 index 0000000000..04db9d9f0b --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Comments/CommentRepository_Tests.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Blogging.Comments +{ + public abstract class CommentRepository_Tests : BloggingTestBase + where TStartupModule : IAbpModule + { + protected ICommentRepository CommentRepository { get; } + protected BloggingTestData BloggingTestData { get; } + + protected CommentRepository_Tests() + { + CommentRepository = GetRequiredService(); + BloggingTestData = GetRequiredService(); + } + + [Fact] + public async Task GetListOfPostAsync() + { + var comments = await CommentRepository.GetListOfPostAsync(BloggingTestData.Blog1Post1Id); + comments.ShouldNotBeNull(); + comments.Count.ShouldBe(2); + comments.ShouldAllBe(x => x.PostId == BloggingTestData.Blog1Post1Id); + } + + [Fact] + public async Task GetCommentCountOfPostAsync() + { + var count = await CommentRepository.GetCommentCountOfPostAsync(BloggingTestData.Blog1Post1Id); + count.ShouldBe(2); + } + + [Fact] + public async Task GetRepliesOfComment() + { + var comment = await CommentRepository.GetRepliesOfComment(BloggingTestData.Blog1Post1Comment1Id); + comment.ShouldNotBeNull(); + comment.ShouldContain(x => x.Id == BloggingTestData.Blog1Post1Comment2Id); + } + + [Fact] + public async Task DeleteOfPost() + { + await CommentRepository.DeleteOfPost(BloggingTestData.Blog1Post1Id); + (await CommentRepository.GetListAsync()).ShouldBeEmpty(); + } + } +} diff --git a/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Posts/PostRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Posts/PostRepository_Tests.cs new file mode 100644 index 0000000000..ee21e200d9 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Posts/PostRepository_Tests.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Blogging.Posts +{ + public abstract class PostRepository_Tests : BloggingTestBase + where TStartupModule : IAbpModule + { + protected IPostRepository PostRepository { get; } + protected BloggingTestData BloggingTestData { get; } + + protected PostRepository_Tests() + { + PostRepository = GetRequiredService(); + BloggingTestData = GetRequiredService(); + } + + [Fact] + public async Task GetListOfPostAsync() + { + var posts = await PostRepository.GetPostsByBlogId(BloggingTestData.Blog1Id); + posts.ShouldNotBeNull(); + posts.Count.ShouldBe(2); + posts.ShouldContain(x => x.Id == BloggingTestData.Blog1Post1Id); + posts.ShouldContain(x => x.Id == BloggingTestData.Blog1Post2Id); + } + + [Fact] + public async Task GetPostByUrl() + { + var post = await PostRepository.GetPostByUrl(BloggingTestData.Blog1Id, "url"); + post.ShouldNotBeNull(); + post.Url.ShouldBe("url"); + } + } +} diff --git a/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Tagging/TagRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Tagging/TagRepository_Tests.cs new file mode 100644 index 0000000000..a81c7dde1e --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Tagging/TagRepository_Tests.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Blogging.Tagging +{ + public abstract class TagRepository_Tests : BloggingTestBase + where TStartupModule : IAbpModule + { + protected ITagRepository TagRepository { get; } + protected BloggingTestData BloggingTestData { get; } + + protected TagRepository_Tests() + { + TagRepository = GetRequiredService(); + BloggingTestData = GetRequiredService(); + } + + [Fact] + public async Task GetListAsync() + { + var tags = await TagRepository.GetListAsync(BloggingTestData.Blog1Id); + tags.ShouldNotBeNull(); + tags.Count.ShouldBe(2); + } + + [Fact] + public async Task GetByNameAsync() + { + var tag = await TagRepository.GetByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name); + tag.ShouldNotBeNull(); + tag.Name.ShouldBe(BloggingTestData.Tag1Name); + } + + [Fact] + public async Task FindByNameAsync() + { + var tag = await TagRepository.FindByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name); + tag.ShouldNotBeNull(); + tag.Name.ShouldBe(BloggingTestData.Tag1Name); + } + + [Fact] + public async Task GetListAsync2() + { + var tagIds = (await TagRepository.GetListAsync()).Select(x => x.Id).ToList(); + var tags = await TagRepository.GetListAsync(tagIds); + tags.ShouldNotBeNull(); + tags.Count.ShouldBe(tagIds.Count); + } + + [Fact] + public async Task DecreaseUsageCountOfTags() + { + var tag = await TagRepository.FindByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name); + var usageCount = tag.UsageCount; + + TagRepository.DecreaseUsageCountOfTags(new List() + { + tag.Id + }); + + await TagRepository.FindByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name); + (await TagRepository.FindByNameAsync(BloggingTestData.Blog1Id, BloggingTestData.Tag1Name)).UsageCount + .ShouldBe(usageCount - 1); + } + } +} diff --git a/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Users/BlogUserRepository_Tests.cs b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Users/BlogUserRepository_Tests.cs new file mode 100644 index 0000000000..3f0e3b7bf7 --- /dev/null +++ b/modules/blogging/test/Volo.Blogging.TestBase/Volo/Blogging/Users/BlogUserRepository_Tests.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Volo.Abp.Modularity; + +namespace Volo.Blogging.Users +{ + public abstract class BlogUserRepository_Tests : BloggingTestBase + where TStartupModule : IAbpModule + { + + } +} diff --git a/modules/docs/README.md b/modules/docs/README.md index 993e009110..ee4e33a785 100644 --- a/modules/docs/README.md +++ b/modules/docs/README.md @@ -1,4 +1,4 @@ -# docs module +# Docs Module This module is used to create technical documentation web sites. [abp.io](https://abp.io) web site uses this module for its documentation. ### Screenshot @@ -7,7 +7,7 @@ This module is used to create technical documentation web sites. [abp.io](https: ### Main Features -* Can read documents from a Github repository. +* Retrieves documents from a Github repository. * Supports Markdown document formatting. * Supports versioning (integrated to Github releases). -* Support multiple projects. \ No newline at end of file +* Supports multiple projects. diff --git a/modules/docs/Volo.Docs.sln b/modules/docs/Volo.Docs.sln index 7e78d7432f..4eaa1cd14a 100644 --- a/modules/docs/Volo.Docs.sln +++ b/modules/docs/Volo.Docs.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{42416152-5BAB-4706-93A6-57A19E71FE14}" EndProject @@ -23,10 +23,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Web", "src\Volo.D EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{555508AD-F593-43E3-9354-9FA51512F181}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.DocsTestApp", "app\Volo.DocsTestApp\Volo.DocsTestApp.csproj", "{30BC20A3-85CE-4907-8FD0-54153C3F190C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.DocsTestApp.EntityFrameworkCore", "app\Volo.DocsTestApp.EntityFrameworkCore\Volo.DocsTestApp.EntityFrameworkCore.csproj", "{A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "domain", "domain", "{A982A58E-1E92-4764-9F56-39E7AABB8556}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "admin-app", "admin-app", "{BCA19441-17E9-43E6-AED1-15344D18F967}" @@ -43,6 +39,24 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Admin.HttpApi.Cli EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Admin.Web", "src\Volo.Docs.Admin.Web\Volo.Docs.Admin.Web.csproj", "{116A6145-9D66-4867-B3EF-A464FAC47946}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{59D430A9-AC61-4457-8338-5DA0705ABB5D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Application.Tests", "test\Volo.Docs.Application.Tests\Volo.Docs.Application.Tests.csproj", "{1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Domain.Tests", "test\Volo.Docs.Domain.Tests\Volo.Docs.Domain.Tests.csproj", "{213F44A8-F9C1-4F04-9159-37E232FF18F2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.EntityFrameworkCore.Tests", "test\Volo.Docs.EntityFrameworkCore.Tests\Volo.Docs.EntityFrameworkCore.Tests.csproj", "{89F895EA-C4A0-4D91-9181-016F78459776}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.TestBase", "test\Volo.Docs.TestBase\Volo.Docs.TestBase.csproj", "{C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.Admin.Application.Tests", "test\Volo.Docs.Admin.Application.Tests\Volo.Docs.Admin.Application.Tests.csproj", "{E9CF69BC-EEA6-4621-BE0E-64EE37C89807}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VoloDocs.EntityFrameworkCore", "app\VoloDocs.EntityFrameworkCore\VoloDocs.EntityFrameworkCore.csproj", "{1B459653-8DAC-41CD-A08E-28D6E74265D3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VoloDocs.Web", "app\VoloDocs.Web\VoloDocs.Web.csproj", "{057EA924-4524-4452-840C-5E3D509F2ED3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VoloDocs.Migrator", "app\VoloDocs.Migrator\VoloDocs.Migrator.csproj", "{8A5E5001-C017-44A8-ADDA-DC66C102556E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -81,14 +95,6 @@ Global {871FB966-C89F-4AF5-BB1D-172625AA571C}.Debug|Any CPU.Build.0 = Debug|Any CPU {871FB966-C89F-4AF5-BB1D-172625AA571C}.Release|Any CPU.ActiveCfg = Release|Any CPU {871FB966-C89F-4AF5-BB1D-172625AA571C}.Release|Any CPU.Build.0 = Release|Any CPU - {30BC20A3-85CE-4907-8FD0-54153C3F190C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {30BC20A3-85CE-4907-8FD0-54153C3F190C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {30BC20A3-85CE-4907-8FD0-54153C3F190C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {30BC20A3-85CE-4907-8FD0-54153C3F190C}.Release|Any CPU.Build.0 = Release|Any CPU - {A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A}.Release|Any CPU.Build.0 = Release|Any CPU {37D483C8-400B-4127-A6D0-2EE4E80CB696}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {37D483C8-400B-4127-A6D0-2EE4E80CB696}.Debug|Any CPU.Build.0 = Debug|Any CPU {37D483C8-400B-4127-A6D0-2EE4E80CB696}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -109,6 +115,38 @@ Global {116A6145-9D66-4867-B3EF-A464FAC47946}.Debug|Any CPU.Build.0 = Debug|Any CPU {116A6145-9D66-4867-B3EF-A464FAC47946}.Release|Any CPU.ActiveCfg = Release|Any CPU {116A6145-9D66-4867-B3EF-A464FAC47946}.Release|Any CPU.Build.0 = Release|Any CPU + {1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1BE0A197-55D0-40FF-A182-DBCF2E38D0C3}.Release|Any CPU.Build.0 = Release|Any CPU + {213F44A8-F9C1-4F04-9159-37E232FF18F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {213F44A8-F9C1-4F04-9159-37E232FF18F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {213F44A8-F9C1-4F04-9159-37E232FF18F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {213F44A8-F9C1-4F04-9159-37E232FF18F2}.Release|Any CPU.Build.0 = Release|Any CPU + {89F895EA-C4A0-4D91-9181-016F78459776}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89F895EA-C4A0-4D91-9181-016F78459776}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89F895EA-C4A0-4D91-9181-016F78459776}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89F895EA-C4A0-4D91-9181-016F78459776}.Release|Any CPU.Build.0 = Release|Any CPU + {C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2}.Release|Any CPU.Build.0 = Release|Any CPU + {E9CF69BC-EEA6-4621-BE0E-64EE37C89807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E9CF69BC-EEA6-4621-BE0E-64EE37C89807}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E9CF69BC-EEA6-4621-BE0E-64EE37C89807}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E9CF69BC-EEA6-4621-BE0E-64EE37C89807}.Release|Any CPU.Build.0 = Release|Any CPU + {1B459653-8DAC-41CD-A08E-28D6E74265D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B459653-8DAC-41CD-A08E-28D6E74265D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B459653-8DAC-41CD-A08E-28D6E74265D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B459653-8DAC-41CD-A08E-28D6E74265D3}.Release|Any CPU.Build.0 = Release|Any CPU + {057EA924-4524-4452-840C-5E3D509F2ED3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {057EA924-4524-4452-840C-5E3D509F2ED3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {057EA924-4524-4452-840C-5E3D509F2ED3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {057EA924-4524-4452-840C-5E3D509F2ED3}.Release|Any CPU.Build.0 = Release|Any CPU + {8A5E5001-C017-44A8-ADDA-DC66C102556E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8A5E5001-C017-44A8-ADDA-DC66C102556E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8A5E5001-C017-44A8-ADDA-DC66C102556E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8A5E5001-C017-44A8-ADDA-DC66C102556E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -122,8 +160,6 @@ Global {30808C64-F590-47F7-AF8A-256F6B6E186B} = {8B0CDFC9-E313-4323-9390-59CFFAAC60B5} {BF3FDDFF-BED8-422C-82E9-07F181A2D47F} = {8B0CDFC9-E313-4323-9390-59CFFAAC60B5} {871FB966-C89F-4AF5-BB1D-172625AA571C} = {8B0CDFC9-E313-4323-9390-59CFFAAC60B5} - {30BC20A3-85CE-4907-8FD0-54153C3F190C} = {555508AD-F593-43E3-9354-9FA51512F181} - {A5F88BCB-6B22-4E2D-AE89-AEF1E3DC727A} = {555508AD-F593-43E3-9354-9FA51512F181} {A982A58E-1E92-4764-9F56-39E7AABB8556} = {42416152-5BAB-4706-93A6-57A19E71FE14} {BCA19441-17E9-43E6-AED1-15344D18F967} = {42416152-5BAB-4706-93A6-57A19E71FE14} {8B0CDFC9-E313-4323-9390-59CFFAAC60B5} = {42416152-5BAB-4706-93A6-57A19E71FE14} @@ -132,6 +168,14 @@ Global {262F38DB-62AF-427F-96E2-C6385C5AB695} = {BCA19441-17E9-43E6-AED1-15344D18F967} {81EE378A-0DE1-47BA-86D9-08EF6317BB95} = {BCA19441-17E9-43E6-AED1-15344D18F967} {116A6145-9D66-4867-B3EF-A464FAC47946} = {BCA19441-17E9-43E6-AED1-15344D18F967} + {1BE0A197-55D0-40FF-A182-DBCF2E38D0C3} = {59D430A9-AC61-4457-8338-5DA0705ABB5D} + {213F44A8-F9C1-4F04-9159-37E232FF18F2} = {59D430A9-AC61-4457-8338-5DA0705ABB5D} + {89F895EA-C4A0-4D91-9181-016F78459776} = {59D430A9-AC61-4457-8338-5DA0705ABB5D} + {C8BF652A-6DDF-4E5C-8CBA-BA5AFC50BFE2} = {59D430A9-AC61-4457-8338-5DA0705ABB5D} + {E9CF69BC-EEA6-4621-BE0E-64EE37C89807} = {59D430A9-AC61-4457-8338-5DA0705ABB5D} + {1B459653-8DAC-41CD-A08E-28D6E74265D3} = {555508AD-F593-43E3-9354-9FA51512F181} + {057EA924-4524-4452-840C-5E3D509F2ED3} = {555508AD-F593-43E3-9354-9FA51512F181} + {8A5E5001-C017-44A8-ADDA-DC66C102556E} = {555508AD-F593-43E3-9354-9FA51512F181} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {13691265-2547-4FFF-B757-E8FACB05679D} diff --git a/modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml b/modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml deleted file mode 100644 index ca46c1b442..0000000000 --- a/modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml +++ /dev/null @@ -1,4 +0,0 @@ -@page -@model Volo.DocsTestApp.Pages.IndexModel -

Welcome to the Docs Demo!

-
Go to documents... \ No newline at end of file diff --git a/modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml.cs b/modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml.cs deleted file mode 100644 index c1600215d5..0000000000 --- a/modules/docs/app/Volo.DocsTestApp/Pages/Index.cshtml.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace Volo.DocsTestApp.Pages -{ - public class IndexModel : PageModel - { - public void OnGet() - { - } - } -} \ No newline at end of file diff --git a/modules/docs/app/Volo.DocsTestApp/appsettings.json b/modules/docs/app/Volo.DocsTestApp/appsettings.json deleted file mode 100644 index 50d08262f8..0000000000 --- a/modules/docs/app/Volo.DocsTestApp/appsettings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ConnectionStrings": { - "SqlServer": "Server=localhost;Database=DocsTestApp;Trusted_Connection=True;MultipleActiveResultSets=true", - "MongoDb": "mongodb://localhost:27017|DocsTestApp" - } -} \ No newline at end of file diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/jquery-validation/localization/messages_de.js b/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/jquery-validation/localization/messages_de.js deleted file mode 100644 index 89c00c1bab..0000000000 --- a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/jquery-validation/localization/messages_de.js +++ /dev/null @@ -1,32 +0,0 @@ -(function( factory ) { - if ( typeof define === "function" && define.amd ) { - define( ["jquery", "../jquery.validate"], factory ); - } else if (typeof module === "object" && module.exports) { - module.exports = factory( require( "jquery" ) ); - } else { - factory( jQuery ); - } -}(function( $ ) { - -/* - * Translated default messages for the jQuery validation plugin. - * Locale: DE (German, Deutsch) - */ -$.extend( $.validator.messages, { - required: "Dieses Feld ist ein Pflichtfeld.", - maxlength: $.validator.format( "Geben Sie bitte maximal {0} Zeichen ein." ), - minlength: $.validator.format( "Geben Sie bitte mindestens {0} Zeichen ein." ), - rangelength: $.validator.format( "Geben Sie bitte mindestens {0} und maximal {1} Zeichen ein." ), - email: "Geben Sie bitte eine gültige E-Mail Adresse ein.", - url: "Geben Sie bitte eine gültige URL ein.", - date: "Bitte geben Sie ein gültiges Datum ein.", - number: "Geben Sie bitte eine Nummer ein.", - digits: "Geben Sie bitte nur Ziffern ein.", - equalTo: "Bitte denselben Wert wiederholen.", - range: $.validator.format( "Geben Sie bitte einen Wert zwischen {0} und {1} ein." ), - max: $.validator.format( "Geben Sie bitte einen Wert kleiner oder gleich {0} ein." ), - min: $.validator.format( "Geben Sie bitte einen Wert größer oder gleich {0} ein." ), - creditcard: "Geben Sie bitte eine gültige Kreditkarten-Nummer ein." -} ); -return $; -})); \ No newline at end of file diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/lodash/lodash.min.js b/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/lodash/lodash.min.js deleted file mode 100644 index fced00b390..0000000000 --- a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/lodash/lodash.min.js +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @license - * Lodash lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE - */ -;(function(){function n(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function t(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u"']/g,G=RegExp(V.source),H=RegExp(K.source),J=/<%-([\s\S]+?)%>/g,Y=/<%([\s\S]+?)%>/g,Q=/<%=([\s\S]+?)%>/g,X=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,nn=/^\w*$/,tn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,rn=/[\\^$.*+?()[\]{}|]/g,en=RegExp(rn.source),un=/^\s+|\s+$/g,on=/^\s+/,fn=/\s+$/,cn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,an=/\{\n\/\* \[wrapped with (.+)\] \*/,ln=/,? & /,sn=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,hn=/\\(\\)?/g,pn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,_n=/\w*$/,vn=/^[-+]0x[0-9a-f]+$/i,gn=/^0b[01]+$/i,dn=/^\[object .+?Constructor\]$/,yn=/^0o[0-7]+$/i,bn=/^(?:0|[1-9]\d*)$/,xn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,jn=/($^)/,wn=/['\n\r\u2028\u2029\\]/g,mn="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?)*",An="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+mn,En="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",kn=RegExp("['\u2019]","g"),Sn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),On=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+En+mn,"g"),In=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])|\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])|\\d+",An].join("|"),"g"),Rn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),zn=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Wn="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Bn={}; -Bn["[object Float32Array]"]=Bn["[object Float64Array]"]=Bn["[object Int8Array]"]=Bn["[object Int16Array]"]=Bn["[object Int32Array]"]=Bn["[object Uint8Array]"]=Bn["[object Uint8ClampedArray]"]=Bn["[object Uint16Array]"]=Bn["[object Uint32Array]"]=true,Bn["[object Arguments]"]=Bn["[object Array]"]=Bn["[object ArrayBuffer]"]=Bn["[object Boolean]"]=Bn["[object DataView]"]=Bn["[object Date]"]=Bn["[object Error]"]=Bn["[object Function]"]=Bn["[object Map]"]=Bn["[object Number]"]=Bn["[object Object]"]=Bn["[object RegExp]"]=Bn["[object Set]"]=Bn["[object String]"]=Bn["[object WeakMap]"]=false; -var Ln={};Ln["[object Arguments]"]=Ln["[object Array]"]=Ln["[object ArrayBuffer]"]=Ln["[object DataView]"]=Ln["[object Boolean]"]=Ln["[object Date]"]=Ln["[object Float32Array]"]=Ln["[object Float64Array]"]=Ln["[object Int8Array]"]=Ln["[object Int16Array]"]=Ln["[object Int32Array]"]=Ln["[object Map]"]=Ln["[object Number]"]=Ln["[object Object]"]=Ln["[object RegExp]"]=Ln["[object Set]"]=Ln["[object String]"]=Ln["[object Symbol]"]=Ln["[object Uint8Array]"]=Ln["[object Uint8ClampedArray]"]=Ln["[object Uint16Array]"]=Ln["[object Uint32Array]"]=true, -Ln["[object Error]"]=Ln["[object Function]"]=Ln["[object WeakMap]"]=false;var Un={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Cn=parseFloat,Dn=parseInt,Mn=typeof global=="object"&&global&&global.Object===Object&&global,Tn=typeof self=="object"&&self&&self.Object===Object&&self,$n=Mn||Tn||Function("return this")(),Fn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Nn=Fn&&typeof module=="object"&&module&&!module.nodeType&&module,Pn=Nn&&Nn.exports===Fn,Zn=Pn&&Mn.process,qn=function(){ -try{var n=Nn&&Nn.f&&Nn.f("util").types;return n?n:Zn&&Zn.binding&&Zn.binding("util")}catch(n){}}(),Vn=qn&&qn.isArrayBuffer,Kn=qn&&qn.isDate,Gn=qn&&qn.isMap,Hn=qn&&qn.isRegExp,Jn=qn&&qn.isSet,Yn=qn&&qn.isTypedArray,Qn=b("length"),Xn=x({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I", -"\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C", -"\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i", -"\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r", -"\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij", -"\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"}),nt=x({"&":"&","<":"<",">":">",'"':""","'":"'"}),tt=x({"&":"&","<":"<",">":">",""":'"',"'":"'"}),rt=function x(mn){function An(n){if(du(n)&&!of(n)&&!(n instanceof Un)){if(n instanceof On)return n;if(ii.call(n,"__wrapped__"))return $e(n)}return new On(n)}function En(){}function On(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=T}function Un(n){this.__wrapped__=n, -this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Mn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t=t?n:t)),n}function _t(n,t,e,u,i,o){var f,c=1&t,a=2&t,l=4&t;if(e&&(f=i?e(n,u,i,o):e(n)),f!==T)return f;if(!gu(n))return n;if(u=of(n)){if(f=me(n),!c)return Ur(n,f)}else{var s=_o(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(cf(n))return Ir(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Ae(n),!c)return a?Mr(n,lt(f,n)):Dr(n,at(f,n))}else{if(!Ln[s])return i?n:{};f=Ee(n,s,c)}}if(o||(o=new Zn), -i=o.get(n))return i;if(o.set(n,f),hf(n))return n.forEach(function(r){f.add(_t(r,t,e,r,n,o))}),f;if(lf(n))return n.forEach(function(r,u){f.set(u,_t(r,t,e,u,n,o))}),f;var a=l?a?ve:_e:a?Wu:zu,p=u?T:a(n);return r(p||n,function(r,u){p&&(u=r,r=n[u]),ot(f,u,_t(r,t,e,u,n,o))}),f}function vt(n){var t=zu(n);return function(r){return gt(r,n,t)}}function gt(n,t,r){var e=r.length;if(null==n)return!e;for(n=Yu(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===T&&!(u in n)||!i(o))return false}return true}function dt(n,t,r){if(typeof n!="function")throw new ni("Expected a function"); -return yo(function(){n.apply(T,r)},t)}function yt(n,t,r,e){var u=-1,i=o,a=true,l=n.length,s=[],h=t.length;if(!l)return s;r&&(t=c(t,k(r))),e?(i=f,a=false):200<=t.length&&(i=O,a=false,t=new Nn(t));n:for(;++ut}function Rt(n,t){return null!=n&&ii.call(n,t)}function zt(n,t){return null!=n&&t in Yu(n)}function Wt(n,t,r){for(var e=r?f:o,u=n[0].length,i=n.length,a=i,l=Vu(i),s=1/0,h=[];a--;){var p=n[a];a&&t&&(p=c(p,k(t))),s=Ui(p.length,s), -l[a]=!r&&(t||120<=u&&120<=p.length)?new Nn(a&&p):T}var p=n[0],_=-1,v=l[0];n:for(;++_r.length?t:kt(t,hr(r,0,-1)),r=null==t?t:t[De(qe(r))],null==r?T:n(r,t,e)}function Ut(n){return du(n)&&"[object Arguments]"==Ot(n)}function Ct(n){ -return du(n)&&"[object ArrayBuffer]"==Ot(n)}function Dt(n){return du(n)&&"[object Date]"==Ot(n)}function Mt(n,t,r,e,u){if(n===t)t=true;else if(null==n||null==t||!du(n)&&!du(t))t=n!==n&&t!==t;else n:{var i=of(n),o=of(t),f=i?"[object Array]":_o(n),c=o?"[object Array]":_o(t),f="[object Arguments]"==f?"[object Object]":f,c="[object Arguments]"==c?"[object Object]":c,a="[object Object]"==f,o="[object Object]"==c;if((c=f==c)&&cf(n)){if(!cf(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Zn),t=i||pf(n)?se(n,t,r,e,Mt,u):he(n,t,f,r,e,Mt,u);else{ -if(!(1&r)&&(i=a&&ii.call(n,"__wrapped__"),f=o&&ii.call(t,"__wrapped__"),i||f)){n=i?n.value():n,t=f?t.value():t,u||(u=new Zn),t=Mt(n,t,r,e,u);break n}if(c)t:if(u||(u=new Zn),i=1&r,f=_e(n),o=f.length,c=_e(t).length,o==c||i){for(a=o;a--;){var l=f[a];if(!(i?l in t:ii.call(t,l))){t=false;break t}}if((c=u.get(n))&&u.get(t))t=c==t;else{c=true,u.set(n,t),u.set(t,n);for(var s=i;++at?r:0,Se(t,r)?n[t]:T}function Xt(n,t,r){var e=-1;return t=c(t.length?t:[Tu],k(ye())), -n=Gt(n,function(n){return{a:c(t,function(t){return t(n)}),b:++e,c:n}}),w(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e=f?c:c*("desc"==r[e]?-1:1);break n}}e=n.b-t.b}return e})}function nr(n,t){return tr(n,t,function(t,r){return Ru(n,r)})}function tr(n,t,r){for(var e=-1,u=t.length,i={};++et||9007199254740991t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Vu(u);++e=u){for(;e>>1,o=n[i];null!==o&&!ju(o)&&(r?o<=t:ot.length?n:kt(n,hr(t,0,-1)),null==n||delete n[De(qe(t))]}function jr(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++ie)return e?br(n[0]):[];for(var u=-1,i=Vu(e);++u=e?n:hr(n,t,r)}function Ir(n,t){if(t)return n.slice();var r=n.length,r=vi?vi(r):new n.constructor(r);return n.copy(r),r}function Rr(n){var t=new n.constructor(n.byteLength);return new _i(t).set(new _i(n)), -t}function zr(n,t){return new n.constructor(t?Rr(n.buffer):n.buffer,n.byteOffset,n.length)}function Wr(n,t){if(n!==t){var r=n!==T,e=null===n,u=n===n,i=ju(n),o=t!==T,f=null===t,c=t===t,a=ju(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&nu?T:i,u=1),t=Yu(t);++eo&&f[0]!==a&&f[o-1]!==a?[]:L(f,a), -o-=c.length,or?r?or(t,n):t:(r=or(t,Si(n/D(t))),Rn.test(t)?Or(M(r),0,n).join(""):r.slice(0,n))}function te(t,r,e,u){function i(){for(var r=-1,c=arguments.length,a=-1,l=u.length,s=Vu(l+c),h=this&&this!==$n&&this instanceof i?f:t;++at||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Br(e,r,h[4]):r,i[4]=e?L(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Lr(e,r,h[6]):r,i[6]=e?L(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Ui(i[8],h[8])),null==i[9]&&(i[9]=h[9]),i[0]=h[0],i[1]=t),n=i[0],t=i[1], -r=i[2],e=i[3],u=i[4],f=i[9]=i[9]===T?c?0:n.length:Li(i[9]-a,0),!f&&24&t&&(t&=-25),Le((h?fo:go)(t&&1!=t?8==t||16==t?Kr(n,t,f):32!=t&&33!=t||u.length?Jr.apply(T,i):te(n,t,r,e):Pr(n,t,r),i),n,t)}function ce(n,t,r,e){return n===T||au(n,ri[r])&&!ii.call(e,r)?t:n}function ae(n,t,r,e,u,i){return gu(n)&&gu(t)&&(i.set(t,n),Yt(n,t,T,ae,i),i.delete(t)),n}function le(n){return bu(n)?T:n}function se(n,t,r,e,u,i){var o=1&r,f=n.length,c=t.length;if(f!=c&&!(o&&c>f))return false;if((c=i.get(n))&&i.get(t))return c==t;var c=-1,a=true,l=2&r?new Nn:T; -for(i.set(n,t),i.set(t,n);++cr&&(r=Li(e+r,0)),_(n,ye(t,3),r)):-1}function Ne(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==T&&(u=Au(r),u=0>r?Li(e+u,0):Ui(u,e-1)),_(n,ye(t,3),u,true)}function Pe(n){return(null==n?0:n.length)?wt(n,1):[]}function Ze(n){ -return n&&n.length?n[0]:T}function qe(n){var t=null==n?0:n.length;return t?n[t-1]:T}function Ve(n,t){return n&&n.length&&t&&t.length?er(n,t):n}function Ke(n){return null==n?n:Ti.call(n)}function Ge(n){if(!n||!n.length)return[];var t=0;return n=i(n,function(n){if(su(n))return t=Li(n.length,t),true}),A(t,function(t){return c(n,b(t))})}function He(t,r){if(!t||!t.length)return[];var e=Ge(t);return null==r?e:c(e,function(t){return n(r,T,t)})}function Je(n){return n=An(n),n.__chain__=true,n}function Ye(n,t){ -return t(n)}function Qe(){return this}function Xe(n,t){return(of(n)?r:eo)(n,ye(t,3))}function nu(n,t){return(of(n)?e:uo)(n,ye(t,3))}function tu(n,t){return(of(n)?c:Gt)(n,ye(t,3))}function ru(n,t,r){return t=r?T:t,t=n&&null==t?n.length:t,fe(n,128,T,T,T,T,t)}function eu(n,t){var r;if(typeof t!="function")throw new ni("Expected a function");return n=Au(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=T),r}}function uu(n,t,r){return t=r?T:t,n=fe(n,8,T,T,T,T,T,t),n.placeholder=uu.placeholder, -n}function iu(n,t,r){return t=r?T:t,n=fe(n,16,T,T,T,T,T,t),n.placeholder=iu.placeholder,n}function ou(n,t,r){function e(t){var r=c,e=a;return c=a=T,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===T||r>=t||0>r||g&&n>=l}function i(){var n=Ko();if(u(n))return o(n);var r,e=yo;r=n-_,n=t-(n-p),r=g?Ui(n,l-r):n,h=e(i,r)}function o(n){return h=T,d&&c?e(n):(c=a=T,s)}function f(){var n=Ko(),r=u(n);if(c=arguments,a=this,p=n,r){if(h===T)return _=n=p,h=yo(i,t),v?e(n):s;if(g)return h=yo(i,t),e(p)}return h===T&&(h=yo(i,t)), -s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ni("Expected a function");return t=ku(t)||0,gu(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Li(ku(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==T&&ao(h),_=0,c=p=a=h=T},f.flush=function(){return h===T?s:o(Ko())},f}function fu(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;return i.has(u)?i.get(u):(e=n.apply(this,e),r.cache=i.set(u,e)||i,e)}if(typeof n!="function"||null!=t&&typeof t!="function")throw new ni("Expected a function"); -return r.cache=new(fu.Cache||Fn),r}function cu(n){if(typeof n!="function")throw new ni("Expected a function");return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function au(n,t){return n===t||n!==n&&t!==t}function lu(n){return null!=n&&vu(n.length)&&!pu(n)}function su(n){return du(n)&&lu(n)}function hu(n){if(!du(n))return false;var t=Ot(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!bu(n); -}function pu(n){return!!gu(n)&&(n=Ot(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function _u(n){return typeof n=="number"&&n==Au(n)}function vu(n){return typeof n=="number"&&-1=n}function gu(n){var t=typeof n;return null!=n&&("object"==t||"function"==t)}function du(n){return null!=n&&typeof n=="object"}function yu(n){return typeof n=="number"||du(n)&&"[object Number]"==Ot(n)}function bu(n){return!(!du(n)||"[object Object]"!=Ot(n))&&(n=gi(n), -null===n||(n=ii.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&ui.call(n)==ai))}function xu(n){return typeof n=="string"||!of(n)&&du(n)&&"[object String]"==Ot(n)}function ju(n){return typeof n=="symbol"||du(n)&&"[object Symbol]"==Ot(n)}function wu(n){if(!n)return[];if(lu(n))return xu(n)?M(n):Ur(n);if(ji&&n[ji]){n=n[ji]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}return t=_o(n),("[object Map]"==t?W:"[object Set]"==t?U:Lu)(n)}function mu(n){return n?(n=ku(n), -n===$||n===-$?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function Au(n){n=mu(n);var t=n%1;return n===n?t?n-t:n:0}function Eu(n){return n?pt(Au(n),0,4294967295):0}function ku(n){if(typeof n=="number")return n;if(ju(n))return F;if(gu(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,n=gu(n)?n+"":n),typeof n!="string")return 0===n?n:+n;n=n.replace(un,"");var t=gn.test(n);return t||yn.test(n)?Dn(n.slice(2),t?2:8):vn.test(n)?F:+n}function Su(n){return Cr(n,Wu(n))}function Ou(n){return null==n?"":yr(n); -}function Iu(n,t,r){return n=null==n?T:kt(n,t),n===T?r:n}function Ru(n,t){return null!=n&&we(n,t,zt)}function zu(n){return lu(n)?qn(n):Vt(n)}function Wu(n){if(lu(n))n=qn(n,true);else if(gu(n)){var t,r=ze(n),e=[];for(t in n)("constructor"!=t||!r&&ii.call(n,t))&&e.push(t);n=e}else{if(t=[],null!=n)for(r in Yu(n))t.push(r);n=t}return n}function Bu(n,t){if(null==n)return{};var r=c(ve(n),function(n){return[n]});return t=ye(t),tr(n,r,function(n,r){return t(n,r[0])})}function Lu(n){return null==n?[]:S(n,zu(n)); -}function Uu(n){return Tf(Ou(n).toLowerCase())}function Cu(n){return(n=Ou(n))&&n.replace(xn,Xn).replace(Sn,"")}function Du(n,t,r){return n=Ou(n),t=r?T:t,t===T?zn.test(n)?n.match(In)||[]:n.match(sn)||[]:n.match(t)||[]}function Mu(n){return function(){return n}}function Tu(n){return n}function $u(n){return qt(typeof n=="function"?n:_t(n,1))}function Fu(n,t,e){var u=zu(t),i=Et(t,u);null!=e||gu(t)&&(i.length||!u.length)||(e=t,t=n,n=this,i=Et(t,zu(t)));var o=!(gu(e)&&"chain"in e&&!e.chain),f=pu(n);return r(i,function(r){ -var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;if(o||t){var r=n(this.__wrapped__);return(r.__actions__=Ur(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,a([this.value()],arguments))})}),n}function Nu(){}function Pu(n){return Ie(n)?b(De(n)):rr(n)}function Zu(){return[]}function qu(){return false}mn=null==mn?$n:rt.defaults($n.Object(),mn,rt.pick($n,Wn));var Vu=mn.Array,Ku=mn.Date,Gu=mn.Error,Hu=mn.Function,Ju=mn.Math,Yu=mn.Object,Qu=mn.RegExp,Xu=mn.String,ni=mn.TypeError,ti=Vu.prototype,ri=Yu.prototype,ei=mn["__core-js_shared__"],ui=Hu.prototype.toString,ii=ri.hasOwnProperty,oi=0,fi=function(){ -var n=/[^.]+$/.exec(ei&&ei.keys&&ei.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),ci=ri.toString,ai=ui.call(Yu),li=$n._,si=Qu("^"+ui.call(ii).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),hi=Pn?mn.Buffer:T,pi=mn.Symbol,_i=mn.Uint8Array,vi=hi?hi.g:T,gi=B(Yu.getPrototypeOf,Yu),di=Yu.create,yi=ri.propertyIsEnumerable,bi=ti.splice,xi=pi?pi.isConcatSpreadable:T,ji=pi?pi.iterator:T,wi=pi?pi.toStringTag:T,mi=function(){try{var n=je(Yu,"defineProperty"); -return n({},"",{}),n}catch(n){}}(),Ai=mn.clearTimeout!==$n.clearTimeout&&mn.clearTimeout,Ei=Ku&&Ku.now!==$n.Date.now&&Ku.now,ki=mn.setTimeout!==$n.setTimeout&&mn.setTimeout,Si=Ju.ceil,Oi=Ju.floor,Ii=Yu.getOwnPropertySymbols,Ri=hi?hi.isBuffer:T,zi=mn.isFinite,Wi=ti.join,Bi=B(Yu.keys,Yu),Li=Ju.max,Ui=Ju.min,Ci=Ku.now,Di=mn.parseInt,Mi=Ju.random,Ti=ti.reverse,$i=je(mn,"DataView"),Fi=je(mn,"Map"),Ni=je(mn,"Promise"),Pi=je(mn,"Set"),Zi=je(mn,"WeakMap"),qi=je(Yu,"create"),Vi=Zi&&new Zi,Ki={},Gi=Me($i),Hi=Me(Fi),Ji=Me(Ni),Yi=Me(Pi),Qi=Me(Zi),Xi=pi?pi.prototype:T,no=Xi?Xi.valueOf:T,to=Xi?Xi.toString:T,ro=function(){ -function n(){}return function(t){return gu(t)?di?di(t):(n.prototype=t,t=new n,n.prototype=T,t):{}}}();An.templateSettings={escape:J,evaluate:Y,interpolate:Q,variable:"",imports:{_:An}},An.prototype=En.prototype,An.prototype.constructor=An,On.prototype=ro(En.prototype),On.prototype.constructor=On,Un.prototype=ro(En.prototype),Un.prototype.constructor=Un,Mn.prototype.clear=function(){this.__data__=qi?qi(null):{},this.size=0},Mn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n], -this.size-=n?1:0,n},Mn.prototype.get=function(n){var t=this.__data__;return qi?(n=t[n],"__lodash_hash_undefined__"===n?T:n):ii.call(t,n)?t[n]:T},Mn.prototype.has=function(n){var t=this.__data__;return qi?t[n]!==T:ii.call(t,n)},Mn.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=qi&&t===T?"__lodash_hash_undefined__":t,this},Tn.prototype.clear=function(){this.__data__=[],this.size=0},Tn.prototype.delete=function(n){var t=this.__data__;return n=ft(t,n),!(0>n)&&(n==t.length-1?t.pop():bi.call(t,n,1), ---this.size,true)},Tn.prototype.get=function(n){var t=this.__data__;return n=ft(t,n),0>n?T:t[n][1]},Tn.prototype.has=function(n){return-1e?(++this.size,r.push([n,t])):r[e][1]=t,this},Fn.prototype.clear=function(){this.size=0,this.__data__={hash:new Mn,map:new(Fi||Tn),string:new Mn}},Fn.prototype.delete=function(n){return n=be(this,n).delete(n),this.size-=n?1:0,n},Fn.prototype.get=function(n){return be(this,n).get(n); -},Fn.prototype.has=function(n){return be(this,n).has(n)},Fn.prototype.set=function(n,t){var r=be(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},Nn.prototype.add=Nn.prototype.push=function(n){return this.__data__.set(n,"__lodash_hash_undefined__"),this},Nn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.clear=function(){this.__data__=new Tn,this.size=0},Zn.prototype.delete=function(n){var t=this.__data__;return n=t.delete(n),this.size=t.size,n},Zn.prototype.get=function(n){ -return this.__data__.get(n)},Zn.prototype.has=function(n){return this.__data__.has(n)},Zn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Tn){var e=r.__data__;if(!Fi||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Fn(e)}return r.set(n,t),this.size=r.size,this};var eo=Fr(mt),uo=Fr(At,true),io=Nr(),oo=Nr(true),fo=Vi?function(n,t){return Vi.set(n,t),n}:Tu,co=mi?function(n,t){return mi(n,"toString",{configurable:true,enumerable:false,value:Mu(t),writable:true})}:Tu,ao=Ai||function(n){ -return $n.clearTimeout(n)},lo=Pi&&1/U(new Pi([,-0]))[1]==$?function(n){return new Pi(n)}:Nu,so=Vi?function(n){return Vi.get(n)}:Nu,ho=Ii?function(n){return null==n?[]:(n=Yu(n),i(Ii(n),function(t){return yi.call(n,t)}))}:Zu,po=Ii?function(n){for(var t=[];n;)a(t,ho(n)),n=gi(n);return t}:Zu,_o=Ot;($i&&"[object DataView]"!=_o(new $i(new ArrayBuffer(1)))||Fi&&"[object Map]"!=_o(new Fi)||Ni&&"[object Promise]"!=_o(Ni.resolve())||Pi&&"[object Set]"!=_o(new Pi)||Zi&&"[object WeakMap]"!=_o(new Zi))&&(_o=function(n){ -var t=Ot(n);if(n=(n="[object Object]"==t?n.constructor:T)?Me(n):"")switch(n){case Gi:return"[object DataView]";case Hi:return"[object Map]";case Ji:return"[object Promise]";case Yi:return"[object Set]";case Qi:return"[object WeakMap]"}return t});var vo=ei?pu:qu,go=Ue(fo),yo=ki||function(n,t){return $n.setTimeout(n,t)},bo=Ue(co),xo=function(n){n=fu(n,function(n){return 500===t.size&&t.clear(),n});var t=n.cache;return n}(function(n){var t=[];return 46===n.charCodeAt(0)&&t.push(""),n.replace(tn,function(n,r,e,u){ -t.push(e?u.replace(hn,"$1"):r||n)}),t}),jo=fr(function(n,t){return su(n)?yt(n,wt(t,1,su,true)):[]}),wo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),ye(r,2)):[]}),mo=fr(function(n,t){var r=qe(t);return su(r)&&(r=T),su(n)?yt(n,wt(t,1,su,true),T,r):[]}),Ao=fr(function(n){var t=c(n,Er);return t.length&&t[0]===n[0]?Wt(t):[]}),Eo=fr(function(n){var t=qe(n),r=c(n,Er);return t===qe(r)?t=T:r.pop(),r.length&&r[0]===n[0]?Wt(r,ye(t,2)):[]}),ko=fr(function(n){var t=qe(n),r=c(n,Er);return(t=typeof t=="function"?t:T)&&r.pop(), -r.length&&r[0]===n[0]?Wt(r,T,t):[]}),So=fr(Ve),Oo=pe(function(n,t){var r=null==n?0:n.length,e=ht(n,t);return ur(n,c(t,function(n){return Se(n,r)?+n:n}).sort(Wr)),e}),Io=fr(function(n){return br(wt(n,1,su,true))}),Ro=fr(function(n){var t=qe(n);return su(t)&&(t=T),br(wt(n,1,su,true),ye(t,2))}),zo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return br(wt(n,1,su,true),T,t)}),Wo=fr(function(n,t){return su(n)?yt(n,t):[]}),Bo=fr(function(n){return mr(i(n,su))}),Lo=fr(function(n){var t=qe(n);return su(t)&&(t=T), -mr(i(n,su),ye(t,2))}),Uo=fr(function(n){var t=qe(n),t=typeof t=="function"?t:T;return mr(i(n,su),T,t)}),Co=fr(Ge),Do=fr(function(n){var t=n.length,t=1=t}),uf=Ut(function(){return arguments}())?Ut:function(n){return du(n)&&ii.call(n,"callee")&&!yi.call(n,"callee")},of=Vu.isArray,ff=Vn?k(Vn):Ct,cf=Ri||qu,af=Kn?k(Kn):Dt,lf=Gn?k(Gn):Tt,sf=Hn?k(Hn):Nt,hf=Jn?k(Jn):Pt,pf=Yn?k(Yn):Zt,_f=ee(Kt),vf=ee(function(n,t){return n<=t}),gf=$r(function(n,t){ -if(ze(t)||lu(t))Cr(t,zu(t),n);else for(var r in t)ii.call(t,r)&&ot(n,r,t[r])}),df=$r(function(n,t){Cr(t,Wu(t),n)}),yf=$r(function(n,t,r,e){Cr(t,Wu(t),n,e)}),bf=$r(function(n,t,r,e){Cr(t,zu(t),n,e)}),xf=pe(ht),jf=fr(function(n,t){n=Yu(n);var r=-1,e=t.length,u=2--n)return t.apply(this,arguments)}},An.ary=ru,An.assign=gf,An.assignIn=df,An.assignInWith=yf,An.assignWith=bf,An.at=xf,An.before=eu,An.bind=Go,An.bindAll=Ff,An.bindKey=Ho,An.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return of(n)?n:[n]},An.chain=Je,An.chunk=function(n,t,r){if(t=(r?Oe(n,t,r):t===T)?1:Li(Au(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Vu(Si(r/t));et?0:t,e)):[]},An.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0,0>t?0:t)):[]},An.dropRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true,true):[]; -},An.dropWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),true):[]},An.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&Oe(n,t,r)&&(r=0,e=u),u=n.length,r=Au(r),0>r&&(r=-r>u?0:u+r),e=e===T||e>u?u:Au(e),0>e&&(e+=u),e=r>e?0:Eu(e);r>>0,r?(n=Ou(n))&&(typeof t=="string"||null!=t&&!sf(t))&&(t=yr(t),!t&&Rn.test(n))?Or(M(n),0,r):n.split(t,r):[]},An.spread=function(t,r){if(typeof t!="function")throw new ni("Expected a function");return r=null==r?0:Li(Au(r),0), -fr(function(e){var u=e[r];return e=Or(e,0,r),u&&a(e,u),n(t,this,e)})},An.tail=function(n){var t=null==n?0:n.length;return t?hr(n,1,t):[]},An.take=function(n,t,r){return n&&n.length?(t=r||t===T?1:Au(t),hr(n,0,0>t?0:t)):[]},An.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===T?1:Au(t),t=e-t,hr(n,0>t?0:t,e)):[]},An.takeRightWhile=function(n,t){return n&&n.length?jr(n,ye(t,3),false,true):[]},An.takeWhile=function(n,t){return n&&n.length?jr(n,ye(t,3)):[]},An.tap=function(n,t){return t(n), -n},An.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ni("Expected a function");return gu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),ou(n,t,{leading:e,maxWait:t,trailing:u})},An.thru=Ye,An.toArray=wu,An.toPairs=Rf,An.toPairsIn=zf,An.toPath=function(n){return of(n)?c(n,De):ju(n)?[n]:Ur(xo(Ou(n)))},An.toPlainObject=Su,An.transform=function(n,t,e){var u=of(n),i=u||cf(n)||pf(n);if(t=ye(t,4),null==e){var o=n&&n.constructor;e=i?u?new o:[]:gu(n)&&pu(o)?ro(gi(n)):{}; -}return(i?r:mt)(n,function(n,r,u){return t(e,n,r,u)}),e},An.unary=function(n){return ru(n,1)},An.union=Io,An.unionBy=Ro,An.unionWith=zo,An.uniq=function(n){return n&&n.length?br(n):[]},An.uniqBy=function(n,t){return n&&n.length?br(n,ye(t,2)):[]},An.uniqWith=function(n,t){return t=typeof t=="function"?t:T,n&&n.length?br(n,T,t):[]},An.unset=function(n,t){return null==n||xr(n,t)},An.unzip=Ge,An.unzipWith=He,An.update=function(n,t,r){return null==n?n:lr(n,t,kr(r)(kt(n,t)),void 0)},An.updateWith=function(n,t,r,e){ -return e=typeof e=="function"?e:T,null!=n&&(n=lr(n,t,kr(r)(kt(n,t)),e)),n},An.values=Lu,An.valuesIn=function(n){return null==n?[]:S(n,Wu(n))},An.without=Wo,An.words=Du,An.wrap=function(n,t){return Xo(kr(t),n)},An.xor=Bo,An.xorBy=Lo,An.xorWith=Uo,An.zip=Co,An.zipObject=function(n,t){return Ar(n||[],t||[],ot)},An.zipObjectDeep=function(n,t){return Ar(n||[],t||[],lr)},An.zipWith=Do,An.entries=Rf,An.entriesIn=zf,An.extend=df,An.extendWith=yf,Fu(An,An),An.add=Yf,An.attempt=$f,An.camelCase=Wf,An.capitalize=Uu, -An.ceil=Qf,An.clamp=function(n,t,r){return r===T&&(r=t,t=T),r!==T&&(r=ku(r),r=r===r?r:0),t!==T&&(t=ku(t),t=t===t?t:0),pt(ku(n),t,r)},An.clone=function(n){return _t(n,4)},An.cloneDeep=function(n){return _t(n,5)},An.cloneDeepWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,5,t)},An.cloneWith=function(n,t){return t=typeof t=="function"?t:T,_t(n,4,t)},An.conformsTo=function(n,t){return null==t||gt(n,t,zu(t))},An.deburr=Cu,An.defaultTo=function(n,t){return null==n||n!==n?t:n},An.divide=Xf,An.endsWith=function(n,t,r){ -n=Ou(n),t=yr(t);var e=n.length,e=r=r===T?e:pt(Au(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},An.eq=au,An.escape=function(n){return(n=Ou(n))&&H.test(n)?n.replace(K,nt):n},An.escapeRegExp=function(n){return(n=Ou(n))&&en.test(n)?n.replace(rn,"\\$&"):n},An.every=function(n,t,r){var e=of(n)?u:bt;return r&&Oe(n,t,r)&&(t=T),e(n,ye(t,3))},An.find=$o,An.findIndex=Fe,An.findKey=function(n,t){return p(n,ye(t,3),mt)},An.findLast=Fo,An.findLastIndex=Ne,An.findLastKey=function(n,t){return p(n,ye(t,3),At); -},An.floor=nc,An.forEach=Xe,An.forEachRight=nu,An.forIn=function(n,t){return null==n?n:io(n,ye(t,3),Wu)},An.forInRight=function(n,t){return null==n?n:oo(n,ye(t,3),Wu)},An.forOwn=function(n,t){return n&&mt(n,ye(t,3))},An.forOwnRight=function(n,t){return n&&At(n,ye(t,3))},An.get=Iu,An.gt=rf,An.gte=ef,An.has=function(n,t){return null!=n&&we(n,t,Rt)},An.hasIn=Ru,An.head=Ze,An.identity=Tu,An.includes=function(n,t,r,e){return n=lu(n)?n:Lu(n),r=r&&!e?Au(r):0,e=n.length,0>r&&(r=Li(e+r,0)),xu(n)?r<=e&&-1r&&(r=Li(e+r,0)),v(n,t,r)):-1},An.inRange=function(n,t,r){return t=mu(t),r===T?(r=t,t=0):r=mu(r),n=ku(n),n>=Ui(t,r)&&n=n},An.isSet=hf,An.isString=xu,An.isSymbol=ju,An.isTypedArray=pf,An.isUndefined=function(n){return n===T},An.isWeakMap=function(n){return du(n)&&"[object WeakMap]"==_o(n)},An.isWeakSet=function(n){return du(n)&&"[object WeakSet]"==Ot(n)},An.join=function(n,t){return null==n?"":Wi.call(n,t)},An.kebabCase=Bf,An.last=qe,An.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==T&&(u=Au(r),u=0>u?Li(e+u,0):Ui(u,e-1)), -t===t){for(r=u+1;r--&&n[r]!==t;);n=r}else n=_(n,d,u,true);return n},An.lowerCase=Lf,An.lowerFirst=Uf,An.lt=_f,An.lte=vf,An.max=function(n){return n&&n.length?xt(n,Tu,It):T},An.maxBy=function(n,t){return n&&n.length?xt(n,ye(t,2),It):T},An.mean=function(n){return y(n,Tu)},An.meanBy=function(n,t){return y(n,ye(t,2))},An.min=function(n){return n&&n.length?xt(n,Tu,Kt):T},An.minBy=function(n,t){return n&&n.length?xt(n,ye(t,2),Kt):T},An.stubArray=Zu,An.stubFalse=qu,An.stubObject=function(){return{}},An.stubString=function(){ -return""},An.stubTrue=function(){return true},An.multiply=tc,An.nth=function(n,t){return n&&n.length?Qt(n,Au(t)):T},An.noConflict=function(){return $n._===this&&($n._=li),this},An.noop=Nu,An.now=Ko,An.pad=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return!t||e>=t?n:(t=(t-e)/2,ne(Oi(t),r)+n+ne(Si(t),r))},An.padEnd=function(n,t,r){n=Ou(n);var e=(t=Au(t))?D(n):0;return t&&et){var e=n;n=t,t=e}return r||n%1||t%1?(r=Mi(),Ui(n+r*(t-n+Cn("1e-"+((r+"").length-1))),t)):ir(n,t)},An.reduce=function(n,t,r){var e=of(n)?l:j,u=3>arguments.length;return e(n,ye(t,4),r,u,eo)},An.reduceRight=function(n,t,r){var e=of(n)?s:j,u=3>arguments.length; -return e(n,ye(t,4),r,u,uo)},An.repeat=function(n,t,r){return t=(r?Oe(n,t,r):t===T)?1:Au(t),or(Ou(n),t)},An.replace=function(){var n=arguments,t=Ou(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},An.result=function(n,t,r){t=Sr(t,n);var e=-1,u=t.length;for(u||(u=1,n=T);++en||9007199254740991=i)return n;if(i=r-D(e),1>i)return e;if(r=o?Or(o,0,i).join(""):n.slice(0,i),u===T)return r+e;if(o&&(i+=r.length-i),sf(u)){if(n.slice(i).search(u)){var f=r;for(u.global||(u=Qu(u.source,Ou(_n.exec(u))+"g")), -u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===T?i:c)}}else n.indexOf(yr(u),i)!=i&&(u=r.lastIndexOf(u),-1e.__dir__?"Right":"")}),e},Un.prototype[n+"Right"]=function(t){return this.reverse()[n](t).reverse()}}),r(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;Un.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({ -iteratee:ye(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),r(["head","last"],function(n,t){var r="take"+(t?"Right":"");Un.prototype[n]=function(){return this[r](1).value()[0]}}),r(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Un.prototype[n]=function(){return this.__filtered__?new Un(this):this[r](1)}}),Un.prototype.compact=function(){return this.filter(Tu)},Un.prototype.find=function(n){return this.filter(n).head()},Un.prototype.findLast=function(n){return this.reverse().find(n); -},Un.prototype.invokeMap=fr(function(n,t){return typeof n=="function"?new Un(this):this.map(function(r){return Lt(r,n,t)})}),Un.prototype.reject=function(n){return this.filter(cu(ye(n)))},Un.prototype.slice=function(n,t){n=Au(n);var r=this;return r.__filtered__&&(0t)?new Un(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),t!==T&&(t=Au(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Un.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Un.prototype.toArray=function(){return this.take(4294967295); -},mt(Un.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=An[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(An.prototype[t]=function(){function t(n){return n=u.apply(An,a([n],f)),e&&h?n[0]:n}var o=this.__wrapped__,f=e?[1]:arguments,c=o instanceof Un,l=f[0],s=c||of(o);s&&r&&typeof l=="function"&&1!=l.length&&(c=s=false);var h=this.__chain__,p=!!this.__actions__.length,l=i&&!h,c=c&&!p;return!i&&s?(o=c?o:new Un(this),o=n.apply(o,f),o.__actions__.push({ -func:Ye,args:[t],thisArg:T}),new On(o,h)):l&&c?n.apply(this,f):(o=this.thru(t),l?e?o.value()[0]:o.value():o)})}),r("pop push shift sort splice unshift".split(" "),function(n){var t=ti[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);An.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(of(u)?u:[],n)}return this[r](function(r){return t.apply(of(r)?r:[],n)})}}),mt(Un.prototype,function(n,t){var r=An[t];if(r){var e=r.name+""; -(Ki[e]||(Ki[e]=[])).push({name:t,func:r})}}),Ki[Jr(T,2).name]=[{name:"wrapper",func:T}],Un.prototype.clone=function(){var n=new Un(this.__wrapped__);return n.__actions__=Ur(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Ur(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Ur(this.__views__),n},Un.prototype.reverse=function(){if(this.__filtered__){var n=new Un(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n; -},Un.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=of(t),u=0>r,i=e?t.length:0;n=i;for(var o=this.__views__,f=0,c=-1,a=o.length;++c=this.__values__.length;return{done:n,value:n?T:this.__values__[this.__index__++]}},An.prototype.plant=function(n){for(var t,r=this;r instanceof En;){ -var e=$e(r);e.__index__=0,e.__values__=T,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},An.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Un?(this.__actions__.length&&(n=new Un(this)),n=n.reverse(),n.__actions__.push({func:Ye,args:[Ke],thisArg:T}),new On(n,this.__chain__)):this.thru(Ke)},An.prototype.toJSON=An.prototype.valueOf=An.prototype.value=function(){return wr(this.__wrapped__,this.__actions__)},An.prototype.first=An.prototype.head,ji&&(An.prototype[ji]=Qe), -An}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?($n._=rt, define(function(){return rt})):Nn?((Nn.exports=rt)._=rt,Fn._=rt):$n._=rt}).call(this); diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/malihu-custom-scrollbar-plugin/package.json b/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/malihu-custom-scrollbar-plugin/package.json deleted file mode 100644 index c0372c902c..0000000000 --- a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/malihu-custom-scrollbar-plugin/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "malihu-custom-scrollbar-plugin", - "version": "3.1.5", - "author": "malihu (http://manos.malihu.gr)", - "description": "Highly customizable custom scrollbar jQuery plugin, featuring vertical/horizontal scrollbars, scrolling momentum, mouse-wheel, keyboard and touch support user defined callbacks etc.", - "license": "MIT", - "homepage": "http://manos.malihu.gr/jquery-custom-content-scroller", - "main": "./jquery.mCustomScrollbar.js", - "repository": { - "type": "git", - "url": "https://github.com/malihu/malihu-custom-scrollbar-plugin.git" - }, - "bugs": { - "url": "https://github.com/malihu/malihu-custom-scrollbar-plugin/issues" - }, - "keywords": [ - "jquery-plugin", - "custom-scrollbar", - "scrollbar" - ], - "files": [ - "jquery.mCustomScrollbar.js", - "jquery.mCustomScrollbar.concat.min.js", - "jquery.mCustomScrollbar.css", - "mCSB_buttons.png", - "readme.md" - ], - "jam": { - "dependencies": { - "jquery": ">=1.6", - "jquery-mousewheel": ">=3.0.6" - } - }, - "dependencies": { - "jquery-mousewheel": ">=3.0.6" - } -} \ No newline at end of file diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/prismjs/package.json b/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/prismjs/package.json deleted file mode 100644 index cbffb02aab..0000000000 --- a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/prismjs/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "prismjs", - "version": "1.15.0", - "description": "Lightweight, robust, elegant syntax highlighting. A spin-off project from Dabblet.", - "main": "prism.js", - "style": "themes/prism.css", - "scripts": { - "test": "mocha tests/testrunner-tests.js && mocha tests/run.js" - }, - "repository": { - "type": "git", - "url": "https://github.com/LeaVerou/prism.git" - }, - "keywords": [ - "prism", - "highlight" - ], - "author": "Lea Verou", - "license": "MIT", - "readmeFilename": "README.md", - "optionalDependencies": { - "clipboard": "^2.0.0" - }, - "devDependencies": { - "chai": "^2.3.0", - "gulp": "^3.8.6", - "gulp-concat": "^2.3.4", - "gulp-header": "^1.0.5", - "gulp-rename": "^1.2.0", - "gulp-uglify": "^0.3.1", - "gulp-replace": "^0.5.4", - "mocha": "^2.2.5", - "yargs": "^3.26.0" - }, - "jspm": { - "main": "prism", - "registry": "jspm", - "jspmPackage": true, - "format": "global", - "files": [ - "components/**/*.js", - "plugins/**/*", - "themes/*.css", - "prism.js" - ] - } -} diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs similarity index 99% rename from modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs index cfa52c4ddc..ab8c782832 100644 --- a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.Designer.cs @@ -5,11 +5,11 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.DocsTestApp.EntityFrameworkCore; +using VoloDocs.EntityFrameworkCore; -namespace Volo.DocsTestApp.EntityFrameworkCore.Migrations +namespace VoloDocs.EntityFrameworkCore.Migrations { - [DbContext(typeof(DocsTestAppDbContext))] + [DbContext(typeof(VoloDocsDbContext))] [Migration("20181225134002_Initial20181225")] partial class Initial20181225 { diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.cs similarity index 99% rename from modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.cs index 5675fc708e..abae1bbc04 100644 --- a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20181225134002_Initial20181225.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace Volo.DocsTestApp.EntityFrameworkCore.Migrations +namespace VoloDocs.EntityFrameworkCore.Migrations { public partial class Initial20181225 : Migration { diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/DocsTestAppDbContextModelSnapshot.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs similarity index 98% rename from modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/DocsTestAppDbContextModelSnapshot.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs index 0037d0cf90..0a93515c64 100644 --- a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Migrations/DocsTestAppDbContextModelSnapshot.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs @@ -4,12 +4,12 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.DocsTestApp.EntityFrameworkCore; +using VoloDocs.EntityFrameworkCore; -namespace Volo.DocsTestApp.EntityFrameworkCore.Migrations +namespace VoloDocs.EntityFrameworkCore.Migrations { - [DbContext(typeof(DocsTestAppDbContext))] - partial class DocsTestAppDbContextModelSnapshot : ModelSnapshot + [DbContext(typeof(VoloDocsDbContext))] + partial class VoloDocsDbContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Volo.DocsTestApp.EntityFrameworkCore.csproj b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocs.EntityFrameworkCore.csproj similarity index 97% rename from modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Volo.DocsTestApp.EntityFrameworkCore.csproj rename to modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocs.EntityFrameworkCore.csproj index 02d4be4be8..b70794e39b 100644 --- a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/Volo.DocsTestApp.EntityFrameworkCore.csproj +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocs.EntityFrameworkCore.csproj @@ -2,6 +2,7 @@ netstandard2.0 + diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/DocsTestAppDbContext.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContext.cs similarity index 76% rename from modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/DocsTestAppDbContext.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContext.cs index 78843aed64..fb6aca4e19 100644 --- a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/DocsTestAppDbContext.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContext.cs @@ -5,11 +5,11 @@ using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Docs.EntityFrameworkCore; -namespace Volo.DocsTestApp.EntityFrameworkCore +namespace VoloDocs.EntityFrameworkCore { - public class DocsTestAppDbContext : AbpDbContext + public class VoloDocsDbContext : AbpDbContext { - public DocsTestAppDbContext(DbContextOptions options) + public VoloDocsDbContext(DbContextOptions options) : base(options) { diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/DocsTestAppDbContextFactory.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContextFactory.cs similarity index 53% rename from modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/DocsTestAppDbContextFactory.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContextFactory.cs index c69e934b64..4daa15555b 100644 --- a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/DocsTestAppDbContextFactory.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContextFactory.cs @@ -3,24 +3,24 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Configuration; -namespace Volo.DocsTestApp.EntityFrameworkCore +namespace VoloDocs.EntityFrameworkCore { - public class DocsTestAppDbContextFactory : IDesignTimeDbContextFactory + public class VoloDocsDbContextFactory : IDesignTimeDbContextFactory { - public DocsTestAppDbContext CreateDbContext(string[] args) + public VoloDocsDbContext CreateDbContext(string[] args) { var configuration = BuildConfiguration(); - var builder = new DbContextOptionsBuilder() - .UseSqlServer(configuration.GetConnectionString("SqlServer")); + var builder = new DbContextOptionsBuilder() + .UseSqlServer(configuration["ConnectionString"]); - return new DocsTestAppDbContext(builder.Options); + return new VoloDocsDbContext(builder.Options); } private static IConfigurationRoot BuildConfiguration() { var builder = new ConfigurationBuilder() - .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../Volo.DocsTestApp/")) + .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../VoloDocs/")) .AddJsonFile("appsettings.json", optional: false); return builder.Build(); diff --git a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/DocsTestAppEntityFrameworkCoreModule.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsEntityFrameworkCoreModule.cs similarity index 84% rename from modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/DocsTestAppEntityFrameworkCoreModule.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsEntityFrameworkCoreModule.cs index f380f6b9d5..44acea9a58 100644 --- a/modules/docs/app/Volo.DocsTestApp.EntityFrameworkCore/DocsTestAppEntityFrameworkCoreModule.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsEntityFrameworkCoreModule.cs @@ -5,7 +5,7 @@ using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Docs.EntityFrameworkCore; -namespace Volo.DocsTestApp.EntityFrameworkCore +namespace VoloDocs.EntityFrameworkCore { [DependsOn( typeof(DocsEntityFrameworkCoreModule), @@ -13,7 +13,7 @@ namespace Volo.DocsTestApp.EntityFrameworkCore typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpEntityFrameworkCoreSqlServerModule))] - public class DocsTestAppEntityFrameworkCoreModule : AbpModule + public class VoloDocsEntityFrameworkCoreModule : AbpModule { } diff --git a/modules/docs/app/VoloDocs.Migrator/AppExtensions.cs b/modules/docs/app/VoloDocs.Migrator/AppExtensions.cs new file mode 100644 index 0000000000..1e99538582 --- /dev/null +++ b/modules/docs/app/VoloDocs.Migrator/AppExtensions.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; + +namespace VoloDocs.Migrator +{ + public static class AppExtensions + { + public static T Resolve(this IAbpApplicationWithInternalServiceProvider app) + { + return (T)app.ServiceProvider.GetRequiredService(); + } + } +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Migrator/Migrate.bat b/modules/docs/app/VoloDocs.Migrator/Migrate.bat new file mode 100644 index 0000000000..0a99a0e804 --- /dev/null +++ b/modules/docs/app/VoloDocs.Migrator/Migrate.bat @@ -0,0 +1 @@ +@dotnet VoloDocs.Migrator.dll \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Migrator/Program.cs b/modules/docs/app/VoloDocs.Migrator/Program.cs new file mode 100644 index 0000000000..68bcb09455 --- /dev/null +++ b/modules/docs/app/VoloDocs.Migrator/Program.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Volo.Abp; +using VoloDocs.EntityFrameworkCore; + +namespace VoloDocs.Migrator +{ + class Program + { + private const string ScriptFile = "Script.txt"; + + static void Main(string[] args) + { + Console.WriteLine("Initializing VoloDocs Migrator ... "); + + using (var app = AbpApplicationFactory.Create()) + { + app.Initialize(); + + using (var dbContext = app.Resolve()) + { + var connectionString = dbContext.Database.GetDbConnection().ConnectionString; + + Console.Clear(); + + if (args != null && args.Contains("-script")) + { + GenerateMigrationScript(dbContext); + return; + } + + RunMigrations(connectionString, dbContext); + } + + Console.WriteLine("\n\nPress ENTER to exit..."); + Console.ReadLine(); + } + } + + private static void RunMigrations(string connectionString, VoloDocsDbContext dbContext) + { + Console.Write("\nThis program updates an existing database or creates a new one if not exists.\n" + + "The following connection string will be used:\n\n" + + connectionString + "\n\n" + + "Are you sure you want to run the migration? (y/n) "); + + if (Console.ReadKey().Key == ConsoleKey.Y) + { + Console.WriteLine("\n\nMigrating database..."); + + try + { + dbContext.Database.Migrate(); + + Console.WriteLine("Migration completed."); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + + while (ex.InnerException != null) + { + ex = ex.InnerException; + Console.WriteLine(ex.Message); + } + + Console.Write("\nThere was problem while applying migrations. " + + "Do you want to create the migration script? (y/n) "); + + if (Console.ReadKey().Key == ConsoleKey.Y) + { + GenerateMigrationScript(dbContext); + } + } + } + } + + private static void GenerateMigrationScript(VoloDocsDbContext dbContext) + { + if (File.Exists(ScriptFile)) + { + File.Delete(ScriptFile); + } + + Console.Write("\nGenerating migration scripts..."); + + File.WriteAllText(ScriptFile, dbContext.Database.GenerateCreateScript()); + + Console.Write("\nMigration script has been created to Script.txt file"); + } + } +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Migrator/VoloDocs.Migrator.csproj b/modules/docs/app/VoloDocs.Migrator/VoloDocs.Migrator.csproj new file mode 100644 index 0000000000..2d828d6735 --- /dev/null +++ b/modules/docs/app/VoloDocs.Migrator/VoloDocs.Migrator.csproj @@ -0,0 +1,27 @@ + + + + Exe + netcoreapp2.2 + win-x64;linux-x64;osx-x64 + + + + + + + + + + PreserveNewest + PreserveNewest + + + + + + PreserveNewest + + + + diff --git a/modules/docs/app/VoloDocs.Migrator/VoloDocsMigratorModule.cs b/modules/docs/app/VoloDocs.Migrator/VoloDocsMigratorModule.cs new file mode 100644 index 0000000000..07aece7a5e --- /dev/null +++ b/modules/docs/app/VoloDocs.Migrator/VoloDocsMigratorModule.cs @@ -0,0 +1,29 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Modularity; +using VoloDocs.EntityFrameworkCore; + +namespace VoloDocs.Migrator +{ + [DependsOn(typeof(VoloDocsEntityFrameworkCoreModule))] + public class VoloDocsMigratorModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + context.Services.AddAbpDbContext(); + + Configure(options => + { + options.ConnectionStrings.Default = configuration["ConnectionString"]; + }); + + Configure(options => + { + options.UseSqlServer(); + }); + } + } +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Migrator/appsettings.json b/modules/docs/app/VoloDocs.Migrator/appsettings.json new file mode 100644 index 0000000000..c9934c1e75 --- /dev/null +++ b/modules/docs/app/VoloDocs.Migrator/appsettings.json @@ -0,0 +1,3 @@ +{ + "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;MultipleActiveResultSets=true" +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Branding/VoloDocsBrandingProvider.cs b/modules/docs/app/VoloDocs.Web/Branding/VoloDocsBrandingProvider.cs new file mode 100644 index 0000000000..88eff01063 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Branding/VoloDocsBrandingProvider.cs @@ -0,0 +1,29 @@ +using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components; +using Volo.Abp.Configuration; +using Volo.Abp.DependencyInjection; + +namespace VoloDocs.Web.Branding +{ + [Dependency(ReplaceServices = true)] + public class VoloDocsBrandingProvider : DefaultBrandingProvider + { + public VoloDocsBrandingProvider(IConfigurationAccessor configurationAccessor) + { + var configuration = configurationAccessor.Configuration; + + if (configuration["Title"] != null) + { + AppName = configuration["Title"]; + } + + if (configuration["LogoUrl"] != null) + { + LogoUrl = configuration["LogoUrl"]; + } + } + + public override string AppName { get; } + + public override string LogoUrl { get; } + } +} diff --git a/modules/docs/app/Volo.DocsTestApp/Controllers/HomeController.cs b/modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs similarity index 79% rename from modules/docs/app/Volo.DocsTestApp/Controllers/HomeController.cs rename to modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs index 0750e72b20..5594306229 100644 --- a/modules/docs/app/Volo.DocsTestApp/Controllers/HomeController.cs +++ b/modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs @@ -1,6 +1,6 @@ using Volo.Abp.AspNetCore.Mvc; -namespace Volo.DocsTestApp.Controllers +namespace VoloDocs.Web.Controllers { public class HomeController : AbpController { diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/en.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/en.json new file mode 100644 index 0000000000..cd8eb98149 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/en.json @@ -0,0 +1,9 @@ +{ + "culture": "en", + "texts": { + "WelcomeVoloDocs": "Welcome to the VoloDocs!", + "NoProjectWarning": "There`s no defined project yet!", + "CreateYourFirstProject": "Click here to start your first project", + "NoProject": "No project!" + } +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/tr.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/tr.json new file mode 100644 index 0000000000..8f49c6e952 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/tr.json @@ -0,0 +1,9 @@ +{ + "culture": "tr", + "texts": { + "WelcomeVoloDocs": "VoloDocs Hoşgeldiniz!", + "NoProjectWarning": "Henüz bir proje yok!", + "CreateYourFirstProject": "İlk projenizi oluşturmak için tıklayın", + "NoProject": "Proje yok!" + } +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Pages/Error.cshtml b/modules/docs/app/VoloDocs.Web/Pages/Error.cshtml new file mode 100644 index 0000000000..1cfff62e21 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Pages/Error.cshtml @@ -0,0 +1,14 @@ +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Docs.Localization +@model VoloDocs.Web.Pages.ErrorModel +@inject IHtmlLocalizer L +@{ +
+
+            @Model.ErrorMessage
+        
+ + @L["BackToWebsite"] +
+} diff --git a/modules/docs/app/Volo.DocsTestApp/Controllers/ErrorController.cs b/modules/docs/app/VoloDocs.Web/Pages/Error.cshtml.cs similarity index 61% rename from modules/docs/app/Volo.DocsTestApp/Controllers/ErrorController.cs rename to modules/docs/app/VoloDocs.Web/Pages/Error.cshtml.cs index 943a3a85f2..5e5c4f639b 100644 --- a/modules/docs/app/Volo.DocsTestApp/Controllers/ErrorController.cs +++ b/modules/docs/app/VoloDocs.Web/Pages/Error.cshtml.cs @@ -1,43 +1,52 @@ -using System; +using System; using System.Collections.Generic; using System.Net; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; -using Serilog; -using Volo.Abp.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; -namespace Volo.DocsTestApp.Controllers +namespace VoloDocs.Web.Pages { - public class ErrorController : AbpController + public class ErrorModel : AbpPageModel { - [Route("error/{statusCode}")] - [HttpGet] - public IActionResult Index(int statusCode = 0) + public string ErrorMessage { get; set; } + + public ActionResult OnGet(string statusCode) { - var statusFeature = HttpContext.Features.Get(); - if (statusFeature != null) + try { - Log.Warning("Handled {0} error for URL: {1}", statusCode, statusFeature.OriginalPath); - } + if (!int.TryParse(statusCode, out var errorStatusCode)) + { + errorStatusCode = (int)HttpStatusCode.BadRequest; + } + + var statusFeature = HttpContext.Features.Get(); + if (statusFeature != null) + { + Logger.LogWarning("Handled {0} error for URL: {1}", statusCode, statusFeature.OriginalPath); + } + + var isValidStatusCode = Enum.IsDefined(typeof(HttpStatusCode), errorStatusCode); + if (!isValidStatusCode) + { + errorStatusCode = (int)HttpStatusCode.BadRequest; + } - var isValidStatusCode = Enum.IsDefined(typeof(HttpStatusCode), statusCode); - if (!isValidStatusCode) + ErrorMessage = _errorMessages.ContainsKey(errorStatusCode) + ? _errorMessages[errorStatusCode] + : "Looks like something went wrong!"; + + } + catch (Exception e) { - statusCode = (int)HttpStatusCode.BadRequest; + Logger.LogError("Error on error page: " + e); } - return new ContentResult - { - ContentType = System.Net.Mime.MediaTypeNames.Text.Html, - StatusCode = statusCode, - Content = string.Format(HtmlBody, _errorMessages.ContainsKey(statusCode) - ? _errorMessages[statusCode] - : "Looks like something went wrong!") - }; + return Page(); } - private const string HtmlBody = ""; - + #region Error Messages /*For more ASCII arts http://patorjk.com/software/taag/#p=display&h=0&f=Big&t=400*/ private readonly Dictionary _errorMessages = new Dictionary { @@ -84,7 +93,7 @@ This is a forbidden area!" | | | |_| | | | |_| \___/ |_| -We can't find the page you're looking for..." +Hmm, we couldn't find the page you're looking for..." }, { 500, @@ -123,5 +132,6 @@ Ooops! Our server is experiencing a mild case of the hiccups." Looks like we're having some server issues." } }; + #endregion } -} +} \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml new file mode 100644 index 0000000000..6f6c083531 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml @@ -0,0 +1,56 @@ +@page + +@using System.Linq +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Docs +@using Volo.Docs.Localization +@using Volo.Docs.Pages.Documents + +@model VoloDocs.Web.Pages.IndexModel +@inject IHtmlLocalizer L + +@section styles { + + + + +} + +
+ +

+ @L["WelcomeVoloDocs"] +

+ + @if (!Model.Projects.Any()) + { +
+ +
+ } + else if (Model.Projects.Count > 1) + { +

@L["Projects"]

+

+

+

+ } + +
diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs new file mode 100644 index 0000000000..8b6ffd2cdf --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Volo.Docs; +using Volo.Docs.Projects; + +namespace VoloDocs.Web.Pages +{ + public class IndexModel : PageModel + { + public IReadOnlyList Projects { get; set; } + + private readonly IProjectAppService _projectAppService; + + public IndexModel(IProjectAppService projectAppService) + { + _projectAppService = projectAppService; + } + + public async Task OnGet() + { + Projects = (await _projectAppService.GetListAsync()).Items; + + if (Projects.Count == 1) + { + return RedirectToPage("./Documents/Project/Index", new + { + projectName = Projects[0].ShortName, + version = DocsAppConsts.Latest, + documentName = Projects[0].DefaultDocumentName + }); + } + + return Page(); + } + } +} \ No newline at end of file diff --git a/modules/docs/app/Volo.DocsTestApp/Pages/_ViewImports.cshtml b/modules/docs/app/VoloDocs.Web/Pages/_ViewImports.cshtml similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/Pages/_ViewImports.cshtml rename to modules/docs/app/VoloDocs.Web/Pages/_ViewImports.cshtml diff --git a/modules/docs/app/Volo.DocsTestApp/Program.cs b/modules/docs/app/VoloDocs.Web/Program.cs similarity index 97% rename from modules/docs/app/Volo.DocsTestApp/Program.cs rename to modules/docs/app/VoloDocs.Web/Program.cs index 470b5e6a98..90c41c061d 100644 --- a/modules/docs/app/Volo.DocsTestApp/Program.cs +++ b/modules/docs/app/VoloDocs.Web/Program.cs @@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Hosting; using Serilog; using Serilog.Events; -namespace Volo.DocsTestApp +namespace VoloDocs.Web { public class Program { diff --git a/modules/docs/app/Volo.DocsTestApp/Properties/launchSettings.json b/modules/docs/app/VoloDocs.Web/Properties/launchSettings.json similarity index 95% rename from modules/docs/app/Volo.DocsTestApp/Properties/launchSettings.json rename to modules/docs/app/VoloDocs.Web/Properties/launchSettings.json index 993312907b..f548eac112 100644 --- a/modules/docs/app/Volo.DocsTestApp/Properties/launchSettings.json +++ b/modules/docs/app/VoloDocs.Web/Properties/launchSettings.json @@ -15,7 +15,7 @@ "ASPNETCORE_ENVIRONMENT": "Development" } }, - "Volo.DocsTestApp": { + "VoloDocs": { "commandName": "Project", "launchBrowser": true, "environmentVariables": { diff --git a/modules/docs/app/Volo.DocsTestApp/Startup.cs b/modules/docs/app/VoloDocs.Web/Startup.cs similarity index 87% rename from modules/docs/app/Volo.DocsTestApp/Startup.cs rename to modules/docs/app/VoloDocs.Web/Startup.cs index e6708d26e8..a05cf9e2c0 100644 --- a/modules/docs/app/Volo.DocsTestApp/Startup.cs +++ b/modules/docs/app/VoloDocs.Web/Startup.cs @@ -5,13 +5,13 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Volo.Abp; -namespace Volo.DocsTestApp +namespace VoloDocs.Web { public class Startup { public IServiceProvider ConfigureServices(IServiceCollection services) { - services.AddApplication(options => + services.AddApplication(options => { options.UseAutofac(); }); diff --git a/modules/docs/app/VoloDocs.Web/Utils/GlobalExceptionHandlerMiddleware.cs b/modules/docs/app/VoloDocs.Web/Utils/GlobalExceptionHandlerMiddleware.cs new file mode 100644 index 0000000000..da303643d4 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/Utils/GlobalExceptionHandlerMiddleware.cs @@ -0,0 +1,45 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Volo.Abp.AspNetCore.Uow; +using Volo.Abp.Domain.Entities; +using Volo.Docs; + +namespace VoloDocs.Web.Utils +{ + public class GlobalExceptionHandlerMiddleware + { + private readonly RequestDelegate _next; + private readonly ILogger _logger; + + public GlobalExceptionHandlerMiddleware(RequestDelegate next, ILogger logger) + { + _logger = logger; + _next = next; + } + + public async Task Invoke(HttpContext httpContext) + { + try + { + await _next(httpContext); + } + catch (Exception ex) + { + _logger.LogError("Handled a global exception: " + ex.Message, ex); + + if (ex.Message.StartsWith("404 error") || + ex is EntityNotFoundException || + ex is DocumentNotFoundException) + { + httpContext.Response.Redirect("/error/404"); + } + else + { + httpContext.Response.Redirect("/error/500"); + } + } + } + } +} \ No newline at end of file diff --git a/modules/docs/app/Volo.DocsTestApp/Volo.DocsTestApp.csproj b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj similarity index 68% rename from modules/docs/app/Volo.DocsTestApp/Volo.DocsTestApp.csproj rename to modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj index b24f84e537..c405b583a8 100644 --- a/modules/docs/app/Volo.DocsTestApp/Volo.DocsTestApp.csproj +++ b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj @@ -2,11 +2,15 @@ netcoreapp2.2 + true + true + false + win-x64;osx-x64;linux-x64 - - + + @@ -23,12 +27,26 @@ - + - + + + + + + + + + + + + PreserveNewest + + + diff --git a/modules/docs/app/Volo.DocsTestApp/DocsTestAppModule.cs b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs similarity index 74% rename from modules/docs/app/Volo.DocsTestApp/DocsTestAppModule.cs rename to modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs index 275eb0f713..9850ed265a 100644 --- a/modules/docs/app/Volo.DocsTestApp/DocsTestAppModule.cs +++ b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs @@ -1,16 +1,12 @@ -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; +using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Localization; -using Microsoft.Extensions.Configuration; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.Account.Web; +using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; @@ -21,6 +17,8 @@ using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.Identity; using Volo.Abp.Identity.Web; +using Volo.Abp.Localization; +using Volo.Abp.Localization.Resources.AbpValidation; using Volo.Abp.Modularity; using Volo.Abp.PermissionManagement; using Volo.Abp.PermissionManagement.Identity; @@ -29,16 +27,18 @@ using Volo.Abp.UI; using Volo.Abp.VirtualFileSystem; using Volo.Docs; using Volo.Docs.Admin; -using Volo.DocsTestApp.EntityFrameworkCore; +using Volo.Docs.Localization; +using VoloDocs.EntityFrameworkCore; +using VoloDocs.Web.Utils; -namespace Volo.DocsTestApp +namespace VoloDocs.Web { [DependsOn( typeof(DocsWebModule), typeof(DocsAdminWebModule), typeof(DocsApplicationModule), typeof(DocsAdminApplicationModule), - typeof(DocsTestAppEntityFrameworkCoreModule), + typeof(VoloDocsEntityFrameworkCoreModule), typeof(AbpAutofacModule), typeof(AbpAccountWebModule), typeof(AbpIdentityWebModule), @@ -47,8 +47,16 @@ namespace Volo.DocsTestApp typeof(AbpPermissionManagementApplicationModule), typeof(AbpAspNetCoreMvcUiBasicThemeModule) )] - public class DocsTestAppModule : AbpModule + public class VoloDocsWebModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(options => + { + options.AddAssemblyResource(typeof(DocsResource), typeof(VoloDocsWebModule).Assembly); + }); + } + public override void ConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); @@ -56,8 +64,7 @@ namespace Volo.DocsTestApp Configure(options => { - const string connStringName = "SqlServer"; - options.ConnectionStrings.Default = configuration.GetConnectionString(connStringName); + options.ConnectionStrings.Default = configuration["ConnectionString"]; }); Configure(options => @@ -83,30 +90,49 @@ namespace Volo.DocsTestApp context.Services.AddSwaggerGen( options => { - options.SwaggerDoc("v1", new Info { Title = "Docs API", Version = "v1" }); + options.SwaggerDoc("v1", new Info + { + Title = "Docs API", + Version = "v1" + }); options.DocInclusionPredicate((docName, description) => true); options.CustomSchemaIds(type => type.FullName); }); - var cultures = new List { new CultureInfo("en"), new CultureInfo("tr") }; - Configure(options => + + Configure(options => + { + options.FileSets.AddEmbedded("VoloDocs.Web"); + }); + + Configure(options => { - options.DefaultRequestCulture = new RequestCulture("en"); - options.SupportedCultures = cultures; - options.SupportedUICultures = cultures; + options + .Languages + .Add(new LanguageInfo("en", "en", "English")); + + options.Resources + .Get() + .AddBaseTypes(typeof(AbpValidationResource)) + .AddBaseTypes(typeof(AbpUiModule)) + .AddVirtualJson("/Localization/Resources/VoloDocs/Web"); }); Configure(options => { options.DefaultThemeName = BasicTheme.Name; }); + + Configure(options => + { + options.Conventions.AddPageRoute("/Error", "error/{statusCode}"); + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); - - app.UseDeveloperExceptionPage(); + var env = context.GetEnvironment(); app.UseVirtualFiles(); @@ -118,9 +144,10 @@ namespace Volo.DocsTestApp app.UseAuthentication(); - app.UseRequestLocalization(app.ApplicationServices.GetRequiredService>().Value); - + app.UseAbpRequestLocalization(); + app.UseStatusCodePagesWithReExecute("/error/{0}"); + app.UseMiddleware(); app.UseMvc(routes => { diff --git a/modules/docs/app/Volo.DocsTestApp/abp.resourcemapping.js b/modules/docs/app/VoloDocs.Web/abp.resourcemapping.js similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/abp.resourcemapping.js rename to modules/docs/app/VoloDocs.Web/abp.resourcemapping.js diff --git a/modules/docs/app/VoloDocs.Web/appsettings.json b/modules/docs/app/VoloDocs.Web/appsettings.json new file mode 100644 index 0000000000..e893a26c7c --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;MultipleActiveResultSets=true", + "Title": "Volo Documents", + "LogoUrl": "/assets/images/Logo.png" +} \ No newline at end of file diff --git a/modules/docs/app/Volo.DocsTestApp/gulpfile.js b/modules/docs/app/VoloDocs.Web/gulpfile.js similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/gulpfile.js rename to modules/docs/app/VoloDocs.Web/gulpfile.js diff --git a/modules/docs/app/Volo.DocsTestApp/package-lock.json b/modules/docs/app/VoloDocs.Web/package-lock.json similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/package-lock.json rename to modules/docs/app/VoloDocs.Web/package-lock.json diff --git a/modules/docs/app/Volo.DocsTestApp/package.json b/modules/docs/app/VoloDocs.Web/package.json similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/package.json rename to modules/docs/app/VoloDocs.Web/package.json diff --git a/modules/docs/app/VoloDocs.Web/publish.bat b/modules/docs/app/VoloDocs.Web/publish.bat new file mode 100644 index 0000000000..2ed332ce78 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/publish.bat @@ -0,0 +1,11 @@ +@echo off + +dotnet clean +dotnet restore +dotnet build + +DEL /F/Q/S "C:\Publishes\VoloDocs" > NUL && RMDIR /Q/S "C:\Publishes\VoloDocs" + +dotnet publish -c Release -o "C:\Publishes\VoloDocs\Web" + +cd..\VoloDocs.Migrator && dotnet publish -c Release -o "C:\Publishes\VoloDocs\Migrator" \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/run.bat b/modules/docs/app/VoloDocs.Web/run.bat new file mode 100644 index 0000000000..3286376287 --- /dev/null +++ b/modules/docs/app/VoloDocs.Web/run.bat @@ -0,0 +1 @@ +@dotnet VoloDocs.Web.dll \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/wwwroot/assets/images/Logo.png b/modules/docs/app/VoloDocs.Web/wwwroot/assets/images/Logo.png new file mode 100644 index 0000000000..30a85a0ca0 Binary files /dev/null and b/modules/docs/app/VoloDocs.Web/wwwroot/assets/images/Logo.png differ diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/abp/core/abp.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/core/abp.js similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/abp/core/abp.js rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/core/abp.js diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/abp/jquery/abp.jquery.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/jquery/abp.jquery.js similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/abp/jquery/abp.jquery.js rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/abp/jquery/abp.jquery.js diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/anchor-js/anchor.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/anchor-js/anchor.js similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/anchor-js/anchor.js rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/anchor-js/anchor.js diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/bootstrap/css/bootstrap.css b/modules/docs/app/VoloDocs.Web/wwwroot/libs/bootstrap/css/bootstrap.css similarity index 98% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/bootstrap/css/bootstrap.css rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/bootstrap/css/bootstrap.css index 7d43e1f107..943532db55 100644 --- a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/bootstrap/css/bootstrap.css +++ b/modules/docs/app/VoloDocs.Web/wwwroot/libs/bootstrap/css/bootstrap.css @@ -1,5 +1,5 @@ /*! - * Bootstrap v4.1.1 (https://getbootstrap.com/) + * Bootstrap v4.1.3 (https://getbootstrap.com/) * Copyright 2011-2018 The Bootstrap Authors * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) @@ -31,7 +31,7 @@ --breakpoint-md: 768px; --breakpoint-lg: 992px; --breakpoint-xl: 1200px; - --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } @@ -47,7 +47,7 @@ html { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; -ms-overflow-style: scrollbar; - -webkit-tap-highlight-color: transparent; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } @-ms-viewport { @@ -60,7 +60,7 @@ article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 1rem; font-weight: 400; line-height: 1.5; @@ -210,8 +210,9 @@ img { border-style: none; } -svg:not(:root) { +svg { overflow: hidden; + vertical-align: middle; } table { @@ -1515,7 +1516,6 @@ pre code { .table { width: 100%; - max-width: 100%; margin-bottom: 1rem; background-color: transparent; } @@ -1811,6 +1811,7 @@ pre code { .form-control { display: block; width: 100%; + height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; @@ -1871,10 +1872,6 @@ pre code { opacity: 1; } -select.form-control:not([size]):not([multiple]) { - height: calc(2.25rem + 2px); -} - select.form-control:focus::-ms-value { color: #495057; background-color: #fff; @@ -1921,55 +1918,33 @@ select.form-control:focus::-ms-value { border-width: 1px 0; } -.form-control-plaintext.form-control-sm, .input-group-sm > .form-control-plaintext.form-control, -.input-group-sm > .input-group-prepend > .form-control-plaintext.input-group-text, -.input-group-sm > .input-group-append > .form-control-plaintext.input-group-text, -.input-group-sm > .input-group-prepend > .form-control-plaintext.btn, -.input-group-sm > .input-group-append > .form-control-plaintext.btn, .form-control-plaintext.form-control-lg, .input-group-lg > .form-control-plaintext.form-control, -.input-group-lg > .input-group-prepend > .form-control-plaintext.input-group-text, -.input-group-lg > .input-group-append > .form-control-plaintext.input-group-text, -.input-group-lg > .input-group-prepend > .form-control-plaintext.btn, -.input-group-lg > .input-group-append > .form-control-plaintext.btn { +.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { padding-right: 0; padding-left: 0; } -.form-control-sm, .input-group-sm > .form-control, -.input-group-sm > .input-group-prepend > .input-group-text, -.input-group-sm > .input-group-append > .input-group-text, -.input-group-sm > .input-group-prepend > .btn, -.input-group-sm > .input-group-append > .btn { +.form-control-sm { + height: calc(1.8125rem + 2px); padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } -select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]), -.input-group-sm > .input-group-prepend > select.input-group-text:not([size]):not([multiple]), -.input-group-sm > .input-group-append > select.input-group-text:not([size]):not([multiple]), -.input-group-sm > .input-group-prepend > select.btn:not([size]):not([multiple]), -.input-group-sm > .input-group-append > select.btn:not([size]):not([multiple]) { - height: calc(1.8125rem + 2px); -} - -.form-control-lg, .input-group-lg > .form-control, -.input-group-lg > .input-group-prepend > .input-group-text, -.input-group-lg > .input-group-append > .input-group-text, -.input-group-lg > .input-group-prepend > .btn, -.input-group-lg > .input-group-append > .btn { +.form-control-lg { + height: calc(2.875rem + 2px); padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } -select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]), -.input-group-lg > .input-group-prepend > select.input-group-text:not([size]):not([multiple]), -.input-group-lg > .input-group-append > select.input-group-text:not([size]):not([multiple]), -.input-group-lg > .input-group-prepend > select.btn:not([size]):not([multiple]), -.input-group-lg > .input-group-append > select.btn:not([size]):not([multiple]) { - height: calc(2.875rem + 2px); +select.form-control[size], select.form-control[multiple] { + height: auto; +} + +textarea.form-control { + height: auto; } .form-group { @@ -2046,13 +2021,13 @@ select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.for z-index: 5; display: none; max-width: 100%; - padding: .5rem; + padding: 0.25rem 0.5rem; margin-top: .1rem; - font-size: .875rem; - line-height: 1; + font-size: 0.875rem; + line-height: 1.5; color: #fff; - background-color: rgba(40, 167, 69, 0.8); - border-radius: .2rem; + background-color: rgba(40, 167, 69, 0.9); + border-radius: 0.25rem; } .was-validated .form-control:valid, .form-control.is-valid, .was-validated @@ -2121,7 +2096,7 @@ select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.for border-color: #28a745; } -.was-validated .custom-file-input:valid ~ .custom-file-label::before, .custom-file-input.is-valid ~ .custom-file-label::before { +.was-validated .custom-file-input:valid ~ .custom-file-label::after, .custom-file-input.is-valid ~ .custom-file-label::after { border-color: inherit; } @@ -2149,13 +2124,13 @@ select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.for z-index: 5; display: none; max-width: 100%; - padding: .5rem; + padding: 0.25rem 0.5rem; margin-top: .1rem; - font-size: .875rem; - line-height: 1; + font-size: 0.875rem; + line-height: 1.5; color: #fff; - background-color: rgba(220, 53, 69, 0.8); - border-radius: .2rem; + background-color: rgba(220, 53, 69, 0.9); + border-radius: 0.25rem; } .was-validated .form-control:invalid, .form-control.is-invalid, .was-validated @@ -2224,7 +2199,7 @@ select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.for border-color: #dc3545; } -.was-validated .custom-file-input:invalid ~ .custom-file-label::before, .custom-file-input.is-invalid ~ .custom-file-label::before { +.was-validated .custom-file-input:invalid ~ .custom-file-label::after, .custom-file-input.is-invalid ~ .custom-file-label::after { border-color: inherit; } @@ -2352,10 +2327,6 @@ select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.for cursor: pointer; } -.btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active { - background-image: none; -} - a.btn.disabled, fieldset:disabled a.btn { pointer-events: none; @@ -3354,12 +3325,6 @@ input[type="button"].btn-block { margin-bottom: 0; } -.input-group > .form-control:focus, -.input-group > .custom-select:focus, -.input-group > .custom-file:focus { - z-index: 3; -} - .input-group > .form-control + .form-control, .input-group > .form-control + .custom-select, .input-group > .form-control + .custom-file, @@ -3372,6 +3337,16 @@ input[type="button"].btn-block { margin-left: -1px; } +.input-group > .form-control:focus, +.input-group > .custom-select:focus, +.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label { + z-index: 3; +} + +.input-group > .custom-file .custom-file-input:focus { + z-index: 4; +} + .input-group > .form-control:not(:last-child), .input-group > .custom-select:not(:last-child) { border-top-right-radius: 0; @@ -3456,6 +3431,30 @@ input[type="button"].btn-block { margin-top: 0; } +.input-group-lg > .form-control, +.input-group-lg > .input-group-prepend > .input-group-text, +.input-group-lg > .input-group-append > .input-group-text, +.input-group-lg > .input-group-prepend > .btn, +.input-group-lg > .input-group-append > .btn { + height: calc(2.875rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.input-group-sm > .form-control, +.input-group-sm > .input-group-prepend > .input-group-text, +.input-group-sm > .input-group-append > .input-group-text, +.input-group-sm > .input-group-prepend > .btn, +.input-group-sm > .input-group-append > .btn { + height: calc(1.8125rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + .input-group > .input-group-prepend > .btn, .input-group > .input-group-prepend > .input-group-text, .input-group > .input-group-append:not(:last-child) > .btn, @@ -3615,7 +3614,7 @@ input[type="button"].btn-block { .custom-select:focus { border-color: #80bdff; outline: 0; - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 5px rgba(128, 189, 255, 0.5); + box-shadow: 0 0 0 0.2rem rgba(128, 189, 255, 0.5); } .custom-select:focus::-ms-value { @@ -3678,6 +3677,10 @@ input[type="button"].btn-block { border-color: #80bdff; } +.custom-file-input:disabled ~ .custom-file-label { + background-color: #e9ecef; +} + .custom-file-input:lang(en) ~ .custom-file-label::after { content: "Browse"; } @@ -3727,6 +3730,18 @@ input[type="button"].btn-block { outline: none; } +.custom-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-range:focus::-ms-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + .custom-range::-moz-focus-outer { border: 0; } @@ -3738,13 +3753,15 @@ input[type="button"].btn-block { background-color: #007bff; border: 0; border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; appearance: none; } -.custom-range::-webkit-slider-thumb:focus { - outline: none; - box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +@media screen and (prefers-reduced-motion: reduce) { + .custom-range::-webkit-slider-thumb { + transition: none; + } } .custom-range::-webkit-slider-thumb:active { @@ -3767,13 +3784,15 @@ input[type="button"].btn-block { background-color: #007bff; border: 0; border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -moz-appearance: none; appearance: none; } -.custom-range::-moz-range-thumb:focus { - outline: none; - box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +@media screen and (prefers-reduced-motion: reduce) { + .custom-range::-moz-range-thumb { + transition: none; + } } .custom-range::-moz-range-thumb:active { @@ -3793,15 +3812,20 @@ input[type="button"].btn-block { .custom-range::-ms-thumb { width: 1rem; height: 1rem; + margin-top: 0; + margin-right: 0.2rem; + margin-left: 0.2rem; background-color: #007bff; border: 0; border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; appearance: none; } -.custom-range::-ms-thumb:focus { - outline: none; - box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +@media screen and (prefers-reduced-motion: reduce) { + .custom-range::-ms-thumb { + transition: none; + } } .custom-range::-ms-thumb:active { @@ -3829,6 +3853,20 @@ input[type="button"].btn-block { border-radius: 1rem; } +.custom-control-label::before, +.custom-file-label, +.custom-select { + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media screen and (prefers-reduced-motion: reduce) { + .custom-control-label::before, + .custom-file-label, + .custom-select { + transition: none; + } +} + .nav { display: -ms-flexbox; display: flex; @@ -5283,16 +5321,16 @@ input[type="button"].btn-block { opacity: .5; } -.close:hover, .close:focus { +.close:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus { color: #000; text-decoration: none; opacity: .75; } -.close:not(:disabled):not(.disabled) { - cursor: pointer; -} - button.close { padding: 0; background-color: transparent; @@ -5304,6 +5342,11 @@ button.close { overflow: hidden; } +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} + .modal { position: fixed; top: 0; @@ -5316,11 +5359,6 @@ button.close { outline: 0; } -.modal-open .modal { - overflow-x: hidden; - overflow-y: auto; -} - .modal-dialog { position: relative; width: auto; @@ -5355,6 +5393,12 @@ button.close { min-height: calc(100% - (0.5rem * 2)); } +.modal-dialog-centered::before { + display: block; + height: calc(100vh - (0.5rem * 2)); + content: ""; +} + .modal-content { position: relative; display: -ms-flexbox; @@ -5453,6 +5497,9 @@ button.close { .modal-dialog-centered { min-height: calc(100% - (1.75rem * 2)); } + .modal-dialog-centered::before { + height: calc(100vh - (1.75rem * 2)); + } .modal-sm { max-width: 300px; } @@ -5469,7 +5516,7 @@ button.close { z-index: 1070; display: block; margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-style: normal; font-weight: 400; line-height: 1.5; @@ -5582,7 +5629,7 @@ button.close { z-index: 1060; display: block; max-width: 276px; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-style: normal; font-weight: 400; line-height: 1.5; @@ -5777,25 +5824,27 @@ button.close { -ms-flex-align: center; align-items: center; width: 100%; - transition: -webkit-transform 0.6s ease; - transition: transform 0.6s ease; - transition: transform 0.6s ease, -webkit-transform 0.6s ease; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; perspective: 1000px; } -@media screen and (prefers-reduced-motion: reduce) { - .carousel-item { - transition: none; - } -} - .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; + transition: -webkit-transform 0.6s ease; + transition: transform 0.6s ease; + transition: transform 0.6s ease, -webkit-transform 0.6s ease; +} + +@media screen and (prefers-reduced-motion: reduce) { + .carousel-item.active, + .carousel-item-next, + .carousel-item-prev { + transition: none; + } } .carousel-item-next, diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/bootstrap/js/bootstrap.bundle.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/bootstrap/js/bootstrap.bundle.js similarity index 96% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/bootstrap/js/bootstrap.bundle.js rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/bootstrap/js/bootstrap.bundle.js index adb3400738..e8b832da6b 100644 --- a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/bootstrap/js/bootstrap.bundle.js +++ b/modules/docs/app/VoloDocs.Web/wwwroot/libs/bootstrap/js/bootstrap.bundle.js @@ -1,5 +1,5 @@ /*! - * Bootstrap v4.1.1 (https://getbootstrap.com/) + * Bootstrap v4.1.3 (https://getbootstrap.com/) * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ @@ -69,7 +69,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): util.js + * Bootstrap (v4.1.3): util.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -146,8 +146,7 @@ } try { - var $selector = $$$1(document).find(selector); - return $selector.length > 0 ? selector : null; + return document.querySelector(selector) ? selector : null; } catch (err) { return null; } @@ -202,7 +201,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): alert.js + * Bootstrap (v4.1.3): alert.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -214,7 +213,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'alert'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.alert'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -277,7 +276,7 @@ var parent = false; if (selector) { - parent = $$$1(selector)[0]; + parent = document.querySelector(selector); } if (!parent) { @@ -377,7 +376,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): button.js + * Bootstrap (v4.1.3): button.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -389,7 +388,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'button'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.button'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -434,14 +433,14 @@ var rootElement = $$$1(this._element).closest(Selector.DATA_TOGGLE)[0]; if (rootElement) { - var input = $$$1(this._element).find(Selector.INPUT)[0]; + var input = this._element.querySelector(Selector.INPUT); if (input) { if (input.type === 'radio') { - if (input.checked && $$$1(this._element).hasClass(ClassName.ACTIVE)) { + if (input.checked && this._element.classList.contains(ClassName.ACTIVE)) { triggerChangeEvent = false; } else { - var activeElement = $$$1(rootElement).find(Selector.ACTIVE)[0]; + var activeElement = rootElement.querySelector(Selector.ACTIVE); if (activeElement) { $$$1(activeElement).removeClass(ClassName.ACTIVE); @@ -454,7 +453,7 @@ return; } - input.checked = !$$$1(this._element).hasClass(ClassName.ACTIVE); + input.checked = !this._element.classList.contains(ClassName.ACTIVE); $$$1(input).trigger('change'); } @@ -464,7 +463,7 @@ } if (addAriaPressed) { - this._element.setAttribute('aria-pressed', !$$$1(this._element).hasClass(ClassName.ACTIVE)); + this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName.ACTIVE)); } if (triggerChangeEvent) { @@ -541,7 +540,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): carousel.js + * Bootstrap (v4.1.3): carousel.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -553,7 +552,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'carousel'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.carousel'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -632,7 +631,7 @@ this.touchTimeout = null; this._config = this._getConfig(config); this._element = $$$1(element)[0]; - this._indicatorsElement = $$$1(this._element).find(Selector.INDICATORS)[0]; + this._indicatorsElement = this._element.querySelector(Selector.INDICATORS); this._addEventListeners(); } // Getters @@ -666,7 +665,7 @@ this._isPaused = true; } - if ($$$1(this._element).find(Selector.NEXT_PREV)[0]) { + if (this._element.querySelector(Selector.NEXT_PREV)) { Util.triggerTransitionEnd(this._element); this.cycle(true); } @@ -693,7 +692,7 @@ _proto.to = function to(index) { var _this = this; - this._activeElement = $$$1(this._element).find(Selector.ACTIVE_ITEM)[0]; + this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); var activeIndex = this._getItemIndex(this._activeElement); @@ -799,7 +798,7 @@ }; _proto._getItemIndex = function _getItemIndex(element) { - this._items = $$$1.makeArray($$$1(element).parent().find(Selector.ITEM)); + this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) : []; return this._items.indexOf(element); }; @@ -824,7 +823,7 @@ _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) { var targetIndex = this._getItemIndex(relatedTarget); - var fromIndex = this._getItemIndex($$$1(this._element).find(Selector.ACTIVE_ITEM)[0]); + var fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM)); var slideEvent = $$$1.Event(Event.SLIDE, { relatedTarget: relatedTarget, @@ -838,7 +837,8 @@ _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) { if (this._indicatorsElement) { - $$$1(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE); + var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE)); + $$$1(indicators).removeClass(ClassName.ACTIVE); var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]; @@ -851,7 +851,7 @@ _proto._slide = function _slide(direction, element) { var _this3 = this; - var activeElement = $$$1(this._element).find(Selector.ACTIVE_ITEM)[0]; + var activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); var activeElementIndex = this._getItemIndex(activeElement); @@ -1017,11 +1017,13 @@ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler); $$$1(window).on(Event.LOAD_DATA_API, function () { - $$$1(Selector.DATA_RIDE).each(function () { - var $carousel = $$$1(this); + var carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE)); + + for (var i = 0, len = carousels.length; i < len; i++) { + var $carousel = $$$1(carousels[i]); Carousel._jQueryInterface.call($carousel, $carousel.data()); - }); + } }); /** * ------------------------------------------------------------------------ @@ -1042,7 +1044,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): collapse.js + * Bootstrap (v4.1.3): collapse.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -1054,7 +1056,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'collapse'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.collapse'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -1102,14 +1104,17 @@ this._isTransitioning = false; this._element = element; this._config = this._getConfig(config); - this._triggerArray = $$$1.makeArray($$$1("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]"))); - var tabToggles = $$$1(Selector.DATA_TOGGLE); + this._triggerArray = $$$1.makeArray(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]"))); + var toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); - for (var i = 0; i < tabToggles.length; i++) { - var elem = tabToggles[i]; + for (var i = 0, len = toggleList.length; i < len; i++) { + var elem = toggleList[i]; var selector = Util.getSelectorFromElement(elem); + var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) { + return foundElem === element; + }); - if (selector !== null && $$$1(selector).filter(element).length > 0) { + if (selector !== null && filterElement.length > 0) { this._selector = selector; this._triggerArray.push(elem); @@ -1150,7 +1155,9 @@ var activesData; if (this._parent) { - actives = $$$1.makeArray($$$1(this._parent).find(Selector.ACTIVES).filter("[data-parent=\"" + this._config.parent + "\"]")); + actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)).filter(function (elem) { + return elem.getAttribute('data-parent') === _this._config.parent; + }); if (actives.length === 0) { actives = null; @@ -1185,7 +1192,7 @@ $$$1(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING); this._element.style[dimension] = 0; - if (this._triggerArray.length > 0) { + if (this._triggerArray.length) { $$$1(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true); } @@ -1226,14 +1233,15 @@ this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px"; Util.reflow(this._element); $$$1(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); + var triggerArrayLength = this._triggerArray.length; - if (this._triggerArray.length > 0) { - for (var i = 0; i < this._triggerArray.length; i++) { + if (triggerArrayLength > 0) { + for (var i = 0; i < triggerArrayLength; i++) { var trigger = this._triggerArray[i]; var selector = Util.getSelectorFromElement(trigger); if (selector !== null) { - var $elem = $$$1(selector); + var $elem = $$$1([].slice.call(document.querySelectorAll(selector))); if (!$elem.hasClass(ClassName.SHOW)) { $$$1(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); @@ -1294,11 +1302,12 @@ parent = this._config.parent[0]; } } else { - parent = $$$1(this._config.parent)[0]; + parent = document.querySelector(this._config.parent); } var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]"; - $$$1(parent).find(selector).each(function (i, element) { + var children = [].slice.call(parent.querySelectorAll(selector)); + $$$1(children).each(function (i, element) { _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]); }); return parent; @@ -1308,7 +1317,7 @@ if (element) { var isOpen = $$$1(element).hasClass(ClassName.SHOW); - if (triggerArray.length > 0) { + if (triggerArray.length) { $$$1(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); } } @@ -1317,7 +1326,7 @@ Collapse._getTargetFromElement = function _getTargetFromElement(element) { var selector = Util.getSelectorFromElement(element); - return selector ? $$$1(selector)[0] : null; + return selector ? document.querySelector(selector) : null; }; Collapse._jQueryInterface = function _jQueryInterface(config) { @@ -1375,7 +1384,8 @@ var $trigger = $$$1(this); var selector = Util.getSelectorFromElement(this); - $$$1(selector).each(function () { + var selectors = [].slice.call(document.querySelectorAll(selector)); + $$$1(selectors).each(function () { var $target = $$$1(this); var data = $target.data(DATA_KEY); var config = data ? 'toggle' : $trigger.data(); @@ -3920,7 +3930,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): dropdown.js + * Bootstrap (v4.1.3): dropdown.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -3932,7 +3942,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'dropdown'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.dropdown'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -4141,14 +4151,16 @@ if (!this._menu) { var parent = Dropdown._getParentFromElement(this._element); - this._menu = $$$1(parent).find(Selector.MENU)[0]; + if (parent) { + this._menu = parent.querySelector(Selector.MENU); + } } return this._menu; }; _proto._getPlacement = function _getPlacement() { - var $parentDropdown = $$$1(this._element).parent(); + var $parentDropdown = $$$1(this._element.parentNode); var placement = AttachmentMap.BOTTOM; // Handle dropup if ($parentDropdown.hasClass(ClassName.DROPUP)) { @@ -4236,9 +4248,9 @@ return; } - var toggles = $$$1.makeArray($$$1(Selector.DATA_TOGGLE)); + var toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); - for (var i = 0; i < toggles.length; i++) { + for (var i = 0, len = toggles.length; i < len; i++) { var parent = Dropdown._getParentFromElement(toggles[i]); var context = $$$1(toggles[i]).data(DATA_KEY); @@ -4246,6 +4258,10 @@ relatedTarget: toggles[i] }; + if (event && event.type === 'click') { + relatedTarget.clickEvent = event; + } + if (!context) { continue; } @@ -4284,7 +4300,7 @@ var selector = Util.getSelectorFromElement(element); if (selector) { - parent = $$$1(selector)[0]; + parent = document.querySelector(selector); } return parent || element.parentNode; @@ -4316,7 +4332,7 @@ if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { if (event.which === ESCAPE_KEYCODE) { - var toggle = $$$1(parent).find(Selector.DATA_TOGGLE)[0]; + var toggle = parent.querySelector(Selector.DATA_TOGGLE); $$$1(toggle).trigger('focus'); } @@ -4324,7 +4340,7 @@ return; } - var items = $$$1(parent).find(Selector.VISIBLE_ITEMS).get(); + var items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS)); if (items.length === 0) { return; @@ -4402,7 +4418,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): modal.js + * Bootstrap (v4.1.3): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -4414,7 +4430,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'modal'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.modal'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -4458,8 +4474,7 @@ DATA_TOGGLE: '[data-toggle="modal"]', DATA_DISMISS: '[data-dismiss="modal"]', FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', - STICKY_CONTENT: '.sticky-top', - NAVBAR_TOGGLER: '.navbar-toggler' + STICKY_CONTENT: '.sticky-top' /** * ------------------------------------------------------------------------ * Class Definition @@ -4474,7 +4489,7 @@ function Modal(element, config) { this._config = this._getConfig(config); this._element = element; - this._dialog = $$$1(element).find(Selector.DIALOG)[0]; + this._dialog = element.querySelector(Selector.DIALOG); this._backdrop = null; this._isShown = false; this._isBodyOverflowing = false; @@ -4731,7 +4746,7 @@ this._backdrop.className = ClassName.BACKDROP; if (animate) { - $$$1(this._backdrop).addClass(animate); + this._backdrop.classList.add(animate); } $$$1(this._backdrop).appendTo(document.body); @@ -4825,23 +4840,19 @@ if (this._isBodyOverflowing) { // Note: DOMNode.style.paddingRight returns the actual value or '' if not set // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set - // Adjust fixed content padding - $$$1(Selector.FIXED_CONTENT).each(function (index, element) { - var actualPadding = $$$1(element)[0].style.paddingRight; + var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); + var stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)); // Adjust fixed content padding + + $$$1(fixedContent).each(function (index, element) { + var actualPadding = element.style.paddingRight; var calculatedPadding = $$$1(element).css('padding-right'); $$$1(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px"); }); // Adjust sticky content margin - $$$1(Selector.STICKY_CONTENT).each(function (index, element) { - var actualMargin = $$$1(element)[0].style.marginRight; + $$$1(stickyContent).each(function (index, element) { + var actualMargin = element.style.marginRight; var calculatedMargin = $$$1(element).css('margin-right'); $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px"); - }); // Adjust navbar-toggler margin - - $$$1(Selector.NAVBAR_TOGGLER).each(function (index, element) { - var actualMargin = $$$1(element)[0].style.marginRight; - var calculatedMargin = $$$1(element).css('margin-right'); - $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) + _this9._scrollbarWidth + "px"); }); // Adjust body padding var actualPadding = document.body.style.paddingRight; @@ -4852,15 +4863,15 @@ _proto._resetScrollbar = function _resetScrollbar() { // Restore fixed content padding - $$$1(Selector.FIXED_CONTENT).each(function (index, element) { + var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); + $$$1(fixedContent).each(function (index, element) { var padding = $$$1(element).data('padding-right'); + $$$1(element).removeData('padding-right'); + element.style.paddingRight = padding ? padding : ''; + }); // Restore sticky content - if (typeof padding !== 'undefined') { - $$$1(element).css('padding-right', padding).removeData('padding-right'); - } - }); // Restore sticky content and navbar-toggler margin - - $$$1(Selector.STICKY_CONTENT + ", " + Selector.NAVBAR_TOGGLER).each(function (index, element) { + var elements = [].slice.call(document.querySelectorAll("" + Selector.STICKY_CONTENT)); + $$$1(elements).each(function (index, element) { var margin = $$$1(element).data('margin-right'); if (typeof margin !== 'undefined') { @@ -4869,10 +4880,8 @@ }); // Restore body padding var padding = $$$1(document.body).data('padding-right'); - - if (typeof padding !== 'undefined') { - $$$1(document.body).css('padding-right', padding).removeData('padding-right'); - } + $$$1(document.body).removeData('padding-right'); + document.body.style.paddingRight = padding ? padding : ''; }; _proto._getScrollbarWidth = function _getScrollbarWidth() { @@ -4937,7 +4946,7 @@ var selector = Util.getSelectorFromElement(this); if (selector) { - target = $$$1(selector)[0]; + target = document.querySelector(selector); } var config = $$$1(target).data(DATA_KEY) ? 'toggle' : _objectSpread({}, $$$1(target).data(), $$$1(this).data()); @@ -4980,7 +4989,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): tooltip.js + * Bootstrap (v4.1.3): tooltip.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -4992,7 +5001,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'tooltip'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.tooltip'; var EVENT_KEY = "." + DATA_KEY; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; @@ -5202,7 +5211,7 @@ var attachment = this._getAttachment(placement); this.addAttachmentClass(attachment); - var container = this.config.container === false ? document.body : $$$1(this.config.container); + var container = this.config.container === false ? document.body : $$$1(document).find(this.config.container); $$$1(tip).data(this.constructor.DATA_KEY, this); if (!$$$1.contains(this.element.ownerDocument.documentElement, this.tip)) { @@ -5341,9 +5350,9 @@ }; _proto.setContent = function setContent() { - var $tip = $$$1(this.getTipElement()); - this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle()); - $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW); + var tip = this.getTipElement(); + this.setElementContent($$$1(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle()); + $$$1(tip).removeClass(ClassName.FADE + " " + ClassName.SHOW); }; _proto.setElementContent = function setElementContent($element, content) { @@ -5536,15 +5545,18 @@ var $tip = $$$1(this.getTipElement()); var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); - if (tabClass !== null && tabClass.length > 0) { + if (tabClass !== null && tabClass.length) { $tip.removeClass(tabClass.join('')); } }; - _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(data) { + _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) { + var popperInstance = popperData.instance; + this.tip = popperInstance.popper; + this._cleanTipClass(); - this.addAttachmentClass(this._getAttachment(data.placement)); + this.addAttachmentClass(this._getAttachment(popperData.placement)); }; _proto._fixTransition = function _fixTransition() { @@ -5647,7 +5659,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): popover.js + * Bootstrap (v4.1.3): popover.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -5659,7 +5671,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'popover'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.popover'; var EVENT_KEY = "." + DATA_KEY; var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; @@ -5844,7 +5856,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): scrollspy.js + * Bootstrap (v4.1.3): scrollspy.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -5856,7 +5868,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'scrollspy'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.scrollspy'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -5938,13 +5950,13 @@ this._offsets = []; this._targets = []; this._scrollHeight = this._getScrollHeight(); - var targets = $$$1.makeArray($$$1(this._selector)); + var targets = [].slice.call(document.querySelectorAll(this._selector)); targets.map(function (element) { var target; var targetSelector = Util.getSelectorFromElement(element); if (targetSelector) { - target = $$$1(targetSelector)[0]; + target = document.querySelector(targetSelector); } if (target) { @@ -6041,7 +6053,9 @@ return; } - for (var i = this._offsets.length; i--;) { + var offsetLength = this._offsets.length; + + for (var i = offsetLength; i--;) { var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); if (isActiveTarget) { @@ -6061,7 +6075,7 @@ queries = queries.map(function (selector) { return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]"); }); - var $link = $$$1(queries.join(',')); + var $link = $$$1([].slice.call(document.querySelectorAll(queries.join(',')))); if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE); @@ -6082,7 +6096,8 @@ }; _proto._clear = function _clear() { - $$$1(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE); + var nodes = [].slice.call(document.querySelectorAll(this._selector)); + $$$1(nodes).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE); }; // Static @@ -6129,9 +6144,10 @@ $$$1(window).on(Event.LOAD_DATA_API, function () { - var scrollSpys = $$$1.makeArray($$$1(Selector.DATA_SPY)); + var scrollSpys = [].slice.call(document.querySelectorAll(Selector.DATA_SPY)); + var scrollSpysLength = scrollSpys.length; - for (var i = scrollSpys.length; i--;) { + for (var i = scrollSpysLength; i--;) { var $spy = $$$1(scrollSpys[i]); ScrollSpy._jQueryInterface.call($spy, $spy.data()); @@ -6156,7 +6172,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): tab.js + * Bootstrap (v4.1.3): tab.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ @@ -6168,7 +6184,7 @@ * ------------------------------------------------------------------------ */ var NAME = 'tab'; - var VERSION = '4.1.1'; + var VERSION = '4.1.3'; var DATA_KEY = 'bs.tab'; var EVENT_KEY = "." + DATA_KEY; var DATA_API_KEY = '.data-api'; @@ -6250,7 +6266,7 @@ } if (selector) { - target = $$$1(selector)[0]; + target = document.querySelector(selector); } this._activate(this._element, listElement); @@ -6332,7 +6348,8 @@ var dropdownElement = $$$1(element).closest(Selector.DROPDOWN)[0]; if (dropdownElement) { - $$$1(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE); + var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE)); + $$$1(dropdownToggleList).addClass(ClassName.ACTIVE); } element.setAttribute('aria-expanded', true); @@ -6404,7 +6421,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v4.1.1): index.js + * Bootstrap (v4.1.3): index.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/clipboard/clipboard.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/clipboard/clipboard.js similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/clipboard/clipboard.js rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/clipboard/clipboard.js diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/clipboard/clipboard.min.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/clipboard/clipboard.min.js similarity index 100% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/clipboard/clipboard.min.js rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/clipboard/clipboard.min.js diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css b/modules/docs/app/VoloDocs.Web/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css similarity index 96% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css index 56ea4f4cae..84ec203661 100644 --- a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css +++ b/modules/docs/app/VoloDocs.Web/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css @@ -4,6 +4,7 @@ table.dataTable { margin-bottom: 6px !important; max-width: none !important; border-collapse: separate !important; + border-spacing: 0; } table.dataTable td, table.dataTable th { @@ -25,7 +26,7 @@ div.dataTables_wrapper div.dataTables_length label { white-space: nowrap; } div.dataTables_wrapper div.dataTables_length select { - width: 75px; + width: auto; display: inline-block; } div.dataTables_wrapper div.dataTables_filter { @@ -132,6 +133,9 @@ div.dataTables_scrollBody table { margin-top: 0 !important; margin-bottom: 0 !important; } +div.dataTables_scrollBody table thead .sorting:before, +div.dataTables_scrollBody table thead .sorting_asc:before, +div.dataTables_scrollBody table thead .sorting_desc:before, div.dataTables_scrollBody table thead .sorting:after, div.dataTables_scrollBody table thead .sorting_asc:after, div.dataTables_scrollBody table thead .sorting_desc:after { diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js similarity index 93% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js index 7977fd79df..f2d2ad583b 100644 --- a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js +++ b/modules/docs/app/VoloDocs.Web/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js @@ -1,9 +1,9 @@ -/*! DataTables Bootstrap 3 integration - * ©2011-2015 SpryMedia Ltd - datatables.net/license +/*! DataTables Bootstrap 4 integration + * ©2011-2017 SpryMedia Ltd - datatables.net/license */ /** - * DataTables integration for Bootstrap 3. This requires Bootstrap 3 and + * DataTables integration for Bootstrap 4. This requires Bootstrap 4 and * DataTables 1.10 or newer. * * This file sets the defaults and adds options to DataTables to style its @@ -55,9 +55,9 @@ $.extend( true, DataTable.defaults, { /* Default class modification */ $.extend( DataTable.ext.classes, { - sWrapper: "dataTables_wrapper container-fluid dt-bootstrap4", + sWrapper: "dataTables_wrapper dt-bootstrap4", sFilterInput: "form-control form-control-sm", - sLengthSelect: "form-control form-control-sm", + sLengthSelect: "custom-select custom-select-sm form-control form-control-sm", sProcessing: "dataTables_processing card", sPageButton: "paginate_button page-item" } ); diff --git a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/datatables.net/js/jquery.dataTables.js b/modules/docs/app/VoloDocs.Web/wwwroot/libs/datatables.net/js/jquery.dataTables.js similarity index 99% rename from modules/docs/app/Volo.DocsTestApp/wwwroot/libs/datatables.net/js/jquery.dataTables.js rename to modules/docs/app/VoloDocs.Web/wwwroot/libs/datatables.net/js/jquery.dataTables.js index ef9828da33..3db866f547 100644 --- a/modules/docs/app/Volo.DocsTestApp/wwwroot/libs/datatables.net/js/jquery.dataTables.js +++ b/modules/docs/app/VoloDocs.Web/wwwroot/libs/datatables.net/js/jquery.dataTables.js @@ -1,15 +1,15 @@ -/*! DataTables 1.10.16 - * ©2008-2017 SpryMedia Ltd - datatables.net/license +/*! DataTables 1.10.19 + * ©2008-2018 SpryMedia Ltd - datatables.net/license */ /** * @summary DataTables * @description Paginate, search and order HTML tables - * @version 1.10.16 + * @version 1.10.19 * @file jquery.dataTables.js * @author SpryMedia Ltd * @contact www.datatables.net - * @copyright Copyright 2008-2017 SpryMedia Ltd. + * @copyright Copyright 2008-2018 SpryMedia Ltd. * * This source file is free software, available under the following license: * MIT license - http://datatables.net/license @@ -909,8 +909,11 @@ var s = allSettings[i]; /* Base check on table node */ - if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) ) - { + if ( + s.nTable == this || + (s.nTHead && s.nTHead.parentNode == this) || + (s.nTFoot && s.nTFoot.parentNode == this) + ) { var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve; var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy; @@ -967,11 +970,7 @@ // Backwards compatibility, before we apply all the defaults _fnCompatOpts( oInit ); - - if ( oInit.oLanguage ) - { - _fnLanguageCompat( oInit.oLanguage ); - } + _fnLanguageCompat( oInit.oLanguage ); // If the length menu is given, but the init display length is not, use the length menu if ( oInit.aLengthMenu && ! oInit.iDisplayLength ) @@ -1354,8 +1353,10 @@ // - fr - Swiss Franc // - kr - Swedish krona, Norwegian krone and Danish krone // - \u2009 is thin space and \u202F is narrow no-break space, both used in many + // - Ƀ - Bitcoin + // - Ξ - Ethereum // standards as thousands separators. - var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi; + var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi; var _empty = function ( d ) { @@ -1730,33 +1731,43 @@ */ function _fnLanguageCompat( lang ) { + // Note the use of the Hungarian notation for the parameters in this method as + // this is called after the mapping of camelCase to Hungarian var defaults = DataTable.defaults.oLanguage; - var zeroRecords = lang.sZeroRecords; - /* Backwards compatibility - if there is no sEmptyTable given, then use the same as - * sZeroRecords - assuming that is given. - */ - if ( ! lang.sEmptyTable && zeroRecords && - defaults.sEmptyTable === "No data available in table" ) - { - _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' ); + // Default mapping + var defaultDecimal = defaults.sDecimal; + if ( defaultDecimal ) { + _addNumericSort( defaultDecimal ); } - /* Likewise with loading records */ - if ( ! lang.sLoadingRecords && zeroRecords && - defaults.sLoadingRecords === "Loading..." ) - { - _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' ); - } + if ( lang ) { + var zeroRecords = lang.sZeroRecords; - // Old parameter name of the thousands separator mapped onto the new - if ( lang.sInfoThousands ) { - lang.sThousands = lang.sInfoThousands; - } + // Backwards compatibility - if there is no sEmptyTable given, then use the same as + // sZeroRecords - assuming that is given. + if ( ! lang.sEmptyTable && zeroRecords && + defaults.sEmptyTable === "No data available in table" ) + { + _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' ); + } - var decimal = lang.sDecimal; - if ( decimal ) { - _addNumericSort( decimal ); + // Likewise with loading records + if ( ! lang.sLoadingRecords && zeroRecords && + defaults.sLoadingRecords === "Loading..." ) + { + _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' ); + } + + // Old parameter name of the thousands separator mapped onto the new + if ( lang.sInfoThousands ) { + lang.sThousands = lang.sInfoThousands; + } + + var decimal = lang.sDecimal; + if ( decimal && defaultDecimal !== decimal ) { + _addNumericSort( decimal ); + } } } @@ -3128,7 +3139,7 @@ } } - _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] ); + _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] ); } // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved @@ -3453,7 +3464,7 @@ // iRowCount and j are not currently documented. Are they at all // useful? _fnCallbackFire( oSettings, 'aoRowCallback', null, - [nRow, aoData._aData, iRowCount, j] ); + [nRow, aoData._aData, iRowCount, j, iDataIndex] ); anRows.push( nRow ); iRowCount++; @@ -3857,12 +3868,12 @@ { ajaxData = ajax.data; - var newData = $.isFunction( ajaxData ) ? + var newData = typeof ajaxData === 'function' ? ajaxData( data, oSettings ) : // fn can manipulate data or return ajaxData; // an object object or array to merge // If the function returned something, use that alone - data = $.isFunction( ajaxData ) && newData ? + data = typeof ajaxData === 'function' && newData ? newData : $.extend( true, data, newData ); @@ -3926,7 +3937,7 @@ url: ajax || oSettings.sAjaxSource } ) ); } - else if ( $.isFunction( ajax ) ) + else if ( typeof ajax === 'function' ) { // Is a function - let the caller define what needs to be done oSettings.jqXHR = ajax.call( instance, data, callback, oSettings ); @@ -5360,14 +5371,18 @@ // both match, but we want to hide it completely. We want to also fix their // width to what they currently are _fnApplyToChildren( function(nSizer, i) { - nSizer.innerHTML = '
'+headerContent[i]+'
'; + nSizer.innerHTML = '
'+headerContent[i]+'
'; + nSizer.childNodes[0].style.height = "0"; + nSizer.childNodes[0].style.overflow = "hidden"; nSizer.style.width = headerWidths[i]; }, headerSrcEls ); if ( footer ) { _fnApplyToChildren( function(nSizer, i) { - nSizer.innerHTML = '
'+footerContent[i]+'
'; + nSizer.innerHTML = '
'+footerContent[i]+'
'; + nSizer.childNodes[0].style.height = "0"; + nSizer.childNodes[0].style.overflow = "hidden"; nSizer.style.width = footerWidths[i]; }, footerSrcEls ); } @@ -6561,7 +6576,7 @@ { $(n) .on( 'click.DT', oData, function (e) { - n.blur(); // Remove focus outline for mouse users + $(n).blur(); // Remove focus outline for mouse users fn(e); } ) .on( 'keypress.DT', oData, function (e){ @@ -7801,13 +7816,26 @@ } } else if ( order == 'current' || order == 'applied' ) { - a = search == 'none' ? - displayMaster.slice() : // no search - search == 'applied' ? - displayFiltered.slice() : // applied search - $.map( displayMaster, function (el, i) { // removed search - return $.inArray( el, displayFiltered ) === -1 ? el : null; - } ); + if ( search == 'none') { + a = displayMaster.slice(); + } + else if ( search == 'applied' ) { + a = displayFiltered.slice(); + } + else if ( search == 'removed' ) { + // O(n+m) solution by creating a hash map + var displayFilteredMap = {}; + + for ( var i=0, ien=displayFiltered.length ; i
- - - - - - + + + + - - - diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs index f06c676079..5bfc221e4d 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs @@ -1,4 +1,3 @@ -using System; using System.Threading.Tasks; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; diff --git a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj index f8143caa2f..9ad8e3bff6 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj +++ b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj @@ -18,6 +18,7 @@ + diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs index 80f42ed3ff..8adf03faa9 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs @@ -1,4 +1,6 @@ -using Volo.Abp.Domain; +using System; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Domain; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; @@ -35,6 +37,11 @@ namespace Volo.Docs options.Stores[GithubDocumentStore.Type] = typeof(GithubDocumentStore); options.Stores[FileSystemDocumentStore.Type] = typeof(FileSystemDocumentStore); }); + + context.Services.AddHttpClient(GithubRepositoryManager.HttpClientName, client => + { + client.Timeout = TimeSpan.FromMilliseconds(15000); + }); } } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs index 5baa073b9c..715306ae5c 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs @@ -1,16 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net; using System.Threading.Tasks; using Microsoft.Extensions.Logging; -using Octokit; -using Octokit.Internal; using Volo.Abp.Domain.Services; using Volo.Docs.Documents; using Volo.Docs.GitHub.Projects; using Volo.Docs.Projects; using Newtonsoft.Json.Linq; +using Octokit; using ProductHeaderValue = Octokit.ProductHeaderValue; using Project = Volo.Docs.Projects.Project; @@ -22,6 +20,13 @@ namespace Volo.Docs.GitHub.Documents { public const string Type = "GitHub"; + private readonly IGithubRepositoryManager _githubRepositoryManager; + + public GithubDocumentStore(IGithubRepositoryManager githubRepositoryManager) + { + _githubRepositoryManager = githubRepositoryManager; + } + public virtual async Task GetDocumentAsync(Project project, string documentName, string version) { var token = project.GetGitHubAccessTokenOrNull(); @@ -102,20 +107,7 @@ namespace Volo.Docs.GitHub.Documents var url = project.GetGitHubUrl(); var ownerName = GetOwnerNameFromUrl(url); var repositoryName = GetRepositoryNameFromUrl(url); - var gitHubClient = CreateGitHubClient(project.GetGitHubAccessTokenOrNull()); - - return await gitHubClient - .Repository - .Release - .GetAll(ownerName, repositoryName); - } - - private static GitHubClient CreateGitHubClient(string token = null) - { - //TODO: Why hard-coded "abpframework"? Should be configurable? - return token.IsNullOrWhiteSpace() - ? new GitHubClient(new ProductHeaderValue("abpframework")) - : new GitHubClient(new ProductHeaderValue("abpframework"), new InMemoryCredentialStore(new Credentials(token))); + return await _githubRepositoryManager.GetReleasesAsync(ownerName, repositoryName, project.GetGitHubAccessTokenOrNull()); } protected virtual string GetOwnerNameFromUrl(string url) @@ -151,19 +143,7 @@ namespace Volo.Docs.GitHub.Documents { Logger.LogInformation("Downloading content from Github (DownloadWebContentAsStringAsync): " + rawUrl); - using (var webClient = new GithubWebClient()) - { - if (!token.IsNullOrWhiteSpace()) - { - webClient.Headers.Add("Authorization", "token " + token); - } - - webClient.Headers.Add("User-Agent", userAgent ?? ""); - - //TODO: SET TIMEOUT? - - return await webClient.DownloadStringTaskAsync(new Uri(rawUrl)); - } + return await _githubRepositoryManager.GetFileRawStringContentAsync(rawUrl, token, userAgent); } catch (Exception ex) { @@ -179,16 +159,7 @@ namespace Volo.Docs.GitHub.Documents { Logger.LogInformation("Downloading content from Github (DownloadWebContentAsByteArrayAsync): " + rawUrl); - using (var webClient = new GithubWebClient()) - { - if (!token.IsNullOrWhiteSpace()) - { - webClient.Headers.Add("Authorization", "token " + token); - } - webClient.Headers.Add("User-Agent", userAgent ?? ""); - - return await webClient.DownloadDataTaskAsync(new Uri(rawUrl)); - } + return await _githubRepositoryManager.GetFileRawByteArrayContentAsync(rawUrl, token, userAgent); } catch (Exception ex) { @@ -237,21 +208,5 @@ namespace Volo.Docs.GitHub.Documents .Replace("github.com", "raw.githubusercontent.com") .ReplaceFirst("/tree/", "/"); } - - private class GithubWebClient : WebClient - { - protected override WebRequest GetWebRequest(Uri address) - { - var webRequest = base.GetWebRequest(address); - if (webRequest == null) - { - return null; - } - - webRequest.Timeout = 15000; - - return webRequest; - } - } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubRepositoryManager.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubRepositoryManager.cs new file mode 100644 index 0000000000..be71fd4772 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubRepositoryManager.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using Octokit; +using Octokit.Internal; +using ProductHeaderValue = Octokit.ProductHeaderValue; + +namespace Volo.Docs.GitHub.Documents +{ + public class GithubRepositoryManager : IGithubRepositoryManager + { + public const string HttpClientName = "GithubRepositoryManagerHttpClientName"; + + private readonly IHttpClientFactory _clientFactory; + + public GithubRepositoryManager(IHttpClientFactory clientFactory) + { + _clientFactory = clientFactory; + } + + public async Task GetFileRawStringContentAsync(string rawUrl, string token, string userAgent) + { + var httpClient = _clientFactory.CreateClient(HttpClientName); + if (!token.IsNullOrWhiteSpace()) + { + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", token); + } + + httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent ?? ""); + + return await httpClient.GetStringAsync(new Uri(rawUrl)); + } + + public async Task GetFileRawByteArrayContentAsync(string rawUrl, string token, string userAgent) + { + var httpClient = _clientFactory.CreateClient(HttpClientName); + if (!token.IsNullOrWhiteSpace()) + { + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", token); + } + + httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent ?? ""); + + return await httpClient.GetByteArrayAsync(new Uri(rawUrl)); + } + + public async Task> GetReleasesAsync(string name, string repositoryName, string token) + { + var client = token.IsNullOrWhiteSpace() + ? new GitHubClient(new ProductHeaderValue(name)) + : new GitHubClient(new ProductHeaderValue(name), new InMemoryCredentialStore(new Credentials(token))); + + return (await client + .Repository + .Release + .GetAll(name, repositoryName)).ToList(); + } + } +} diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/IGithubRepositoryManager.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/IGithubRepositoryManager.cs new file mode 100644 index 0000000000..519b9829d5 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/IGithubRepositoryManager.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Octokit; +using Volo.Abp.DependencyInjection; + +namespace Volo.Docs.GitHub.Documents +{ + public interface IGithubRepositoryManager : ITransientDependency + { + Task GetFileRawStringContentAsync(string rawUrl, string token, string userAgent); + + Task GetFileRawByteArrayContentAsync(string rawUrl, string token, string userAgent); + + Task> GetReleasesAsync(string name, string repositoryName, string token); + + } +} diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json new file mode 100644 index 0000000000..05a642010c --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json @@ -0,0 +1,18 @@ +{ + "culture": "pt-BR", + "texts": { + "Documents": "Documentos", + "BackToWebsite": "Voltar para o site", + "Contributors": "Contribuidores", + "ShareOn": "Compartilhar em:", + "Version": "Versão", + "Edit": "Editar", + "Delete": "Excluir", + "InThisDocument": "Neste documento", + "GoToTop": "Ir pra o topo", + "Projects": "Projeto(s)", + "NoProjectWarning": "Ainda não há projetos!", + "DocumentNotFound": "Oops, o documento solicitado foi encontrado", + "NavigationDocumentNotFound": "Esta versão não possui um documento de navegação!" + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs index 1872d33cd8..4a6ad77ddd 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs @@ -9,8 +9,6 @@ namespace Volo.Docs.Projects { Task> GetListAsync(string sorting, int maxResultCount, int skipCount); - Task GetTotalProjectCount(); - Task GetByShortNameAsync(string shortName); } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs index f9e6ab4fa7..b54869edcd 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs @@ -21,18 +21,13 @@ namespace Volo.Docs.Projects public async Task> GetListAsync(string sorting, int maxResultCount, int skipCount) { - var projects = await DbSet.OrderBy(sorting ?? "creationTime desc") + var projects = await DbSet.OrderBy(sorting ?? "Id desc") .PageBy(skipCount, maxResultCount) .ToListAsync(); return projects; } - public async Task GetTotalProjectCount() - { - return await DbSet.CountAsync(); - } - public async Task GetByShortNameAsync(string shortName) { var project = await DbSet.FirstOrDefaultAsync(p => p.ShortName == shortName); diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml index 00e5bcf069..1c5976e760 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml @@ -1,5 +1,4 @@ @page -@using Castle.Core.Internal @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Docs @using Volo.Docs.Localization @@ -11,18 +10,17 @@ @section styles { - }
- @if (Model.Projects.IsNullOrEmpty()) + @if (Model.Projects == null || !Model.Projects.Any()) { } - @if (Model.Projects.Count > 0) + else {

@L["Projects"]

diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css index 0e9f1cdb01..ac21149c59 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css @@ -72,7 +72,7 @@ font-weight: 700; padding: 7px 0; display: block; - border-bottom: 1px solid #eeeff3; } + border-bottom: 0; } .docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover { color: #000; } .docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a.last-link { @@ -82,7 +82,7 @@ color: #999; padding: 7px 0; display: block; - border-bottom: 1px solid #eeeff3; } + border-bottom: 0; } .docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon { font-size: .85em; transition: .3s; @@ -321,7 +321,7 @@ color: #aaa; } .docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a { color: #aaa; - border-bottom: 1px solid #333; } + border-bottom: 0; } .docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover { color: #fff; } .docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon { @@ -349,7 +349,7 @@ color: #555; padding: 7px 0; display: block; - border-bottom: 1px solid #333; } + border-bottom: 0; } .docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree > a { color: #fff; transition: .4s; } diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.min.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.min.css index 833d37db6d..30820acc67 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.min.css +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.min.css @@ -1 +1 @@ -body{position:relative;}.docs-page{background:#f5f7f9;}.docs-page .anchorjs-link{transition:all .25s linear;}.docs-page *:hover>.anchorjs-link{margin-left:-1.125em !important;transition:color .25s linear;color:#808080;}.docs-page .anchorjs-link:hover{color:#007bff;text-decoration:none;}.docs-page .docs-sidebar{background:#f5f7f9;padding-right:1rem;position:relative;top:0;left:0;position:fixed;}.docs-page .docs-sidebar .docs-sidebar-wrapper{width:270px;float:right;}.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control{background:none;background:#fff;border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:visited{box-shadow:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version{position:relative;padding:0 1rem;margin:.45rem 0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select{border-radius:8px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select .input-group-text{border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{line-height:1;border-top-left-radius:0;border-bottom-left-radius:0;padding:.3em .5em .5em;border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:visited,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:visited{box-shadow:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter{padding:0 1rem;margin:.5rem 0;font-size:.9em;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter .filter-icon i.fa{color:#ddd;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{height:100vh;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list>ul{display:block;height:calc(100vh - 220px);overflow-y:auto;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul{font-size:.935em;list-style:none;padding:0 1rem;margin:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li{margin-left:0;padding-left:24px;display:block;width:100%;position:relative;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#999;font-weight:700;padding:7px 0;display:block;border-bottom:1px solid #eeeff3;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover{color:#000;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a.last-link{top:11px;color:#aaa;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li span.tree-toggle{color:#999;padding:7px 0;display:block;border-bottom:1px solid #eeeff3;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon{font-size:.85em;transition:.3s;width:18px;height:18px;text-align:center;padding:0;line-height:1;border-radius:50%;margin-right:4px;position:absolute;left:2px;top:11px;color:#aaa;cursor:default;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon .fa-long-arrow-right.no-link{color:#555;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon .fa-chevron-right{cursor:pointer;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li a{font-weight:400;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul li a{font-weight:300;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#000;transition:.4s;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>span .fa{transform:rotate(90deg);color:#007bff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree.last-link>span .fa{transform:rotate(0deg);}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:1.5rem;color:#000;font-weight:700;padding:20px 0 10px;line-height:1;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand strong{font-weight:300;text-transform:uppercase;font-size:.9rem;opacity:.6;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{color:#000;opacity:.15;transition:.4s;font-size:.75rem;font-weight:300;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site:hover{text-decoration:none;opacity:.5;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:.85em;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc strong{display:block;}.docs-page .docs-content{overflow-x:scroll;}.docs-page .docs-content .contributors{position:absolute;top:15px;right:5px;}.docs-page .docs-content .contributors .contributors-avatar{border-radius:21px;width:21px;height:21px;}.docs-page .docs-content .contributors a{padding:0;width:21px;height:21px;display:inline-block;margin:0 0 0 2px;}.docs-page .docs-content .contributors a:hover{text-decoration:none;}.docs-page .docs-content .docs-link-btns{border-bottom:1px solid #f4f5f7;background:#fdfdfd;padding:10px 20px;margin:0 -15px;text-align:right;font-size:.8em;min-height:40px;}.docs-page .docs-content .docs-link-btns a{color:#999;}.docs-page .docs-content .docs-link-btns a:hover{color:#444;text-decoration:none;}.docs-page .docs-content .docs-link-btns .twitter{color:#00acee;}.docs-page .docs-content .docs-link-btns .linkedin{color:#0077b5;}.docs-page .docs-content .docs-link-btns .email{color:#5a5a5a;}.docs-page .docs-content .docs-link-btns .share-button{margin-left:10px;}.docs-page .docs-content .docs-text-field{padding:2rem;}.docs-page .docs-content article.docs-body h1{padding-top:1rem;font-size:2.25rem;padding-bottom:10px;}.docs-page .docs-content article.docs-body h2{padding-top:2rem;padding-bottom:10px;font-size:2rem;}.docs-page .docs-content article.docs-body h3,.docs-page .docs-content article.docs-body h4,.docs-page .docs-content article.docs-body h5,.docs-page .docs-content article.docs-body h6{padding-top:20px;padding-bottom:5px;font-size:1.5rem;}.docs-page .docs-content article.docs-body h1,.docs-page .docs-content article.docs-body h2,.docs-page .docs-content article.docs-body h3,.docs-page .docs-content article.docs-body h4,.docs-page .docs-content article.docs-body h5,.docs-page .docs-content article.docs-body h6{position:relative;}.docs-page .docs-content article.docs-body h1 .anchor,.docs-page .docs-content article.docs-body h2 .anchor,.docs-page .docs-content article.docs-body h3 .anchor,.docs-page .docs-content article.docs-body h4 .anchor,.docs-page .docs-content article.docs-body h5 .anchor,.docs-page .docs-content article.docs-body h6 .anchor{position:absolute;right:-26px;font-size:18px;bottom:5px;color:#999;opacity:0;transition:.5s;}.docs-page .docs-content article.docs-body h1:hover .anchor,.docs-page .docs-content article.docs-body h2:hover .anchor,.docs-page .docs-content article.docs-body h3:hover .anchor,.docs-page .docs-content article.docs-body h4:hover .anchor,.docs-page .docs-content article.docs-body h5:hover .anchor,.docs-page .docs-content article.docs-body h6:hover .anchor{opacity:1;}.docs-page .docs-content article.docs-body img{max-width:100%;border:1px solid #f4f5f7;margin:15px 0 25px;box-shadow:0 0 45px #f8f9fa;border-radius:6px;}.docs-page .docs-content article.docs-body table{display:block;overflow:auto;width:100%;}.docs-page .docs-content article.docs-body table thead tr{border-bottom:2px inset;}.docs-page .docs-content article.docs-body table th{font-weight:600;}.docs-page .docs-content article.docs-body table td,.docs-page .docs-content article.docs-body table th{border:1px solid #dfe2e5;padding:6px 13px;}.docs-page .docs-content article.docs-body table tr{background-color:#fff;border-top:1px solid #c6cbd1;}.docs-page .docs-content article.docs-body table tr:nth-child(2n){background-color:#f6f8fa;}.docs-page .docs-content article.docs-body table img{background-color:initial;}.docs-page .docs-page-index{min-height:100vh;}.docs-page .docs-page-index #scroll-index{max-height:100vh;}.docs-page .docs-page-index .docs-inner-anchors{position:fixed;top:0;padding:10px;font-size:.9em;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills{font-size:.92em;margin-left:15px;border-left:1px solid #eee;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link{padding:3px 14px 4px;color:#aaa;line-height:1.2;position:relative;border-left:1px solid #eee;border-radius:0;margin-left:-1px;margin-top:1px;margin-bottom:1px;transition:.2s;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link.active{border-left:2px solid #007bff;background:none;color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-link.active{color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-pills .nav-link.active{color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .index-scroll{margin-left:-30px;}.docs-page .docs-page-index .docs-inner-anchors .docs-anchors-wrapper{max-width:300px;float:left;}.docs-page .docs-page-index .scroll-top-btn{display:none;font-size:.85em;color:#aaa;text-decoration:none;padding-left:18px;}.docs-page .docs-page-index .scroll-top-btn.showup{display:block;}@media(min-width:1100px){.container{max-width:1080px;}.docs-page .docs-sidebar.dark-sidebar{background:#191919;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control,.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{background:#333;border-color:#333;color:#999;font-size:.9em;min-height:40px;padding-left:8px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{background:#333;border-color:#333;color:#999;font-size:.9em;min-height:40px;padding-left:12px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control::placeholder{color:#999;opacity:.5;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select label{background:#444;border-color:#444;color:#ddd;width:36px;text-align:center;padding-left:0;padding-right:0;display:inline-block;line-height:26px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-filter .form-control{background:#333;color:#999;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-filter select{border:0;border-radius:6px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-filter .filter-icon i.fa{color:#aaa;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#aaa;border-bottom:1px solid #333;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover{color:#fff;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon{font-size:.85em;transition:.3s;width:18px;height:18px;text-align:center;padding:0;line-height:1;border-radius:50%;margin-right:4px;position:absolute;left:2px;top:11px;color:#aaa;cursor:default;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon .fa-long-arrow-right.no-link{color:#555;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon .fa-chevron-right{cursor:pointer;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon.last-link{top:11px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li span.tree-toggle{color:#555;padding:7px 0;display:block;border-bottom:1px solid #333;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#fff;transition:.4s;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a span .fa{color:#fff;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a span:not(.last-link) .fa{transform:rotate(90deg);color:#fff;}.docs-page .docs-sidebar.dark-sidebar .docs-top .navbar-logo .navbar-brand{color:#fff;text-transform:uppercase;white-space:unset;}.docs-page .docs-sidebar.dark-sidebar .docs-top .navbar-logo .go-back-site{color:#fff;}.docs-page .docs-sidebar.dark-sidebar .docs-top .navbar-logo .navbar-logo-desc{color:#ddd;}}@media(min-width:1366px){.container{max-width:1340px;}}@media(min-width:1440px){.container{max-width:1400px;}}@media(max-width:767px){.docs-page .docs-content article.docs-body h1{padding-top:1.5rem;}.docs-page{background:#f5f7f9;}.docs-page>.container-fluid{display:block;}.docs-page>.container-fluid>.row{display:block;}.docs-page .docs-sidebar{position:fixed;max-width:100%;width:100%;display:block;padding:0 !important;top:0;left:0;z-index:100;right:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper{max-width:100%;width:100%;top:0;position:relative;margin:0 !important;height:72px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{padding:.5rem 1.5rem 2rem 1.5rem;position:fixed;top:70px;font-size:17px;left:0;width:100%;z-index:100;background:#f5f7f9;display:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-filter{padding:0 0 1rem !important;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version label{width:36px;text-align:center;padding-left:0;padding-right:0;display:inline-block;line-height:26px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version input.form-control{padding-left:12px !important;}.docs-page .docs-sidebar .docs-top .navbar-logo{padding:0;padding-top:.3rem;display:block;text-align:center;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:1.5rem;font-weight:700;display:block;margin-right:0;padding:7px 0 10px;text-transform:uppercase;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand .docs-logo{width:110px;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{display:none;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:1em;display:none;}.docs-page .docs-sidebar .docs-top .open-dmenu{position:absolute;top:10px;left:20px;}.docs-page .docs-content{padding-top:72px;max-width:100%;display:block !important;}.docs-page .docs-content .docs-text-field{padding:1rem 1.5rem;}.docs-page .docs-page-index{display:none;}}.for-mobile{display:none;}.for-desktop{display:inline-block;}pre[class*="language-"]{padding:1.4em 2em !important;margin:15px 0 25px !important;border-radius:6px;}code{padding:.2em .4em;margin:0;font-size:82%;background-color:#f0f1f3;border-radius:3px;color:#28a745;}pre code{padding:0;}pre .token.keyword{color:#569cd6;}pre .token.atrule,pre .token.attr-value,pre .token.function,pre .token.class-name{color:#d69d85;}:not(pre)>code[class*="language-"],pre[class*="language-"]{background:#191919 !important;}div.code-toolbar>.toolbar span{cursor:default;}div.code-toolbar>.toolbar a{cursor:copy;}@media(max-width:767px){body{font-size:14px;}.for-mobile{display:inline-block;}.for-desktop{display:none;}.close-mmenu,.close-dmenu{position:absolute;top:-78px;left:25px;color:#fff;font-size:68px;background:#fff;opacity:0;}.navbar{padding:.5rem 1.75rem;}.navbar .navbar-collapse{background:#38003d;position:fixed;top:86px;left:0;width:100%;height:100vh;height:calc(100vh - 86px);z-index:100 !important;}.navbar .navbar-collapse .navbar-nav{height:100vh;padding:20px 30px;overflow:auto;}.navbar .navbar-collapse .navbar-nav .nav-link{padding:1.2rem !important;}.navbar .navbar-toggler{padding:.5rem .75rem;font-size:1.5rem;line-height:1;background-color:transparent;border:0;border-radius:.25rem;color:#fff !important;margin-left:-1rem;}.section-with-logos img{margin:15px;opacity:1;-webkit-filter:grayscale(0%);filter:grayscale(0%);}span.code-arrow{padding:0 0 0;display:block;transform:rotate(90deg);font-size:2em;}.mb-5,.my-5{margin-bottom:2rem !important;}}@media screen and (max-width:767px){.navbar-logo .navbar-brand{display:inline-block;margin:0 auto !important;max-width:70%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}} \ No newline at end of file +body{position:relative;}.docs-page{background:#f5f7f9;}.docs-page .anchorjs-link{transition:all .25s linear;}.docs-page *:hover>.anchorjs-link{margin-left:-1.125em !important;transition:color .25s linear;color:#808080;}.docs-page .anchorjs-link:hover{color:#007bff;text-decoration:none;}.docs-page .docs-sidebar{background:#f5f7f9;padding-right:1rem;position:relative;top:0;left:0;position:fixed;}.docs-page .docs-sidebar .docs-sidebar-wrapper{width:270px;float:right;}.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control{background:none;background:#fff;border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:visited{box-shadow:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version{position:relative;padding:0 1rem;margin:.45rem 0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select{border-radius:8px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select .input-group-text{border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{line-height:1;border-top-left-radius:0;border-bottom-left-radius:0;padding:.3em .5em .5em;border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:visited,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:visited{box-shadow:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter{padding:0 1rem;margin:.5rem 0;font-size:.9em;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter .filter-icon i.fa{color:#ddd;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{height:100vh;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list>ul{display:block;height:calc(100vh - 220px);overflow-y:auto;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul{font-size:.935em;list-style:none;padding:0 1rem;margin:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li{margin-left:0;padding-left:24px;display:block;width:100%;position:relative;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#999;font-weight:700;padding:7px 0;display:block;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover{color:#000;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a.last-link{top:11px;color:#aaa;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li span.tree-toggle{color:#999;padding:7px 0;display:block;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon{font-size:.85em;transition:.3s;width:18px;height:18px;text-align:center;padding:0;line-height:1;border-radius:50%;margin-right:4px;position:absolute;left:2px;top:11px;color:#aaa;cursor:default;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon .fa-long-arrow-right.no-link{color:#555;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon .fa-chevron-right{cursor:pointer;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li a{font-weight:400;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul li a{font-weight:300;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#000;transition:.4s;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>span .fa{transform:rotate(90deg);color:#007bff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree.last-link>span .fa{transform:rotate(0deg);}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:1.5rem;color:#000;font-weight:700;padding:20px 0 10px;line-height:1;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand strong{font-weight:300;text-transform:uppercase;font-size:.9rem;opacity:.6;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{color:#000;opacity:.15;transition:.4s;font-size:.75rem;font-weight:300;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site:hover{text-decoration:none;opacity:.5;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:.85em;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc strong{display:block;}.docs-page .docs-content{overflow-x:scroll;}.docs-page .docs-content .contributors{position:absolute;top:15px;right:5px;}.docs-page .docs-content .contributors .contributors-avatar{border-radius:21px;width:21px;height:21px;}.docs-page .docs-content .contributors a{padding:0;width:21px;height:21px;display:inline-block;margin:0 0 0 2px;}.docs-page .docs-content .contributors a:hover{text-decoration:none;}.docs-page .docs-content .docs-link-btns{border-bottom:1px solid #f4f5f7;background:#fdfdfd;padding:10px 20px;margin:0 -15px;text-align:right;font-size:.8em;min-height:40px;}.docs-page .docs-content .docs-link-btns a{color:#999;}.docs-page .docs-content .docs-link-btns a:hover{color:#444;text-decoration:none;}.docs-page .docs-content .docs-link-btns .twitter{color:#00acee;}.docs-page .docs-content .docs-link-btns .linkedin{color:#0077b5;}.docs-page .docs-content .docs-link-btns .email{color:#5a5a5a;}.docs-page .docs-content .docs-link-btns .share-button{margin-left:10px;}.docs-page .docs-content .docs-text-field{padding:2rem;}.docs-page .docs-content article.docs-body h1{padding-top:1rem;font-size:2.25rem;padding-bottom:10px;}.docs-page .docs-content article.docs-body h2{padding-top:2rem;padding-bottom:10px;font-size:2rem;}.docs-page .docs-content article.docs-body h3,.docs-page .docs-content article.docs-body h4,.docs-page .docs-content article.docs-body h5,.docs-page .docs-content article.docs-body h6{padding-top:20px;padding-bottom:5px;font-size:1.5rem;}.docs-page .docs-content article.docs-body h1,.docs-page .docs-content article.docs-body h2,.docs-page .docs-content article.docs-body h3,.docs-page .docs-content article.docs-body h4,.docs-page .docs-content article.docs-body h5,.docs-page .docs-content article.docs-body h6{position:relative;}.docs-page .docs-content article.docs-body h1 .anchor,.docs-page .docs-content article.docs-body h2 .anchor,.docs-page .docs-content article.docs-body h3 .anchor,.docs-page .docs-content article.docs-body h4 .anchor,.docs-page .docs-content article.docs-body h5 .anchor,.docs-page .docs-content article.docs-body h6 .anchor{position:absolute;right:-26px;font-size:18px;bottom:5px;color:#999;opacity:0;transition:.5s;}.docs-page .docs-content article.docs-body h1:hover .anchor,.docs-page .docs-content article.docs-body h2:hover .anchor,.docs-page .docs-content article.docs-body h3:hover .anchor,.docs-page .docs-content article.docs-body h4:hover .anchor,.docs-page .docs-content article.docs-body h5:hover .anchor,.docs-page .docs-content article.docs-body h6:hover .anchor{opacity:1;}.docs-page .docs-content article.docs-body img{max-width:100%;border:1px solid #f4f5f7;margin:15px 0 25px;box-shadow:0 0 45px #f8f9fa;border-radius:6px;}.docs-page .docs-content article.docs-body table{display:block;overflow:auto;width:100%;}.docs-page .docs-content article.docs-body table thead tr{border-bottom:2px inset;}.docs-page .docs-content article.docs-body table th{font-weight:600;}.docs-page .docs-content article.docs-body table td,.docs-page .docs-content article.docs-body table th{border:1px solid #dfe2e5;padding:6px 13px;}.docs-page .docs-content article.docs-body table tr{background-color:#fff;border-top:1px solid #c6cbd1;}.docs-page .docs-content article.docs-body table tr:nth-child(2n){background-color:#f6f8fa;}.docs-page .docs-content article.docs-body table img{background-color:initial;}.docs-page .docs-page-index{min-height:100vh;}.docs-page .docs-page-index #scroll-index{max-height:100vh;}.docs-page .docs-page-index .docs-inner-anchors{position:fixed;top:0;padding:10px;font-size:.9em;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills{font-size:.92em;margin-left:15px;border-left:1px solid #eee;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link{padding:3px 14px 4px;color:#aaa;line-height:1.2;position:relative;border-left:1px solid #eee;border-radius:0;margin-left:-1px;margin-top:1px;margin-bottom:1px;transition:.2s;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link.active{border-left:2px solid #007bff;background:none;color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-link.active{color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-pills .nav-link.active{color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .index-scroll{margin-left:-30px;}.docs-page .docs-page-index .docs-inner-anchors .docs-anchors-wrapper{max-width:300px;float:left;}.docs-page .docs-page-index .scroll-top-btn{display:none;font-size:.85em;color:#aaa;text-decoration:none;padding-left:18px;}.docs-page .docs-page-index .scroll-top-btn.showup{display:block;}@media(min-width:1100px){.container{max-width:1080px;}.docs-page .docs-sidebar.dark-sidebar{background:#191919;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control,.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{background:#333;border-color:#333;color:#999;font-size:.9em;min-height:40px;padding-left:8px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{background:#333;border-color:#333;color:#999;font-size:.9em;min-height:40px;padding-left:12px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control::placeholder{color:#999;opacity:.5;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-version .version-select label{background:#444;border-color:#444;color:#ddd;width:36px;text-align:center;padding-left:0;padding-right:0;display:inline-block;line-height:26px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-filter .form-control{background:#333;color:#999;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-filter select{border:0;border-radius:6px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-filter .filter-icon i.fa{color:#aaa;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#aaa;border-bottom:0;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover{color:#fff;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon{font-size:.85em;transition:.3s;width:18px;height:18px;text-align:center;padding:0;line-height:1;border-radius:50%;margin-right:4px;position:absolute;left:2px;top:11px;color:#aaa;cursor:default;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon .fa-long-arrow-right.no-link{color:#555;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon .fa-chevron-right{cursor:pointer;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon.last-link{top:11px;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li span.tree-toggle{color:#555;padding:7px 0;display:block;border-bottom:0;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#fff;transition:.4s;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a span .fa{color:#fff;}.docs-page .docs-sidebar.dark-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a span:not(.last-link) .fa{transform:rotate(90deg);color:#fff;}.docs-page .docs-sidebar.dark-sidebar .docs-top .navbar-logo .navbar-brand{color:#fff;text-transform:uppercase;white-space:unset;}.docs-page .docs-sidebar.dark-sidebar .docs-top .navbar-logo .go-back-site{color:#fff;}.docs-page .docs-sidebar.dark-sidebar .docs-top .navbar-logo .navbar-logo-desc{color:#ddd;}}@media(min-width:1366px){.container{max-width:1340px;}}@media(min-width:1440px){.container{max-width:1400px;}}@media(max-width:767px){.docs-page .docs-content article.docs-body h1{padding-top:1.5rem;}.docs-page{background:#f5f7f9;}.docs-page>.container-fluid{display:block;}.docs-page>.container-fluid>.row{display:block;}.docs-page .docs-sidebar{position:fixed;max-width:100%;width:100%;display:block;padding:0 !important;top:0;left:0;z-index:100;right:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper{max-width:100%;width:100%;top:0;position:relative;margin:0 !important;height:72px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{padding:.5rem 1.5rem 2rem 1.5rem;position:fixed;top:70px;font-size:17px;left:0;width:100%;z-index:100;background:#f5f7f9;display:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-filter{padding:0 0 1rem !important;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version label{width:36px;text-align:center;padding-left:0;padding-right:0;display:inline-block;line-height:26px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version input.form-control{padding-left:12px !important;}.docs-page .docs-sidebar .docs-top .navbar-logo{padding:0;padding-top:.3rem;display:block;text-align:center;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:1.5rem;font-weight:700;display:block;margin-right:0;padding:7px 0 10px;text-transform:uppercase;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand .docs-logo{width:110px;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{display:none;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:1em;display:none;}.docs-page .docs-sidebar .docs-top .open-dmenu{position:absolute;top:10px;left:20px;}.docs-page .docs-content{padding-top:72px;max-width:100%;display:block !important;}.docs-page .docs-content .docs-text-field{padding:1rem 1.5rem;}.docs-page .docs-page-index{display:none;}}.for-mobile{display:none;}.for-desktop{display:inline-block;}pre[class*="language-"]{padding:1.4em 2em !important;margin:15px 0 25px !important;border-radius:6px;}code{padding:.2em .4em;margin:0;font-size:82%;background-color:#f0f1f3;border-radius:3px;color:#28a745;}pre code{padding:0;}pre .token.keyword{color:#569cd6;}pre .token.atrule,pre .token.attr-value,pre .token.function,pre .token.class-name{color:#d69d85;}:not(pre)>code[class*="language-"],pre[class*="language-"]{background:#191919 !important;}div.code-toolbar>.toolbar span{cursor:default;}div.code-toolbar>.toolbar a{cursor:copy;}@media(max-width:767px){body{font-size:14px;}.for-mobile{display:inline-block;}.for-desktop{display:none;}.close-mmenu,.close-dmenu{position:absolute;top:-78px;left:25px;color:#fff;font-size:68px;background:#fff;opacity:0;}.navbar{padding:.5rem 1.75rem;}.navbar .navbar-collapse{background:#38003d;position:fixed;top:86px;left:0;width:100%;height:100vh;height:calc(100vh - 86px);z-index:100 !important;}.navbar .navbar-collapse .navbar-nav{height:100vh;padding:20px 30px;overflow:auto;}.navbar .navbar-collapse .navbar-nav .nav-link{padding:1.2rem !important;}.navbar .navbar-toggler{padding:.5rem .75rem;font-size:1.5rem;line-height:1;background-color:transparent;border:0;border-radius:.25rem;color:#fff !important;margin-left:-1rem;}.section-with-logos img{margin:15px;opacity:1;-webkit-filter:grayscale(0%);filter:grayscale(0%);}span.code-arrow{padding:0 0 0;display:block;transform:rotate(90deg);font-size:2em;}.mb-5,.my-5{margin-bottom:2rem !important;}}@media screen and (max-width:767px){.navbar-logo .navbar-brand{display:inline-block;margin:0 auto !important;max-width:70%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss index 728c5ad94a..22edcbb149 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss @@ -113,7 +113,7 @@ body { font-weight: 700; padding: 7px 0; display: block; - border-bottom: 1px solid #eeeff3; + border-bottom: 0; &:hover { color: #000; @@ -129,7 +129,7 @@ body { color: #999; padding: 7px 0; display: block; - border-bottom: 1px solid #eeeff3; + border-bottom: 0; } .plus-icon { @@ -555,7 +555,7 @@ body { a { color: #aaa; - border-bottom: 1px solid #333; + border-bottom: 0; &:hover { color: #fff; @@ -598,7 +598,7 @@ body { color: #555; padding: 7px 0; display: block; - border-bottom: 1px solid #333; + border-bottom: 0; } diff --git a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo.Docs.Admin.Application.Tests.csproj b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo.Docs.Admin.Application.Tests.csproj new file mode 100644 index 0000000000..390476a38f --- /dev/null +++ b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo.Docs.Admin.Application.Tests.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.2 + + + + + + + + + + + + + diff --git a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestBase.cs b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestBase.cs new file mode 100644 index 0000000000..c11233849a --- /dev/null +++ b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestBase.cs @@ -0,0 +1,7 @@ +namespace Volo.Docs +{ + public class DocsAdminApplicationTestBase : DocsTestBase + { + + } +} diff --git a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestModule.cs b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestModule.cs new file mode 100644 index 0000000000..e85bac8ce3 --- /dev/null +++ b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestModule.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Modularity; +using Volo.Docs.Admin; + +namespace Volo.Docs +{ + [DependsOn( + typeof(DocsAdminApplicationModule), + typeof(DocsDomainTestModule) + )] + public class DocsAdminApplicationTestModule : AbpModule + { + + } +} diff --git a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/ProjectAdminAppService_Tests.cs b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/ProjectAdminAppService_Tests.cs new file mode 100644 index 0000000000..9fcb65f9ae --- /dev/null +++ b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/ProjectAdminAppService_Tests.cs @@ -0,0 +1,121 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Application.Dtos; +using Volo.Docs.Admin.Projects; +using Volo.Docs.Projects; +using Xunit; + +namespace Volo.Docs +{ + public class ProjectAdminAppService_Tests : DocsAdminApplicationTestBase + { + private readonly IProjectAdminAppService _projectAdminAppService; + private readonly IProjectRepository _projectRepository; + private readonly DocsTestData _testData; + + public ProjectAdminAppService_Tests() + { + _projectRepository = GetRequiredService(); + _projectAdminAppService = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task GetListAsync() + { + var projects = await _projectAdminAppService.GetListAsync(new PagedAndSortedResultRequestDto()); + projects.ShouldNotBeNull(); + projects.TotalCount.ShouldBe(1); + projects.Items.ShouldContain(x => x.Name == "ABP vNext"); + } + + [Fact] + public async Task GetAsync() + { + var project = await _projectAdminAppService.GetAsync(_testData.PorjectId); + project.ShouldNotBeNull(); + project.Id.ShouldBe(_testData.PorjectId); + } + + [Fact] + public async Task CreateAsync() + { + var createProjectDto = new CreateProjectDto + { + Name = "ABP vNext", + ShortName = "ABP", + Format = "md", + DefaultDocumentName = "index", + NavigationDocumentName = "docs-nav.json", + MinimumVersion = "1", + MainWebsiteUrl = "abp.io", + LatestVersionBranchName = "", + DocumentStoreType = "GitHub", + ExtraProperties = new Dictionary() + }; + createProjectDto.ExtraProperties.Add("GitHubRootUrl", + "https://github.com/abpframework/abp/tree/{version}/docs/en/"); + createProjectDto.ExtraProperties.Add("GitHubAccessToken", "123456"); + createProjectDto.ExtraProperties.Add("GitHubUserAgent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); + + //Act + var projectDto = await _projectAdminAppService.CreateAsync(createProjectDto); + projectDto.ShouldNotBeNull(); + projectDto.Name.ShouldBe(createProjectDto.Name); + projectDto.ShortName.ShouldBe(createProjectDto.ShortName); + projectDto.Format.ShouldBe(createProjectDto.Format); + projectDto.DefaultDocumentName.ShouldBe(createProjectDto.DefaultDocumentName); + projectDto.NavigationDocumentName.ShouldBe(createProjectDto.NavigationDocumentName); + projectDto.MinimumVersion.ShouldBe(createProjectDto.MinimumVersion); + projectDto.MainWebsiteUrl.ShouldBe(createProjectDto.MainWebsiteUrl); + projectDto.LatestVersionBranchName.ShouldBe(createProjectDto.LatestVersionBranchName); + projectDto.DocumentStoreType.ShouldBe(createProjectDto.DocumentStoreType); + + projectDto.ExtraProperties.Except(createProjectDto.ExtraProperties).Any().ShouldBe(false); + } + + [Fact] + public async Task UpdateAsync() + { + var updateProjectDto = new UpdateProjectDto + { + Name = "ABP vNext", + Format = "md", + DefaultDocumentName = "index", + NavigationDocumentName = "docs-nav.json", + + MinimumVersion = "1", + MainWebsiteUrl = "abp.io", + LatestVersionBranchName = "", + ExtraProperties = new Dictionary() + }; + updateProjectDto.ExtraProperties.Add("test", "test"); + + var projectDto = await _projectAdminAppService.UpdateAsync(_testData.PorjectId, updateProjectDto); + + + projectDto.ShouldNotBeNull(); + projectDto.Name.ShouldBe(updateProjectDto.Name); + + projectDto.Format.ShouldBe(updateProjectDto.Format); + projectDto.DefaultDocumentName.ShouldBe(updateProjectDto.DefaultDocumentName); + projectDto.NavigationDocumentName.ShouldBe(updateProjectDto.NavigationDocumentName); + projectDto.MinimumVersion.ShouldBe(updateProjectDto.MinimumVersion); + projectDto.MainWebsiteUrl.ShouldBe(updateProjectDto.MainWebsiteUrl); + projectDto.LatestVersionBranchName.ShouldBe(updateProjectDto.LatestVersionBranchName); + projectDto.ExtraProperties.ShouldContainKey("test"); + } + + [Fact] + public async Task DeleteAsync() + { + (await _projectRepository.GetAsync(_testData.PorjectId)).ShouldNotBeNull(); + + await _projectAdminAppService.DeleteAsync(_testData.PorjectId); + + (await _projectRepository.GetListAsync()).ShouldBeEmpty(); + } + } +} diff --git a/modules/docs/test/Volo.Docs.Application.Tests/Volo.Docs.Application.Tests.csproj b/modules/docs/test/Volo.Docs.Application.Tests/Volo.Docs.Application.Tests.csproj new file mode 100644 index 0000000000..87144ccfe9 --- /dev/null +++ b/modules/docs/test/Volo.Docs.Application.Tests/Volo.Docs.Application.Tests.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.2 + + + + + + + + + + + + + diff --git a/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs new file mode 100644 index 0000000000..bff7f09e1f --- /dev/null +++ b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs @@ -0,0 +1,45 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Docs.Projects; +using Xunit; + +namespace Volo.Docs +{ + public class ApplicationService_Tests : DocsApplicationTestBase + { + private readonly IProjectAppService _projectAppService; + private readonly DocsTestData _testData; + + public ApplicationService_Tests() + { + _projectAppService = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task GetListAsync() + { + var projects = await _projectAppService.GetListAsync(); + projects.ShouldNotBeNull(); + projects.Items.Count.ShouldBe(1); + projects.Items.ShouldContain(x => x.Id == _testData.PorjectId); + } + + [Fact] + public async Task GetAsync() + { + var project = await _projectAppService.GetAsync("ABP"); + project.ShouldNotBeNull(); + project.ShortName.ShouldBe("ABP"); + } + + [Fact] + public async Task GetVersionsAsync() + { + var versions = await _projectAppService.GetVersionsAsync("ABP"); + versions.ShouldNotBeNull(); + versions.Items.Count.ShouldBe(1); + versions.Items.ShouldContain(x => x.Name == "0.15.0" && x.DisplayName == "0.15.0"); + } + } +} diff --git a/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/DocsApplicationTestBase.cs b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/DocsApplicationTestBase.cs new file mode 100644 index 0000000000..f0fb94d40b --- /dev/null +++ b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/DocsApplicationTestBase.cs @@ -0,0 +1,7 @@ +namespace Volo.Docs +{ + public class DocsApplicationTestBase : DocsTestBase + { + + } +} diff --git a/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/DocsApplicationTestModule.cs b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/DocsApplicationTestModule.cs new file mode 100644 index 0000000000..62d027c220 --- /dev/null +++ b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/DocsApplicationTestModule.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Modularity; + +namespace Volo.Docs +{ + [DependsOn( + typeof(DocsApplicationModule), + typeof(DocsDomainTestModule) + )] + public class DocsApplicationTestModule : AbpModule + { + + } +} diff --git a/modules/docs/test/Volo.Docs.Domain.Tests/Volo.Docs.Domain.Tests.csproj b/modules/docs/test/Volo.Docs.Domain.Tests/Volo.Docs.Domain.Tests.csproj new file mode 100644 index 0000000000..ba1185b397 --- /dev/null +++ b/modules/docs/test/Volo.Docs.Domain.Tests/Volo.Docs.Domain.Tests.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.2 + + + + + + + + + + + + + diff --git a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestBase.cs b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestBase.cs new file mode 100644 index 0000000000..b46e054370 --- /dev/null +++ b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestBase.cs @@ -0,0 +1,7 @@ +namespace Volo.Docs +{ + public abstract class DocsDomainTestBase : DocsTestBase + { + + } +} diff --git a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestModule.cs b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestModule.cs new file mode 100644 index 0000000000..c8ed977193 --- /dev/null +++ b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestModule.cs @@ -0,0 +1,14 @@ +using Volo.Docs.EntityFrameworkCore; +using Volo.Abp.Modularity; + +namespace Volo.Docs +{ + [DependsOn( + typeof(DocsEntityFrameworkCoreTestModule), + typeof(DocsTestBaseModule) + )] + public class DocsDomainTestModule : AbpModule + { + + } +} diff --git a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocumentStoreFactory_Tests.cs b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocumentStoreFactory_Tests.cs new file mode 100644 index 0000000000..73e07ec8e2 --- /dev/null +++ b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocumentStoreFactory_Tests.cs @@ -0,0 +1,25 @@ +using Shouldly; +using Volo.Docs.Documents; +using Volo.Docs.FileSystem.Documents; +using Volo.Docs.GitHub.Documents; +using Xunit; + +namespace Volo.Docs +{ + public class DocumentStoreFactory_Tests : DocsDomainTestBase + { + private readonly IDocumentStoreFactory _documentStoreFactory; + + public DocumentStoreFactory_Tests() + { + _documentStoreFactory = GetRequiredService(); + } + + [Fact] + public void Create() + { + _documentStoreFactory.Create(GithubDocumentStore.Type).GetType().ShouldBe(typeof(GithubDocumentStore)); + _documentStoreFactory.Create(FileSystemDocumentStore.Type).GetType().ShouldBe(typeof(FileSystemDocumentStore)); + } + } +} diff --git a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs new file mode 100644 index 0000000000..1f8bfeca77 --- /dev/null +++ b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs @@ -0,0 +1,72 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Docs.Documents; +using Volo.Docs.GitHub.Documents; +using Volo.Docs.Projects; +using Xunit; + +namespace Volo.Docs +{ + public class GithubDocumentStore_Tests : DocsDomainTestBase + { + private readonly IDocumentStoreFactory _documentStoreFactory; + private readonly IProjectRepository _projectRepository; + private readonly DocsTestData _testData; + + public GithubDocumentStore_Tests() + { + _documentStoreFactory = GetRequiredService(); + _projectRepository = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task GetDocumentAsync() + { + var store = _documentStoreFactory.Create(GithubDocumentStore.Type); + + var project = await _projectRepository.FindAsync(_testData.PorjectId); + project.ShouldNotBeNull(); + + var document = await store.GetDocumentAsync(project, "index2", "0.123.0"); + document.ShouldNotBeNull(); + + document.Title.ShouldBe("index2"); + document.FileName.ShouldBe("index2"); + document.Version.ShouldBe("0.123.0"); + document.Content.ShouldBe("stringContent"); + } + + [Fact] + public async Task GetVersionsAsync() + { + var store = _documentStoreFactory.Create(GithubDocumentStore.Type); + + var project = await _projectRepository.FindAsync(_testData.PorjectId); + project.ShouldNotBeNull(); + + var document = await store.GetVersionsAsync(project); + document.ShouldNotBeNull(); + + document.Count.ShouldBe(1); + document.ShouldContain(x => x.Name == "0.15.0" && x.DisplayName == "0.15.0"); + } + + [Fact] + public async Task GetResource() + { + var store = _documentStoreFactory.Create(GithubDocumentStore.Type); + + var project = await _projectRepository.FindAsync(_testData.PorjectId); + project.ShouldNotBeNull(); + + var documentResource = await store.GetResource(project, "index.md", "0.123.0"); + documentResource.ShouldNotBeNull(); + + documentResource.Content.ShouldBe(new byte[] + { + 0x01, 0x02, 0x03 + }); + } + } +} diff --git a/modules/docs/test/Volo.Docs.EntityFrameworkCore.Tests/Volo.Docs.EntityFrameworkCore.Tests.csproj b/modules/docs/test/Volo.Docs.EntityFrameworkCore.Tests/Volo.Docs.EntityFrameworkCore.Tests.csproj new file mode 100644 index 0000000000..666c1e813f --- /dev/null +++ b/modules/docs/test/Volo.Docs.EntityFrameworkCore.Tests/Volo.Docs.EntityFrameworkCore.Tests.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp2.2 + + + + + + + + + + + + + + + + diff --git a/modules/docs/test/Volo.Docs.EntityFrameworkCore.Tests/Volo/Docs/EntityFrameworkCore/DocsEntityFrameworkCoreTestModule.cs b/modules/docs/test/Volo.Docs.EntityFrameworkCore.Tests/Volo/Docs/EntityFrameworkCore/DocsEntityFrameworkCoreTestModule.cs new file mode 100644 index 0000000000..a4d5eb5a25 --- /dev/null +++ b/modules/docs/test/Volo.Docs.EntityFrameworkCore.Tests/Volo/Docs/EntityFrameworkCore/DocsEntityFrameworkCoreTestModule.cs @@ -0,0 +1,41 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.Modularity; + +namespace Volo.Docs.EntityFrameworkCore +{ + [DependsOn( + typeof(DocsTestBaseModule), + typeof(DocsEntityFrameworkCoreModule) + )] + public class DocsEntityFrameworkCoreTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var sqliteConnection = CreateDatabaseAndGetConnection(); + + Configure(options => + { + options.Configure(abpDbContextConfigurationContext => + { + abpDbContextConfigurationContext.DbContextOptions.UseSqlite(sqliteConnection); + }); + }); + } + + private static SqliteConnection CreateDatabaseAndGetConnection() + { + var connection = new SqliteConnection("Data Source=:memory:"); + connection.Open(); + + new DocsDbContext( + new DbContextOptionsBuilder().UseSqlite(connection).Options + ).GetService().CreateTables(); + + return connection; + } + } +} diff --git a/modules/docs/test/Volo.Docs.EntityFrameworkCore.Tests/Volo/Docs/EntityFrameworkCore/ProjectRepository_Tests.cs b/modules/docs/test/Volo.Docs.EntityFrameworkCore.Tests/Volo/Docs/EntityFrameworkCore/ProjectRepository_Tests.cs new file mode 100644 index 0000000000..9f04386b09 --- /dev/null +++ b/modules/docs/test/Volo.Docs.EntityFrameworkCore.Tests/Volo/Docs/EntityFrameworkCore/ProjectRepository_Tests.cs @@ -0,0 +1,7 @@ +namespace Volo.Docs.EntityFrameworkCore +{ + public class ProjectRepository_Tests : ProjectRepository_Tests + { + + } +} diff --git a/modules/docs/test/Volo.Docs.TestBase/Volo.Docs.TestBase.csproj b/modules/docs/test/Volo.Docs.TestBase/Volo.Docs.TestBase.csproj new file mode 100644 index 0000000000..a92946140a --- /dev/null +++ b/modules/docs/test/Volo.Docs.TestBase/Volo.Docs.TestBase.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp2.2 + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBase.cs b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBase.cs new file mode 100644 index 0000000000..e8b7fa0126 --- /dev/null +++ b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBase.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; +using Octokit; +using Volo.Abp; +using Volo.Abp.Modularity; +using Volo.Docs.GitHub.Documents; + +namespace Volo.Docs +{ + public abstract class DocsTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + var repositoryManager = Substitute.For(); + repositoryManager.GetFileRawStringContentAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .Returns("stringContent"); + repositoryManager.GetFileRawByteArrayContentAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .Returns(new byte[] { 0x01, 0x02, 0x03 }); + repositoryManager.GetReleasesAsync(Arg.Any(), Arg.Any(), Arg.Any()) + .Returns(new List + { + new Release("https://api.github.com/repos/abpframework/abp/releases/16293679", + "https://github.com/abpframework/abp/releases/tag/0.15.0", + "https://api.github.com/repos/abpframework/abp/releases/16293679/assets", + "https://uploads.github.com/repos/abpframework/abp/releases/16293679/assets{?name,label}", + 16293679, + "0.15.0", + "master", + "0.15.0", + "0.15.0 already release", + false, + false, + DateTimeOffset.Parse("2019-03-22T18:43:58Z"), + DateTimeOffset.Parse("2019-03-22T19:44:25Z"), + null, + "https://api.github.com/repos/abpframework/abp/tarball/0.15.0", + "https://api.github.com/repos/abpframework/abp/zipball/0.15.0", + null) + }); + services.AddSingleton(repositoryManager); + } + } +} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/AbpFeatureManagementTestBaseModule.cs b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBaseModule.cs similarity index 79% rename from modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/AbpFeatureManagementTestBaseModule.cs rename to modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBaseModule.cs index bf6169b488..a4661075d0 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/AbpFeatureManagementTestBaseModule.cs +++ b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBaseModule.cs @@ -1,17 +1,18 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp; using Volo.Abp.Authorization; using Volo.Abp.Autofac; using Volo.Abp.Modularity; -namespace Volo.Abp.FeatureManagement +namespace Volo.Docs { [DependsOn( typeof(AbpAutofacModule), typeof(AbpTestBaseModule), typeof(AbpAuthorizationModule), - typeof(AbpFeatureManagementDomainModule) + typeof(DocsDomainModule) )] - public class AbpFeatureManagementTestBaseModule : AbpModule + public class DocsTestBaseModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { @@ -28,7 +29,7 @@ namespace Volo.Abp.FeatureManagement using (var scope = context.ServiceProvider.CreateScope()) { scope.ServiceProvider - .GetRequiredService() + .GetRequiredService() .Build(); } } diff --git a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestData.cs b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestData.cs new file mode 100644 index 0000000000..829195efe6 --- /dev/null +++ b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestData.cs @@ -0,0 +1,10 @@ +using System; +using Volo.Abp.DependencyInjection; + +namespace Volo.Docs +{ + public class DocsTestData : ISingletonDependency + { + public Guid PorjectId { get; } = Guid.NewGuid(); + } +} diff --git a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestDataBuilder.cs b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestDataBuilder.cs new file mode 100644 index 0000000000..39ffc9691e --- /dev/null +++ b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestDataBuilder.cs @@ -0,0 +1,41 @@ +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Docs.GitHub.Documents; +using Volo.Docs.Projects; + +namespace Volo.Docs +{ + public class DocsTestDataBuilder : ITransientDependency + { + private readonly DocsTestData _testData; + private readonly IProjectRepository _projectRepository; + + public DocsTestDataBuilder( + DocsTestData testData, + IProjectRepository projectRepository) + { + _testData = testData; + _projectRepository = projectRepository; + } + + public void Build() + { + var project = new Project( + _testData.PorjectId, + "ABP vNext", + "ABP", + GithubDocumentStore.Type, + "md", + "index", + "docs-nav.json" + ); + + project + .SetProperty("GitHubRootUrl", "https://github.com/abpframework/abp/tree/{version}/docs/en/") + .SetProperty("GitHubAccessToken", "123456") + .SetProperty("GitHubUserAgent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); + + _projectRepository.Insert(project); + } + } +} \ No newline at end of file diff --git a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/ProjectRepository_Tests.cs b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/ProjectRepository_Tests.cs new file mode 100644 index 0000000000..d4351aa11e --- /dev/null +++ b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/ProjectRepository_Tests.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Docs.Projects; +using Xunit; + +namespace Volo.Docs +{ + public abstract class ProjectRepository_Tests : DocsTestBase + where TStartupModule : IAbpModule + { + protected readonly IProjectRepository ProjectRepository; + + protected ProjectRepository_Tests() + { + ProjectRepository = GetRequiredService(); ; + } + + [Fact] + public async Task GetListAsync() + { + var projects = await ProjectRepository.GetListAsync(); + + projects.Count.ShouldBe(1); + } + + [Fact] + public async Task GetByShortNameAsync() + { + var project = await ProjectRepository.GetByShortNameAsync("ABP"); + + project.ShouldNotBeNull(); + project.ShortName.ShouldBe("ABP"); + } + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pt-BR.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pt-BR.json new file mode 100644 index 0000000000..6d746df04c --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/pt-BR.json @@ -0,0 +1,6 @@ +{ + "culture": "pt-BR", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/zh-Hans.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/zh-Hans.json new file mode 100644 index 0000000000..25137f1ee3 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/zh-Hans.json @@ -0,0 +1,6 @@ +{ + "culture": "zh-Hans", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application/Volo/Abp/FeatureManagement/FeatureAppService.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application/Volo/Abp/FeatureManagement/FeatureAppService.cs index b8b6c33d7c..ca2ea995c7 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application/Volo/Abp/FeatureManagement/FeatureAppService.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application/Volo/Abp/FeatureManagement/FeatureAppService.cs @@ -45,7 +45,7 @@ namespace Volo.Abp.FeatureManagement { Name = featureDefinition.Name, ValueType = featureDefinition.ValueType, - Description = featureDefinition.Description.Localize(_stringLocalizerFactory), + Description = featureDefinition.Description?.Localize(_stringLocalizerFactory), ParentName = featureDefinition.Parent?.Name, Value = await _featureManager.GetOrNullAsync(featureDefinition.Name, providerName, providerKey) }); diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json new file mode 100644 index 0000000000..6d746df04c --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/pt-BR.json @@ -0,0 +1,6 @@ +{ + "culture": "pt-BR", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/tr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/tr.json new file mode 100644 index 0000000000..3f906a3cdc --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/tr.json @@ -0,0 +1,6 @@ +{ + "culture": "tr", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/zh-Hans.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/zh-Hans.json new file mode 100644 index 0000000000..25137f1ee3 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/zh-Hans.json @@ -0,0 +1,6 @@ +{ + "culture": "zh-Hans", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pt-BR.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pt-BR.json new file mode 100644 index 0000000000..6d746df04c --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/pt-BR.json @@ -0,0 +1,6 @@ +{ + "culture": "pt-BR", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/tr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/tr.json new file mode 100644 index 0000000000..3f906a3cdc --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/tr.json @@ -0,0 +1,6 @@ +{ + "culture": "tr", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/zh-Hans.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/zh-Hans.json new file mode 100644 index 0000000000..25137f1ee3 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/zh-Hans.json @@ -0,0 +1,6 @@ +{ + "culture": "zh-Hans", + "texts": { + + } +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Volo.Abp.FeatureManagement.Web.csproj b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Volo.Abp.FeatureManagement.Web.csproj index ffe9acd932..2983c95ddf 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Volo.Abp.FeatureManagement.Web.csproj +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Volo.Abp.FeatureManagement.Web.csproj @@ -21,7 +21,6 @@ - diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/FeatureAppService_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/FeatureAppService_Tests.cs new file mode 100644 index 0000000000..5198ea7277 --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/FeatureAppService_Tests.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; +using Shouldly; +using Volo.Abp.Features; +using Volo.Abp.Users; +using Xunit; + +namespace Volo.Abp.FeatureManagement +{ + public class FeatureAppService_Tests : FeatureManagementApplicationTestBase + { + private readonly IFeatureAppService _featureAppService; + private readonly IFeatureValueRepository _featureValueRepository; + private ICurrentUser _currentUser; + private readonly FeatureManagementTestData _testData; + + + public FeatureAppService_Tests() + { + _featureAppService = GetRequiredService(); + _featureValueRepository = GetRequiredService(); + _testData = GetRequiredService(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + _currentUser = Substitute.For(); + services.AddSingleton(_currentUser); + } + + [Fact] + public async Task GetAsync() + { + Login(_testData.User1Id); + + var featureList = await _featureAppService.GetAsync(EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N")); + + featureList.ShouldNotBeNull(); + featureList.Features.ShouldContain(feature => feature.Name == TestFeatureDefinitionProvider.SocialLogins); + } + + [Fact] + public async Task UpdateAsync() + { + Login(_testData.User1Id); + + await _featureAppService.UpdateAsync(EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"), new UpdateFeaturesDto() + { + Features = new List() + { + new UpdateFeatureDto() + { + Name = TestFeatureDefinitionProvider.SocialLogins, + Value = false.ToString().ToLowerInvariant() + } + } + }); + + (await _featureAppService.GetAsync(EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"))).Features.Any(x => + x.Name == TestFeatureDefinitionProvider.SocialLogins && + x.Value == false.ToString().ToLowerInvariant()) + .ShouldBeTrue(); + + } + + private void Login(Guid userId) + { + _currentUser.Id.Returns(userId); + _currentUser.IsAuthenticated.Returns(true); + } + } +} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/FeatureManagementApplicationTestBase.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/FeatureManagementApplicationTestBase.cs new file mode 100644 index 0000000000..f9e74aed57 --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/FeatureManagementApplicationTestBase.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.FeatureManagement +{ + public class FeatureManagementApplicationTestBase : FeatureManagementTestBase + { + + } +} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationTestModule.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/FeatureManagementApplicationTestModule.cs similarity index 75% rename from modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationTestModule.cs rename to modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/FeatureManagementApplicationTestModule.cs index fb65739dca..2952c7da60 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationTestModule.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/FeatureManagementApplicationTestModule.cs @@ -6,7 +6,7 @@ namespace Volo.Abp.FeatureManagement typeof(AbpFeatureManagementApplicationModule), typeof(AbpFeatureManagementDomainTestModule) )] - public class AbpFeatureManagementApplicationTestModule : AbpModule + public class FeatureManagementApplicationTestModule : AbpModule { } diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureValueCacheItemInvalidator_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureValueCacheItemInvalidator_Tests.cs new file mode 100644 index 0000000000..d6666c6c09 --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.Domain.Tests/Volo/Abp/FeatureManagement/FeatureValueCacheItemInvalidator_Tests.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Caching; +using Volo.Abp.Features; +using Xunit; + +namespace Volo.Abp.FeatureManagement +{ + public class FeatureValueCacheItemInvalidator_Tests : FeatureManagementTestBase + { + private IDistributedCache _cache; + private IFeatureValueRepository _featureValueRepository; + private IFeatureManagementStore _featureManagementStore; + + public FeatureValueCacheItemInvalidator_Tests() + { + _cache = GetRequiredService>(); + _featureValueRepository = GetRequiredService(); + _featureManagementStore = GetRequiredService(); + } + + [Fact] + public async Task Cache_Should_Invalidator_WhenFeatureChanged() + { + // Arrange cache feature. + await _featureManagementStore.GetOrNullAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N")); + + var feature = await _featureValueRepository.FindAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N")); + + // Act + await _featureValueRepository.DeleteAsync(feature); + + // Assert + (await _cache.GetAsync(FeatureValueCacheItem.CalculateCacheKey(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N")))).ShouldBeNull(); + + } + } +} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.EntityFrameworkCore.Tests/Volo/Abp/FeatureManagement/EntityFrameworkCore/AbpFeatureManagementEntityFrameworkCoreTestModule.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.EntityFrameworkCore.Tests/Volo/Abp/FeatureManagement/EntityFrameworkCore/AbpFeatureManagementEntityFrameworkCoreTestModule.cs index 7a1eef410e..d5c573a360 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.EntityFrameworkCore.Tests/Volo/Abp/FeatureManagement/EntityFrameworkCore/AbpFeatureManagementEntityFrameworkCoreTestModule.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.EntityFrameworkCore.Tests/Volo/Abp/FeatureManagement/EntityFrameworkCore/AbpFeatureManagementEntityFrameworkCoreTestModule.cs @@ -8,7 +8,7 @@ using Volo.Abp.Modularity; namespace Volo.Abp.FeatureManagement.EntityFrameworkCore { [DependsOn( - typeof(AbpFeatureManagementTestBaseModule), + typeof(FeatureManagementTestBaseModule), typeof(AbpFeatureManagementEntityFrameworkCoreModule) )] public class AbpFeatureManagementEntityFrameworkCoreTestModule : AbpModule diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.EntityFrameworkCore.Tests/Volo/Abp/FeatureManagement/EntityFrameworkCore/FeatureManagementStore_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.EntityFrameworkCore.Tests/Volo/Abp/FeatureManagement/EntityFrameworkCore/FeatureManagementStore_Tests.cs new file mode 100644 index 0000000000..78f27fa222 --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.EntityFrameworkCore.Tests/Volo/Abp/FeatureManagement/EntityFrameworkCore/FeatureManagementStore_Tests.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.FeatureManagement.EntityFrameworkCore +{ + public class FeatureManagementStore_Tests : FeatureManagementStore_Tests + { + + } +} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/AbpFeatureManagementMongoDbTestModule.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/AbpFeatureManagementMongoDbTestModule.cs index bc5dfa0b52..6c39cf74ae 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/AbpFeatureManagementMongoDbTestModule.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/AbpFeatureManagementMongoDbTestModule.cs @@ -5,7 +5,7 @@ using Volo.Abp.Modularity; namespace Volo.Abp.FeatureManagement.MongoDB { [DependsOn( - typeof(AbpFeatureManagementTestBaseModule), + typeof(FeatureManagementTestBaseModule), typeof(AbpFeatureManagementMongoDbModule) )] public class AbpFeatureManagementMongoDbTestModule : AbpModule diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureManagementStore_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureManagementStore_Tests.cs new file mode 100644 index 0000000000..7df6e3516b --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo/Abp/FeatureManagement/MongoDB/FeatureManagementStore_Tests.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.FeatureManagement.MongoDB +{ + public class FeatureManagementStore_Tests : FeatureManagementStore_Tests + { + + } +} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementStore_Tests.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementStore_Tests.cs new file mode 100644 index 0000000000..c03c5dea65 --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementStore_Tests.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Features; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.FeatureManagement +{ + public abstract class FeatureManagementStore_Tests : FeatureManagementTestBase + where TStartupModule : IAbpModule + { + private IFeatureManagementStore FeatureManagementStore { get; set; } + private IFeatureValueRepository FeatureValueRepository { get; set; } + + protected FeatureManagementStore_Tests() + { + FeatureManagementStore = GetRequiredService(); + FeatureValueRepository = GetRequiredService(); + } + + [Fact] + public async Task GetOrNullAsync() + { + // Act + (await FeatureManagementStore.GetOrNullAsync(Guid.NewGuid().ToString("N"), + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"))).ShouldBeNull(); + + (await FeatureManagementStore.GetOrNullAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"))).ShouldNotBeNull(); + } + + [Fact] + public async Task Should_Get_Null_Where_Feature_Deleted() + { + // Arrange + (await FeatureManagementStore.GetOrNullAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"))).ShouldNotBeNull(); + + // Act + await FeatureManagementStore.DeleteAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N")); + + // Assert + (await FeatureManagementStore.GetOrNullAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"))).ShouldBeNull(); + } + + [Fact] + public async Task SetAsync() + { + // Arrange + (await FeatureValueRepository.FindAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"))).Value.ShouldBe(true.ToString().ToLowerInvariant()); + + // Act + await FeatureManagementStore.SetAsync(TestFeatureDefinitionProvider.SocialLogins, + false.ToString().ToUpperInvariant(), + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N")); + + // Assert + (await FeatureValueRepository.FindAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"))).Value.ShouldBe(false.ToString().ToUpperInvariant()); + } + + [Fact] + public async Task DeleteAsync() + { + // Arrange + (await FeatureValueRepository.FindAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"))).ShouldNotBeNull(); + + // Act + await FeatureManagementStore.DeleteAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N")); + + + // Assert + (await FeatureValueRepository.FindAsync(TestFeatureDefinitionProvider.SocialLogins, + EditionFeatureValueProvider.ProviderName, + TestEditionIds.Regular.ToString("N"))).ShouldBeNull(); + + + } + } +} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementTestBaseModule.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementTestBaseModule.cs new file mode 100644 index 0000000000..48a90400c8 --- /dev/null +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementTestBaseModule.cs @@ -0,0 +1,46 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Authorization; +using Volo.Abp.Autofac; +using Volo.Abp.Features; +using Volo.Abp.Modularity; + +namespace Volo.Abp.FeatureManagement +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(AbpTestBaseModule), + typeof(AbpAuthorizationModule), + typeof(AbpFeatureManagementDomainModule) + )] + public class FeatureManagementTestBaseModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAlwaysAllowAuthorization(); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + public override void PostConfigureServices(ServiceConfigurationContext context) + { + context.Services.Configure(options => + { + //TODO: Any value can pass. After completing the permission unit test, look at it again. + options.ProviderPolicies[EditionFeatureValueProvider.ProviderName] = EditionFeatureValueProvider.ProviderName; + }); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + using (var scope = context.ServiceProvider.CreateScope()) + { + scope.ServiceProvider + .GetRequiredService() + .Build(); + } + } + } +} diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementTestData.cs b/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementTestData.cs index e6d2273307..ede4af5f2a 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementTestData.cs +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.TestBase/Volo/Abp/FeatureManagement/FeatureManagementTestData.cs @@ -1,9 +1,10 @@ -using Volo.Abp.DependencyInjection; +using System; +using Volo.Abp.DependencyInjection; namespace Volo.Abp.FeatureManagement { public class FeatureManagementTestData : ISingletonDependency { - + public Guid User1Id { get; } = Guid.NewGuid(); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pt-BR.json b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pt-BR.json index bef013c26a..d57c51ed5e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pt-BR.json +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/Localization/ApplicationContracts/pt-BR.json @@ -1,12 +1,14 @@ { "culture": "pt-BR", "texts": { + "Volo.Abp.Identity:010001": "Você não pode deletar sua própria conta!", "Permission:IdentityManagement": "Acessos", "Permission:RoleManagement": "Perfis", "Permission:Create": "Criar", "Permission:Edit": "Editar", "Permission:Delete": "Excluir", "Permission:ChangePermissions": "Alterar Permissões", - "Permission:UserManagement": "Usuários" + "Permission:UserManagement": "Usuários", + "Permission:UserLookup": "Pesquisa de usuário" } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs index e9646d38cf..bac63a0c11 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs @@ -981,7 +981,7 @@ namespace Volo.Abp.Identity /// The value of the token. /// The used to propagate notifications that the operation should be canceled. /// The that represents the asynchronous operation. - public virtual async Task SetTokenAsync([NotNull] IdentityUser user, string loginProvider, string name, string value, CancellationToken cancellationToken) + public virtual async Task SetTokenAsync([NotNull] IdentityUser user, string loginProvider, string name, string value, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); @@ -1000,7 +1000,7 @@ namespace Volo.Abp.Identity /// The name of the token. /// The used to propagate notifications that the operation should be canceled. /// The that represents the asynchronous operation. - public async Task RemoveTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken) + public async Task RemoveTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); @@ -1019,7 +1019,7 @@ namespace Volo.Abp.Identity /// The name of the token. /// The used to propagate notifications that the operation should be canceled. /// The that represents the asynchronous operation. - public async Task GetTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken) + public async Task GetTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); @@ -1030,12 +1030,12 @@ namespace Volo.Abp.Identity return user.FindToken(loginProvider, name)?.Value; } - public Task SetAuthenticatorKeyAsync(IdentityUser user, string key, CancellationToken cancellationToken) + public Task SetAuthenticatorKeyAsync(IdentityUser user, string key, CancellationToken cancellationToken = default) { return SetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, key, cancellationToken); } - public Task GetAuthenticatorKeyAsync(IdentityUser user, CancellationToken cancellationToken) + public Task GetAuthenticatorKeyAsync(IdentityUser user, CancellationToken cancellationToken = default) { return GetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, cancellationToken); } @@ -1046,7 +1046,7 @@ namespace Volo.Abp.Identity /// The user who owns the recovery code. /// The used to propagate notifications that the operation should be canceled. /// The number of valid recovery codes for the user.. - public virtual async Task CountCodesAsync(IdentityUser user, CancellationToken cancellationToken) + public virtual async Task CountCodesAsync(IdentityUser user, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); @@ -1068,7 +1068,7 @@ namespace Volo.Abp.Identity /// The new recovery codes for the user. /// The used to propagate notifications that the operation should be canceled. /// The new recovery codes for the user. - public virtual Task ReplaceCodesAsync(IdentityUser user, IEnumerable recoveryCodes, CancellationToken cancellationToken) + public virtual Task ReplaceCodesAsync(IdentityUser user, IEnumerable recoveryCodes, CancellationToken cancellationToken = default) { var mergedCodes = string.Join(";", recoveryCodes); return SetTokenAsync(user, InternalLoginProvider, RecoveryCodeTokenName, mergedCodes, cancellationToken); @@ -1082,7 +1082,7 @@ namespace Volo.Abp.Identity /// The recovery code to use. /// The used to propagate notifications that the operation should be canceled. /// True if the recovery code was found for the user. - public virtual async Task RedeemCodeAsync(IdentityUser user, string code, CancellationToken cancellationToken) + public virtual async Task RedeemCodeAsync(IdentityUser user, string code, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml index 1979c87bb2..d2758f05d4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/Index.cshtml @@ -12,6 +12,11 @@ PageLayout.Content.BreadCrumb.Add(L["Menu:IdentityManagement"].Value); PageLayout.Content.MenuItemName = IdentityMenuNames.Roles; } +@section styles { + + + +} @section scripts { diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml index bcef02cc72..23f7747ac8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/Index.cshtml @@ -15,6 +15,11 @@ PageLayout.Content.BreadCrumb.Add(L["Menu:IdentityManagement"].Value); PageLayout.Content.MenuItemName = IdentityMenuNames.Users; } +@section styles { + + + +} @section scripts { diff --git a/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserLookupAppService_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserLookupAppService_Tests.cs new file mode 100644 index 0000000000..7358238294 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserLookupAppService_Tests.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Identity +{ + public class IdentityUserLookupAppService_Tests : AbpIdentityApplicationTestBase + { + private readonly IIdentityUserLookupAppService _identityUserLookupAppService; + private readonly IIdentityUserRepository _identityUserRepository; + private readonly ILookupNormalizer _lookupNormalizer; + + public IdentityUserLookupAppService_Tests() + { + _identityUserLookupAppService = GetRequiredService(); + _identityUserRepository = GetRequiredService(); + _lookupNormalizer = GetRequiredService(); + } + + [Fact] + public async Task FindByIdAsync() + { + var user = await _identityUserRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserLookupAppService.FindByIdAsync(user.Id)).UserName.ShouldBe(user.UserName); + } + + [Fact] + public async Task FindById_NotExist_Should_Return_Null() + { + var user = await _identityUserLookupAppService.FindByIdAsync(Guid.NewGuid()); + user.ShouldBeNull(); + } + + [Fact] + public async Task FindByUserNameAsync() + { + var user = await _identityUserRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserLookupAppService.FindByUserNameAsync(user.UserName)).UserName.ShouldBe(user.UserName); + } + + [Fact] + public async Task FindByUserName_NotExist_Should_Return_Null() + { + var user = await _identityUserLookupAppService.FindByUserNameAsync(Guid.NewGuid().ToString()); + user.ShouldBeNull(); + } + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdenityClaimTypeManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdenityClaimTypeManager_Tests.cs new file mode 100644 index 0000000000..c27967e704 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdenityClaimTypeManager_Tests.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Identity +{ + public class IdenityClaimTypeManager_Tests : AbpIdentityDomainTestBase + { + private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository; + private readonly IdenityClaimTypeManager _claimTypeManager; + private readonly IdentityTestData _testData; + + public IdenityClaimTypeManager_Tests() + { + _identityClaimTypeRepository = GetRequiredService(); + _claimTypeManager = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task CreateAsync() + { + var claimType = await _claimTypeManager.CreateAsync(new IdentityClaimType(Guid.NewGuid(), "Phone", false, + false, null, + null, null, IdentityClaimValueType.String)); + + claimType.ShouldNotBeNull(); + claimType.Name.ShouldBe("Phone"); + } + + [Fact] + public async Task Create_Name_Exist_Should_Exception() + { + await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.CreateAsync( + new IdentityClaimType( + Guid.NewGuid(), "Age"))); + } + + [Fact] + public async Task UpdateAsync() + { + var ageClaim = _identityClaimTypeRepository.Find(_testData.AgeClaimId); + ageClaim.ShouldNotBeNull(); + ageClaim.Description = "this is age"; + + var updatedAgeClaimType = await _claimTypeManager.UpdateAsync(ageClaim); + updatedAgeClaimType.ShouldNotBeNull(); + updatedAgeClaimType.Description.ShouldBe("this is age"); + } + + + [Fact] + public async Task Update_Name_Exist_Should_Exception() + { + await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.UpdateAsync( + new IdentityClaimType( + Guid.NewGuid(), "Age"))); + } + + + [Fact] + public async Task Static_IdentityClaimType_Cant_Not_Update() + { + var phoneClaim = new IdentityClaimType(Guid.NewGuid(), "Phone", true, true); + _identityClaimTypeRepository.Insert(phoneClaim); + + await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.UpdateAsync(phoneClaim)); + } + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleManager_Tests.cs new file mode 100644 index 0000000000..9cdafa10bb --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleManager_Tests.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Shouldly; +using Volo.Abp.Uow; +using Xunit; + +namespace Volo.Abp.Identity +{ + public class IdentityRoleManager_Tests : AbpIdentityDomainTestBase + { + private readonly IdentityRoleManager _identityRoleManager; + private readonly IIdentityRoleRepository _identityRoleRepository; + private readonly ILookupNormalizer _lookupNormalizer; + private readonly IdentityTestData _testData; + + public IdentityRoleManager_Tests() + { + _identityRoleManager = GetRequiredService(); + _identityRoleRepository = GetRequiredService(); + _lookupNormalizer = GetRequiredService(); + _testData = GetRequiredService(); + } + + + [Fact] + public async Task GetByIdAsync() + { + var role = await _identityRoleManager.FindByIdAsync(_testData.RoleModeratorId.ToString()); + + role.ShouldNotBeNull(); + role.Name.ShouldBe("moderator"); + } + + [Fact] + public async Task SetRoleNameAsync() + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + (await _identityRoleManager.SetRoleNameAsync(role, "teacher")).Succeeded.ShouldBeTrue(); + + role.Name.ShouldBe("teacher"); + } + + [Fact] + public async Task DeleteAsync() + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + await _identityRoleManager.DeleteAsync(role); + + (await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"))).ShouldBeNull(); + } + + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleStore_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleStore_Tests.cs new file mode 100644 index 0000000000..d2f674411b --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleStore_Tests.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Shouldly; +using Volo.Abp.Uow; +using Xunit; + +namespace Volo.Abp.Identity +{ + public class IdentityRoleStore_Tests : AbpIdentityDomainTestBase + { + private readonly IdentityRoleStore _identityRoleStore; + private readonly ILookupNormalizer _lookupNormalizer; + private readonly IIdentityRoleRepository _identityRoleRepository; + private readonly IdentityTestData _testData; + private readonly IUnitOfWorkManager _unitOfWorkManager; + + public IdentityRoleStore_Tests() + { + _identityRoleStore = GetRequiredService(); + _lookupNormalizer = GetRequiredService(); + _identityRoleRepository = GetRequiredService(); + _testData = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); + } + + [Fact] + public async Task CreateAsync() + { + var roleId = Guid.NewGuid(); + var role = new IdentityRole(roleId, "teacher"); + (await _identityRoleStore.CreateAsync(role)).Succeeded.ShouldBeTrue(); + + var teacher = await _identityRoleStore.FindByIdAsync(roleId.ToString()); + + teacher.ShouldNotBeNull(); + teacher.Name.ShouldBe("teacher"); + } + + [Fact] + public async Task UpdateAsync() + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + role.IsDefault = true; + await _identityRoleStore.UpdateAsync(role); + + role.IsDefault.ShouldBeTrue(); + } + + + [Fact] + public async Task DeleteAsync() + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + await _identityRoleStore.DeleteAsync(role); + + (await _identityRoleStore.FindByIdAsync(_testData.RoleModeratorId.ToString())).ShouldBeNull(); + } + + [Fact] + public async Task GetRoleIdAsync() + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + (await _identityRoleStore.GetRoleIdAsync(role)).ShouldBe(_testData.RoleModeratorId.ToString()); + } + + [Fact] + public async Task GetRoleNameAsync() + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + (await _identityRoleStore.GetRoleNameAsync(role)).ShouldBe(role.Name); + } + + + [Fact] + public async Task SetRoleNameAsync() + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + await _identityRoleStore.SetRoleNameAsync(role, "teacher"); + + role.Name.ShouldBe("teacher"); + } + + [Fact] + public async Task FindByIdAsync() + { + var role = await _identityRoleStore.FindByIdAsync(_testData.RoleModeratorId.ToString()); + + role.ShouldNotBeNull(); + role.Name.ShouldBe("moderator"); + } + + [Fact] + public async Task FindByNameAsync() + { + var role = await _identityRoleStore.FindByNameAsync(_lookupNormalizer.Normalize("moderator")); + + role.ShouldNotBeNull(); + role.Name.ShouldBe("moderator"); + } + + [Fact] + public async Task GetNormalizedRoleNameAsync() + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + (await _identityRoleStore.GetNormalizedRoleNameAsync(role)).ShouldBe(role.NormalizedName); + } + + [Fact] + public async Task SetNormalizedRoleNameAsync() + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + await _identityRoleStore.SetNormalizedRoleNameAsync(role, _lookupNormalizer.Normalize("teacher")); + + role.NormalizedName.ShouldBe(_lookupNormalizer.Normalize("teacher")); + } + + [Fact] + public async Task GetClaimsAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + var claims = await _identityRoleStore.GetClaimsAsync(role); + + claims.ShouldNotBeEmpty(); + claims.ShouldContain(x => x.Type == "test-claim" && x.Value == "test-value"); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task AddClaimAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + await _identityRoleStore.AddClaimAsync(role, new Claim("my-claim", "my-value")); + + role.Claims.ShouldContain(x => x.ClaimType == "my-claim" && x.ClaimValue == "my-value"); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task RemoveClaimAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator")); + role.ShouldNotBeNull(); + + await _identityRoleStore.RemoveClaimAsync(role, new Claim("test-claim", "test-value")); + + role.Claims.ShouldNotContain(x => x.ClaimType == "test-claim" && x.ClaimValue == "test-value"); + + await uow.CompleteAsync(); + } + } + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs new file mode 100644 index 0000000000..3755342375 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Shouldly; +using Volo.Abp.Uow; +using Xunit; + +namespace Volo.Abp.Identity +{ + public class IdentityUserManager_Tests : AbpIdentityDomainTestBase + { + private readonly IdentityUserManager _identityUserManager; + private readonly IIdentityUserRepository _identityUserRepository; + private readonly IIdentityRoleRepository _identityRoleRepository; + private readonly ILookupNormalizer _lookupNormalizer; + private readonly IUnitOfWorkManager _unitOfWorkManager; + private readonly IdentityTestData _testData; + + public IdentityUserManager_Tests() + { + _identityUserManager = GetRequiredService(); + _identityUserRepository = GetRequiredService(); + _identityRoleRepository = GetRequiredService(); + _lookupNormalizer = GetRequiredService(); + _testData = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); + } + + [Fact] + public async Task GetByIdAsync() + { + var user = await _identityUserManager.GetByIdAsync(_testData.UserJohnId); + + user.ShouldNotBeNull(); + user.UserName.ShouldBe("john.nash"); + } + + [Fact] + public async Task SetRolesAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _identityUserRepository.FindByNormalizedUserNameAsync( + _lookupNormalizer.Normalize("david")); + user.ShouldNotBeNull(); + + var identityResult = await _identityUserManager.SetRolesAsync(user, new List() + { + "moderator", + }); + + identityResult.Succeeded.ShouldBeTrue(); + user.Roles.ShouldContain(x => x.RoleId == _testData.RoleModeratorId); + + await uow.CompleteAsync(); + } + } + + [Fact] + public async Task SetRoles_Should_Remove_Other_Roles() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var roleSupporter = + await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("supporter")); + roleSupporter.ShouldNotBeNull(); + + var user = await _identityUserRepository.FindByNormalizedUserNameAsync( + _lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + var identityResult = await _identityUserManager.SetRolesAsync(user, new List() + { + "admin", + }); + + identityResult.Succeeded.ShouldBeTrue(); + user.Roles.ShouldNotContain(x => x.RoleId == _testData.RoleModeratorId); + user.Roles.ShouldNotContain(x => x.RoleId == roleSupporter.Id); + + await uow.CompleteAsync(); + } + } + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs new file mode 100644 index 0000000000..0e4c1e8bc6 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs @@ -0,0 +1,777 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Shouldly; +using Volo.Abp.Guids; +using Volo.Abp.Uow; +using Xunit; + +namespace Volo.Abp.Identity +{ + public class IdentityUserStore_Tests : AbpIdentityDomainTestBase + { + private readonly IdentityUserStore _identityUserStore; + private readonly ILookupNormalizer _lookupNormalizer; + private readonly IIdentityUserRepository _userRepository; + private readonly IdentityTestData _testData; + private readonly IUnitOfWorkManager _unitOfWorkManager; + + public IdentityUserStore_Tests() + { + _identityUserStore = GetRequiredService(); + _lookupNormalizer = GetRequiredService(); + _userRepository = GetRequiredService(); + _testData = GetRequiredService(); + _unitOfWorkManager = GetRequiredService(); + } + + [Fact] + public async Task GetUserIdAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetUserIdAsync(user)).ShouldBe(user.Id.ToString()); + } + + + [Fact] + public async Task GetUserNameAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetUserNameAsync(user)).ShouldBe(user.UserName); + } + + [Fact] + public async Task SetUserNameAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.SetUserNameAsync(user, "bob.lee"); + user.UserName.ShouldBe("bob.lee"); + //user.NormalizedUserName.ShouldBe(_lookupNormalizer.Normalize("bob.lee")); + } + + + [Fact] + public async Task GetNormalizedUserNameAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetNormalizedUserNameAsync(user)).ShouldBe(user.NormalizedUserName); + } + + [Fact] + public async Task SetNormalizedUserNameAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.SetNormalizedUserNameAsync(user, _lookupNormalizer.Normalize("bob.lee")); + + user.NormalizedUserName.ShouldBe(_lookupNormalizer.Normalize("bob.lee")); + } + + [Fact] + public async Task CreateAsync() + { + var userId = Guid.NewGuid(); + var user = new IdentityUser(userId, "bob.lee", "bob.lee@abp.io"); + + await _identityUserStore.CreateAsync(user); + + var bobLee = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("bob.lee")); + bobLee.ShouldNotBeNull(); + bobLee.UserName.ShouldBe("bob.lee"); + bobLee.Email.ShouldBe("bob.lee@abp.io"); + } + + [Fact] + public async Task UpdateAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + user.Name = "lee"; + (await _identityUserStore.UpdateAsync(user)).Succeeded.ShouldBeTrue(); + + (await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"))).Name + .ShouldBe("lee"); + } + + [Fact] + public async Task Update_Concurrency() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.UpdateAsync(user)).Succeeded.ShouldBeTrue(); + + user.ConcurrencyStamp = Guid.NewGuid().ToString(); + var identityResult = await _identityUserStore.UpdateAsync(user); + + identityResult.Succeeded.ShouldBeFalse(); + identityResult.Errors.ShouldContain(x => + x.Code == nameof(IdentityErrorDescriber.ConcurrencyFailure)); + + // && x.Description == Resources.PasswordMismatch); + } + + + [Fact] + public async Task DeleteAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.DeleteAsync(user)).Succeeded.ShouldBeTrue(); + + (await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"))).ShouldBeNull(); + } + + + [Fact] + public async Task FindByIdAsync() + { + var user = await _identityUserStore.FindByIdAsync(_testData.UserJohnId.ToString()); + + user.ShouldNotBeNull(); + user.UserName.ShouldBe("john.nash"); + } + + + [Fact] + public async Task FindByNameAsync() + { + var user = await _identityUserStore.FindByNameAsync(_lookupNormalizer.Normalize("john.nash")); + + user.ShouldNotBeNull(); + user.UserName.ShouldBe("john.nash"); + } + + + [Fact] + public async Task SetPasswordHashAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + user.PasswordHash.ShouldBeNull(); + + await _identityUserStore.SetPasswordHashAsync(user, "P@ssw0rd"); + user.PasswordHash.ShouldBe("P@ssw0rd"); + } + + + [Fact] + public async Task GetPasswordHashAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + await _identityUserStore.SetPasswordHashAsync(user, "P@ssw0rd"); + + (await _identityUserStore.GetPasswordHashAsync(user)).ShouldBe("P@ssw0rd"); + } + + + [Fact] + public async Task HasPasswordAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + (await _identityUserStore.HasPasswordAsync(user)).ShouldBeFalse(); + + await _identityUserStore.SetPasswordHashAsync(user, "P@ssw0rd"); + (await _identityUserStore.HasPasswordAsync(user)).ShouldBeTrue(); + } + + + [Fact] + public async Task AddToRoleAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("david")); + user.ShouldNotBeNull(); + user.Roles.ShouldBeEmpty(); + + await _identityUserStore.AddToRoleAsync(user, _lookupNormalizer.Normalize("moderator")); + + user.Roles.ShouldContain(x => x.RoleId == _testData.RoleModeratorId); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task RemoveFromRoleAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + user.Roles.ShouldContain(x => x.RoleId == _testData.RoleModeratorId); + + await _identityUserStore.RemoveFromRoleAsync(user, _lookupNormalizer.Normalize("moderator")); + + user.Roles.ShouldNotContain(x => x.RoleId == _testData.RoleModeratorId); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task GetRolesAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + var roleNames = await _identityUserStore.GetRolesAsync(user); + roleNames.ShouldNotBeEmpty(); + roleNames.ShouldContain(x => x == "moderator"); + roleNames.ShouldContain(x => x == "supporter"); + } + + [Fact] + public async Task IsInRoleAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.IsInRoleAsync(user, _lookupNormalizer.Normalize("moderator"))).ShouldBeTrue(); + (await _identityUserStore.IsInRoleAsync(user, _lookupNormalizer.Normalize("moderatorNotExist"))).ShouldBeFalse(); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task GetClaimsAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + var claims = await _identityUserStore.GetClaimsAsync(user); + claims.ShouldNotBeEmpty(); + claims.ShouldContain(x => x.Type == "TestClaimType" && x.Value == "42"); + + await uow.CompleteAsync(); + } + } + + [Fact] + public async Task AddClaimsAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.AddClaimsAsync(user, new List() + { + new Claim("MyClaimType", "MyClaimValue") + }); + + user.Claims.ShouldContain(x => x.ClaimType == "MyClaimType" && x.ClaimValue == "MyClaimValue"); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task ReplaceClaimAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.ReplaceClaimAsync(user, new Claim("TestClaimType", "42"), new Claim("MyClaimType", "MyClaimValue")); + + user.Claims.ShouldNotContain(x => x.ClaimType == "TestClaimType" && x.ClaimValue == "42"); + user.Claims.ShouldContain(x => x.ClaimType == "MyClaimType" && x.ClaimValue == "MyClaimValue"); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task RemoveClaimsAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.RemoveClaimsAsync(user, new List() + { + new Claim("TestClaimType", "42") + }); + + user.Claims.ShouldNotContain(x => x.ClaimType == "TestClaimType" && x.ClaimValue == "42"); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task AddLoginAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + user.Logins.ShouldNotContain(x => x.LoginProvider == "facebook" && x.ProviderKey == "john"); + + await _identityUserStore.AddLoginAsync(user, new UserLoginInfo("facebook", "john", "John Nash")); + + user.Logins.ShouldContain(x => x.LoginProvider == "facebook" && x.ProviderKey == "john"); + + await uow.CompleteAsync(); + } + } + + [Fact] + public async Task RemoveLoginAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + user.Logins.ShouldContain(x => x.LoginProvider == "github" && x.ProviderKey == "john"); + + await _identityUserStore.RemoveLoginAsync(user, "github", "john"); + + user.Logins.ShouldNotContain(x => x.LoginProvider == "github" && x.ProviderKey == "john"); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task GetLoginsAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + var logins = await _identityUserStore.GetLoginsAsync(user); + + logins.ShouldNotBeNull(); + logins.ShouldContain(x => x.LoginProvider == "github" && x.ProviderKey == "john"); + logins.ShouldContain(x => x.LoginProvider == "twitter" && x.ProviderKey == "johnx"); + + await uow.CompleteAsync(); + } + } + + + [Fact] + public async Task FindByLoginAsync() + { + var user = await _identityUserStore.FindByLoginAsync("github", "john"); + user.ShouldNotBeNull(); + user.UserName.ShouldBe("john.nash"); + } + + + [Fact] + public async Task GetEmailConfirmedAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetEmailConfirmedAsync(user)).ShouldBe(user.EmailConfirmed); + } + + + [Fact] + public async Task SetEmailConfirmedAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + var emailConfirmed = user.EmailConfirmed; + + await _identityUserStore.SetEmailConfirmedAsync(user, !emailConfirmed); + + user.EmailConfirmed.ShouldBe(!emailConfirmed); + } + + [Fact] + public async Task SetEmailAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.SetEmailAsync(user, "john.nash.kobe@abp.io"); + + user.Email.ShouldBe("john.nash.kobe@abp.io"); + //user.NormalizedEmail.ShouldBe(_lookupNormalizer.Normalize("john.nash.kobe@abp.io")); + } + + [Fact] + public async Task GetEmailAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetEmailAsync(user)).ShouldBe(user.Email); + } + + [Fact] + public async Task GetNormalizedEmailAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetNormalizedEmailAsync(user)).ShouldBe(user.NormalizedEmail); + } + + [Fact] + public async Task SetNormalizedEmailAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.SetNormalizedEmailAsync(user, _lookupNormalizer.Normalize("john.nash.kobe@abp.io")); + + user.NormalizedEmail.ShouldBe(_lookupNormalizer.Normalize("john.nash.kobe@abp.io")); + } + + [Fact] + public async Task FindByEmailAsync() + { + var user = await _identityUserStore.FindByEmailAsync(_lookupNormalizer.Normalize("john.nash@abp.io")); + + user.ShouldNotBeNull(); + user.Email.ShouldBe("john.nash@abp.io"); + } + + [Fact] + public async Task GetLockoutEndDateAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetLockoutEndDateAsync(user)).ShouldBe(user.LockoutEnd); + } + + [Fact] + public async Task SetLockoutEndDateAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.SetLockoutEndDateAsync(user, DateTimeOffset.Parse("01/01/2019")); + + user.LockoutEnd.ShouldBe(DateTimeOffset.Parse("01/01/2019")); + } + + + [Fact] + public async Task IncrementAccessFailedCountAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + var count = user.AccessFailedCount; + + await _identityUserStore.IncrementAccessFailedCountAsync(user); + + user.AccessFailedCount.ShouldBe(count + 1); + } + + [Fact] + public async Task ResetAccessFailedCountAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.ResetAccessFailedCountAsync(user); + + user.AccessFailedCount.ShouldBe(0); + } + + [Fact] + public async Task GetAccessFailedCountAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetAccessFailedCountAsync(user)).ShouldBe(user.AccessFailedCount); + } + + [Fact] + public async Task GetLockoutEnabledAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetLockoutEnabledAsync(user)).ShouldBe(user.LockoutEnabled); + } + + [Fact] + public async Task SetLockoutEnabledAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + var lockoutEnabled = user.LockoutEnabled; + + await _identityUserStore.SetLockoutEnabledAsync(user, !lockoutEnabled); + + user.LockoutEnabled.ShouldBe(!lockoutEnabled); + } + + + [Fact] + public async Task SetPhoneNumberAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.SetPhoneNumberAsync(user, "13800138000"); + + user.PhoneNumber.ShouldBe("13800138000"); + } + + + [Fact] + public async Task GetPhoneNumberAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetPhoneNumberAsync(user)).ShouldBe(user.PhoneNumber); + } + + [Fact] + public async Task GetPhoneNumberConfirmedAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetPhoneNumberConfirmedAsync(user)).ShouldBe(user.PhoneNumberConfirmed); + } + + + [Fact] + public async Task SetPhoneNumberConfirmedAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + var phoneNumberConfirmed = user.PhoneNumberConfirmed; + + await _identityUserStore.SetPhoneNumberConfirmedAsync(user, !phoneNumberConfirmed); + + user.PhoneNumberConfirmed.ShouldBe(!phoneNumberConfirmed); + } + + + [Fact] + public async Task SetSecurityStampAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + var securityStamp = Guid.NewGuid().ToString(); + + await _identityUserStore.SetSecurityStampAsync(user, securityStamp); + + user.SecurityStamp.ShouldBe(securityStamp); + } + + [Fact] + public async Task GetSecurityStampAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetSecurityStampAsync(user)).ShouldBe(user.SecurityStamp); + } + + + [Fact] + public async Task SetTwoFactorEnabledAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + var twoFactorEnabled = user.TwoFactorEnabled; + + await _identityUserStore.SetTwoFactorEnabledAsync(user, !twoFactorEnabled); + + user.TwoFactorEnabled.ShouldBe(!twoFactorEnabled); + } + + + [Fact] + public async Task GetTwoFactorEnabledAsync() + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetTwoFactorEnabledAsync(user)).ShouldBe(user.TwoFactorEnabled); + } + + [Fact] + public async Task GetUsersForClaimAsync() + { + var user = await _identityUserStore.GetUsersForClaimAsync(new Claim("TestClaimType", "42")); + user.ShouldNotBeNull(); + user.ShouldNotBeEmpty(); + user.ShouldContain(x => x.UserName == "john.nash"); + } + + [Fact] + public async Task GetUsersInRoleAsync() + { + var user = await _identityUserStore.GetUsersInRoleAsync(_lookupNormalizer.Normalize("moderator")); + user.ShouldNotBeNull(); + user.ShouldContain(x => x.UserName == "john.nash"); + } + + [Fact] + public async Task SetTokenAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.SetTokenAsync(user, "test-provider", "test-name", "123123"); + + user.Tokens.ShouldNotBeEmpty(); + user.Tokens.ShouldContain(x => x.LoginProvider == "test-provider" && x.Name == "test-name" && x.Value == "123123"); + + await uow.CompleteAsync(); + } + } + + [Fact] + public async Task RemoveTokenAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.RemoveTokenAsync(user, "test-provider", "test-name"); + + user.Tokens.ShouldNotContain(x => x.LoginProvider == "test-provider" && x.Name == "test-name" && x.Value == "123123"); + + await uow.CompleteAsync(); + } + } + + [Fact] + public async Task GetTokenAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + (await _identityUserStore.GetTokenAsync(user, "test-provider", "test-name")).ShouldBe("test-value"); + + await uow.CompleteAsync(); + } + } + + [Fact] + public async Task SetAuthenticatorKeyAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.SetAuthenticatorKeyAsync(user, "testKey"); + + user.Tokens.ShouldContain(x => x.LoginProvider == "[AspNetUserStore]" && x.Name == "AuthenticatorKey" && x.Value == "testKey"); + + await uow.CompleteAsync(); + } + } + + [Fact] + public async Task GetAuthenticatorKeyAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + await _identityUserStore.SetAuthenticatorKeyAsync(user, "testKey"); + + (await _identityUserStore.GetAuthenticatorKeyAsync(user)).ShouldBe("testKey"); + + await uow.CompleteAsync(); + } + + } + + [Fact] + public async Task CountCodesAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + await _identityUserStore.SetTokenAsync(user, "[AspNetUserStore]", "RecoveryCodes", "testKey;testKey2"); + + (await _identityUserStore.CountCodesAsync(user)).ShouldBe(2); + + await uow.CompleteAsync(); + } + } + + [Fact] + public async Task ReplaceCodesAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + + await _identityUserStore.ReplaceCodesAsync(user, new List() + { + "testKey", + "testKey2" + }); + + user.Tokens.ShouldContain(x => x.LoginProvider == "[AspNetUserStore]" && x.Name == "RecoveryCodes" && x.Value == "testKey;testKey2"); + + await uow.CompleteAsync(); + } + } + + [Fact] + public async Task RedeemCodeAsync() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash")); + user.ShouldNotBeNull(); + await _identityUserStore.SetTokenAsync(user, "[AspNetUserStore]", "RecoveryCodes", "testKey;testKey2"); + + (await _identityUserStore.RedeemCodeAsync(user, "testKey")).ShouldBeTrue(); + + await uow.CompleteAsync(); + } + } + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/UserRoleFinder_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/UserRoleFinder_Tests.cs new file mode 100644 index 0000000000..ef06949500 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/UserRoleFinder_Tests.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Identity +{ + public class UserRoleFinder_Tests : AbpIdentityDomainTestBase + { + private readonly IUserRoleFinder _userRoleFinder; + private readonly IdentityTestData _testData; + + public UserRoleFinder_Tests() + { + _userRoleFinder = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task GetRolesAsync() + { + var roleNames = await _userRoleFinder.GetRolesAsync(_testData.UserJohnId); + roleNames.ShouldNotBeEmpty(); + roleNames.ShouldContain(x => x == "moderator"); + roleNames.ShouldContain(x => x == "supporter"); + } + } +} diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs similarity index 100% rename from modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs rename to modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/ClientStore_Tests.cs diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs similarity index 100% rename from modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs rename to modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/IdentityResourceStore_Tests.cs diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs similarity index 100% rename from modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs rename to modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/Clients/PersistentGrant_Tests.cs diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs new file mode 100644 index 0000000000..79bab1d23a --- /dev/null +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.EntityFrameworkCore.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.IdentityServer +{ + public class PersistentGrantRepository_Tests : PersistentGrantRepository_Tests + { + + } +} diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs new file mode 100644 index 0000000000..fd2763dc6c --- /dev/null +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.IdentityServer +{ + public class PersistentGrantRepository_Tests : PersistentGrantRepository_Tests + { + + } +} diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs index 0c18e85350..016820af49 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/AbpIdentityServerTestDataBuilder.cs @@ -1,6 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; +using Volo.Abp.Identity; using Volo.Abp.IdentityServer.ApiResources; using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.Grants; @@ -14,7 +16,8 @@ namespace Volo.Abp.IdentityServer private readonly IApiResourceRepository _apiResourceRepository; private readonly IClientRepository _clientRepository; private readonly IIdentityResourceRepository _identityResourceRepository; - //private readonly IPersistentGrantRepository _persistentGrantRepository; + private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository; + private readonly IPersistentGrantRepository _persistentGrantRepository; private readonly AbpIdentityServerTestData _testData; public AbpIdentityServerTestDataBuilder( @@ -22,15 +25,17 @@ namespace Volo.Abp.IdentityServer IApiResourceRepository apiResourceRepository, IClientRepository clientRepository, IIdentityResourceRepository identityResourceRepository, - AbpIdentityServerTestData testData - /*IPersistentGrantRepository persistentGrantRepository*/) + IIdentityClaimTypeRepository identityClaimTypeRepository, + AbpIdentityServerTestData testData, + IPersistentGrantRepository persistentGrantRepository) { _testData = testData; _guidGenerator = guidGenerator; _apiResourceRepository = apiResourceRepository; _clientRepository = clientRepository; _identityResourceRepository = identityResourceRepository; - //_persistentGrantRepository = persistentGrantRepository; + _identityClaimTypeRepository = identityClaimTypeRepository; + _persistentGrantRepository = persistentGrantRepository; } public void Build() @@ -39,13 +44,30 @@ namespace Volo.Abp.IdentityServer AddIdentityResources(); AddApiResources(); AddClients(); + AddClaimTypes(); } private void AddPersistedGrants() { - //_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())); - //_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())); - //_persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create())); + _persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create()) + { + + Key = "PersistedGrantKey1", + SubjectId = "PersistedGrantSubjectId1", + ClientId = "PersistedGrantClientId1", + Type = "PersistedGrantType1" + }); + _persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create()) + { + Key = "PersistedGrantKey2", + SubjectId = "PersistedGrantSubjectId2" + }); + + _persistentGrantRepository.Insert(new PersistedGrant(_guidGenerator.Create()) + { + Key = "PersistedGrantKey3", + SubjectId = "PersistedGrantSubjectId3" + }); } private void AddIdentityResources() @@ -105,5 +127,12 @@ namespace Volo.Abp.IdentityServer _clientRepository.Insert(new Client(_guidGenerator.Create(), "ClientId2")); _clientRepository.Insert(new Client(_guidGenerator.Create(), "ClientId3")); } + + private void AddClaimTypes() + { + var ageClaim = new IdentityClaimType(Guid.NewGuid(), "Age", false, false, null, null, null, + IdentityClaimValueType.Int); + _identityClaimTypeRepository.Insert(ageClaim); + } } } diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs new file mode 100644 index 0000000000..20f6674515 --- /dev/null +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.TestBase/Volo/Abp/IdentityServer/PersistentGrantRepository_Tests.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.IdentityServer.Grants; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.IdentityServer +{ + public abstract class PersistentGrantRepository_Tests : AbpIdentityServerTestBase + where TStartupModule : IAbpModule + { + private readonly IPersistentGrantRepository _persistentGrantRepository; + + protected PersistentGrantRepository_Tests() + { + _persistentGrantRepository = GetRequiredService(); + } + + [Fact] + public async Task FindByKeyAsync() + { + (await _persistentGrantRepository.FindByKeyAsync("PersistedGrantKey1")).ShouldNotBeNull(); + } + + [Fact] + public async Task GetListBySubjectIdAsync() + { + var persistedGrants = await _persistentGrantRepository.GetListBySubjectIdAsync("PersistedGrantSubjectId1"); + persistedGrants.ShouldNotBeEmpty(); + persistedGrants.ShouldContain(x => x.Key == "PersistedGrantKey1"); + } + + [Fact] + public async Task DeleteBySubjectIdAndClientId() + { + await _persistentGrantRepository.DeleteAsync("PersistedGrantSubjectId1", "PersistedGrantClientId1"); + + var persistedGrants = await _persistentGrantRepository.GetListAsync(); + persistedGrants.ShouldNotBeEmpty(); + persistedGrants.ShouldNotContain(x => + x.Key == "PersistedGrantKey1" && x.SubjectId == "PersistedGrantSubjectId1" && + x.ClientId == "PersistedGrantClientId1"); + } + + [Fact] + public async Task DeleteBySubjectIdAndClientIdAndType() + { + await _persistentGrantRepository.DeleteAsync("PersistedGrantSubjectId1", "PersistedGrantClientId1", + "PersistedGrantClientId1"); + + var persistedGrants = await _persistentGrantRepository.GetListAsync(); + persistedGrants.ShouldNotBeEmpty(); + persistedGrants.ShouldNotContain(x => + x.Key == "PersistedGrantKey1" && x.SubjectId == "PersistedGrantSubjectId1" && + x.ClientId == "PersistedGrantClientId1" && x.Type == "PersistedGrantClientId1"); + + } + } +} diff --git a/modules/permission-management/Volo.Abp.PermissionManagement.sln b/modules/permission-management/Volo.Abp.PermissionManagement.sln index e0fdd1e0ec..5812918a3c 100644 --- a/modules/permission-management/Volo.Abp.PermissionManagement.sln +++ b/modules/permission-management/Volo.Abp.PermissionManagement.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27428.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B559B878-38F7-49CC-BC06-43A32D68C1A7}" EndProject @@ -29,9 +29,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.PermissionManageme EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.PermissionManagement.MongoDB.Tests", "test\Volo.Abp.PermissionManagement.MongoDB.Tests\Volo.Abp.PermissionManagement.MongoDB.Tests.csproj", "{AFA65E08-1F17-4BBE-96A6-80F3CFE22A75}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.PermissionManagement.HttpApi", "src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj", "{9E0B517E-F02E-436F-9695-7CF12795D34C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.PermissionManagement.HttpApi", "src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj", "{9E0B517E-F02E-436F-9695-7CF12795D34C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.PermissionManagement.HttpApi.Client", "src\Volo.Abp.PermissionManagement.HttpApi.Client\Volo.Abp.PermissionManagement.HttpApi.Client.csproj", "{1CD80519-9431-48DB-B0EA-291A73FF9F49}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.PermissionManagement.HttpApi.Client", "src\Volo.Abp.PermissionManagement.HttpApi.Client\Volo.Abp.PermissionManagement.HttpApi.Client.csproj", "{1CD80519-9431-48DB-B0EA-291A73FF9F49}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.PermissionManagement.Application.Tests", "test\Volo.Abp.PermissionManagement.Application.Tests\Volo.Abp.PermissionManagement.Application.Tests.csproj", "{A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -91,6 +93,10 @@ Global {1CD80519-9431-48DB-B0EA-291A73FF9F49}.Debug|Any CPU.Build.0 = Debug|Any CPU {1CD80519-9431-48DB-B0EA-291A73FF9F49}.Release|Any CPU.ActiveCfg = Release|Any CPU {1CD80519-9431-48DB-B0EA-291A73FF9F49}.Release|Any CPU.Build.0 = Release|Any CPU + {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -109,6 +115,7 @@ Global {AFA65E08-1F17-4BBE-96A6-80F3CFE22A75} = {63DA4A89-5908-4F37-B7E6-525AEEF20C77} {9E0B517E-F02E-436F-9695-7CF12795D34C} = {B559B878-38F7-49CC-BC06-43A32D68C1A7} {1CD80519-9431-48DB-B0EA-291A73FF9F49} = {B559B878-38F7-49CC-BC06-43A32D68C1A7} + {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1} = {63DA4A89-5908-4F37-B7E6-525AEEF20C77} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8FC7DF78-5E2D-489F-9D43-147D2ABAA112} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pt-BR.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pt-BR.json index 358cf16281..93adef2871 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pt-BR.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Localization/Resources/AbpPermissionManagement/pt-BR.json @@ -1,4 +1,3 @@ - { "culture": "pt-BR", "texts": { @@ -6,4 +5,4 @@ "OnlyProviderPermissons": "Apenas este provedor", "All": "Todos" } -} +} \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml index d1081f2f84..e95e56abe9 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml @@ -8,19 +8,21 @@ @{ Layout = null; } +

- + - + @for (var i = 0; i < Model.Groups.Count; i++) {

@Model.Groups[i].DisplayName

-
-
+
+
+
@for (var j = 0; j < Model.Groups[i].Permissions.Count; j++) { } +
} @@ -38,4 +41,4 @@ - \ No newline at end of file + diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.css b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.css new file mode 100644 index 0000000000..d1f8731614 --- /dev/null +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.css @@ -0,0 +1,12 @@ +.custom-scroll-container > .col-4 { + overflow: hidden; + overflow-y: auto; + max-height: 499px; + display: block; + position: relative; + z-index: 123; +} + +.custom-scroll-content { + max-height: 440px; +} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js index f32b00720e..cde7903a2e 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js @@ -49,6 +49,15 @@ }); }); }); + + $(function () { + $(".custom-scroll-content").mCustomScrollbar({ + theme: "minimal-dark" + }); + $(".custom-scroll-container > .col-4").mCustomScrollbar({ + theme: "minimal-dark" + }); + }); }; }; })(jQuery); \ No newline at end of file diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo.Abp.PermissionManagement.Application.Tests.csproj b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo.Abp.PermissionManagement.Application.Tests.csproj new file mode 100644 index 0000000000..7e817abf24 --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo.Abp.PermissionManagement.Application.Tests.csproj @@ -0,0 +1,18 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestBase.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestBase.cs new file mode 100644 index 0000000000..7102b8f851 --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestBase.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; +using Volo.Abp.Users; + +namespace Volo.Abp.PermissionManagement +{ + public class AbpPermissionManagementApplicationTestBase : PermissionManagementTestBase + { + protected Guid? CurrentUserId { get; set; } + + protected AbpPermissionManagementApplicationTestBase() + { + CurrentUserId = Guid.NewGuid(); + } + protected override void AfterAddApplication(IServiceCollection services) + { + var currentUser = Substitute.For(); + //currentUser.Id.Returns(ci => CurrentUserId); + currentUser.IsAuthenticated.Returns(true); + + services.AddSingleton(currentUser); + } + } +} diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestModule.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestModule.cs new file mode 100644 index 0000000000..2bbfb07acd --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestModule.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Modularity; + +namespace Volo.Abp.PermissionManagement +{ + [DependsOn( + typeof(AbpPermissionManagementApplicationModule), + typeof(AbpPermissionManagementTestModule) + )] + public class AbpPermissionManagementApplicationTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAlwaysAllowAuthorization(); + + context.Services.Configure(options => + { + options.ProviderPolicies[UserPermissionValueProvider.ProviderName] = UserPermissionValueProvider.ProviderName; + options.ProviderPolicies["Test"] = "Test"; + options.ManagementProviders.Add(); + }); + } + } +} diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs new file mode 100644 index 0000000000..8b36b02877 --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Authorization.Permissions; +using Xunit; + +namespace Volo.Abp.PermissionManagement.Application.Tests.Volo.Abp.PermissionManagement +{ + public class PermissionAppService_Tests : AbpPermissionManagementApplicationTestBase + { + private readonly IPermissionAppService _permissionAppService; + private readonly IPermissionGrantRepository _permissionGrantRepository; + + public PermissionAppService_Tests() + { + _permissionAppService = GetRequiredService(); + _permissionGrantRepository = GetRequiredService(); + } + + [Fact] + public async Task GetAsync() + { + var permissionListResultDto = await _permissionAppService.GetAsync(UserPermissionValueProvider.ProviderName, + PermissionTestDataBuilder.User1Id.ToString()); + + permissionListResultDto.ShouldNotBeNull(); + permissionListResultDto.EntityDisplayName.ShouldBe(PermissionTestDataBuilder.User1Id.ToString()); + permissionListResultDto.Groups.Count.ShouldBe(1); + permissionListResultDto.Groups.ShouldContain(x => x.Name == "TestGroup"); + + permissionListResultDto.Groups.First().Permissions.Count.ShouldBe(4); + permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission1"); + permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission2"); + permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission2.ChildPermission1"); + permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission3"); + + } + + [Fact] + public async Task UpdateAsync() + { + (await _permissionGrantRepository.FindAsync("MyPermission1", "Test", + "Test")).ShouldBeNull(); + + await _permissionAppService.UpdateAsync("Test", + "Test", new UpdatePermissionsDto() + { + Permissions = new UpdatePermissionDto[] + { + new UpdatePermissionDto() + { + IsGranted = true, + Name = "MyPermission1" + } + } + }); + + (await _permissionGrantRepository.FindAsync("MyPermission1", "Test", + "Test")).ShouldNotBeNull(); + } + + [Fact] + public async Task Update_Revoke_Test() + { + _permissionGrantRepository.Insert( + new PermissionGrant( + Guid.NewGuid(), + "MyPermission1", + "Test", + "Test" + ) + ); + (await _permissionGrantRepository.FindAsync("MyPermission1", "Test", + "Test")).ShouldNotBeNull(); + + await _permissionAppService.UpdateAsync("Test", + "Test", new UpdatePermissionsDto() + { + Permissions = new UpdatePermissionDto[] + { + new UpdatePermissionDto() + { + IsGranted = false, + Name = "MyPermission1" + } + } + }); + + (await _permissionGrantRepository.FindAsync("MyPermission1", "Test", + "Test")).ShouldBeNull(); + } + } +} diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs index 4423cf114b..ec343d9615 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs @@ -12,6 +12,14 @@ namespace Volo.Abp.PermissionManagement )] public class AbpPermissionManagementTestBaseModule : AbpModule { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.Configure(options => + { + options.ManagementProviders.Add(); + }); + } + public override void OnApplicationInitialization(ApplicationInitializationContext context) { SeedTestData(context); diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestPermissionManagementProvider.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestPermissionManagementProvider.cs new file mode 100644 index 0000000000..f66ed2995d --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestPermissionManagementProvider.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Volo.Abp.Guids; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.PermissionManagement +{ + public class TestPermissionManagementProvider : PermissionManagementProvider + { + public override string Name => "Test"; + + public TestPermissionManagementProvider( + IPermissionGrantRepository permissionGrantRepository, + IGuidGenerator guidGenerator, + ICurrentTenant currentTenant) + : base( + permissionGrantRepository, + guidGenerator, + currentTenant) + { + + } + } +} diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Basic_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionChecker_Basic_Tests.cs similarity index 100% rename from modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Basic_Tests.cs rename to modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionChecker_Basic_Tests.cs diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionDataSeeder_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionDataSeeder_Tests.cs new file mode 100644 index 0000000000..6868421a8a --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionDataSeeder_Tests.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.PermissionManagement +{ + public class PermissionDataSeeder_Tests : PermissionTestBase + { + private readonly IPermissionDataSeeder _permissionDataSeeder; + private readonly IPermissionGrantRepository _grantpermissionGrantRepository; + + public PermissionDataSeeder_Tests() + { + _permissionDataSeeder = GetRequiredService(); + _grantpermissionGrantRepository = GetRequiredService(); + } + + [Fact] + public async Task SeedAsync() + { + (await _grantpermissionGrantRepository.FindAsync("MyPermission1", "Test", "Test")).ShouldBeNull(); + (await _grantpermissionGrantRepository.FindAsync("MyPermission2", "Test", "Test")).ShouldBeNull(); + + await _permissionDataSeeder.SeedAsync("Test", "Test", new List() + { + "MyPermission1", + "MyPermission2" + }); + + (await _grantpermissionGrantRepository.FindAsync("MyPermission1", "Test", "Test")).ShouldNotBeNull(); + (await _grantpermissionGrantRepository.FindAsync("MyPermission2", "Test", "Test")).ShouldNotBeNull(); + + } + } +} diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionGrantCacheItemInvalidator_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionGrantCacheItemInvalidator_Tests.cs new file mode 100644 index 0000000000..9d4248bb5a --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionGrantCacheItemInvalidator_Tests.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Caching; +using Volo.Abp.MultiTenancy; +using Xunit; + +namespace Volo.Abp.PermissionManagement +{ + public class PermissionGrantCacheItemInvalidator_Tests : PermissionTestBase + { + private readonly IDistributedCache _cache; + private readonly IPermissionStore _permissionStore; + private readonly IPermissionGrantRepository _permissionGrantRepository; + + public PermissionGrantCacheItemInvalidator_Tests() + { + _cache = GetRequiredService>(); + _permissionStore = GetRequiredService(); + _permissionGrantRepository = GetRequiredService(); + } + + [Fact] + public async Task PermissionStore_IsGrantedAsync_Should_Cache_PermissionGrant() + { + (await _cache.GetAsync(PermissionGrantCacheItem.CalculateCacheKey("MyPermission1", + UserPermissionValueProvider.ProviderName, + PermissionTestDataBuilder.User1Id.ToString()))).ShouldBeNull(); + + + await _permissionStore.IsGrantedAsync("MyPermission1", + UserPermissionValueProvider.ProviderName, + PermissionTestDataBuilder.User1Id.ToString()); + + + (await _cache.GetAsync(PermissionGrantCacheItem.CalculateCacheKey("MyPermission1", + UserPermissionValueProvider.ProviderName, + PermissionTestDataBuilder.User1Id.ToString()))).ShouldNotBeNull(); + } + + [Fact] + public async Task Cache_Should_Invalidator_WhenPermissionGrantChanged() + { + // IsGrantedAsync will cache PermissionGrant + await _permissionStore.IsGrantedAsync("MyPermission1", + UserPermissionValueProvider.ProviderName, + PermissionTestDataBuilder.User1Id.ToString()); + + var permissionGrant = await _permissionGrantRepository.FindAsync("MyPermission1", + UserPermissionValueProvider.ProviderName, + PermissionTestDataBuilder.User1Id.ToString()); + permissionGrant.ShouldNotBeNull(); + await _permissionGrantRepository.DeleteAsync(permissionGrant); + + (await _cache.GetAsync(PermissionGrantCacheItem.CalculateCacheKey("MyPermission1", + UserPermissionValueProvider.ProviderName, + PermissionTestDataBuilder.User1Id.ToString()))).ShouldBeNull(); + } + } +} diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManagementProvider_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManagementProvider_Tests.cs new file mode 100644 index 0000000000..d1e249c29a --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManagementProvider_Tests.cs @@ -0,0 +1,79 @@ +using System; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Authorization.Permissions; +using Xunit; + +namespace Volo.Abp.PermissionManagement +{ + public class PermissionManagementProvider_Tests : PermissionTestBase + { + private readonly IPermissionManagementProvider _permissionManagementProvider; + private readonly IPermissionGrantRepository _permissionGrantRepository; + + + public PermissionManagementProvider_Tests() + { + _permissionManagementProvider = GetRequiredService(); + _permissionGrantRepository = GetRequiredService(); + } + + + [Fact] + public async Task CheckAsync() + { + _permissionGrantRepository.Insert( + new PermissionGrant( + Guid.NewGuid(), + "MyPermission1", + "Test", + "Test" + ) + ); + + var permissionValueProviderGrantInfo = await _permissionManagementProvider.CheckAsync("MyPermission1", + "Test", + "Test"); + + permissionValueProviderGrantInfo.IsGranted.ShouldBeTrue(); + permissionValueProviderGrantInfo.ProviderKey.ShouldBe("Test"); + } + + [Fact] + public async Task Check_Should_Return_NonGranted_When_ProviderName_NotEquals_Name() + { + var permissionValueProviderGrantInfo = await _permissionManagementProvider.CheckAsync("MyPermission1", + "TestNotExist", + "Test"); + + permissionValueProviderGrantInfo.IsGranted.ShouldBeFalse(); + permissionValueProviderGrantInfo.ProviderKey.ShouldBeNull(); + } + + + [Fact] + public async Task SetAsync() + { + _permissionGrantRepository.Insert( + new PermissionGrant( + Guid.NewGuid(), + "MyPermission1", + "Test", + "Test" + ) + ); + (await _permissionGrantRepository.FindAsync("MyPermission1", + "Test", + "Test")).ShouldNotBeNull(); + + await _permissionManagementProvider.SetAsync("MyPermission1", + "Test", + false); + + (await _permissionGrantRepository.FindAsync("MyPermission1", + "Test", + "Test")).ShouldBeNull(); + } + + } +} diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs new file mode 100644 index 0000000000..b5fe647c89 --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Authorization.Permissions; +using Xunit; + +namespace Volo.Abp.PermissionManagement +{ + public class PermissionManager_Tests : PermissionTestBase + { + private readonly IPermissionManager _permissionManager; + private readonly IPermissionGrantRepository _permissionGrantRepository; + + public PermissionManager_Tests() + { + _permissionManager = GetRequiredService(); + _permissionGrantRepository = GetRequiredService(); + } + + [Fact] + public async Task GetAsync() + { + await _permissionGrantRepository.InsertAsync(new PermissionGrant( + Guid.NewGuid(), + "MyPermission1", + "Test", + "Test") + ); + + var grantedProviders = await _permissionManager.GetAsync("MyPermission1", + "Test", + "Test"); + + grantedProviders.ShouldNotBeNull(); + grantedProviders.IsGranted.ShouldBeTrue(); + grantedProviders.Name.ShouldBe("MyPermission1"); + grantedProviders.Providers.ShouldContain(x => x.Key == "Test"); + } + + [Fact] + public async Task Get_Should_Exception_When_Permission_Undefined() + { + await Assert.ThrowsAsync(async () => await _permissionManager.GetAsync( + "MyPermission1NotExist", + "Test", + "Test")); + } + + [Fact] + public async Task GetAllAsync() + { + await _permissionGrantRepository.InsertAsync(new PermissionGrant( + Guid.NewGuid(), + "MyPermission1", + "Test", + "Test") + ); + + await _permissionGrantRepository.InsertAsync(new PermissionGrant( + Guid.NewGuid(), + "MyPermission2", + "Test", + "Test") + ); + + var permissionWithGrantedProviders = await _permissionManager.GetAllAsync( + "Test", + "Test"); + + permissionWithGrantedProviders.ShouldNotBeNull(); + permissionWithGrantedProviders.ShouldContain(x => + x.IsGranted && x.Name == "MyPermission1" && x.Providers.Any(p => p.Key == "Test")); + permissionWithGrantedProviders.ShouldContain(x => + x.IsGranted && x.Name == "MyPermission2" && x.Providers.Any(p => p.Key == "Test")); + } + + [Fact] + public async Task SetAsync() + { + (await _permissionGrantRepository.FindAsync("MyPermission2", + "Test", + "Test")).ShouldBeNull(); + + await _permissionManager.SetAsync( + "MyPermission2", + "Test", + "Test", true); + + (await _permissionGrantRepository.FindAsync("MyPermission2", + "Test", + "Test")).ShouldNotBeNull(); + } + + [Fact] + public async Task Set_Should_Exception_When_Permission_Undefined() + { + await Assert.ThrowsAsync(async () => await _permissionManager.SetAsync( + "MyPermission1NotExist", + "Test", + "Test", + true)); + } + + } +} diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionStore_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionStore_Tests.cs new file mode 100644 index 0000000000..965899ede9 --- /dev/null +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionStore_Tests.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Authorization.Permissions; +using Xunit; + +namespace Volo.Abp.PermissionManagement +{ + public class PermissionStore_Tests : PermissionTestBase + { + private readonly IPermissionStore _permissionStore; + + public PermissionStore_Tests() + { + _permissionStore = GetRequiredService(); + } + + [Fact] + public async Task IsGrantedAsync() + { + (await _permissionStore.IsGrantedAsync("MyPermission1", + UserPermissionValueProvider.ProviderName, + PermissionTestDataBuilder.User1Id.ToString())).ShouldBeTrue(); + + + (await _permissionStore.IsGrantedAsync("MyPermission1NotExist", + UserPermissionValueProvider.ProviderName, + PermissionTestDataBuilder.User1Id.ToString())).ShouldBeFalse(); + + } + } +} diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pt-BR.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pt-BR.json new file mode 100644 index 0000000000..343e299acd --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Localization/Resources/AbpSettingManagement/pt-BR.json @@ -0,0 +1,6 @@ +{ + "culture": "pt-BR", + "texts": { + "Settings": "Configurações" + } +} \ No newline at end of file diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Volo.Abp.SettingManagement.Web.csproj b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Volo.Abp.SettingManagement.Web.csproj index bef5707d83..7749711271 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Volo.Abp.SettingManagement.Web.csproj +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Volo.Abp.SettingManagement.Web.csproj @@ -26,8 +26,8 @@ + - diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestData.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestData.cs index 066ec4c45d..5b93721110 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestData.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestData.cs @@ -7,5 +7,7 @@ namespace Volo.Abp.SettingManagement { public Guid User1Id { get; } = Guid.NewGuid(); public Guid User2Id { get; } = Guid.NewGuid(); + + public Guid SettingId { get; } = Guid.NewGuid(); } } \ No newline at end of file diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestDataBuilder.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestDataBuilder.cs index 79ae4702c8..a66a4fe253 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestDataBuilder.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/SettingTestDataBuilder.cs @@ -24,7 +24,7 @@ namespace Volo.Abp.SettingManagement { _settingRepository.Insert( new Setting( - _guidGenerator.Create(), + _testData.SettingId, "MySetting1", "42", GlobalSettingValueProvider.ProviderName diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/TestSettingDefinitionProvider.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/TestSettingDefinitionProvider.cs index 2bf4a628da..950d0b5d2b 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/TestSettingDefinitionProvider.cs +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.TestBase/Volo/Abp/SettingManagement/TestSettingDefinitionProvider.cs @@ -8,8 +8,11 @@ namespace Volo.Abp.SettingManagement { context.Add(new SettingDefinition("MySetting1")); context.Add(new SettingDefinition("MySetting2")); + context.Add(new SettingDefinition("MySetting3", "123")); context.Add(new SettingDefinition("MySettingWithoutInherit", isInherited: false)); context.Add(new SettingDefinition("SettingNotSetInStore", defaultValue: "default-value")); + + } } } \ No newline at end of file diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/DefaultValueSettingManagementProvider_Tests.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/DefaultValueSettingManagementProvider_Tests.cs new file mode 100644 index 0000000000..d19f587a78 --- /dev/null +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/DefaultValueSettingManagementProvider_Tests.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Settings; +using Xunit; + +namespace Volo.Abp.SettingManagement +{ + public class DefaultValueSettingManagementProvider_Tests : SettingsTestBase + { + private readonly ISettingDefinitionManager _settingDefinitionManager; + + public DefaultValueSettingManagementProvider_Tests() + { + _settingDefinitionManager = GetRequiredService(); + } + + [Fact] + public async Task GetOrNullAsync() + { + var mySetting3 = _settingDefinitionManager.Get("MySetting3"); + + var defaultValueSettingManagementProvider = new DefaultValueSettingManagementProvider(); + (await defaultValueSettingManagementProvider + .GetOrNullAsync(mySetting3, DefaultValueSettingValueProvider.ProviderName)).ShouldBe("123"); + } + + [Fact] + public async Task SetAsync() + { + var mySetting3 = _settingDefinitionManager.Get("MySetting3"); + + await Assert.ThrowsAsync(async () => await new DefaultValueSettingManagementProvider().SetAsync(mySetting3, "123", + DefaultValueSettingValueProvider.ProviderName)); + } + + [Fact] + public async Task ClearAsync() + { + var mySetting3 = _settingDefinitionManager.Get("MySetting3"); + + await Assert.ThrowsAsync(async () => + await new DefaultValueSettingManagementProvider().ClearAsync(mySetting3, + DefaultValueSettingValueProvider.ProviderName)); + } + } +} diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingCacheItemInvalidator_Tests.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingCacheItemInvalidator_Tests.cs new file mode 100644 index 0000000000..de956d0202 --- /dev/null +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingCacheItemInvalidator_Tests.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Castle.DynamicProxy.Generators; +using Shouldly; +using Volo.Abp.Caching; +using Volo.Abp.Settings; +using Xunit; + +namespace Volo.Abp.SettingManagement +{ + public class SettingCacheItemInvalidator_Tests : SettingsTestBase + { + private readonly IDistributedCache _cache; + private readonly ISettingManagementStore _settingManagementStore; + private readonly ISettingRepository _settingRepository; + private readonly SettingTestData _testData; + + public SettingCacheItemInvalidator_Tests() + { + _settingManagementStore = GetRequiredService(); + _cache = GetRequiredService>(); + _settingRepository = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task GetOrNullAsync_Should_Cached() + { + // Act + (await _cache.GetAsync(SettingCacheItem.CalculateCacheKey("MySetting2", "User", _testData.User1Id.ToString()))).ShouldBeNull(); + await _settingManagementStore.GetOrNullAsync("MySetting2", "User", _testData.User1Id.ToString()); + (await _cache.GetAsync(SettingCacheItem.CalculateCacheKey("MySetting2", "User", _testData.User1Id.ToString()))).ShouldNotBeNull(); + } + + [Fact] + public async Task Cache_Should_Invalidator_WhenSettingChanged() + { + // Arrange + // GetOrNullAsync will cache language. + await _settingManagementStore.GetOrNullAsync("MySetting2", "User", _testData.User1Id.ToString()); + + // Act + var lang = await _settingRepository.FindAsync("MySetting2", "User", _testData.User1Id.ToString()); + await _settingRepository.DeleteAsync(lang); + + // Assert + (await _cache.GetAsync( + SettingCacheItem.CalculateCacheKey("MySetting2", "User", _testData.User1Id.ToString()))).ShouldBeNull(); + } + } +} diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManagementStore_Tests.cs b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManagementStore_Tests.cs new file mode 100644 index 0000000000..753ba15054 --- /dev/null +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.Tests/Volo/Abp/SettingManagement/SettingManagementStore_Tests.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Settings; +using Xunit; + +namespace Volo.Abp.SettingManagement +{ + public class SettingManagementStore_Tests : SettingsTestBase + { + private readonly ISettingManagementStore _settingManagementStore; + private readonly ISettingRepository _settingRepository; + private readonly SettingTestData _testData; + + public SettingManagementStore_Tests() + { + _settingManagementStore = GetRequiredService(); + _settingRepository = GetRequiredService(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task GetOrNull_NotExist_Should_Be_Null() + { + var value = await _settingManagementStore.GetOrNullAsync("notExistName", "notExistProviderName", + "notExistProviderKey"); + + value.ShouldBeNull(); + } + + [Fact] + public async Task GetOrNullAsync() + { + var value = await _settingManagementStore.GetOrNullAsync("MySetting1", GlobalSettingValueProvider.ProviderName, null); + + value.ShouldNotBeNull(); + value.ShouldBe("42"); + } + + [Fact] + public async Task SetAsync() + { + var setting = await _settingRepository.FindAsync(_testData.SettingId); + setting.Value.ShouldBe("42"); + + await _settingManagementStore.SetAsync("MySetting1", "43", GlobalSettingValueProvider.ProviderName, null); + + (await _settingRepository.FindAsync(_testData.SettingId)).Value.ShouldBe("43"); + } + + [Fact] + public async Task DeleteAsync() + { + (await _settingRepository.FindAsync(_testData.SettingId)).ShouldNotBeNull(); + + await _settingManagementStore.DeleteAsync("MySetting1", GlobalSettingValueProvider.ProviderName, null); + + (await _settingRepository.FindAsync(_testData.SettingId)).ShouldBeNull(); + } + + } +} diff --git a/modules/tenant-management/Volo.Abp.TenantManagement.sln b/modules/tenant-management/Volo.Abp.TenantManagement.sln index 82e976220f..99ca26e1f0 100644 --- a/modules/tenant-management/Volo.Abp.TenantManagement.sln +++ b/modules/tenant-management/Volo.Abp.TenantManagement.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27428.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{799CA525-4748-421A-9892-05C68BB2FA13}" EndProject @@ -33,6 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.TenantManagement.M EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.TenantManagement.TestBase", "test\Volo.Abp.TenantManagement.TestBase\Volo.Abp.TenantManagement.TestBase.csproj", "{C3BAD6E8-00CD-4283-9416-64287BB5B265}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TenantManagement.Domain.Tests", "test\Volo.Abp.TenantManagement.Domain.Tests\Volo.Abp.TenantManagement.Domain.Tests.csproj", "{F7219BE2-4588-489C-9D31-647C59694C03}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -91,6 +93,10 @@ Global {C3BAD6E8-00CD-4283-9416-64287BB5B265}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3BAD6E8-00CD-4283-9416-64287BB5B265}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3BAD6E8-00CD-4283-9416-64287BB5B265}.Release|Any CPU.Build.0 = Release|Any CPU + {F7219BE2-4588-489C-9D31-647C59694C03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7219BE2-4588-489C-9D31-647C59694C03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7219BE2-4588-489C-9D31-647C59694C03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7219BE2-4588-489C-9D31-647C59694C03}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -109,6 +115,7 @@ Global {ED95242E-3C31-4A89-9C62-93B306EFEB15} = {799CA525-4748-421A-9892-05C68BB2FA13} {F75B4C54-A5F1-4101-99F5-A5B868A5146B} = {C6941869-A9FC-4BEA-AD3F-C1E104826ECA} {C3BAD6E8-00CD-4283-9416-64287BB5B265} = {C6941869-A9FC-4BEA-AD3F-C1E104826ECA} + {F7219BE2-4588-489C-9D31-647C59694C03} = {C6941869-A9FC-4BEA-AD3F-C1E104826ECA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7C258726-2CE0-44D3-A2D7-71812E8F505C} diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pt-BR.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pt-BR.json index e828f7f76b..bf461ab29e 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pt-BR.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/pt-BR.json @@ -4,6 +4,7 @@ "Permission:TenantManagement": "Inquilinos", "Permission:Create": "Criar", "Permission:Edit": "Editar", - "Permission:Delete": "Excluir" + "Permission:Delete": "Excluir", + "Permission:ManageFeatures": "Gerenciar Funcionalidades" } } \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/zh-Hans.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/zh-Hans.json index e75ef463f1..e670d9f206 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/zh-Hans.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/zh-Hans.json @@ -4,6 +4,7 @@ "Permission:TenantManagement": "租户管理", "Permission:Create": "创建", "Permission:Edit": "编辑", - "Permission:Delete": "删除" + "Permission:Delete": "删除", + "Permission:ManageFeatures": "管理功能" } } \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs index b410632502..79d7cf891e 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs @@ -12,6 +12,7 @@ namespace Volo.Abp.TenantManagement public TenantManager(ITenantRepository tenantRepository) { _tenantRepository = tenantRepository; + } public async Task CreateAsync(string name) diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo.Abp.TenantManagement.Domain.Tests.csproj b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo.Abp.TenantManagement.Domain.Tests.csproj new file mode 100644 index 0000000000..0993f200ea --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo.Abp.TenantManagement.Domain.Tests.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.2 + + + + + + + + + + + + + diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpTenantManagementDomainTestBase.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpTenantManagementDomainTestBase.cs new file mode 100644 index 0000000000..2a50504941 --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpTenantManagementDomainTestBase.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.TenantManagement +{ + public class AbpTenantManagementDomainTestBase : TenantManagementTestBase + { + + } +} diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpTenantManagementDomainTestModule.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpTenantManagementDomainTestModule.cs new file mode 100644 index 0000000000..e765db4afb --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/AbpTenantManagementDomainTestModule.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Modularity; +using Volo.Abp.TenantManagement.EntityFrameworkCore; + +namespace Volo.Abp.TenantManagement +{ + [DependsOn( + typeof(AbpTenantManagementEntityFrameworkCoreTestModule), + typeof(AbpTenantManagementTestBaseModule))] + public class AbpSettingManagementDomainTestModule : AbpModule + { + + } +} diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantConnectionString_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantConnectionString_Tests.cs new file mode 100644 index 0000000000..24c27db8ae --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantConnectionString_Tests.cs @@ -0,0 +1,21 @@ +using System; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.TenantManagement +{ + public class TenantConnectionString_Tests + { + [Theory] + [InlineData("aaa")] + [InlineData("bbb")] + public async Task SetValue(string value) + { + var tenantConnectionString = + new TenantConnectionString(Guid.NewGuid(), "MyConnString", "MyConnString-Value"); + tenantConnectionString.SetValue(value); + tenantConnectionString.Value.ShouldBe(value); + } + } +} diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs new file mode 100644 index 0000000000..8605047bbb --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs @@ -0,0 +1,52 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.TenantManagement +{ + public class TenantManager_Tests : AbpTenantManagementDomainTestBase + { + private readonly ITenantManager _tenantManager; + private readonly ITenantRepository _tenantRepository; + + public TenantManager_Tests() + { + _tenantManager = GetRequiredService(); + _tenantRepository = GetRequiredService(); + } + + + [Fact] + public async Task CreateAsync() + { + var tenant = await _tenantManager.CreateAsync("Test"); + tenant.Name.ShouldBe("Test"); + } + + [Fact] + public async Task Create_Tenant_Name_Can_Not_Duplicate() + { + await Assert.ThrowsAsync(async () => await _tenantManager.CreateAsync("volosoft")); + } + + [Fact] + public async Task ChangeNameAsync() + { + var tenant = await _tenantRepository.FindByNameAsync("volosoft"); + tenant.ShouldNotBeNull(); + + await _tenantManager.ChangeNameAsync(tenant, "newVolosoft"); + + tenant.Name.ShouldBe("newVolosoft"); + } + + [Fact] + public async Task ChangeName_Tenant_Name_Can_Not_Duplicate() + { + var tenant = await _tenantRepository.FindByNameAsync("acme"); + tenant.ShouldNotBeNull(); + + await Assert.ThrowsAsync(async () => await _tenantManager.ChangeNameAsync(tenant, "volosoft")); + } + } +} diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs new file mode 100644 index 0000000000..f199124bca --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantStore_Tests.cs @@ -0,0 +1,36 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.MultiTenancy; +using Xunit; + +namespace Volo.Abp.TenantManagement +{ + public class TenantStore_Tests : AbpTenantManagementDomainTestBase + { + private readonly ITenantStore _tenantStore; + private readonly ITenantRepository _tenantRepository; + + public TenantStore_Tests() + { + _tenantStore = GetRequiredService(); + _tenantRepository = GetRequiredService(); + } + + [Fact] + public async Task FindAsyncByName() + { + var acme = await _tenantStore.FindAsync("acme"); + acme.ShouldNotBeNull(); + acme.Name.ShouldBe("acme"); + } + + [Fact] + public async Task FindAsyncById() + { + var acme = await _tenantRepository.FindByNameAsync("acme"); + acme.ShouldNotBeNull(); + + (await _tenantStore.FindAsync(acme.Id)).ShouldNotBeNull(); + } + } +} diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs new file mode 100644 index 0000000000..5107d1a06d --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/Tenant_Tests.cs @@ -0,0 +1,35 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.TenantManagement +{ + public class Tenant_Tests : AbpTenantManagementDomainTestBase + { + private readonly ITenantRepository _tenantRepository; + + public Tenant_Tests() + { + _tenantRepository = GetRequiredService(); + } + + [Fact] + public async Task FindDefaultConnectionString() + { + var acme = await _tenantRepository.FindByNameAsync("acme"); + + acme.ShouldNotBeNull(); + acme.FindDefaultConnectionString().ShouldBe("DefaultConnString-Value"); + } + + [Fact] + public async Task FindConnectionString() + { + var acme = await _tenantRepository.FindByNameAsync("acme"); + + acme.ShouldNotBeNull(); + acme.FindConnectionString(Data.ConnectionStrings.DefaultConnectionStringName).ShouldBe("DefaultConnString-Value"); + acme.FindConnectionString("MyConnString").ShouldBe("MyConnString-Value"); + } + } +} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServerDataSeeder.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServerDataSeeder.cs new file mode 100644 index 0000000000..b10c5d626c --- /dev/null +++ b/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServerDataSeeder.cs @@ -0,0 +1,224 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.Identity; +using Volo.Abp.IdentityServer.ApiResources; +using Volo.Abp.IdentityServer.Clients; +using Volo.Abp.IdentityServer.IdentityResources; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; + +namespace AuthServer.Host +{ + public class AuthServerDataSeeder : IDataSeedContributor, ITransientDependency + { + private readonly IApiResourceRepository _apiResourceRepository; + private readonly IClientRepository _clientRepository; + private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder; + private readonly IGuidGenerator _guidGenerator; + private readonly IPermissionDataSeeder _permissionDataSeeder; + + public AuthServerDataSeeder( + IClientRepository clientRepository, + IApiResourceRepository apiResourceRepository, + IIdentityResourceDataSeeder identityResourceDataSeeder, + IGuidGenerator guidGenerator, + IPermissionDataSeeder permissionDataSeeder) + { + _clientRepository = clientRepository; + _apiResourceRepository = apiResourceRepository; + _identityResourceDataSeeder = identityResourceDataSeeder; + _guidGenerator = guidGenerator; + _permissionDataSeeder = permissionDataSeeder; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await _identityResourceDataSeeder.CreateStandardResourcesAsync(); + await CreateApiResourcesAsync(); + await CreateClientsAsync(); + } + + private async Task CreateApiResourcesAsync() + { + var commonApiUserClaims = new[] + { + "email", + "email_verified", + "name", + "phone_number", + "phone_number_verified", + "role" + }; + + await CreateApiResourceAsync("IdentityService", commonApiUserClaims); + await CreateApiResourceAsync("BloggingService", commonApiUserClaims); + await CreateApiResourceAsync("ProductService", commonApiUserClaims); + await CreateApiResourceAsync("InternalGateway", commonApiUserClaims); + await CreateApiResourceAsync("BackendAdminAppGateway", commonApiUserClaims); + await CreateApiResourceAsync("PublicWebSiteGateway", commonApiUserClaims); + } + + private async Task CreateApiResourceAsync(string name, IEnumerable claims) + { + var apiResource = await _apiResourceRepository.FindByNameAsync(name); + if (apiResource == null) + { + apiResource = await _apiResourceRepository.InsertAsync( + new ApiResource( + _guidGenerator.Create(), + name, + name + " API" + ), + autoSave: true + ); + } + + foreach (var claim in claims) + { + if (apiResource.FindClaim(claim) == null) + { + apiResource.AddUserClaim(claim); + } + } + + return await _apiResourceRepository.UpdateAsync(apiResource); + } + + private async Task CreateClientsAsync() + { + const string commonSecret = "E5Xd4yMqjP5kjWFKrYgySBju6JVfCzMyFp7n2QmMrME="; + + var commonScopes = new[] + { + "email", + "openid", + "profile", + "role", + "phone", + "address" + }; + + await CreateClientAsync( + "console-client-demo", + new[] { "BloggingService", "IdentityService", "InternalGateway", "ProductService" }, + new[] { "client_credentials", "password" }, + commonSecret, + permissions: new[] { IdentityPermissions.Users.Default, "ProductManagement.Product" } + ); + + await CreateClientAsync( + "backend-admin-app-client", + commonScopes.Union(new[] { "BackendAdminAppGateway", "IdentityService", "ProductService" }), + new[] { "hybrid" }, + commonSecret, + redirectUri: "http://localhost:51954/signin-oidc", + postLogoutRedirectUri: "http://localhost:51954/signout-callback-oidc" + ); + + await CreateClientAsync( + "public-website-client", + commonScopes.Union(new[] { "PublicWebSiteGateway", "BloggingService", "ProductService" }), + new[] { "hybrid" }, + commonSecret, + redirectUri: "http://localhost:53435/signin-oidc", + postLogoutRedirectUri: "http://localhost:53435/signout-callback-oidc" + ); + + await CreateClientAsync( + "blogging-service-client", + new[] { "InternalGateway", "IdentityService" }, + new[] { "client_credentials" }, + commonSecret, + permissions: new[] { IdentityPermissions.UserLookup.Default } + ); + } + + private async Task CreateClientAsync( + string name, + IEnumerable scopes, + IEnumerable grantTypes, + string secret, + string redirectUri = null, + string postLogoutRedirectUri = null, + IEnumerable permissions = null) + { + var client = await _clientRepository.FindByCliendIdAsync(name); + if (client == null) + { + client = await _clientRepository.InsertAsync( + new Client( + _guidGenerator.Create(), + name + ) + { + ClientName = name, + ProtocolType = "oidc", + Description = name, + AlwaysIncludeUserClaimsInIdToken = true, + AllowOfflineAccess = true, + AbsoluteRefreshTokenLifetime = 31536000, //365 days + AccessTokenLifetime = 31536000, //365 days + AuthorizationCodeLifetime = 300, + IdentityTokenLifetime = 300, + RequireConsent = false + }, + autoSave: true + ); + } + + foreach (var scope in scopes) + { + if (client.FindScope(scope) == null) + { + client.AddScope(scope); + } + } + + foreach (var grantType in grantTypes) + { + if (client.FindGrantType(grantType) == null) + { + client.AddGrantType(grantType); + } + } + + if (client.FindSecret(secret) == null) + { + client.AddSecret(secret); + } + + if (redirectUri != null) + { + if (client.FindRedirectUri(redirectUri) == null) + { + client.AddRedirectUri(redirectUri); + } + } + + if (postLogoutRedirectUri != null) + { + if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null) + { + client.AddPostLogoutRedirectUri(postLogoutRedirectUri); + } + } + + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions + ); + } + + return await _clientRepository.UpdateAsync(client); + } + } +} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServerHostModule.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServerHostModule.cs index 19baec6988..5fb1ff7104 100644 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServerHostModule.cs +++ b/samples/MicroserviceDemo/applications/AuthServer.Host/AuthServerHostModule.cs @@ -9,11 +9,11 @@ using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; using Volo.Abp.Auditing; using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.Authorization.Permissions; -using Volo.Abp.EventBus.RabbitMq; using Volo.Abp.Autofac; using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.SqlServer; +using Volo.Abp.EventBus.RabbitMq; using Volo.Abp.Identity; using Volo.Abp.Identity.EntityFrameworkCore; using Volo.Abp.IdentityServer.EntityFrameworkCore; @@ -89,15 +89,15 @@ namespace AuthServer.Host app.UseMvcWithDefaultRouteAndArea(); //TODO: Problem on a clustered environment - using (var scope = context.ServiceProvider.CreateScope()) + AsyncHelper.RunSync(async () => { - AsyncHelper.RunSync(async () => + using (var scope = context.ServiceProvider.CreateScope()) { await scope.ServiceProvider .GetRequiredService() .SeedAsync(); - }); - } + } + }); } } } diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190117081756_Initial.Designer.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190117081756_Initial.Designer.cs deleted file mode 100644 index fc7980a757..0000000000 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190117081756_Initial.Designer.cs +++ /dev/null @@ -1,1142 +0,0 @@ -// -using System; -using AuthServer.Host.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace AuthServer.Host.Migrations -{ - [DbContext(typeof(AuthServerDbContext))] - [Migration("20190117081756_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BrowserInfo") - .HasColumnName("BrowserInfo") - .HasMaxLength(512); - - b.Property("ClientIpAddress") - .HasColumnName("ClientIpAddress") - .HasMaxLength(64); - - b.Property("ClientName") - .HasColumnName("ClientName") - .HasMaxLength(128); - - b.Property("Comments") - .HasColumnName("Comments") - .HasMaxLength(256); - - b.Property("ConcurrencyStamp"); - - b.Property("Exceptions") - .HasColumnName("Exceptions") - .HasMaxLength(4000); - - b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration"); - - b.Property("ExecutionTime"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("HttpMethod") - .HasColumnName("HttpMethod") - .HasMaxLength(16); - - b.Property("HttpStatusCode") - .HasColumnName("HttpStatusCode"); - - b.Property("ImpersonatorTenantId") - .HasColumnName("ImpersonatorTenantId"); - - b.Property("ImpersonatorUserId") - .HasColumnName("ImpersonatorUserId"); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.Property("Url") - .HasColumnName("Url") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnName("UserId"); - - b.Property("UserName") - .HasColumnName("UserName") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ExecutionTime"); - - b.HasIndex("TenantId", "UserId", "ExecutionTime"); - - b.ToTable("AbpAuditLogs"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuditLogId") - .HasColumnName("AuditLogId"); - - b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration"); - - b.Property("ExecutionTime") - .HasColumnName("ExecutionTime"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("MethodName") - .HasColumnName("MethodName") - .HasMaxLength(128); - - b.Property("Parameters") - .HasColumnName("Parameters") - .HasMaxLength(2000); - - b.Property("ServiceName") - .HasColumnName("ServiceName") - .HasMaxLength(256); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("AuditLogId"); - - b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); - - b.ToTable("AbpAuditLogActions"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuditLogId") - .HasColumnName("AuditLogId"); - - b.Property("ChangeTime") - .HasColumnName("ChangeTime"); - - b.Property("ChangeType") - .HasColumnName("ChangeType"); - - b.Property("EntityId") - .IsRequired() - .HasColumnName("EntityId") - .HasMaxLength(128); - - b.Property("EntityTypeFullName") - .IsRequired() - .HasColumnName("EntityTypeFullName") - .HasMaxLength(128); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("AuditLogId"); - - b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); - - b.ToTable("AbpEntityChanges"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("EntityChangeId"); - - b.Property("NewValue") - .HasColumnName("NewValue") - .HasMaxLength(512); - - b.Property("OriginalValue") - .HasColumnName("OriginalValue") - .HasMaxLength(512); - - b.Property("PropertyName") - .IsRequired() - .HasColumnName("PropertyName") - .HasMaxLength(128); - - b.Property("PropertyTypeFullName") - .IsRequired() - .HasColumnName("PropertyTypeFullName") - .HasMaxLength(64); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("EntityChangeId"); - - b.ToTable("AbpEntityPropertyChanges"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasColumnName("ConcurrencyStamp") - .HasMaxLength(256); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsStatic"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256); - - b.Property("Regex") - .HasMaxLength(512); - - b.Property("RegexDescription") - .HasMaxLength(128); - - b.Property("Required"); - - b.Property("ValueType"); - - b.HasKey("Id"); - - b.ToTable("AbpClaimTypes"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasColumnName("ConcurrencyStamp") - .HasMaxLength(256); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsDefault") - .HasColumnName("IsDefault"); - - b.Property("IsPublic") - .HasColumnName("IsPublic"); - - b.Property("IsStatic") - .HasColumnName("IsStatic"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256); - - b.Property("NormalizedName") - .IsRequired() - .HasMaxLength(256); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName"); - - b.ToTable("AbpRoles"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClaimType") - .IsRequired() - .HasMaxLength(256); - - b.Property("ClaimValue") - .HasMaxLength(1024); - - b.Property("RoleId"); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AbpRoleClaims"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AccessFailedCount") - .ValueGeneratedOnAdd() - .HasColumnName("AccessFailedCount") - .HasDefaultValue(0); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnName("CreatorId"); - - b.Property("DeleterId") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnName("DeletionTime"); - - b.Property("Email") - .HasColumnName("Email") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .ValueGeneratedOnAdd() - .HasColumnName("EmailConfirmed") - .HasDefaultValue(false); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") - .HasDefaultValue(false); - - b.Property("LastModificationTime") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnName("LastModifierId"); - - b.Property("LockoutEnabled") - .ValueGeneratedOnAdd() - .HasColumnName("LockoutEnabled") - .HasDefaultValue(false); - - b.Property("LockoutEnd"); - - b.Property("Name") - .HasColumnName("Name") - .HasMaxLength(64); - - b.Property("NormalizedEmail") - .HasColumnName("NormalizedEmail") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .IsRequired() - .HasColumnName("NormalizedUserName") - .HasMaxLength(256); - - b.Property("PasswordHash") - .HasColumnName("PasswordHash") - .HasMaxLength(256); - - b.Property("PhoneNumber") - .HasColumnName("PhoneNumber") - .HasMaxLength(16); - - b.Property("PhoneNumberConfirmed") - .ValueGeneratedOnAdd() - .HasColumnName("PhoneNumberConfirmed") - .HasDefaultValue(false); - - b.Property("SecurityStamp") - .IsRequired() - .HasColumnName("SecurityStamp") - .HasMaxLength(256); - - b.Property("Surname") - .HasColumnName("Surname") - .HasMaxLength(64); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.Property("TwoFactorEnabled") - .ValueGeneratedOnAdd() - .HasColumnName("TwoFactorEnabled") - .HasDefaultValue(false); - - b.Property("UserName") - .IsRequired() - .HasColumnName("UserName") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("Email"); - - b.HasIndex("NormalizedEmail"); - - b.HasIndex("NormalizedUserName"); - - b.HasIndex("UserName"); - - b.ToTable("AbpUsers"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClaimType") - .IsRequired() - .HasMaxLength(256); - - b.Property("ClaimValue") - .HasMaxLength(1024); - - b.Property("TenantId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AbpUserClaims"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => - { - b.Property("UserId"); - - b.Property("LoginProvider") - .HasMaxLength(64); - - b.Property("ProviderDisplayName") - .HasMaxLength(128); - - b.Property("ProviderKey") - .IsRequired() - .HasMaxLength(196); - - b.Property("TenantId"); - - b.HasKey("UserId", "LoginProvider"); - - b.HasIndex("LoginProvider", "ProviderKey"); - - b.ToTable("AbpUserLogins"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => - { - b.Property("UserId"); - - b.Property("RoleId"); - - b.Property("TenantId"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId", "UserId"); - - b.ToTable("AbpUserRoles"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => - { - b.Property("UserId"); - - b.Property("LoginProvider") - .HasMaxLength(64); - - b.Property("Name") - .HasMaxLength(128); - - b.Property("TenantId"); - - b.Property("Value"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AbpUserTokens"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Enabled"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.ToTable("IdentityServerApiResources"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => - { - b.Property("ApiResourceId"); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("ApiResourceId", "Type"); - - b.ToTable("IdentityServerApiClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => - { - b.Property("ApiResourceId"); - - b.Property("Name") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("DisplayName") - .HasMaxLength(128); - - b.Property("Emphasize"); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("ApiResourceId", "Name"); - - b.ToTable("IdentityServerApiScopes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => - { - b.Property("ApiResourceId"); - - b.Property("Name") - .HasMaxLength(196); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("ApiResourceId", "Name", "Type"); - - b.ToTable("IdentityServerApiScopeClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => - { - b.Property("ApiResourceId"); - - b.Property("Type") - .HasMaxLength(32); - - b.Property("Value") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("Expiration"); - - b.HasKey("ApiResourceId", "Type", "Value"); - - b.ToTable("IdentityServerApiSecrets"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AbsoluteRefreshTokenLifetime"); - - b.Property("AccessTokenLifetime"); - - b.Property("AccessTokenType"); - - b.Property("AllowAccessTokensViaBrowser"); - - b.Property("AllowOfflineAccess"); - - b.Property("AllowPlainTextPkce"); - - b.Property("AllowRememberConsent"); - - b.Property("AlwaysIncludeUserClaimsInIdToken"); - - b.Property("AlwaysSendClientClaims"); - - b.Property("AuthorizationCodeLifetime"); - - b.Property("BackChannelLogoutSessionRequired"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ClientName") - .HasMaxLength(200); - - b.Property("ClientUri") - .HasMaxLength(2000); - - b.Property("ConcurrencyStamp"); - - b.Property("ConsentLifetime"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("EnableLocalLogin"); - - b.Property("Enabled"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("FrontChannelLogoutSessionRequired"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("IdentityTokenLifetime"); - - b.Property("IncludeJwtId"); - - b.Property("LogoUri") - .HasMaxLength(2000); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200); - - b.Property("RefreshTokenExpiration"); - - b.Property("RefreshTokenUsage"); - - b.Property("RequireClientSecret"); - - b.Property("RequireConsent"); - - b.Property("RequirePkce"); - - b.Property("SlidingRefreshTokenLifetime"); - - b.Property("UpdateAccessTokenClaimsOnRefresh"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("IdentityServerClients"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => - { - b.Property("ClientId"); - - b.Property("Type") - .HasMaxLength(250); - - b.Property("Value") - .HasMaxLength(250); - - b.HasKey("ClientId", "Type", "Value"); - - b.ToTable("IdentityServerClientClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => - { - b.Property("ClientId"); - - b.Property("Origin") - .HasMaxLength(150); - - b.HasKey("ClientId", "Origin"); - - b.ToTable("IdentityServerClientCorsOrigins"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => - { - b.Property("ClientId"); - - b.Property("GrantType") - .HasMaxLength(196); - - b.HasKey("ClientId", "GrantType"); - - b.ToTable("IdentityServerClientGrantTypes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => - { - b.Property("ClientId"); - - b.Property("Provider") - .HasMaxLength(64); - - b.HasKey("ClientId", "Provider"); - - b.ToTable("IdentityServerClientIdPRestrictions"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => - { - b.Property("ClientId"); - - b.Property("PostLogoutRedirectUri") - .HasMaxLength(2000); - - b.HasKey("ClientId", "PostLogoutRedirectUri"); - - b.ToTable("IdentityServerClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => - { - b.Property("ClientId"); - - b.Property("Key") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("ClientId", "Key"); - - b.ToTable("IdentityServerClientProperties"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => - { - b.Property("ClientId"); - - b.Property("RedirectUri") - .HasMaxLength(2000); - - b.HasKey("ClientId", "RedirectUri"); - - b.ToTable("IdentityServerClientRedirectUris"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => - { - b.Property("ClientId"); - - b.Property("Scope") - .HasMaxLength(196); - - b.HasKey("ClientId", "Scope"); - - b.ToTable("IdentityServerClientScopes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => - { - b.Property("ClientId"); - - b.Property("Type") - .HasMaxLength(32); - - b.Property("Value") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("Expiration"); - - b.HasKey("ClientId", "Type", "Value"); - - b.ToTable("IdentityServerClientSecrets"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Grants.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ConcurrencyStamp"); - - b.Property("CreationTime"); - - b.Property("Data") - .IsRequired(); - - b.Property("Expiration"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Id"); - - b.Property("SubjectId") - .HasMaxLength(200); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50); - - b.HasKey("Key"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.ToTable("IdentityServerPersistedGrants"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => - { - b.Property("IdentityResourceId"); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("IdentityResourceId", "Type"); - - b.ToTable("IdentityServerIdentityClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Enabled"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.ToTable("IdentityServerIdentityResources"); - }); - - modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("ProviderKey") - .IsRequired() - .HasMaxLength(64); - - b.Property("ProviderName") - .IsRequired() - .HasMaxLength(64); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("Name", "ProviderName", "ProviderKey"); - - b.ToTable("AbpPermissionGrants"); - }); - - modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("ProviderKey") - .HasMaxLength(64); - - b.Property("ProviderName") - .HasMaxLength(64); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2048); - - b.HasKey("Id"); - - b.HasIndex("Name", "ProviderName", "ProviderKey"); - - b.ToTable("AbpSettings"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => - { - b.HasOne("Volo.Abp.AuditLogging.AuditLog") - .WithMany("Actions") - .HasForeignKey("AuditLogId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => - { - b.HasOne("Volo.Abp.AuditLogging.AuditLog") - .WithMany("EntityChanges") - .HasForeignKey("AuditLogId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => - { - b.HasOne("Volo.Abp.AuditLogging.EntityChange") - .WithMany("PropertyChanges") - .HasForeignKey("EntityChangeId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => - { - b.HasOne("Volo.Abp.Identity.IdentityRole") - .WithMany("Claims") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Claims") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Logins") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => - { - b.HasOne("Volo.Abp.Identity.IdentityRole") - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Roles") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Tokens") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiScope") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId", "Name") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190208210234_Added_ClientId_And_CorrelationId_To_AuditLogs.Designer.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190208210234_Added_ClientId_And_CorrelationId_To_AuditLogs.Designer.cs deleted file mode 100644 index eafb17ae17..0000000000 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190208210234_Added_ClientId_And_CorrelationId_To_AuditLogs.Designer.cs +++ /dev/null @@ -1,1150 +0,0 @@ -// -using System; -using AuthServer.Host.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace AuthServer.Host.Migrations -{ - [DbContext(typeof(AuthServerDbContext))] - [Migration("20190208210234_Added_ClientId_And_CorrelationId_To_AuditLogs")] - partial class Added_ClientId_And_CorrelationId_To_AuditLogs - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BrowserInfo") - .HasColumnName("BrowserInfo") - .HasMaxLength(512); - - b.Property("ClientId") - .HasColumnName("ClientId") - .HasMaxLength(64); - - b.Property("ClientIpAddress") - .HasColumnName("ClientIpAddress") - .HasMaxLength(64); - - b.Property("ClientName") - .HasColumnName("ClientName") - .HasMaxLength(128); - - b.Property("Comments") - .HasColumnName("Comments") - .HasMaxLength(256); - - b.Property("ConcurrencyStamp"); - - b.Property("CorrelationId") - .HasColumnName("CorrelationId") - .HasMaxLength(64); - - b.Property("Exceptions") - .HasColumnName("Exceptions") - .HasMaxLength(4000); - - b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration"); - - b.Property("ExecutionTime"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("HttpMethod") - .HasColumnName("HttpMethod") - .HasMaxLength(16); - - b.Property("HttpStatusCode") - .HasColumnName("HttpStatusCode"); - - b.Property("ImpersonatorTenantId") - .HasColumnName("ImpersonatorTenantId"); - - b.Property("ImpersonatorUserId") - .HasColumnName("ImpersonatorUserId"); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.Property("Url") - .HasColumnName("Url") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnName("UserId"); - - b.Property("UserName") - .HasColumnName("UserName") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ExecutionTime"); - - b.HasIndex("TenantId", "UserId", "ExecutionTime"); - - b.ToTable("AbpAuditLogs"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuditLogId") - .HasColumnName("AuditLogId"); - - b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration"); - - b.Property("ExecutionTime") - .HasColumnName("ExecutionTime"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("MethodName") - .HasColumnName("MethodName") - .HasMaxLength(128); - - b.Property("Parameters") - .HasColumnName("Parameters") - .HasMaxLength(2000); - - b.Property("ServiceName") - .HasColumnName("ServiceName") - .HasMaxLength(256); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("AuditLogId"); - - b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); - - b.ToTable("AbpAuditLogActions"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuditLogId") - .HasColumnName("AuditLogId"); - - b.Property("ChangeTime") - .HasColumnName("ChangeTime"); - - b.Property("ChangeType") - .HasColumnName("ChangeType"); - - b.Property("EntityId") - .IsRequired() - .HasColumnName("EntityId") - .HasMaxLength(128); - - b.Property("EntityTypeFullName") - .IsRequired() - .HasColumnName("EntityTypeFullName") - .HasMaxLength(128); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("AuditLogId"); - - b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); - - b.ToTable("AbpEntityChanges"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("EntityChangeId"); - - b.Property("NewValue") - .HasColumnName("NewValue") - .HasMaxLength(512); - - b.Property("OriginalValue") - .HasColumnName("OriginalValue") - .HasMaxLength(512); - - b.Property("PropertyName") - .IsRequired() - .HasColumnName("PropertyName") - .HasMaxLength(128); - - b.Property("PropertyTypeFullName") - .IsRequired() - .HasColumnName("PropertyTypeFullName") - .HasMaxLength(64); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("EntityChangeId"); - - b.ToTable("AbpEntityPropertyChanges"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasColumnName("ConcurrencyStamp") - .HasMaxLength(256); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsStatic"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256); - - b.Property("Regex") - .HasMaxLength(512); - - b.Property("RegexDescription") - .HasMaxLength(128); - - b.Property("Required"); - - b.Property("ValueType"); - - b.HasKey("Id"); - - b.ToTable("AbpClaimTypes"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasColumnName("ConcurrencyStamp") - .HasMaxLength(256); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsDefault") - .HasColumnName("IsDefault"); - - b.Property("IsPublic") - .HasColumnName("IsPublic"); - - b.Property("IsStatic") - .HasColumnName("IsStatic"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256); - - b.Property("NormalizedName") - .IsRequired() - .HasMaxLength(256); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName"); - - b.ToTable("AbpRoles"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClaimType") - .IsRequired() - .HasMaxLength(256); - - b.Property("ClaimValue") - .HasMaxLength(1024); - - b.Property("RoleId"); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AbpRoleClaims"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AccessFailedCount") - .ValueGeneratedOnAdd() - .HasColumnName("AccessFailedCount") - .HasDefaultValue(0); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnName("CreatorId"); - - b.Property("DeleterId") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnName("DeletionTime"); - - b.Property("Email") - .HasColumnName("Email") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .ValueGeneratedOnAdd() - .HasColumnName("EmailConfirmed") - .HasDefaultValue(false); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") - .HasDefaultValue(false); - - b.Property("LastModificationTime") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnName("LastModifierId"); - - b.Property("LockoutEnabled") - .ValueGeneratedOnAdd() - .HasColumnName("LockoutEnabled") - .HasDefaultValue(false); - - b.Property("LockoutEnd"); - - b.Property("Name") - .HasColumnName("Name") - .HasMaxLength(64); - - b.Property("NormalizedEmail") - .HasColumnName("NormalizedEmail") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .IsRequired() - .HasColumnName("NormalizedUserName") - .HasMaxLength(256); - - b.Property("PasswordHash") - .HasColumnName("PasswordHash") - .HasMaxLength(256); - - b.Property("PhoneNumber") - .HasColumnName("PhoneNumber") - .HasMaxLength(16); - - b.Property("PhoneNumberConfirmed") - .ValueGeneratedOnAdd() - .HasColumnName("PhoneNumberConfirmed") - .HasDefaultValue(false); - - b.Property("SecurityStamp") - .IsRequired() - .HasColumnName("SecurityStamp") - .HasMaxLength(256); - - b.Property("Surname") - .HasColumnName("Surname") - .HasMaxLength(64); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.Property("TwoFactorEnabled") - .ValueGeneratedOnAdd() - .HasColumnName("TwoFactorEnabled") - .HasDefaultValue(false); - - b.Property("UserName") - .IsRequired() - .HasColumnName("UserName") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("Email"); - - b.HasIndex("NormalizedEmail"); - - b.HasIndex("NormalizedUserName"); - - b.HasIndex("UserName"); - - b.ToTable("AbpUsers"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClaimType") - .IsRequired() - .HasMaxLength(256); - - b.Property("ClaimValue") - .HasMaxLength(1024); - - b.Property("TenantId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AbpUserClaims"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => - { - b.Property("UserId"); - - b.Property("LoginProvider") - .HasMaxLength(64); - - b.Property("ProviderDisplayName") - .HasMaxLength(128); - - b.Property("ProviderKey") - .IsRequired() - .HasMaxLength(196); - - b.Property("TenantId"); - - b.HasKey("UserId", "LoginProvider"); - - b.HasIndex("LoginProvider", "ProviderKey"); - - b.ToTable("AbpUserLogins"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => - { - b.Property("UserId"); - - b.Property("RoleId"); - - b.Property("TenantId"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId", "UserId"); - - b.ToTable("AbpUserRoles"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => - { - b.Property("UserId"); - - b.Property("LoginProvider") - .HasMaxLength(64); - - b.Property("Name") - .HasMaxLength(128); - - b.Property("TenantId"); - - b.Property("Value"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AbpUserTokens"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Enabled"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.ToTable("IdentityServerApiResources"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => - { - b.Property("ApiResourceId"); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("ApiResourceId", "Type"); - - b.ToTable("IdentityServerApiClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => - { - b.Property("ApiResourceId"); - - b.Property("Name") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("DisplayName") - .HasMaxLength(128); - - b.Property("Emphasize"); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("ApiResourceId", "Name"); - - b.ToTable("IdentityServerApiScopes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => - { - b.Property("ApiResourceId"); - - b.Property("Name") - .HasMaxLength(196); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("ApiResourceId", "Name", "Type"); - - b.ToTable("IdentityServerApiScopeClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => - { - b.Property("ApiResourceId"); - - b.Property("Type") - .HasMaxLength(32); - - b.Property("Value") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("Expiration"); - - b.HasKey("ApiResourceId", "Type", "Value"); - - b.ToTable("IdentityServerApiSecrets"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AbsoluteRefreshTokenLifetime"); - - b.Property("AccessTokenLifetime"); - - b.Property("AccessTokenType"); - - b.Property("AllowAccessTokensViaBrowser"); - - b.Property("AllowOfflineAccess"); - - b.Property("AllowPlainTextPkce"); - - b.Property("AllowRememberConsent"); - - b.Property("AlwaysIncludeUserClaimsInIdToken"); - - b.Property("AlwaysSendClientClaims"); - - b.Property("AuthorizationCodeLifetime"); - - b.Property("BackChannelLogoutSessionRequired"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ClientName") - .HasMaxLength(200); - - b.Property("ClientUri") - .HasMaxLength(2000); - - b.Property("ConcurrencyStamp"); - - b.Property("ConsentLifetime"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("EnableLocalLogin"); - - b.Property("Enabled"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("FrontChannelLogoutSessionRequired"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("IdentityTokenLifetime"); - - b.Property("IncludeJwtId"); - - b.Property("LogoUri") - .HasMaxLength(2000); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200); - - b.Property("RefreshTokenExpiration"); - - b.Property("RefreshTokenUsage"); - - b.Property("RequireClientSecret"); - - b.Property("RequireConsent"); - - b.Property("RequirePkce"); - - b.Property("SlidingRefreshTokenLifetime"); - - b.Property("UpdateAccessTokenClaimsOnRefresh"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("IdentityServerClients"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => - { - b.Property("ClientId"); - - b.Property("Type") - .HasMaxLength(250); - - b.Property("Value") - .HasMaxLength(250); - - b.HasKey("ClientId", "Type", "Value"); - - b.ToTable("IdentityServerClientClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => - { - b.Property("ClientId"); - - b.Property("Origin") - .HasMaxLength(150); - - b.HasKey("ClientId", "Origin"); - - b.ToTable("IdentityServerClientCorsOrigins"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => - { - b.Property("ClientId"); - - b.Property("GrantType") - .HasMaxLength(196); - - b.HasKey("ClientId", "GrantType"); - - b.ToTable("IdentityServerClientGrantTypes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => - { - b.Property("ClientId"); - - b.Property("Provider") - .HasMaxLength(64); - - b.HasKey("ClientId", "Provider"); - - b.ToTable("IdentityServerClientIdPRestrictions"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => - { - b.Property("ClientId"); - - b.Property("PostLogoutRedirectUri") - .HasMaxLength(200); - - b.HasKey("ClientId", "PostLogoutRedirectUri"); - - b.ToTable("IdentityServerClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => - { - b.Property("ClientId"); - - b.Property("Key") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("ClientId", "Key"); - - b.ToTable("IdentityServerClientProperties"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => - { - b.Property("ClientId"); - - b.Property("RedirectUri") - .HasMaxLength(2000); - - b.HasKey("ClientId", "RedirectUri"); - - b.ToTable("IdentityServerClientRedirectUris"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => - { - b.Property("ClientId"); - - b.Property("Scope") - .HasMaxLength(196); - - b.HasKey("ClientId", "Scope"); - - b.ToTable("IdentityServerClientScopes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => - { - b.Property("ClientId"); - - b.Property("Type") - .HasMaxLength(32); - - b.Property("Value") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("Expiration"); - - b.HasKey("ClientId", "Type", "Value"); - - b.ToTable("IdentityServerClientSecrets"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Grants.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ConcurrencyStamp"); - - b.Property("CreationTime"); - - b.Property("Data") - .IsRequired(); - - b.Property("Expiration"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Id"); - - b.Property("SubjectId") - .HasMaxLength(200); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50); - - b.HasKey("Key"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.ToTable("IdentityServerPersistedGrants"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => - { - b.Property("IdentityResourceId"); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("IdentityResourceId", "Type"); - - b.ToTable("IdentityServerIdentityClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Enabled"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.ToTable("IdentityServerIdentityResources"); - }); - - modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("ProviderKey") - .IsRequired() - .HasMaxLength(64); - - b.Property("ProviderName") - .IsRequired() - .HasMaxLength(64); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("Name", "ProviderName", "ProviderKey"); - - b.ToTable("AbpPermissionGrants"); - }); - - modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("ProviderKey") - .HasMaxLength(64); - - b.Property("ProviderName") - .HasMaxLength(64); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2048); - - b.HasKey("Id"); - - b.HasIndex("Name", "ProviderName", "ProviderKey"); - - b.ToTable("AbpSettings"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => - { - b.HasOne("Volo.Abp.AuditLogging.AuditLog") - .WithMany("Actions") - .HasForeignKey("AuditLogId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => - { - b.HasOne("Volo.Abp.AuditLogging.AuditLog") - .WithMany("EntityChanges") - .HasForeignKey("AuditLogId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => - { - b.HasOne("Volo.Abp.AuditLogging.EntityChange") - .WithMany("PropertyChanges") - .HasForeignKey("EntityChangeId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => - { - b.HasOne("Volo.Abp.Identity.IdentityRole") - .WithMany("Claims") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Claims") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Logins") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => - { - b.HasOne("Volo.Abp.Identity.IdentityRole") - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Roles") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Tokens") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiScope") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId", "Name") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190208210234_Added_ClientId_And_CorrelationId_To_AuditLogs.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190208210234_Added_ClientId_And_CorrelationId_To_AuditLogs.cs deleted file mode 100644 index 38d3168029..0000000000 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190208210234_Added_ClientId_And_CorrelationId_To_AuditLogs.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Reflection.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace AuthServer.Host.Migrations -{ - public partial class Added_ClientId_And_CorrelationId_To_AuditLogs : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - "PK_IdentityServerClientPostLogoutRedirectUris", - "IdentityServerClientPostLogoutRedirectUris" - ); - - migrationBuilder.AlterColumn( - name: "PostLogoutRedirectUri", - table: "IdentityServerClientPostLogoutRedirectUris", - maxLength: 200, - nullable: false, - oldClrType: typeof(string), - oldMaxLength: 2000); - - migrationBuilder.AddPrimaryKey( - "PK_IdentityServerClientPostLogoutRedirectUris", - "IdentityServerClientPostLogoutRedirectUris", - new[] {"ClientId", "PostLogoutRedirectUri"} - ); - - migrationBuilder.AddColumn( - name: "ClientId", - table: "AbpAuditLogs", - maxLength: 64, - nullable: true); - - migrationBuilder.AddColumn( - name: "CorrelationId", - table: "AbpAuditLogs", - maxLength: 64, - nullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "ClientId", - table: "AbpAuditLogs"); - - migrationBuilder.DropColumn( - name: "CorrelationId", - table: "AbpAuditLogs"); - - migrationBuilder.DropPrimaryKey( - "PK_IdentityServerClientPostLogoutRedirectUris", - "IdentityServerClientPostLogoutRedirectUris" - ); - - migrationBuilder.AlterColumn( - name: "PostLogoutRedirectUri", - table: "IdentityServerClientPostLogoutRedirectUris", - maxLength: 2000, - nullable: false, - oldClrType: typeof(string), - oldMaxLength: 200); - - migrationBuilder.AddPrimaryKey( - "PK_IdentityServerClientPostLogoutRedirectUris", - "IdentityServerClientPostLogoutRedirectUris", - new[] { "ClientId", "PostLogoutRedirectUri" } - ); - } - } -} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190209193341_Added_ApplicationName_To_AuditLogs.Designer.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190209193341_Added_ApplicationName_To_AuditLogs.Designer.cs deleted file mode 100644 index c40fb65f22..0000000000 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190209193341_Added_ApplicationName_To_AuditLogs.Designer.cs +++ /dev/null @@ -1,1154 +0,0 @@ -// -using System; -using AuthServer.Host.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace AuthServer.Host.Migrations -{ - [DbContext(typeof(AuthServerDbContext))] - [Migration("20190209193341_Added_ApplicationName_To_AuditLogs")] - partial class Added_ApplicationName_To_AuditLogs - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ApplicationName") - .HasColumnName("ApplicationName") - .HasMaxLength(96); - - b.Property("BrowserInfo") - .HasColumnName("BrowserInfo") - .HasMaxLength(512); - - b.Property("ClientId") - .HasColumnName("ClientId") - .HasMaxLength(64); - - b.Property("ClientIpAddress") - .HasColumnName("ClientIpAddress") - .HasMaxLength(64); - - b.Property("ClientName") - .HasColumnName("ClientName") - .HasMaxLength(128); - - b.Property("Comments") - .HasColumnName("Comments") - .HasMaxLength(256); - - b.Property("ConcurrencyStamp"); - - b.Property("CorrelationId") - .HasColumnName("CorrelationId") - .HasMaxLength(64); - - b.Property("Exceptions") - .HasColumnName("Exceptions") - .HasMaxLength(4000); - - b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration"); - - b.Property("ExecutionTime"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("HttpMethod") - .HasColumnName("HttpMethod") - .HasMaxLength(16); - - b.Property("HttpStatusCode") - .HasColumnName("HttpStatusCode"); - - b.Property("ImpersonatorTenantId") - .HasColumnName("ImpersonatorTenantId"); - - b.Property("ImpersonatorUserId") - .HasColumnName("ImpersonatorUserId"); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.Property("Url") - .HasColumnName("Url") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnName("UserId"); - - b.Property("UserName") - .HasColumnName("UserName") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("TenantId", "ExecutionTime"); - - b.HasIndex("TenantId", "UserId", "ExecutionTime"); - - b.ToTable("AbpAuditLogs"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuditLogId") - .HasColumnName("AuditLogId"); - - b.Property("ExecutionDuration") - .HasColumnName("ExecutionDuration"); - - b.Property("ExecutionTime") - .HasColumnName("ExecutionTime"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("MethodName") - .HasColumnName("MethodName") - .HasMaxLength(128); - - b.Property("Parameters") - .HasColumnName("Parameters") - .HasMaxLength(2000); - - b.Property("ServiceName") - .HasColumnName("ServiceName") - .HasMaxLength(256); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("AuditLogId"); - - b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); - - b.ToTable("AbpAuditLogActions"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuditLogId") - .HasColumnName("AuditLogId"); - - b.Property("ChangeTime") - .HasColumnName("ChangeTime"); - - b.Property("ChangeType") - .HasColumnName("ChangeType"); - - b.Property("EntityId") - .IsRequired() - .HasColumnName("EntityId") - .HasMaxLength(128); - - b.Property("EntityTypeFullName") - .IsRequired() - .HasColumnName("EntityTypeFullName") - .HasMaxLength(128); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("AuditLogId"); - - b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); - - b.ToTable("AbpEntityChanges"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("EntityChangeId"); - - b.Property("NewValue") - .HasColumnName("NewValue") - .HasMaxLength(512); - - b.Property("OriginalValue") - .HasColumnName("OriginalValue") - .HasMaxLength(512); - - b.Property("PropertyName") - .IsRequired() - .HasColumnName("PropertyName") - .HasMaxLength(128); - - b.Property("PropertyTypeFullName") - .IsRequired() - .HasColumnName("PropertyTypeFullName") - .HasMaxLength(64); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("EntityChangeId"); - - b.ToTable("AbpEntityPropertyChanges"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasColumnName("ConcurrencyStamp") - .HasMaxLength(256); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsStatic"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256); - - b.Property("Regex") - .HasMaxLength(512); - - b.Property("RegexDescription") - .HasMaxLength(128); - - b.Property("Required"); - - b.Property("ValueType"); - - b.HasKey("Id"); - - b.ToTable("AbpClaimTypes"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .IsRequired() - .HasColumnName("ConcurrencyStamp") - .HasMaxLength(256); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsDefault") - .HasColumnName("IsDefault"); - - b.Property("IsPublic") - .HasColumnName("IsPublic"); - - b.Property("IsStatic") - .HasColumnName("IsStatic"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256); - - b.Property("NormalizedName") - .IsRequired() - .HasMaxLength(256); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName"); - - b.ToTable("AbpRoles"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClaimType") - .IsRequired() - .HasMaxLength(256); - - b.Property("ClaimValue") - .HasMaxLength(1024); - - b.Property("RoleId"); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AbpRoleClaims"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AccessFailedCount") - .ValueGeneratedOnAdd() - .HasColumnName("AccessFailedCount") - .HasDefaultValue(0); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnName("CreatorId"); - - b.Property("DeleterId") - .HasColumnName("DeleterId"); - - b.Property("DeletionTime") - .HasColumnName("DeletionTime"); - - b.Property("Email") - .HasColumnName("Email") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .ValueGeneratedOnAdd() - .HasColumnName("EmailConfirmed") - .HasDefaultValue(false); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("IsDeleted") - .ValueGeneratedOnAdd() - .HasColumnName("IsDeleted") - .HasDefaultValue(false); - - b.Property("LastModificationTime") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnName("LastModifierId"); - - b.Property("LockoutEnabled") - .ValueGeneratedOnAdd() - .HasColumnName("LockoutEnabled") - .HasDefaultValue(false); - - b.Property("LockoutEnd"); - - b.Property("Name") - .HasColumnName("Name") - .HasMaxLength(64); - - b.Property("NormalizedEmail") - .HasColumnName("NormalizedEmail") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .IsRequired() - .HasColumnName("NormalizedUserName") - .HasMaxLength(256); - - b.Property("PasswordHash") - .HasColumnName("PasswordHash") - .HasMaxLength(256); - - b.Property("PhoneNumber") - .HasColumnName("PhoneNumber") - .HasMaxLength(16); - - b.Property("PhoneNumberConfirmed") - .ValueGeneratedOnAdd() - .HasColumnName("PhoneNumberConfirmed") - .HasDefaultValue(false); - - b.Property("SecurityStamp") - .IsRequired() - .HasColumnName("SecurityStamp") - .HasMaxLength(256); - - b.Property("Surname") - .HasColumnName("Surname") - .HasMaxLength(64); - - b.Property("TenantId") - .HasColumnName("TenantId"); - - b.Property("TwoFactorEnabled") - .ValueGeneratedOnAdd() - .HasColumnName("TwoFactorEnabled") - .HasDefaultValue(false); - - b.Property("UserName") - .IsRequired() - .HasColumnName("UserName") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("Email"); - - b.HasIndex("NormalizedEmail"); - - b.HasIndex("NormalizedUserName"); - - b.HasIndex("UserName"); - - b.ToTable("AbpUsers"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ClaimType") - .IsRequired() - .HasMaxLength(256); - - b.Property("ClaimValue") - .HasMaxLength(1024); - - b.Property("TenantId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AbpUserClaims"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => - { - b.Property("UserId"); - - b.Property("LoginProvider") - .HasMaxLength(64); - - b.Property("ProviderDisplayName") - .HasMaxLength(128); - - b.Property("ProviderKey") - .IsRequired() - .HasMaxLength(196); - - b.Property("TenantId"); - - b.HasKey("UserId", "LoginProvider"); - - b.HasIndex("LoginProvider", "ProviderKey"); - - b.ToTable("AbpUserLogins"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => - { - b.Property("UserId"); - - b.Property("RoleId"); - - b.Property("TenantId"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId", "UserId"); - - b.ToTable("AbpUserRoles"); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => - { - b.Property("UserId"); - - b.Property("LoginProvider") - .HasMaxLength(64); - - b.Property("Name") - .HasMaxLength(128); - - b.Property("TenantId"); - - b.Property("Value"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AbpUserTokens"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Enabled"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("Id"); - - b.ToTable("IdentityServerApiResources"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => - { - b.Property("ApiResourceId"); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("ApiResourceId", "Type"); - - b.ToTable("IdentityServerApiClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => - { - b.Property("ApiResourceId"); - - b.Property("Name") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("DisplayName") - .HasMaxLength(128); - - b.Property("Emphasize"); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("ApiResourceId", "Name"); - - b.ToTable("IdentityServerApiScopes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => - { - b.Property("ApiResourceId"); - - b.Property("Name") - .HasMaxLength(196); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("ApiResourceId", "Name", "Type"); - - b.ToTable("IdentityServerApiScopeClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => - { - b.Property("ApiResourceId"); - - b.Property("Type") - .HasMaxLength(32); - - b.Property("Value") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("Expiration"); - - b.HasKey("ApiResourceId", "Type", "Value"); - - b.ToTable("IdentityServerApiSecrets"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AbsoluteRefreshTokenLifetime"); - - b.Property("AccessTokenLifetime"); - - b.Property("AccessTokenType"); - - b.Property("AllowAccessTokensViaBrowser"); - - b.Property("AllowOfflineAccess"); - - b.Property("AllowPlainTextPkce"); - - b.Property("AllowRememberConsent"); - - b.Property("AlwaysIncludeUserClaimsInIdToken"); - - b.Property("AlwaysSendClientClaims"); - - b.Property("AuthorizationCodeLifetime"); - - b.Property("BackChannelLogoutSessionRequired"); - - b.Property("BackChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("ClientClaimsPrefix") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ClientName") - .HasMaxLength(200); - - b.Property("ClientUri") - .HasMaxLength(2000); - - b.Property("ConcurrencyStamp"); - - b.Property("ConsentLifetime"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("EnableLocalLogin"); - - b.Property("Enabled"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("FrontChannelLogoutSessionRequired"); - - b.Property("FrontChannelLogoutUri") - .HasMaxLength(2000); - - b.Property("IdentityTokenLifetime"); - - b.Property("IncludeJwtId"); - - b.Property("LogoUri") - .HasMaxLength(2000); - - b.Property("PairWiseSubjectSalt") - .HasMaxLength(200); - - b.Property("ProtocolType") - .IsRequired() - .HasMaxLength(200); - - b.Property("RefreshTokenExpiration"); - - b.Property("RefreshTokenUsage"); - - b.Property("RequireClientSecret"); - - b.Property("RequireConsent"); - - b.Property("RequirePkce"); - - b.Property("SlidingRefreshTokenLifetime"); - - b.Property("UpdateAccessTokenClaimsOnRefresh"); - - b.HasKey("Id"); - - b.HasIndex("ClientId") - .IsUnique(); - - b.ToTable("IdentityServerClients"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => - { - b.Property("ClientId"); - - b.Property("Type") - .HasMaxLength(250); - - b.Property("Value") - .HasMaxLength(250); - - b.HasKey("ClientId", "Type", "Value"); - - b.ToTable("IdentityServerClientClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => - { - b.Property("ClientId"); - - b.Property("Origin") - .HasMaxLength(150); - - b.HasKey("ClientId", "Origin"); - - b.ToTable("IdentityServerClientCorsOrigins"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => - { - b.Property("ClientId"); - - b.Property("GrantType") - .HasMaxLength(196); - - b.HasKey("ClientId", "GrantType"); - - b.ToTable("IdentityServerClientGrantTypes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => - { - b.Property("ClientId"); - - b.Property("Provider") - .HasMaxLength(64); - - b.HasKey("ClientId", "Provider"); - - b.ToTable("IdentityServerClientIdPRestrictions"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => - { - b.Property("ClientId"); - - b.Property("PostLogoutRedirectUri") - .HasMaxLength(200); - - b.HasKey("ClientId", "PostLogoutRedirectUri"); - - b.ToTable("IdentityServerClientPostLogoutRedirectUris"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => - { - b.Property("ClientId"); - - b.Property("Key") - .HasMaxLength(250); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2000); - - b.HasKey("ClientId", "Key"); - - b.ToTable("IdentityServerClientProperties"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => - { - b.Property("ClientId"); - - b.Property("RedirectUri") - .HasMaxLength(2000); - - b.HasKey("ClientId", "RedirectUri"); - - b.ToTable("IdentityServerClientRedirectUris"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => - { - b.Property("ClientId"); - - b.Property("Scope") - .HasMaxLength(196); - - b.HasKey("ClientId", "Scope"); - - b.ToTable("IdentityServerClientScopes"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => - { - b.Property("ClientId"); - - b.Property("Type") - .HasMaxLength(32); - - b.Property("Value") - .HasMaxLength(196); - - b.Property("Description") - .HasMaxLength(256); - - b.Property("Expiration"); - - b.HasKey("ClientId", "Type", "Value"); - - b.ToTable("IdentityServerClientSecrets"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Grants.PersistedGrant", b => - { - b.Property("Key") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasMaxLength(200); - - b.Property("ConcurrencyStamp"); - - b.Property("CreationTime"); - - b.Property("Data") - .IsRequired(); - - b.Property("Expiration"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Id"); - - b.Property("SubjectId") - .HasMaxLength(200); - - b.Property("Type") - .IsRequired() - .HasMaxLength(50); - - b.HasKey("Key"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.ToTable("IdentityServerPersistedGrants"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => - { - b.Property("IdentityResourceId"); - - b.Property("Type") - .HasMaxLength(196); - - b.HasKey("IdentityResourceId", "Type"); - - b.ToTable("IdentityServerIdentityClaims"); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ConcurrencyStamp"); - - b.Property("Description") - .HasMaxLength(1000); - - b.Property("DisplayName") - .HasMaxLength(200); - - b.Property("Emphasize"); - - b.Property("Enabled"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.Property("Required"); - - b.Property("ShowInDiscoveryDocument"); - - b.HasKey("Id"); - - b.ToTable("IdentityServerIdentityResources"); - }); - - modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("ProviderKey") - .IsRequired() - .HasMaxLength(64); - - b.Property("ProviderName") - .IsRequired() - .HasMaxLength(64); - - b.Property("TenantId"); - - b.HasKey("Id"); - - b.HasIndex("Name", "ProviderName", "ProviderKey"); - - b.ToTable("AbpPermissionGrants"); - }); - - modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Name") - .IsRequired() - .HasMaxLength(128); - - b.Property("ProviderKey") - .HasMaxLength(64); - - b.Property("ProviderName") - .HasMaxLength(64); - - b.Property("Value") - .IsRequired() - .HasMaxLength(2048); - - b.HasKey("Id"); - - b.HasIndex("Name", "ProviderName", "ProviderKey"); - - b.ToTable("AbpSettings"); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => - { - b.HasOne("Volo.Abp.AuditLogging.AuditLog") - .WithMany("Actions") - .HasForeignKey("AuditLogId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => - { - b.HasOne("Volo.Abp.AuditLogging.AuditLog") - .WithMany("EntityChanges") - .HasForeignKey("AuditLogId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => - { - b.HasOne("Volo.Abp.AuditLogging.EntityChange") - .WithMany("PropertyChanges") - .HasForeignKey("EntityChangeId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => - { - b.HasOne("Volo.Abp.Identity.IdentityRole") - .WithMany("Claims") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Claims") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Logins") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => - { - b.HasOne("Volo.Abp.Identity.IdentityRole") - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Roles") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => - { - b.HasOne("Volo.Abp.Identity.IdentityUser") - .WithMany("Tokens") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("Scopes") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiScope") - .WithMany("UserClaims") - .HasForeignKey("ApiResourceId", "Name") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b => - { - b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource") - .WithMany("Secrets") - .HasForeignKey("ApiResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("Claims") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedCorsOrigins") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedGrantTypes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("IdentityProviderRestrictions") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("PostLogoutRedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("Properties") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("RedirectUris") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("AllowedScopes") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => - { - b.HasOne("Volo.Abp.IdentityServer.Clients.Client") - .WithMany("ClientSecrets") - .HasForeignKey("ClientId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityClaim", b => - { - b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource") - .WithMany("UserClaims") - .HasForeignKey("IdentityResourceId") - .OnDelete(DeleteBehavior.Cascade); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190209193341_Added_ApplicationName_To_AuditLogs.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190209193341_Added_ApplicationName_To_AuditLogs.cs deleted file mode 100644 index 91ed4a25a1..0000000000 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190209193341_Added_ApplicationName_To_AuditLogs.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace AuthServer.Host.Migrations -{ - public partial class Added_ApplicationName_To_AuditLogs : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "ApplicationName", - table: "AbpAuditLogs", - maxLength: 96, - nullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "ApplicationName", - table: "AbpAuditLogs"); - } - } -} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190404130536_Make_IDS4_Entities_Audited.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190404130536_Make_IDS4_Entities_Audited.cs deleted file mode 100644 index 5ef97dc0af..0000000000 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190404130536_Make_IDS4_Entities_Audited.cs +++ /dev/null @@ -1,347 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace AuthServer.Host.Migrations -{ - public partial class Make_IDS4_Entities_Audited : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CreationTime", - table: "IdentityServerIdentityResources", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - - migrationBuilder.AddColumn( - name: "CreatorId", - table: "IdentityServerIdentityResources", - nullable: true); - - migrationBuilder.AddColumn( - name: "DeleterId", - table: "IdentityServerIdentityResources", - nullable: true); - - migrationBuilder.AddColumn( - name: "DeletionTime", - table: "IdentityServerIdentityResources", - nullable: true); - - migrationBuilder.AddColumn( - name: "IsDeleted", - table: "IdentityServerIdentityResources", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "LastModificationTime", - table: "IdentityServerIdentityResources", - nullable: true); - - migrationBuilder.AddColumn( - name: "LastModifierId", - table: "IdentityServerIdentityResources", - nullable: true); - - migrationBuilder.AlterColumn( - name: "LogoUri", - table: "IdentityServerClients", - maxLength: 300, - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 2000, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "FrontChannelLogoutUri", - table: "IdentityServerClients", - maxLength: 300, - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 2000, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ClientUri", - table: "IdentityServerClients", - maxLength: 300, - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 2000, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "BackChannelLogoutUri", - table: "IdentityServerClients", - maxLength: 300, - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 2000, - oldNullable: true); - - migrationBuilder.AddColumn( - name: "CreationTime", - table: "IdentityServerClients", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - - migrationBuilder.AddColumn( - name: "CreatorId", - table: "IdentityServerClients", - nullable: true); - - migrationBuilder.AddColumn( - name: "DeleterId", - table: "IdentityServerClients", - nullable: true); - - migrationBuilder.AddColumn( - name: "DeletionTime", - table: "IdentityServerClients", - nullable: true); - - migrationBuilder.AddColumn( - name: "IsDeleted", - table: "IdentityServerClients", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "LastModificationTime", - table: "IdentityServerClients", - nullable: true); - - migrationBuilder.AddColumn( - name: "LastModifierId", - table: "IdentityServerClients", - nullable: true); - - //migrationBuilder.AlterColumn( - // name: "RedirectUri", - // table: "IdentityServerClientRedirectUris", - // maxLength: 200, - // nullable: false, - // oldClrType: typeof(string), - // oldMaxLength: 2000); - - //migrationBuilder.AlterColumn( - // name: "Value", - // table: "IdentityServerClientProperties", - // maxLength: 128, - // nullable: false, - // oldClrType: typeof(string), - // oldMaxLength: 2000); - - //migrationBuilder.AlterColumn( - // name: "Key", - // table: "IdentityServerClientProperties", - // maxLength: 64, - // nullable: false, - // oldClrType: typeof(string), - // oldMaxLength: 250); - - migrationBuilder.AddColumn( - name: "CreationTime", - table: "IdentityServerApiResources", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); - - migrationBuilder.AddColumn( - name: "CreatorId", - table: "IdentityServerApiResources", - nullable: true); - - migrationBuilder.AddColumn( - name: "DeleterId", - table: "IdentityServerApiResources", - nullable: true); - - migrationBuilder.AddColumn( - name: "DeletionTime", - table: "IdentityServerApiResources", - nullable: true); - - migrationBuilder.AddColumn( - name: "IsDeleted", - table: "IdentityServerApiResources", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "LastModificationTime", - table: "IdentityServerApiResources", - nullable: true); - - migrationBuilder.AddColumn( - name: "LastModifierId", - table: "IdentityServerApiResources", - nullable: true); - - migrationBuilder.AddColumn( - name: "EntityTenantId", - table: "AbpEntityChanges", - nullable: true); - - migrationBuilder.AddColumn( - name: "TenantName", - table: "AbpAuditLogs", - nullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CreationTime", - table: "IdentityServerIdentityResources"); - - migrationBuilder.DropColumn( - name: "CreatorId", - table: "IdentityServerIdentityResources"); - - migrationBuilder.DropColumn( - name: "DeleterId", - table: "IdentityServerIdentityResources"); - - migrationBuilder.DropColumn( - name: "DeletionTime", - table: "IdentityServerIdentityResources"); - - migrationBuilder.DropColumn( - name: "IsDeleted", - table: "IdentityServerIdentityResources"); - - migrationBuilder.DropColumn( - name: "LastModificationTime", - table: "IdentityServerIdentityResources"); - - migrationBuilder.DropColumn( - name: "LastModifierId", - table: "IdentityServerIdentityResources"); - - migrationBuilder.DropColumn( - name: "CreationTime", - table: "IdentityServerClients"); - - migrationBuilder.DropColumn( - name: "CreatorId", - table: "IdentityServerClients"); - - migrationBuilder.DropColumn( - name: "DeleterId", - table: "IdentityServerClients"); - - migrationBuilder.DropColumn( - name: "DeletionTime", - table: "IdentityServerClients"); - - migrationBuilder.DropColumn( - name: "IsDeleted", - table: "IdentityServerClients"); - - migrationBuilder.DropColumn( - name: "LastModificationTime", - table: "IdentityServerClients"); - - migrationBuilder.DropColumn( - name: "LastModifierId", - table: "IdentityServerClients"); - - migrationBuilder.DropColumn( - name: "CreationTime", - table: "IdentityServerApiResources"); - - migrationBuilder.DropColumn( - name: "CreatorId", - table: "IdentityServerApiResources"); - - migrationBuilder.DropColumn( - name: "DeleterId", - table: "IdentityServerApiResources"); - - migrationBuilder.DropColumn( - name: "DeletionTime", - table: "IdentityServerApiResources"); - - migrationBuilder.DropColumn( - name: "IsDeleted", - table: "IdentityServerApiResources"); - - migrationBuilder.DropColumn( - name: "LastModificationTime", - table: "IdentityServerApiResources"); - - migrationBuilder.DropColumn( - name: "LastModifierId", - table: "IdentityServerApiResources"); - - migrationBuilder.DropColumn( - name: "EntityTenantId", - table: "AbpEntityChanges"); - - migrationBuilder.DropColumn( - name: "TenantName", - table: "AbpAuditLogs"); - - migrationBuilder.AlterColumn( - name: "LogoUri", - table: "IdentityServerClients", - maxLength: 2000, - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 300, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "FrontChannelLogoutUri", - table: "IdentityServerClients", - maxLength: 2000, - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 300, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ClientUri", - table: "IdentityServerClients", - maxLength: 2000, - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 300, - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "BackChannelLogoutUri", - table: "IdentityServerClients", - maxLength: 2000, - nullable: true, - oldClrType: typeof(string), - oldMaxLength: 300, - oldNullable: true); - - //migrationBuilder.AlterColumn( - // name: "RedirectUri", - // table: "IdentityServerClientRedirectUris", - // maxLength: 2000, - // nullable: false, - // oldClrType: typeof(string), - // oldMaxLength: 200); - - //migrationBuilder.AlterColumn( - // name: "Value", - // table: "IdentityServerClientProperties", - // maxLength: 2000, - // nullable: false, - // oldClrType: typeof(string), - // oldMaxLength: 128); - - //migrationBuilder.AlterColumn( - // name: "Key", - // table: "IdentityServerClientProperties", - // maxLength: 250, - // nullable: false, - // oldClrType: typeof(string), - // oldMaxLength: 64); - } - } -} diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190404130536_Make_IDS4_Entities_Audited.Designer.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190408114124_Initial.Designer.cs similarity index 99% rename from samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190404130536_Make_IDS4_Entities_Audited.Designer.cs rename to samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190408114124_Initial.Designer.cs index 4dac4a6a72..dcbfde13e8 100644 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190404130536_Make_IDS4_Entities_Audited.Designer.cs +++ b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190408114124_Initial.Designer.cs @@ -10,8 +10,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace AuthServer.Host.Migrations { [DbContext(typeof(AuthServerDbContext))] - [Migration("20190404130536_Make_IDS4_Entities_Audited")] - partial class Make_IDS4_Entities_Audited + [Migration("20190408114124_Initial")] + partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { diff --git a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190117081756_Initial.cs b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190408114124_Initial.cs similarity index 94% rename from samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190117081756_Initial.cs rename to samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190408114124_Initial.cs index 6d08db79b9..d80105e24c 100644 --- a/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190117081756_Initial.cs +++ b/samples/MicroserviceDemo/applications/AuthServer.Host/Migrations/20190408114124_Initial.cs @@ -14,15 +14,19 @@ namespace AuthServer.Host.Migrations Id = table.Column(nullable: false), ExtraProperties = table.Column(nullable: true), ConcurrencyStamp = table.Column(nullable: true), + ApplicationName = table.Column(maxLength: 96, nullable: true), UserId = table.Column(nullable: true), UserName = table.Column(maxLength: 256, nullable: true), TenantId = table.Column(nullable: true), + TenantName = table.Column(nullable: true), ImpersonatorUserId = table.Column(nullable: true), ImpersonatorTenantId = table.Column(nullable: true), ExecutionTime = table.Column(nullable: false), ExecutionDuration = table.Column(nullable: false), ClientIpAddress = table.Column(maxLength: 64, nullable: true), ClientName = table.Column(maxLength: 128, nullable: true), + ClientId = table.Column(maxLength: 64, nullable: true), + CorrelationId = table.Column(maxLength: 64, nullable: true), BrowserInfo = table.Column(maxLength: 512, nullable: true), HttpMethod = table.Column(maxLength: 16, nullable: true), Url = table.Column(maxLength: 256, nullable: true), @@ -147,6 +151,13 @@ namespace AuthServer.Host.Migrations Id = table.Column(nullable: false), ExtraProperties = table.Column(nullable: true), ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), Name = table.Column(maxLength: 200, nullable: false), DisplayName = table.Column(maxLength: 200, nullable: true), Description = table.Column(maxLength: 1000, nullable: true), @@ -164,11 +175,18 @@ namespace AuthServer.Host.Migrations Id = table.Column(nullable: false), ExtraProperties = table.Column(nullable: true), ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), ClientId = table.Column(maxLength: 200, nullable: false), ClientName = table.Column(maxLength: 200, nullable: true), Description = table.Column(maxLength: 1000, nullable: true), - ClientUri = table.Column(maxLength: 2000, nullable: true), - LogoUri = table.Column(maxLength: 2000, nullable: true), + ClientUri = table.Column(maxLength: 300, nullable: true), + LogoUri = table.Column(maxLength: 300, nullable: true), Enabled = table.Column(nullable: false), ProtocolType = table.Column(maxLength: 200, nullable: false), RequireClientSecret = table.Column(nullable: false), @@ -178,9 +196,9 @@ namespace AuthServer.Host.Migrations RequirePkce = table.Column(nullable: false), AllowPlainTextPkce = table.Column(nullable: false), AllowAccessTokensViaBrowser = table.Column(nullable: false), - FrontChannelLogoutUri = table.Column(maxLength: 2000, nullable: true), + FrontChannelLogoutUri = table.Column(maxLength: 300, nullable: true), FrontChannelLogoutSessionRequired = table.Column(nullable: false), - BackChannelLogoutUri = table.Column(maxLength: 2000, nullable: true), + BackChannelLogoutUri = table.Column(maxLength: 300, nullable: true), BackChannelLogoutSessionRequired = table.Column(nullable: false), AllowOfflineAccess = table.Column(nullable: false), IdentityTokenLifetime = table.Column(nullable: false), @@ -211,6 +229,13 @@ namespace AuthServer.Host.Migrations Id = table.Column(nullable: false), ExtraProperties = table.Column(nullable: true), ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), Name = table.Column(maxLength: 200, nullable: false), DisplayName = table.Column(maxLength: 200, nullable: true), Description = table.Column(maxLength: 1000, nullable: true), @@ -278,6 +303,7 @@ namespace AuthServer.Host.Migrations TenantId = table.Column(nullable: true), ChangeTime = table.Column(nullable: false), ChangeType = table.Column(nullable: false), + EntityTenantId = table.Column(nullable: true), EntityId = table.Column(maxLength: 128, nullable: false), EntityTypeFullName = table.Column(maxLength: 128, nullable: false), ExtraProperties = table.Column(nullable: true) @@ -542,7 +568,7 @@ namespace AuthServer.Host.Migrations columns: table => new { ClientId = table.Column(nullable: false), - PostLogoutRedirectUri = table.Column(maxLength: 2000, nullable: false) + PostLogoutRedirectUri = table.Column(maxLength: 200, nullable: false) }, constraints: table => { @@ -560,8 +586,8 @@ namespace AuthServer.Host.Migrations columns: table => new { ClientId = table.Column(nullable: false), - Key = table.Column(maxLength: 250, nullable: false), - Value = table.Column(maxLength: 2000, nullable: false) + Key = table.Column(maxLength: 64, nullable: false), + Value = table.Column(maxLength: 128, nullable: false) }, constraints: table => { @@ -579,7 +605,7 @@ namespace AuthServer.Host.Migrations columns: table => new { ClientId = table.Column(nullable: false), - RedirectUri = table.Column(maxLength: 2000, nullable: false) + RedirectUri = table.Column(maxLength: 200, nullable: false) }, constraints: table => { diff --git a/samples/MicroserviceDemo/databases/MsDemo_Identity.zip b/samples/MicroserviceDemo/databases/MsDemo_Identity.zip index f31c9e4f3d..0cba5df02d 100644 Binary files a/samples/MicroserviceDemo/databases/MsDemo_Identity.zip and b/samples/MicroserviceDemo/databases/MsDemo_Identity.zip differ diff --git a/samples/MicroserviceDemo/databases/MsDemo_ProductManagement.zip b/samples/MicroserviceDemo/databases/MsDemo_ProductManagement.zip index 28ed35d8ca..2e722f4eda 100644 Binary files a/samples/MicroserviceDemo/databases/MsDemo_ProductManagement.zip and b/samples/MicroserviceDemo/databases/MsDemo_ProductManagement.zip differ diff --git a/samples/MicroserviceDemo/databases/restore/entrypoint.sh b/samples/MicroserviceDemo/databases/restore/entrypoint.sh index 91de230f78..6a13650271 100644 --- a/samples/MicroserviceDemo/databases/restore/entrypoint.sh +++ b/samples/MicroserviceDemo/databases/restore/entrypoint.sh @@ -25,7 +25,7 @@ done /opt/mssql-tools/bin/sqlcmd \ -S sqlserver -U SA -P $SA_PASSWORD \ -d MsDemo_Identity \ - -Q 'UPDATE IdentityServerClientRedirectUris SET RedirectUri = "http://localhost:51512/signin-oidc" WHERE ClientId = "00265494-2D70-9615-4BD0-39EB2AF3CD33" - UPDATE IdentityServerClientRedirectUris SET RedirectUri = "http://localhost:51513/signin-oidc" WHERE ClientId = "10265494-2D70-9615-4BD0-39EB2AF3CD33" - UPDATE IdentityServerClientPostLogoutRedirectUris SET PostLogoutRedirectUri = "http://localhost:51512/signout-callback-oidc" WHERE ClientId = "00265494-2D70-9615-4BD0-39EB2AF3CD33" - UPDATE IdentityServerClientPostLogoutRedirectUris SET PostLogoutRedirectUri = "http://localhost:51513/signout-callback-oidc" WHERE ClientId = "10265494-2D70-9615-4BD0-39EB2AF3CD33"' \ No newline at end of file + -Q 'UPDATE IdentityServerClientRedirectUris SET RedirectUri = "http://localhost:51512/signin-oidc" WHERE RedirectUri = "http://localhost:51954/signin-oidc" + UPDATE IdentityServerClientRedirectUris SET RedirectUri = "http://localhost:51513/signin-oidc" WHERE RedirectUri = "http://localhost:53435/signin-oidc" + UPDATE IdentityServerClientPostLogoutRedirectUris SET PostLogoutRedirectUri = "http://localhost:51512/signout-callback-oidc" WHERE PostLogoutRedirectUri = "http://localhost:51954/signout-callback-oidc" + UPDATE IdentityServerClientPostLogoutRedirectUris SET PostLogoutRedirectUri = "http://localhost:51513/signout-callback-oidc" WHERE PostLogoutRedirectUri = "http://localhost:53435/signout-callback-oidc"' \ No newline at end of file diff --git a/samples/MicroserviceDemo/microservices/BloggingService.Host/BlogServiceDataSeeder.cs b/samples/MicroserviceDemo/microservices/BloggingService.Host/BlogServiceDataSeeder.cs new file mode 100644 index 0000000000..fec44e25e5 --- /dev/null +++ b/samples/MicroserviceDemo/microservices/BloggingService.Host/BlogServiceDataSeeder.cs @@ -0,0 +1,216 @@ +using System.Threading.Tasks; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; +using Volo.Blogging; +using Volo.Blogging.Blogs; +using Volo.Blogging.Posts; + +namespace BloggingService.Host +{ + public class BlogServiceDataSeeder : IDataSeedContributor, ITransientDependency + { + private readonly IBlogRepository _blogRepository; + private readonly IPostRepository _postRepository; + private readonly IGuidGenerator _guidGenerator; + private readonly IPermissionDataSeeder _permissionDataSeeder; + + public BlogServiceDataSeeder( + IBlogRepository blogRepository, + IGuidGenerator guidGenerator, + IPostRepository postRepository, + IPermissionDataSeeder permissionDataSeeder) + { + _blogRepository = blogRepository; + _guidGenerator = guidGenerator; + _postRepository = postRepository; + _permissionDataSeeder = permissionDataSeeder; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await CreateBlogPostsAsync(); + await GrantAdminPermissionsAsync(); + } + + private async Task GrantAdminPermissionsAsync() + { + await _permissionDataSeeder.SeedAsync( + RolePermissionValueProvider.ProviderName, + "admin", + BloggingPermissions.GetAll() + ); + } + + private async Task CreateBlogPostsAsync() + { + if (await _blogRepository.GetCountAsync() > 0) + { + return; + } + + var abpBlog = await _blogRepository.InsertAsync( + new Blog( + _guidGenerator.Create(), + "ABP", + "abp" + ) + ); + + await _postRepository.InsertAsync( + new Post( + _guidGenerator.Create(), + abpBlog.Id, + "Introduction to ABP vNext", + "/api/blogging/files/www/100d4c0445cbf55f687339ec8e656abb.jpg", + "introduction-to-abp-vnext" + ) + { + Content = @"### Introduction +For a while, we were working to design a new major version of the ASP.NET Boilerplate framework. Now, it’s time to share it with the community. We are too excited and we believe that you are too. + +#### Naming +The name of the framework remains same, except we will call it only as “ABP” instead of “ASP.NET Boilerplate”. Because, the “boilerplate” word leads to misunderstandings and does not reflect that it is a framework (instead of some boilerplate code). We continue to use the “ABP” name since it’s the successor of the current ASP.NET Boilerplate framework, except it’s a rewrite. + +### How To Start + +We have created a startup template. You can just create a new project from https://abp.io/Templates and start your development. For more information, visit [abp.io](https://abp.io). + +### Why A Complete Rewrite? +Why we spent our valuable time to rewrite it from scratch instead of incremental changes and improvements. Why? + +#### ASP.NET Core +When we first introduced the ABP framework, it was 2013 (5 years ago)! There was no .Net Core & ASP.NET Core and there was no Angular2+. They were all developed from scratch after ABP’s release. + +ASP.NET Core introduced many built-in solutions (extension libraries) for dependency injection, logging, caching, localization, configuration and so on. These are actually independent from the ASP.NET Core and usable for any type of application. + +We were using 3rd-party libraries and our own solutions for these requirements. We immediately integrated to ASP.NET Core features once they were released. But that was an integration, instead of building the ABP framework on top of these extension libraries. For instance, current ASP.NET Boilerplate still depends on Castle Windsor for dependency injection even it’s integrated to ASP.NET Core’s DI system. + +We wanted to depend on these new extension libraries instead of 3rd-party and custom solutions and this changes fundamental structures of the framework. + +#### Self Modularization +While current ABP is already modular itself and consists of dozens of packages, we still wanted to split the functionalities to more fine grained nuget packages. + +For example, the core Abp package contains many features like DDD classes, auditing, authorization, background jobs, event bus, json serialization, localization, multi-tenancy, threading, timing and so on… We wanted to split all these functionality into their own packages and make them optional. + +#### Dropping Support for Legacy Technologies +Yes, the new ABP framework will not support ASP.NET MVC 5.x, Entity Framework 6.x and other legacy technologies. + +These legacy technologies are maintained by Microsoft but no new feature is being added. So, if you are still using these technologies, you can continue with the current ASP.NET Boilerplate framework. We will continue to maintain it, fix bugs and will add new features. + +Dropping support for these legacy libraries will improve our development speed (since we currently duplicate our work for some features) and concentrate on the .Net Core & ASP.NET Core. + +The new ABP framework will be based on .net standard. So, it’s still possible to use full .net framework or .net core with the new ABP framework. + +### Goals +We have learnt much from the community and had experience of developing the current ASP.NET Boilerplate framework. New ABP framework has significant and exciting goals. + +#### Application Modularity +The first goal is to provide a good infrastructure to develop application modules. We think a module as a set of application features with its own database, its own entities, services, APIs, UI pages, components and so on. + +We will create a module market which will contain free & paid application modules. You will also be able to publish your own modules on the market. More information will be coming soon. + +#### Microservices +We are designing the new ABP framework to be ready to develop microservices and communicate them to each other. + +We are designing application modules so that they can be separately deployable as microservices or they can be embedded into a monolithic application. + +We are creating a [specification / best practice documentation](https://github.com/abpframework/abp/blob/master/docs/Best-Practices/Index.md) for that. + +#### Theming and UI Composition +The new ABP framework will provide a theming infrastructure based on the latest Twitter Bootstrap 4.x. We developed a basic theme that only uses the plain Bootstrap 4.x styling. It’s free and open source. We are also developing premium & paid themes. + +UI Composition is one of the main goals. For this purpose, theme system will provide menus, toolbars and other extensible areas to allow other modules to contribute. + +#### ORM/Database Independence & MongoDB Integration +While current ASP.NET Boilerplate framework has implemented the repository pattern for ORM/Database independence, identity integration module (Abp.Zero* packages) has never worked well with ORMs other than EF. + +With the new ABP framework, the ultimate goal is completely abstract underlying data store system and develop modules EF Core independent. + +We embrace the MongoDB as a first-class citizen database and designing entities and repositories without any relational database or ORM assumption. + +#### More Extensibility +New ABP framework provides more extensibility points and overriding capabilities for built-in services. + +### Some Features +In this section, I will introduce some exciting new features of the new ABP framework. + +#### Bootstrap Tag Helpers +We are creating a library to wrap twitter bootstrap 4.x elements/components into tag helpers... + +#### Virtual File System +Virtual File System allows you to embed views, pages, components, javascript, css, json and other type of files into your module assembly / package(dll) and use your assembly in any application.Your virtual files behave just like physical files in the containing application with complete ASP.NET Core Integration. + +Read more [about the Virtual File System](https://medium.com/volosoft/designing-modularity-on-asp-net-core-virtual-file-system-2dd2cc2078bd) and see [its documentation](https://github.com/abpframework/abp/blob/master/docs/Virtual-File-System.md). + +#### Dynamic Bundling & Minification System +Dynamic bundling & minification system works on the virtual file system and allows modules to create, modify and contribute to bundles in a modular, dynamic and powerful way. + +This code creates a new style bundle on the fly by including bootstrap(and its dependencies if there are) and two more css files.These files are bundled & minified on production environment, but will be added individually on the development environment. + +See [the documentation](https://github.com/abpframework/abp/blob/master/docs/AspNetCore/Bundling-Minification.md) for more. + +#### Distributed Event Bus +In current ABP, there is an IEventBus service to trigger and handle events inside the application.In addition to this local event bus, we are creating a distributed event bus abstraction (and RabbitMQ integration) to implement distributed messaging patterns. + +#### Dynamic C# HTTP Client Proxies +ABP was already creating dynamic javascript proxies for all HTTP APIs.This feature does also exists in the new ABP framework.In addition, it now can create dynamic C# proxies for all HTTP APIs. + +### Future Works +All the stuffs mentioned above are already in development.However, we haven’t started some concepts yet. + +#### Single Page Applications +We designed the new framework SPAs in mind.However, we haven’t tried it with any SPA framework and we haven’t prepared a startup template for it yet. + +### What About ASP.NET Boilerplate (Current Version) and ASP.NET Zero? + +We have dedicated development & support teams actively working on the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) and [ASP.NET Zero](https://aspnetzero.com/) projects. These projects have a big community and we are also getting contributions from the community. + + +We will continue to make enhancements, add new features and fix bugs for these projects for a long time.So, you can safely continue to use them. + +### Is New ABP Production Ready? +No, not yet. Our first goal is to make fundamental features stable then incrementally complete other features. + + +We will frequently release new versions and every new version will probably have breaking changes.We will write breaking changes on the release notes. + + +We currently define it experimental.But we hope that this will not continue for a long time. We can not declare a date yet, follow our releases. + +### Packages & Versioning +New ABP framework will start with v1.0 instead of following current ASP.NET Boilerplate's version to reflect the fact that it’s a rewrite. + + +We will frequently[release](https://github.com/abpframework/abp/releases) it. You can expect many breaking changes until v1.0. Starting with the v1.0, we will pay attention to not introduce breaking changes in 1.x releases. + + +Current ABP’s package names start with[Abp](https://www.nuget.org/packages/Abp) prefix (like Abp.EntityFrameworkCore). New package names start with [Volo.Abp](https://www.nuget.org/packages/Volo.Abp.Core) prefix (like Volo.Abp.EntityFrameworkCore). + +### Which One Should I Start With? +If you are creating a new project, we suggest to continue with the current ASP.NET Boilerplate framework since it’s very mature, feature rich and production ready. + +If you are open to breaking changes and want to have experience on the new framework, you can start with the new ABP.We don’t suggest it yet for projects with close deadlines and go to the production in a short term. + +### Contribution +Just like the current ABP framework, the new framework is available for your contribution. + +* You can send pull requests for code or documentation. +* You can write blog posts or tutorials about it. +* You can try it and share your experiences. +* You can create enhancement and feature requests. +* You can report bugs and other issues. + +### Communication / Links +*** Official web site**: [abp.io](https://abp.io) +* **Github**: [github.com/abpframework](https://github.com/abpframework) +* **Twitter**: [@abpframework](https://twitter.com/abpframework)" + } + ); + } + } +} diff --git a/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingServiceHostModule.cs b/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingServiceHostModule.cs index ac7af17fd4..4ec47d8f4f 100644 --- a/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingServiceHostModule.cs +++ b/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingServiceHostModule.cs @@ -10,6 +10,7 @@ using Volo.Abp; using Volo.Abp.Auditing; using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.Autofac; +using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.SqlServer; using Volo.Abp.EventBus.RabbitMq; @@ -119,27 +120,16 @@ namespace BloggingService.Host app.UseAuditing(); app.UseMvcWithDefaultRouteAndArea(); - AsyncHelper.RunSync(() => SeedDataAsync(context.ServiceProvider)); - } - - public async Task SeedDataAsync(IServiceProvider serviceProvider) - { - using (var scope = serviceProvider.CreateScope()) + //TODO: Problem on a clustered environment + AsyncHelper.RunSync(async () => { - var blogRepository = scope.ServiceProvider.GetRequiredService(); - var guidGenerator = scope.ServiceProvider.GetRequiredService(); - - if (await blogRepository.FindByShortNameAsync("abp") == null) + using (var scope = context.ServiceProvider.CreateScope()) { - await blogRepository.InsertAsync( - new Blog( - guidGenerator.Create(), - "ABP Blog", - "abp" - ) - ); + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); } - } + }); } } } diff --git a/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/6b32831845a8807aa8b839ed0f28182c.jpg b/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/6b32831845a8807aa8b839ed0f28182c.jpg new file mode 100644 index 0000000000..d0748ce2e4 Binary files /dev/null and b/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/6b32831845a8807aa8b839ed0f28182c.jpg differ diff --git a/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/90974f3f1edb4ab0a10cf9759fd5f9ae.png b/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/90974f3f1edb4ab0a10cf9759fd5f9ae.png deleted file mode 100644 index 17aea07098..0000000000 Binary files a/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/90974f3f1edb4ab0a10cf9759fd5f9ae.png and /dev/null differ diff --git a/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/ec882345a403be325bc539ebda211e79.jpg b/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/ec882345a403be325bc539ebda211e79.jpg deleted file mode 100644 index be89ceb73d..0000000000 Binary files a/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/ec882345a403be325bc539ebda211e79.jpg and /dev/null differ diff --git a/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190121115908_Initial.Designer.cs b/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190121115908_Initial.Designer.cs deleted file mode 100644 index 4e613b0da7..0000000000 --- a/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190121115908_Initial.Designer.cs +++ /dev/null @@ -1,71 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using ProductService.Host.EntityFrameworkCore; - -namespace ProductService.Host.Migrations -{ - [DbContext(typeof(ProductServiceMigrationDbContext))] - [Migration("20190121115908_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("ProductManagement.Product", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Code") - .IsRequired() - .HasMaxLength(32); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreationTime") - .HasColumnName("CreationTime"); - - b.Property("CreatorId") - .HasColumnName("CreatorId"); - - b.Property("ExtraProperties") - .HasColumnName("ExtraProperties"); - - b.Property("LastModificationTime") - .HasColumnName("LastModificationTime"); - - b.Property("LastModifierId") - .HasColumnName("LastModifierId"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256); - - b.Property("Price"); - - b.Property("StockCount"); - - b.HasKey("Id"); - - b.HasIndex("Code"); - - b.HasIndex("Name"); - - b.ToTable("PmProducts"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190307065413_Added_ImageName_To_Product.cs b/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190307065413_Added_ImageName_To_Product.cs deleted file mode 100644 index 082bf9bf52..0000000000 --- a/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190307065413_Added_ImageName_To_Product.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace ProductService.Host.Migrations -{ - public partial class Added_ImageName_To_Product : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "ImageName", - table: "PmProducts", - maxLength: 128, - nullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "ImageName", - table: "PmProducts"); - } - } -} diff --git a/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190307065413_Added_ImageName_To_Product.Designer.cs b/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190408114353_Initial.Designer.cs similarity index 95% rename from samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190307065413_Added_ImageName_To_Product.Designer.cs rename to samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190408114353_Initial.Designer.cs index 7106d08d50..d0c67347eb 100644 --- a/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190307065413_Added_ImageName_To_Product.Designer.cs +++ b/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190408114353_Initial.Designer.cs @@ -10,8 +10,8 @@ using ProductService.Host.EntityFrameworkCore; namespace ProductService.Host.Migrations { [DbContext(typeof(ProductServiceMigrationDbContext))] - [Migration("20190307065413_Added_ImageName_To_Product")] - partial class Added_ImageName_To_Product + [Migration("20190408114353_Initial")] + partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { diff --git a/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190121115908_Initial.cs b/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190408114353_Initial.cs similarity index 95% rename from samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190121115908_Initial.cs rename to samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190408114353_Initial.cs index f66fb70eca..5ee9f460ae 100644 --- a/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190121115908_Initial.cs +++ b/samples/MicroserviceDemo/microservices/ProductService.Host/Migrations/20190408114353_Initial.cs @@ -21,7 +21,8 @@ namespace ProductService.Host.Migrations Code = table.Column(maxLength: 32, nullable: false), Name = table.Column(maxLength: 256, nullable: false), Price = table.Column(nullable: false), - StockCount = table.Column(nullable: false) + StockCount = table.Column(nullable: false), + ImageName = table.Column(maxLength: 128, nullable: true) }, constraints: table => { diff --git a/samples/MicroserviceDemo/microservices/ProductService.Host/ProductServiceDataSeeder.cs b/samples/MicroserviceDemo/microservices/ProductService.Host/ProductServiceDataSeeder.cs new file mode 100644 index 0000000000..1251719315 --- /dev/null +++ b/samples/MicroserviceDemo/microservices/ProductService.Host/ProductServiceDataSeeder.cs @@ -0,0 +1,110 @@ +using System; +using System.Threading.Tasks; +using ProductManagement; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Uow; + +namespace ProductService.Host +{ + public class ProductServiceDataSeeder : IDataSeedContributor, ITransientDependency + { + private readonly ProductManager _productManager; + private readonly IRepository _productRepository; + + public ProductServiceDataSeeder( + IRepository productRepository, + ProductManager productManager) + { + _productRepository = productRepository; + _productManager = productManager; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + await AddProductsAsync(); + } + + private async Task AddProductsAsync() + { + if (await _productRepository.GetCountAsync() > 0) + { + return; + } + + await _productManager.CreateAsync( + "ABP04918", + "Lego Star Wars - 75059 Sandcrawler UCS", + 999, + 42, + "lego.jpg" + ); + + await _productManager.CreateAsync( + "ABP23849", + "Nikon AF-S 50mm f/1.8 G Lens", + 1499, + 56, + "nikon.jpg" + ); + + await _productManager.CreateAsync( + "ABP82731", + "Beats Solo3 Wireless On-Ear Headphone", + 97, + 20, + "beats.jpg" + ); + + await _productManager.CreateAsync( + "ABP12322", + "Rampage Sn-Rw2 Gamer Headphone", + 654, + 42, + "rampage.jpg" + ); + + await _productManager.CreateAsync( + "ABP00291", + "Asus Transformer Book T300CHI-FH011H", + 1249, + 3, + "asus.jpg" + ); + + await _productManager.CreateAsync( + "ABP02918", + "OKI C332DN Dublex + Network A4 Laser Printer", + 215, + 6, + "oki.jpg" + ); + + await _productManager.CreateAsync( + "ABP11121", + "Bluecat Rd810 Mini Led", + 449, + 13, + "bluecat.jpg" + ); + + await _productManager.CreateAsync( + "ABP44432", + "Sunny 55\" TV 4K Ultra HD Curved Smart Led TV", + 2249, + 1, + "sunny.jpg" + ); + + await _productManager.CreateAsync( + "ABP37182", + "Sony Playstation 4 Slim 500 GB (PAL)", + 699, + 120, + "playstation.jpg" + ); + } + } +} diff --git a/samples/MicroserviceDemo/microservices/ProductService.Host/ProductServiceHostModule.cs b/samples/MicroserviceDemo/microservices/ProductService.Host/ProductServiceHostModule.cs index 6e08ad8e93..465495edae 100644 --- a/samples/MicroserviceDemo/microservices/ProductService.Host/ProductServiceHostModule.cs +++ b/samples/MicroserviceDemo/microservices/ProductService.Host/ProductServiceHostModule.cs @@ -9,6 +9,7 @@ using Volo.Abp; using Volo.Abp.Auditing; using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.Autofac; +using Volo.Abp.Data; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.SqlServer; using Volo.Abp.EventBus.RabbitMq; @@ -17,6 +18,7 @@ using Volo.Abp.Modularity; using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.Security.Claims; using Volo.Abp.SettingManagement.EntityFrameworkCore; +using Volo.Abp.Threading; namespace ProductService.Host { @@ -101,6 +103,17 @@ namespace ProductService.Host }); app.UseAuditing(); app.UseMvcWithDefaultRouteAndArea(); + + //TODO: Problem on a clustered environment + AsyncHelper.RunSync(async () => + { + using (var scope = context.ServiceProvider.CreateScope()) + { + await scope.ServiceProvider + .GetRequiredService() + .SeedAsync(); + } + }); } } } diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/DemoAppModule.cs b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/DemoAppModule.cs index 4bf1ab94f8..442ffa7d07 100644 --- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/DemoAppModule.cs +++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/DemoAppModule.cs @@ -115,7 +115,6 @@ namespace MyCompanyName.MyProjectName.DemoApp app.UseAbpRequestLocalization(); app.UseAuditing(); - app.UseMvcWithDefaultRouteAndArea(); using (var scope = context.ServiceProvider.CreateScope()) diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.Designer.cs b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.Designer.cs similarity index 99% rename from templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.Designer.cs rename to templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.Designer.cs index 91a4c096ff..9189ba1c41 100644 --- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.Designer.cs +++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.Designer.cs @@ -10,7 +10,7 @@ using MyCompanyName.MyProjectName.DemoApp; namespace MyCompanyName.MyProjectName.DemoApp.Migrations { [DbContext(typeof(DemoAppDbContext))] - [Migration("20190320125012_Initial")] + [Migration("20190410095748_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.cs b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.cs similarity index 100% rename from templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.cs rename to templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.cs diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj index 041d6cf9ce..4e019c6d9b 100644 --- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj +++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj @@ -35,8 +35,4 @@ - - - - diff --git a/templates/service/docker-compose.override.yml b/templates/service/docker-compose.override.yml index 6fb4c52fa2..8d583bacd7 100644 --- a/templates/service/docker-compose.override.yml +++ b/templates/service/docker-compose.override.yml @@ -6,10 +6,11 @@ services: - SA_PASSWORD=yourStrong(!)Password - ACCEPT_EULA=Y ports: - - "1433:1433" + - "51599:1433" identity-server: environment: + - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionStrings__Default=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=MyProjectName_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false ports: @@ -17,10 +18,12 @@ services: my-project-name: environment: + - ASPNETCORE_URLS=http://0.0.0.0:80 - ConnectionStrings__Default=Server=sqlserver;Database=MyProjectName_ModuleDb;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - ConnectionStrings__AbpSettingManagement=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - ConnectionStrings__AbpPermissionManagement=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - ConnectionStrings__AbpAuditLogging=Server=sqlserver;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=MyProjectName_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false + - AuthServer__Authority=http://identity-server ports: - "51601:80" \ No newline at end of file diff --git a/templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.Designer.cs b/templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.Designer.cs similarity index 93% rename from templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.Designer.cs rename to templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.Designer.cs index 8ef18c7e12..edb0c5cedf 100644 --- a/templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.Designer.cs +++ b/templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.Designer.cs @@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace IdentityServerHost.Migrations { [DbContext(typeof(DemoAppDbContext))] - [Migration("20190320142333_Initial")] + [Migration("20190410095119_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -84,6 +84,8 @@ namespace IdentityServerHost.Migrations b.Property("TenantId") .HasColumnName("TenantId"); + b.Property("TenantName"); + b.Property("Url") .HasColumnName("Url") .HasMaxLength(256); @@ -163,6 +165,8 @@ namespace IdentityServerHost.Migrations .HasColumnName("EntityId") .HasMaxLength(128); + b.Property("EntityTenantId"); + b.Property("EntityTypeFullName") .IsRequired() .HasColumnName("EntityTypeFullName") @@ -522,6 +526,18 @@ namespace IdentityServerHost.Migrations b.Property("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + b.Property("Description") .HasMaxLength(1000); @@ -533,6 +549,17 @@ namespace IdentityServerHost.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -660,6 +687,18 @@ namespace IdentityServerHost.Migrations b.Property("ConsentLifetime"); + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + b.Property("Description") .HasMaxLength(1000); @@ -679,6 +718,17 @@ namespace IdentityServerHost.Migrations b.Property("IncludeJwtId"); + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + b.Property("LogoUri") .HasMaxLength(300); @@ -890,6 +940,18 @@ namespace IdentityServerHost.Migrations b.Property("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + b.Property("Description") .HasMaxLength(1000); @@ -903,6 +965,17 @@ namespace IdentityServerHost.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + b.Property("Name") .IsRequired() .HasMaxLength(200); diff --git a/templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.cs b/templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.cs similarity index 96% rename from templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.cs rename to templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.cs index 88588fb970..b90275e883 100644 --- a/templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.cs +++ b/templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.cs @@ -18,6 +18,7 @@ namespace IdentityServerHost.Migrations UserId = table.Column(nullable: true), UserName = table.Column(maxLength: 256, nullable: true), TenantId = table.Column(nullable: true), + TenantName = table.Column(nullable: true), ImpersonatorUserId = table.Column(nullable: true), ImpersonatorTenantId = table.Column(nullable: true), ExecutionTime = table.Column(nullable: false), @@ -150,6 +151,13 @@ namespace IdentityServerHost.Migrations Id = table.Column(nullable: false), ExtraProperties = table.Column(nullable: true), ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), Name = table.Column(maxLength: 200, nullable: false), DisplayName = table.Column(maxLength: 200, nullable: true), Description = table.Column(maxLength: 1000, nullable: true), @@ -167,6 +175,13 @@ namespace IdentityServerHost.Migrations Id = table.Column(nullable: false), ExtraProperties = table.Column(nullable: true), ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), ClientId = table.Column(maxLength: 200, nullable: false), ClientName = table.Column(maxLength: 200, nullable: true), Description = table.Column(maxLength: 1000, nullable: true), @@ -214,6 +229,13 @@ namespace IdentityServerHost.Migrations Id = table.Column(nullable: false), ExtraProperties = table.Column(nullable: true), ConcurrencyStamp = table.Column(nullable: true), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + IsDeleted = table.Column(nullable: false, defaultValue: false), + DeleterId = table.Column(nullable: true), + DeletionTime = table.Column(nullable: true), Name = table.Column(maxLength: 200, nullable: false), DisplayName = table.Column(maxLength: 200, nullable: true), Description = table.Column(maxLength: 1000, nullable: true), @@ -281,6 +303,7 @@ namespace IdentityServerHost.Migrations TenantId = table.Column(nullable: true), ChangeTime = table.Column(nullable: false), ChangeType = table.Column(nullable: false), + EntityTenantId = table.Column(nullable: true), EntityId = table.Column(maxLength: 128, nullable: false), EntityTypeFullName = table.Column(maxLength: 128, nullable: false), ExtraProperties = table.Column(nullable: true) diff --git a/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs b/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs index 1aec48ea05..3b63d152aa 100644 --- a/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs +++ b/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs @@ -82,6 +82,8 @@ namespace IdentityServerHost.Migrations b.Property("TenantId") .HasColumnName("TenantId"); + b.Property("TenantName"); + b.Property("Url") .HasColumnName("Url") .HasMaxLength(256); @@ -161,6 +163,8 @@ namespace IdentityServerHost.Migrations .HasColumnName("EntityId") .HasMaxLength(128); + b.Property("EntityTenantId"); + b.Property("EntityTypeFullName") .IsRequired() .HasColumnName("EntityTypeFullName") @@ -520,6 +524,18 @@ namespace IdentityServerHost.Migrations b.Property("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + b.Property("Description") .HasMaxLength(1000); @@ -531,6 +547,17 @@ namespace IdentityServerHost.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -658,6 +685,18 @@ namespace IdentityServerHost.Migrations b.Property("ConsentLifetime"); + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + b.Property("Description") .HasMaxLength(1000); @@ -677,6 +716,17 @@ namespace IdentityServerHost.Migrations b.Property("IncludeJwtId"); + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + b.Property("LogoUri") .HasMaxLength(300); @@ -888,6 +938,18 @@ namespace IdentityServerHost.Migrations b.Property("ConcurrencyStamp"); + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + b.Property("Description") .HasMaxLength(1000); @@ -901,6 +963,17 @@ namespace IdentityServerHost.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + b.Property("Name") .IsRequired() .HasMaxLength(200); diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/DemoAppModule.cs b/templates/service/host/MyCompanyName.MyProjectName.Host/DemoAppModule.cs index f9a27076af..c02be99661 100644 --- a/templates/service/host/MyCompanyName.MyProjectName.Host/DemoAppModule.cs +++ b/templates/service/host/MyCompanyName.MyProjectName.Host/DemoAppModule.cs @@ -81,7 +81,7 @@ namespace MyCompanyName.MyProjectName.Host context.Services.AddAuthentication("Bearer") .AddIdentityServerAuthentication(options => { - options.Authority = "http://localhost:61517"; + options.Authority = configuration["AuthServer:Authority"]; options.RequireHttpsMetadata = false; options.ApiName = "api1"; diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.Designer.cs b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.Designer.cs similarity index 98% rename from templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.Designer.cs rename to templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.Designer.cs index 423eb1cb0a..4803948516 100644 --- a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.Designer.cs +++ b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.Designer.cs @@ -10,7 +10,7 @@ using MyCompanyName.MyProjectName.Host; namespace MyCompanyName.MyProjectName.Host.Migrations { [DbContext(typeof(DemoAppDbContext))] - [Migration("20190320142412_Initial")] + [Migration("20190410095222_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -84,6 +84,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations b.Property("TenantId") .HasColumnName("TenantId"); + b.Property("TenantName"); + b.Property("Url") .HasColumnName("Url") .HasMaxLength(256); @@ -163,6 +165,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasColumnName("EntityId") .HasMaxLength(128); + b.Property("EntityTenantId"); + b.Property("EntityTypeFullName") .IsRequired() .HasColumnName("EntityTypeFullName") diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.cs b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.cs similarity index 98% rename from templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.cs rename to templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.cs index b2074c3513..ecef8c8f9a 100644 --- a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.cs +++ b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.cs @@ -18,6 +18,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations UserId = table.Column(nullable: true), UserName = table.Column(maxLength: 256, nullable: true), TenantId = table.Column(nullable: true), + TenantName = table.Column(nullable: true), ImpersonatorUserId = table.Column(nullable: true), ImpersonatorTenantId = table.Column(nullable: true), ExecutionTime = table.Column(nullable: false), @@ -102,6 +103,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations TenantId = table.Column(nullable: true), ChangeTime = table.Column(nullable: false), ChangeType = table.Column(nullable: false), + EntityTenantId = table.Column(nullable: true), EntityId = table.Column(maxLength: 128, nullable: false), EntityTypeFullName = table.Column(maxLength: 128, nullable: false), ExtraProperties = table.Column(nullable: true) diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/DemoAppDbContextModelSnapshot.cs b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/DemoAppDbContextModelSnapshot.cs index ffe92c9c59..b6682a0c1c 100644 --- a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/DemoAppDbContextModelSnapshot.cs +++ b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/DemoAppDbContextModelSnapshot.cs @@ -82,6 +82,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations b.Property("TenantId") .HasColumnName("TenantId"); + b.Property("TenantName"); + b.Property("Url") .HasColumnName("Url") .HasMaxLength(256); @@ -161,6 +163,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations .HasColumnName("EntityId") .HasMaxLength(128); + b.Property("EntityTenantId"); + b.Property("EntityTypeFullName") .IsRequired() .HasColumnName("EntityTypeFullName") diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/appsettings.json b/templates/service/host/MyCompanyName.MyProjectName.Host/appsettings.json index a09353bfef..3f4cd2c43c 100644 --- a/templates/service/host/MyCompanyName.MyProjectName.Host/appsettings.json +++ b/templates/service/host/MyCompanyName.MyProjectName.Host/appsettings.json @@ -5,7 +5,11 @@ "AbpSettingManagement": "Server=localhost;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true", "AbpPermissionManagement": "Server=localhost;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true", "AbpAuditLogging": "Server=localhost;Database=MyProjectName_Identity;Trusted_Connection=True;MultipleActiveResultSets=true", - + "SqlServerCache": "Server=localhost;Database=MyProjectName_Cache;Trusted_Connection=True;MultipleActiveResultSets=true" - } + }, + + "AuthServer": { + "Authority": "http://localhost:61517" + } } \ No newline at end of file