├── POC └── nyw.microservice │ ├── Nyw.Portal │ ├── wwwroot │ │ ├── js │ │ │ ├── site.min.js │ │ │ └── site.js │ │ ├── favicon.ico │ │ ├── lib │ │ │ ├── bootstrap │ │ │ │ ├── dist │ │ │ │ │ ├── fonts │ │ │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ │ │ └── js │ │ │ │ │ │ └── npm.js │ │ │ │ ├── .bower.json │ │ │ │ └── LICENSE │ │ │ ├── jquery │ │ │ │ ├── .bower.json │ │ │ │ └── LICENSE.txt │ │ │ ├── jquery-validation │ │ │ │ ├── .bower.json │ │ │ │ ├── LICENSE.md │ │ │ │ └── dist │ │ │ │ │ ├── additional-methods.min.js │ │ │ │ │ └── jquery.validate.min.js │ │ │ └── jquery-validation-unobtrusive │ │ │ │ ├── .bower.json │ │ │ │ └── jquery.validate.unobtrusive.min.js │ │ ├── css │ │ │ ├── site.min.css │ │ │ └── site.css │ │ └── images │ │ │ ├── banner2.svg │ │ │ ├── banner1.svg │ │ │ ├── banner3.svg │ │ │ └── banner4.svg │ ├── Views │ │ ├── _ViewStart.cshtml │ │ ├── _ViewImports.cshtml │ │ ├── Home │ │ │ ├── About.cshtml │ │ │ ├── Contact.cshtml │ │ │ └── Index.cshtml │ │ ├── Redis │ │ │ └── Index.cshtml │ │ └── Shared │ │ │ ├── Error.cshtml │ │ │ ├── _ValidationScriptsPartial.cshtml │ │ │ └── _Layout.cshtml │ ├── appsettings.json │ ├── appsettings.Development.json │ ├── Models │ │ └── ErrorViewModel.cs │ ├── Nyw.Portal.csproj │ ├── bundleconfig.json │ ├── Program.cs │ ├── Controllers │ │ ├── HomeController.cs │ │ └── RedisController.cs │ └── Startup.cs │ ├── Nyw.Employee │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── Controllers │ │ ├── HealthController.cs │ │ └── ValuesController.cs │ ├── Models │ │ └── EmployeeModel.cs │ ├── Nyw.Employee.csproj │ ├── Program.cs │ └── Startup.cs │ ├── Nyw.Vendor │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── Controllers │ │ ├── HealthController.cs │ │ └── ValuesController.cs │ ├── Models │ │ └── VendorModel.cs │ ├── Nyw.Vendor.csproj │ ├── Program.cs │ └── Startup.cs │ ├── Nyw.ApiGateway │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── ocelot.global.json │ ├── Nyw.ApiGateway.csproj │ ├── Startup.cs │ ├── Administration │ │ └── OcelotBuilderExtensions.cs │ ├── Controllers │ │ ├── GlobalController.cs │ │ └── RerouteController.cs │ ├── nlog.config │ ├── Program.cs │ ├── ocelot.route.json │ └── ocelot.json │ ├── Nyw.IdentityServer │ ├── appsettings.json │ ├── appsettings.Development.json │ ├── User │ │ ├── UserModel.cs │ │ ├── IdentityServerBuilderExtensions.cs │ │ ├── UserResourceOwnerPasswordValidator.cs │ │ ├── UserProfileService.cs │ │ └── UserStore.cs │ ├── Nyw.IdentityServer.csproj │ ├── nlog.config │ ├── Program.cs │ └── Startup.cs │ ├── Nyw.AppExtensions │ ├── ServiceEntity.cs │ ├── Nyw.AppExtensions.csproj │ └── ConsulExtensions.cs │ ├── Nyw.ExchangeRateTask │ ├── Nyw.ExchangeRateTask.csproj │ └── Program.cs │ └── Nyw.Microservice.sln ├── DevOps ├── Jenkins │ ├── 1.png │ ├── 2.png │ └── Readme.md └── Sonarqube │ ├── 1.png │ ├── 2.png │ ├── docker-compose.yml │ └── README.md ├── Env ├── ELK │ ├── docker-elk-master.zip │ └── README.md ├── Redis │ ├── docker-compose.yml │ └── README.md └── Consul │ ├── README.md │ └── docker-compose.yml ├── .gitattributes ├── README.zh-CN.md ├── README.md ├── .gitignore └── LICENSE /POC/nyw.microservice/Nyw.Portal/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Write your JavaScript code. 2 | -------------------------------------------------------------------------------- /DevOps/Jenkins/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/DevOps/Jenkins/1.png -------------------------------------------------------------------------------- /DevOps/Jenkins/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/DevOps/Jenkins/2.png -------------------------------------------------------------------------------- /DevOps/Jenkins/Readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/DevOps/Jenkins/Readme.md -------------------------------------------------------------------------------- /DevOps/Sonarqube/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/DevOps/Sonarqube/1.png -------------------------------------------------------------------------------- /DevOps/Sonarqube/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/DevOps/Sonarqube/2.png -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Env/ELK/docker-elk-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/Env/ELK/docker-elk-master.zip -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/POC/nyw.microservice/Nyw.Portal/wwwroot/favicon.ico -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Nyw.Portal 2 | @using Nyw.Portal.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "About"; 3 | } 4 |

@ViewData["Title"]

5 |

@ViewData["Message"]

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Views/Redis/Index.cshtml: -------------------------------------------------------------------------------- 1 | 2 | @{ 3 | ViewData["Title"] = "Redis"; 4 | Layout = "~/Views/Shared/_Layout.cshtml"; 5 | } 6 | 7 |

缓存 - Redis Cache

8 | 9 |
10 |
-------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niyw/honeycomb/HEAD/POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /Env/Redis/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | redis: 4 | image: redis 5 | ports: 6 | - "6379:6379" 7 | command: redis-server --appendonly yes --bind 0.0.0.0 8 | networks: 9 | - webnet 10 | networks: 11 | webnet: -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Employee/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Vendor/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "ConnectionStrings": { 8 | "NsbAuthDB": "Data Source=(LocalDb)\\MSSQLLocalDB;database=NsbAuthDB;trusted_connection=yes;" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Nyw.Portal.Models 4 | { 5 | public class ErrorViewModel 6 | { 7 | public string RequestId { get; set; } 8 | 9 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 10 | } 11 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}.carousel-caption p{font-size:20px;line-height:1.4}.carousel-inner .item img[src$=".svg"]{width:100%}#qrCode{margin:15px}@media screen and (max-width:767px){.carousel-caption{display:none}} -------------------------------------------------------------------------------- /Env/Redis/README.md: -------------------------------------------------------------------------------- 1 | ## 环境说明 2 | - Windows 10 v1803 3 | - Docker Version 18.03.1-ce-win65 4 | 5 | ## 使用说明: 6 | - 打开命令行,切换到此目录 7 | - 运行命令: 8 | ```cmd 9 | docker-compose up 10 | ``` 11 | - 使用Psping执行psping localhost:6379,检查是否正常 12 | - 完成 13 | 14 | 15 | ## 其他 16 | - docker pull redis:4 17 | - 官方镜像默认无法从外部连接,所以才使用docker-compose 18 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Vendor/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ServicePort": 8810, 3 | "Logging": { 4 | "IncludeScopes": false, 5 | "Debug": { 6 | "LogLevel": { 7 | "Default": "Warning" 8 | } 9 | }, 10 | "Console": { 11 | "LogLevel": { 12 | "Default": "Warning" 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Employee/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ServicePort": 8820, 3 | "Logging": { 4 | "IncludeScopes": false, 5 | "Debug": { 6 | "LogLevel": { 7 | "Default": "Warning" 8 | } 9 | }, 10 | "Console": { 11 | "LogLevel": { 12 | "Default": "Warning" 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Env/Consul/README.md: -------------------------------------------------------------------------------- 1 | ## 环境说明 2 | - Windows 10 v1803 3 | - Docker Version 18.03.1-ce-win65 4 | 5 | ## 使用说明: 6 | - 打开命令行,切换到此目录 7 | - 运行命令: 8 | ```cmd 9 | docker-compose up 10 | ``` 11 | - 打开浏览器,访问http://localhost:8500 12 | - 完成 13 | 14 | ## 其他 15 | 原始文件参考:[docker-compose-cluster](https://github.com/hashicorp/consul/tree/master/demo/docker-compose-cluster) 16 | -------------------------------------------------------------------------------- /Env/ELK/README.md: -------------------------------------------------------------------------------- 1 | ## 环境说明 2 | - Windows 10 v1803 3 | - Docker Version 18.03.1-ce-win65 4 | 5 | ## 使用说明: 6 | - 打开命令行,切换到此目录 7 | - 运行命令: 8 | ```cmd 9 | docker-compose up 10 | ``` 11 | - 打开浏览器,访问http://localhost:5601 12 | - 完成 13 | 14 | 15 | ## 其他 16 | Elasticsearch地址:http://localhost:9200 17 | 原始文件参考:[docker-compose-cluster](https://github.com/deviantony/docker-elk) 18 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Vendor/Controllers/HealthController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Nyw.Vendor.Controllers { 4 | [Produces("application/json")] 5 | [Route("api/Health")] 6 | public class HealthController : Controller { 7 | [HttpGet] 8 | public IActionResult Get() => Ok( $"{Request.Host.Value} is ok"); 9 | } 10 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Employee/Controllers/HealthController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Nyw.Employee.Controllers { 4 | [Produces("application/json")] 5 | [Route("api/Health")] 6 | public class HealthController : Controller { 7 | [HttpGet] 8 | public IActionResult Get() => Ok($"{Request.Host.Value} is ok"); 9 | } 10 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | }, 10 | "ConnectionStrings": { 11 | "NsbAuthDB": "Data Source=(LocalDb)\\MSSQLLocalDB;database=NsbAuthDB;trusted_connection=yes;" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "Debug": { 5 | "LogLevel": { 6 | "Default": "Warning" 7 | } 8 | }, 9 | "Console": { 10 | "LogLevel": { 11 | "Default": "Warning" 12 | } 13 | }, 14 | "LogLevel": { 15 | "Default": "Trace", 16 | "Microsoft": "Information" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Vendor/Models/VendorModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Nyw.VendorService.Models { 7 | public class VendorModel { 8 | public int Id { get; set; } = 0; 9 | public string Name { get; set; } = "Microsoft"; 10 | public string Address { get; set; } = "上海市虹桥路3号"; 11 | public string Country { get; set; } = "CN"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.AppExtensions/ServiceEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Nyw.AppExtensions { 6 | public class ConsulServiceOptions { 7 | public string Address { get; set; } 8 | public int Port { get; set; } 9 | public string Service { get; set; } 10 | public string ConsulAddress { get; set; } = "localhost"; 11 | public int ConsulPort { get; set; } = 8500; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Employee/Models/EmployeeModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Nyw.EmployeeServices.Models 7 | { 8 | public class EmployeeModel 9 | { 10 | public int Id { get; set; } 11 | public string Alias { get; set; } 12 | public string Mail { get; set; } 13 | public string NameCN { get; set; } 14 | public string NameEN { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Contact"; 3 | } 4 |

@ViewData["Title"]

5 |

@ViewData["Message"]

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
18 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Nyw.Portal.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ExchangeRateTask/Nyw.ExchangeRateTask.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/User/UserModel.cs: -------------------------------------------------------------------------------- 1 | using IdentityModel; 2 | using System.Collections.Generic; 3 | using System.Security.Claims; 4 | 5 | namespace Nyw.IdentityServer.User { 6 | public class UserModel { 7 | public string SubjectId { get; set; } 8 | public string Username { get; set; } 9 | public string Password { get; set; } 10 | public string Usermail { get; set; } 11 | public string MobilePhone { get; set; } 12 | public bool IsActive { get; set; } = true; 13 | public ICollection Claims { get; set; } = new HashSet(new ClaimComparer()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "2.2.0", 16 | "_release": "2.2.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "2.2.0", 20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5" 21 | }, 22 | "_source": "git://github.com/jquery/jquery-dist.git", 23 | "_target": "2.2.0", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/ocelot.global.json: -------------------------------------------------------------------------------- 1 | { 2 | "GlobalConfiguration": { 3 | "ServiceDiscoveryProvider": { 4 | "Host": "localhost", 5 | "Port": 8500, 6 | "ConfigurationKey": "Nyw.Oceolot" 7 | }, 8 | "RateLimitOptions": { 9 | "ClientIdHeader": "ClientId", /*specifiy the header that should be used to identify clients*/ 10 | "QuotaExceededMessage": "Exceeded access quota limit", /*This value specifies the exceeded message*/ 11 | "RateLimitCounterPrefix": "ocelot", 12 | "DisableRateLimitHeaders": false, /*This value specifies whether X-Rate-Limit and Rety-After headers are disabled.*/ 13 | "HttpStatusCode": 429 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/bundleconfig.json: -------------------------------------------------------------------------------- 1 | // Configure bundling and minification for the project. 2 | // More info at https://go.microsoft.com/fwlink/?LinkId=808241 3 | [ 4 | { 5 | "outputFileName": "wwwroot/css/site.min.css", 6 | // An array of relative input file paths. Globbing patterns supported 7 | "inputFiles": [ 8 | "wwwroot/css/site.css" 9 | ] 10 | }, 11 | { 12 | "outputFileName": "wwwroot/js/site.min.js", 13 | "inputFiles": [ 14 | "wwwroot/js/site.js" 15 | ], 16 | // Optionally specify minification options 17 | "minify": { 18 | "enabled": true, 19 | "renameLocals": true 20 | }, 21 | // Optionally generate .map file 22 | "sourceMap": false 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Employee/Nyw.Employee.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | Nyw.EmployeeServices 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Employee/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Nyw.EmployeeServices { 12 | public class Program { 13 | public static void Main(string[] args) { 14 | CreateWebHostBuilder(args).Build().Run(); 15 | } 16 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 17 | WebHost.CreateDefaultBuilder(args) 18 | .ConfigureAppConfiguration(Startup.ConfigureAppConfiguration) 19 | .UseStartup(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Env/Consul/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | 5 | consul-agent-1: &consul-agent 6 | image: consul:latest 7 | networks: 8 | - consul-demo 9 | command: "agent -retry-join consul-server-bootstrap -client 0.0.0.0" 10 | 11 | consul-agent-2: 12 | <<: *consul-agent 13 | 14 | consul-agent-3: 15 | <<: *consul-agent 16 | 17 | consul-server-1: &consul-server 18 | <<: *consul-agent 19 | command: "agent -server -retry-join consul-server-bootstrap -client 0.0.0.0" 20 | 21 | consul-server-2: 22 | <<: *consul-server 23 | 24 | consul-server-bootstrap: 25 | <<: *consul-agent 26 | ports: 27 | - "8400:8400" 28 | - "8500:8500" 29 | - "8600:8600" 30 | command: "agent -server -bootstrap-expect 3 -ui -client 0.0.0.0" 31 | 32 | networks: 33 | consul-demo: -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Wrapping element */ 7 | /* Set some basic padding to keep content from hitting the edges */ 8 | .body-content { 9 | padding-left: 15px; 10 | padding-right: 15px; 11 | } 12 | 13 | /* Carousel */ 14 | .carousel-caption p { 15 | font-size: 20px; 16 | line-height: 1.4; 17 | } 18 | 19 | /* Make .svg files in the carousel display properly in older browsers */ 20 | .carousel-inner .item img[src$=".svg"] { 21 | width: 100%; 22 | } 23 | 24 | /* QR code generator */ 25 | #qrCode { 26 | margin: 15px; 27 | } 28 | 29 | /* Hide/rearrange for smaller screens */ 30 | @media screen and (max-width: 767px) { 31 | /* Hide captions */ 32 | .carousel-caption { 33 | display: none; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/Nyw.IdentityServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | PreserveNewest 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Nyw.Portal { 12 | public class Program { 13 | public static void Main(string[] args) { 14 | CreateWebHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static IWebHost BuildWebHost(string[] args) => 18 | WebHost.CreateDefaultBuilder(args) 19 | .UseStartup() 20 | .Build(); 21 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 22 | WebHost.CreateDefaultBuilder(args) 23 | .UseStartup(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.AppExtensions/Nyw.AppExtensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.hosting.abstractions\2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll 14 | 15 | 16 | C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.http.abstractions\2.0.3\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Nyw.Portal.Models; 8 | 9 | namespace Nyw.Portal.Controllers { 10 | public class HomeController : Controller { 11 | public IActionResult Index() { 12 | return View(); 13 | } 14 | 15 | public IActionResult About() { 16 | ViewData["Message"] = "Your application description page."; 17 | 18 | return View(); 19 | } 20 | 21 | public IActionResult Contact() { 22 | ViewData["Message"] = "Your contact page."; 23 | 24 | return View(); 25 | } 26 | 27 | public IActionResult Error() { 28 | return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 22 |

23 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/User/IdentityServerBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Nyw.IdentityServer.User; 2 | using System.Collections.Generic; 3 | 4 | namespace Microsoft.Extensions.DependencyInjection { 5 | /// 6 | /// Extension methods for the IdentityServer builder 7 | /// 8 | public static class IdentityServerBuilderExtensions { 9 | /// 10 | /// Adds test users. 11 | /// 12 | /// The builder. 13 | /// The users. 14 | /// 15 | public static IIdentityServerBuilder AddUserModel(this IIdentityServerBuilder builder) { 16 | builder.Services.AddSingleton(new UserStore()); 17 | builder.AddProfileService(); 18 | builder.AddResourceOwnerValidator(); 19 | return builder; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Controllers/RedisController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using StackExchange.Redis; 7 | 8 | 9 | namespace Nyw.Portal.Controllers { 10 | public class RedisController : Controller { 11 | public IActionResult Index() { 12 | var cfg = ConfigurationOptions.Parse("localhost:6379"); 13 | //cfg.Password = "P2ssw0rd"; 14 | 15 | ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(cfg); 16 | IDatabase db = redis.GetDatabase(); 17 | 18 | string cVal = "abcdefg"; 19 | var cKey = "mykey"; 20 | db.StringSet(cKey, cVal); 21 | System.Diagnostics.Trace.WriteLine($"Set {nameof(cKey)}'s value : {cVal} to Redis"); 22 | 23 | cVal = db.StringGet(cKey); 24 | System.Diagnostics.Trace.WriteLine($"Get {nameof(cKey)}'s value : {cVal} from Redis"); 25 | return View(); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "http://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jzaefferer/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.14.0", 31 | "_release": "1.14.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.14.0", 35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" 36 | }, 37 | "_source": "git://github.com/jzaefferer/jquery-validation.git", 38 | "_target": ">=1.8", 39 | "_originalSource": "jquery-validation" 40 | } -------------------------------------------------------------------------------- /DevOps/Sonarqube/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | services: 4 | sonarqube: 5 | image: sonarqube 6 | ports: 7 | - "9000:9000" 8 | networks: 9 | - sonarnet 10 | environment: 11 | - SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar 12 | volumes: 13 | - sonarqube_conf:/opt/sonarqube/conf 14 | - sonarqube_data:/opt/sonarqube/data 15 | - sonarqube_extensions:/opt/sonarqube/extensions 16 | - sonarqube_bundled-plugins:/opt/sonarqube/lib/bundled-plugins 17 | 18 | db: 19 | image: postgres 20 | networks: 21 | - sonarnet 22 | environment: 23 | - POSTGRES_USER=sonar 24 | - POSTGRES_PASSWORD=sonar 25 | volumes: 26 | - postgresql:/var/lib/postgresql 27 | # This needs explicit mapping due to https://github.com/docker-library/postgres/blob/4e48e3228a30763913ece952c611e5e9b95c8759/Dockerfile.template#L52 28 | - postgresql_data:/var/lib/postgresql/data 29 | 30 | networks: 31 | sonarnet: 32 | driver: bridge 33 | 34 | volumes: 35 | sonarqube_conf: 36 | sonarqube_data: 37 | sonarqube_extensions: 38 | sonarqube_bundled-plugins: 39 | postgresql: 40 | postgresql_data: -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 3" 33 | }, 34 | "version": "3.3.7", 35 | "_release": "3.3.7", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.7", 39 | "commit": "0b9c4a4007c44201dce9a6cc1a38407005c26c86" 40 | }, 41 | "_source": "https://github.com/twbs/bootstrap.git", 42 | "_target": "v3.3.7", 43 | "_originalSource": "bootstrap", 44 | "_direct": true 45 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2016 Twitter, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Vendor/Nyw.Vendor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | Nyw.VendorService 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/Nyw.ApiGateway.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | PreserveNewest 24 | 25 | 26 | PreserveNewest 27 | 28 | 29 | PreserveNewest 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | using Ocelot.Middleware; 7 | using Ocelot.DependencyInjection; 8 | using Ocelot.Administration; 9 | 10 | namespace Ocelot.POC { 11 | public class Startup { 12 | public Startup(IConfiguration configuration) { 13 | Configuration = configuration; 14 | } 15 | 16 | public IConfiguration Configuration { get; } 17 | 18 | // This method gets called by the runtime. Use this method to add services to the container. 19 | public void ConfigureServices(IServiceCollection services) { 20 | services.AddMvc(); 21 | services.AddOcelot() 22 | .AddAdministration(); 23 | } 24 | 25 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 26 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) { 27 | if (env.IsDevelopment()) { 28 | app.UseDeveloperExceptionPage(); 29 | } 30 | app.UseAuthentication(); 31 | app.UseMvc(); 32 | app.UseOcelot().Wait(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "version": "3.2.6", 4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", 6 | "main": [ 7 | "jquery.validate.unobtrusive.js" 8 | ], 9 | "ignore": [ 10 | "**/.*", 11 | "*.json", 12 | "*.md", 13 | "*.txt", 14 | "gulpfile.js" 15 | ], 16 | "keywords": [ 17 | "jquery", 18 | "asp.net", 19 | "mvc", 20 | "validation", 21 | "unobtrusive" 22 | ], 23 | "authors": [ 24 | "Microsoft" 25 | ], 26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" 30 | }, 31 | "dependencies": { 32 | "jquery-validation": ">=1.8", 33 | "jquery": ">=1.8" 34 | }, 35 | "_release": "3.2.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.2.6", 39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" 40 | }, 41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", 42 | "_target": "3.2.6", 43 | "_originalSource": "jquery-validation-unobtrusive" 44 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/Administration/OcelotBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Ocelot.Administration { 2 | using System; 3 | using DependencyInjection; 4 | using IdentityServer4.AccessTokenValidation; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | 9 | public static class OcelotBuilderExtensions { 10 | public static IOcelotBuilder AddAdministration(this IOcelotBuilder builder) { 11 | 12 | IConfiguration configuration = builder.Configuration; 13 | 14 | Action idpOptions = o => { 15 | o.Authority = configuration.GetValue("Idp:Authority");// @"http://localhost:8500"; 16 | o.ApiName = configuration.GetValue("Idp:ApiName", "apigw.admin"); //"apigw.admin"; 17 | o.RequireHttpsMetadata = configuration.GetValue("Idp:RequireHttpsMetadata", false); //false; 18 | o.SupportedTokens = SupportedTokens.Both; 19 | }; 20 | 21 | builder.Services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) 22 | .AddIdentityServerAuthentication(idpOptions); 23 | //return new OcelotAdministrationBuilder(builder.Services, builder.Configuration); 24 | return builder; 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/Controllers/GlobalController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Authorization; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Extensions.Logging; 6 | using Ocelot.Configuration.File; 7 | using Ocelot.Configuration.Repository; 8 | using Ocelot.Configuration.Setter; 9 | 10 | namespace NSB.ApiManagement.ApiMgtService.Controllers { 11 | //此Controller操作FileConfiguration.GlobalConfiguration,包括查询/更新 12 | [Route("admin/[controller]")] 13 | [ApiController] 14 | [Authorize] 15 | public class GlobalController : ControllerBase 16 | { 17 | private readonly IFileConfigurationRepository _repo; 18 | private readonly IFileConfigurationSetter _setter; 19 | private readonly IServiceProvider _provider; 20 | private readonly ILogger _logger; 21 | 22 | public GlobalController(IFileConfigurationRepository repo, IFileConfigurationSetter setter, IServiceProvider provider, ILogger logger) { 23 | _repo = repo; 24 | _setter = setter; 25 | _provider = provider; 26 | _logger = logger; 27 | } 28 | [HttpGet] 29 | public async Task Get() { 30 | _logger.LogInformation("get demo log"); 31 | var response = await _repo.Get(); 32 | if (response.IsError) { 33 | return new BadRequestObjectResult(response.Errors); 34 | } 35 | return new OkObjectResult(response.Data.GlobalConfiguration); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/nlog.config: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/nlog.config: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /DevOps/Sonarqube/README.md: -------------------------------------------------------------------------------- 1 | ## 环境说明 2 | - Windows 10 v1803 3 | - Docker Version 18.03.1-ce-win65 4 | - [JDK1.8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 5 | - .NET Core 2.x 6 | 7 | ## 准备条件 8 | - 使用docker-compose准备Sonarqube环境 9 | - 本地安装dotnet-sonarscaner工具 10 | ```cmd 11 | dotnet tool install --global dotnet-sonarscanner --version 4.3.1 12 | ``` 13 | 14 | ## 启动Sonarqube: 15 | - 打开命令行,切换到此目录 16 | - 运行命令: 17 | ```cmd 18 | docker-compose up 19 | ``` 20 | - 打开浏览器,访问http://localhost:9000 21 | - 完成 22 | - 重启 23 | ```cmd 24 | docker-compose restart sonarqube 25 | ``` 26 | 27 | ## 扫描代码 28 | - 打开浏览器,访问http://localhost:9000,使用管理员账号密码登录(默认都是admin),进入Sonar项目管理界面 29 | ![1](1.png) 30 | - 输入项目名称,生成token 31 | - 点击继续,选择项目类型,输入项目唯一key(任意字符,唯一即可) 32 | - 点击完后会生执行步骤,可复制,稍后使用 33 | - 打开命令行(cmd或powershell)窗口,切换目录到项目目录下 34 | - 依次执行刚才复制的命令 35 | ```cmd 36 | dotnet sonarscanner begin /k:"TestProject" /d:sonar.host.url="http://localhost:9000" /d:sonar.login="cfe594fd605f2e4821835e43c69da82e489c2f23" 37 | dotnet build 38 | dotnet sonarscanner end /d:sonar.login="cfe594fd605f2e4821835e43c69da82e489c2f23" 39 | ``` 40 | - 等待命令执行完毕后即可重新访问http://localhost:9000查看扫描报告 41 | ![2](2.png) 42 | 43 | ## 注意事项 44 | - 本地需安装配置JDK,否则执行dotnet sonarscanner end会失败 45 | - 如果是对整个解决方案进行扫描,或目录下有多个项目时,需在dotnet build命令后添加要扫描的解决方案或项目,如 46 | ``` cmd 47 | dotnet build ./test.sln 48 | ``` 49 | 50 | ## 参考 51 | - 原始文件[docker-compose](https://github.com/SonarSource/docker-sonarqube/blob/master/recipes.md) 52 | - [使用说明](https://www.cnblogs.com/myzony/p/9233667.html) 53 | - [dotnet build](https://docs.microsoft.com/zh-cn/dotnet/core/tools/dotnet-build?tabs=netcore2x) 54 | - [dotnte tool install](https://docs.microsoft.com/zh-cn/dotnet/core/tools/dotnet-tool-install) -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using SkyWalking.AspNetCore; 10 | 11 | namespace Nyw.Portal { 12 | public class Startup { 13 | public Startup(IConfiguration configuration) { 14 | Configuration = configuration; 15 | } 16 | 17 | public IConfiguration Configuration { get; } 18 | 19 | // This method gets called by the runtime. Use this method to add services to the container. 20 | public void ConfigureServices(IServiceCollection services) { 21 | services.AddMvc(); 22 | //services.AddSkyWalking(option => { 23 | // option.ApplicationCode = "Nyw.Portal"; 24 | // option.DirectServers = "10.0.1.202:11800"; 25 | //}); 26 | } 27 | 28 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 29 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) { 30 | if (env.IsDevelopment()) { 31 | app.UseDeveloperExceptionPage(); 32 | } 33 | else { 34 | app.UseExceptionHandler("/Home/Error"); 35 | } 36 | 37 | app.UseStaticFiles(); 38 | 39 | app.UseMvc(routes => { 40 | routes.MapRoute( 41 | name: "default", 42 | template: "{controller=Home}/{action=Index}/{id?}"); 43 | }); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Vendor/Controllers/ValuesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Logging; 7 | using Nyw.VendorService.Models; 8 | 9 | namespace Nyw.VendorService.Controllers { 10 | [Route("api/[controller]")] 11 | public class ValuesController : Controller { 12 | private static List vendors = new List { 13 | new VendorModel{ Id=1 }, 14 | new VendorModel{ Id=2, Name="京东" }, 15 | new VendorModel{ Id=3, Name="腾讯"} 16 | }; 17 | private ILogger log = null; 18 | public ValuesController(ILogger logger) { 19 | this.log = logger; 20 | } 21 | // GET api/values 22 | [HttpGet] 23 | public IEnumerable Get() { 24 | 25 | return vendors; 26 | } 27 | 28 | // GET api/values/5 29 | [HttpGet("{id}")] 30 | public VendorModel Get(int id) { 31 | var vendor = vendors.Where(v => v.Id == id).FirstOrDefault(); 32 | log.LogInformation("Read {@Vendor}",vendor); 33 | return vendor; 34 | } 35 | 36 | // POST api/values 37 | [HttpPost] 38 | public void Post([FromBody]string value) { 39 | } 40 | 41 | // PUT api/values/5 42 | [HttpPut("{id}")] 43 | public void Put(int id, [FromBody]string value) { 44 | } 45 | 46 | // DELETE api/values/5 47 | [HttpDelete("{id}")] 48 | public string Delete(int id) { 49 | return $"delete vendor:{id} success"; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Employee/Controllers/ValuesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Nyw.EmployeeServices.Models; 7 | 8 | namespace Nyw.EmployeeServices.Controllers { 9 | [Route("api/[controller]")] 10 | public class ValuesController : Controller { 11 | private static List employees = new List { 12 | new EmployeeModel{Id=1, Alias="zhangsan", NameCN="张三", NameEN="san zhang", Mail="zhangsan@nyw.com" }, 13 | new EmployeeModel{Id=2, Alias="lisi", NameCN="李四", NameEN="si li", Mail="lisi@nyw.com" }, 14 | new EmployeeModel{Id=3, Alias="wangwu", NameCN="王五", NameEN="wu wang", Mail="wangwu@nyw.com" }, 15 | new EmployeeModel{Id=4, Alias="zhaoliu", NameCN="赵六", NameEN="liu zhao", Mail="zhaoliu@nyw.com" } 16 | }; 17 | // GET api/values 18 | [HttpGet] 19 | public IEnumerable Get() { 20 | return employees; 21 | } 22 | 23 | // GET api/values/5 24 | [HttpGet("{id}")] 25 | public EmployeeModel Get(int id) { 26 | return employees.Where(e => e.Id == id).FirstOrDefault(); 27 | } 28 | 29 | // POST api/values 30 | [HttpPost] 31 | public void Post([FromBody]string value) { 32 | } 33 | 34 | // PUT api/values/5 35 | [HttpPut("{id}")] 36 | public void Put(int id, [FromBody]string value) { 37 | } 38 | 39 | // DELETE api/values/5 40 | [HttpDelete("{id}")] 41 | public string Delete(int id) { 42 | return $"delete employee:{id} success"; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/User/UserResourceOwnerPasswordValidator.cs: -------------------------------------------------------------------------------- 1 | using IdentityModel; 2 | using IdentityServer4.Validation; 3 | using System.Threading.Tasks; 4 | using System; 5 | using Microsoft.AspNetCore.Authentication; 6 | 7 | namespace Nyw.IdentityServer.User { 8 | public class UserResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator { 9 | private readonly UserStore _users; 10 | private readonly ISystemClock _clock; 11 | 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | /// The users. 16 | /// The clock. 17 | public UserResourceOwnerPasswordValidator(UserStore users, ISystemClock clock) { 18 | _users = users; 19 | _clock = clock; 20 | } 21 | 22 | /// 23 | /// Validates the resource owner password credential 24 | /// 25 | /// The context. 26 | /// 27 | public Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { 28 | if (_users.ValidateCredentials(context.UserName, context.Password)) { 29 | var user = _users.FindByUsername(context.UserName); 30 | context.Result = new GrantValidationResult( 31 | user.SubjectId ?? throw new ArgumentException("Subject ID not set", nameof(user.SubjectId)), 32 | OidcConstants.AuthenticationMethods.Password, _clock.UtcNow.UtcDateTime, 33 | user.Claims); 34 | } 35 | 36 | return Task.CompletedTask; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.Logging; 5 | using NLog.Web; 6 | using System; 7 | using System.IO; 8 | 9 | namespace Nyw.IdentityServer { 10 | public class Program { 11 | public static void Main(string[] args) { 12 | var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); 13 | try { 14 | logger.Debug("init main"); 15 | CreateWebHostBuilder(args).Build().Run(); 16 | } 17 | catch (Exception ex) { 18 | logger.Error(ex, "Stopped program because of exception"); 19 | throw; 20 | } 21 | finally { 22 | NLog.LogManager.Shutdown(); 23 | } 24 | } 25 | 26 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 27 | WebHost.CreateDefaultBuilder(args) 28 | .UseContentRoot(Directory.GetCurrentDirectory()) 29 | .ConfigureAppConfiguration((hostingContext, config) => { 30 | config 31 | .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) 32 | .AddJsonFile("appsettings.json", true, true) 33 | .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) 34 | .AddEnvironmentVariables(); 35 | }) 36 | .ConfigureLogging(logging => { 37 | logging.ClearProviders(); 38 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); 39 | }) 40 | .UseNLog() 41 | .UseStartup(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.AppExtensions/ConsulExtensions.cs: -------------------------------------------------------------------------------- 1 | using Consul; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using System; 5 | 6 | namespace Nyw.AppExtensions { 7 | public static class ConsulExtensions { 8 | public static IApplicationBuilder RegisterConsulService(this IApplicationBuilder app, IApplicationLifetime lifetime, ConsulServiceOptions options) { 9 | //Action tt = null; 10 | 11 | var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{options.ConsulAddress}:{options.ConsulPort}"));//请求注册的 Consul 地址 12 | // Register service with consul 13 | var registration = new AgentServiceRegistration() { 14 | Checks = new[] { 15 | new AgentServiceCheck() { 16 | DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册 17 | Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔,或者称为心跳间隔 18 | HTTP = $"http://{options.Address}:{options.Port}/api/health",//健康检查地址 19 | Timeout = TimeSpan.FromSeconds(5) 20 | } }, 21 | ID = Guid.NewGuid().ToString(), 22 | Name = options.Service, 23 | Address = options.Address, 24 | Port = options.Port, 25 | Tags = new[] { $"urlprefix-/{options.Service}" }//添加 urlprefix-/servicename 格式的 tag 标签,以便 Fabio 识别 26 | }; 27 | 28 | consulClient.Agent.ServiceRegister(registration).Wait();//服务启动时注册,内部实现其实就是使用 Consul API 进行注册(HttpClient发起) 29 | lifetime.ApplicationStopping.Register(() => { 30 | consulClient.Agent.ServiceDeregister(registration.ID).Wait();//服务停止时取消注册 31 | }); 32 | 33 | return app; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Microsoft.AspNetCore; 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.Logging; 7 | using NLog.Web; 8 | using Ocelot.DependencyInjection; 9 | 10 | namespace Ocelot.POC { 11 | public class Program { 12 | public static void Main(string[] args) { 13 | var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); 14 | try { 15 | logger.Debug("init main"); 16 | CreateWebHostBuilder(args).Build().Run(); 17 | } 18 | catch (Exception ex) { 19 | logger.Error(ex, "Stopped program because of exception"); 20 | throw; 21 | } 22 | finally { 23 | // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) 24 | NLog.LogManager.Shutdown(); 25 | } 26 | } 27 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 28 | WebHost.CreateDefaultBuilder(args) 29 | .UseContentRoot(Directory.GetCurrentDirectory()) 30 | .ConfigureAppConfiguration((hostingContext, config) => { 31 | config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) 32 | .AddJsonFile("appsettings.json", true, true) 33 | .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) 34 | //.AddJsonFile("ocelot.json") 35 | .AddOcelot(hostingContext.HostingEnvironment) 36 | .AddEnvironmentVariables(); 37 | }) 38 | .ConfigureLogging(logging => { 39 | logging.ClearProviders(); 40 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); 41 | }) 42 | .UseNLog() 43 | .UseStartup(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/ocelot.route.json: -------------------------------------------------------------------------------- 1 | { 2 | "ReRoutes": [ 3 | { 4 | "DownstreamPathTemplate": "/api/values/{id}", 5 | "DownstreamScheme": "http", 6 | "ServiceName": "vendor", 7 | "UseServiceDiscovery": true, 8 | "LoadBalancerOptions": { 9 | "Type": "LeastConnection", 10 | "Key": null, 11 | "Expiry": 0 12 | }, 13 | "UpstreamPathTemplate": "/vendor/{id}", 14 | "UpstreamHttpMethod": [ "Get", "Delete" ], 15 | /*Quality of Service*/ 16 | "QoSOptions": { 17 | "ExceptionsAllowedBeforeBreaking": 3, 18 | "DurationOfBreak": 10, 19 | "TimeoutValue": 5000 /*毫秒*/ 20 | }, 21 | "RateLimitOptions": { 22 | "ClientWhitelist": [], /*the client in this array will not be affected by the rate limiting*/ 23 | "EnableRateLimiting": false, 24 | "Period": "1s", /*This value specifies the period, such as 1s, 5m, 1h,1d and so on. */ 25 | "PeriodTimespan": 1.0, /* This value specifies that we can retry after a certain number of seconds*/ 26 | "Limit": 10 /*This value specifies the maximum number of requests that a client can make in a defined period*/ 27 | }, 28 | "HttpHandlerOptions": { 29 | "AllowAutoRedirect": false, 30 | "UseCookieContainer": false, 31 | "UseTracing": false, 32 | "UseProxy": true 33 | } 34 | }, 35 | { 36 | "DownstreamPathTemplate": "/api/values/{id}", 37 | "DownstreamScheme": "http", 38 | "ServiceName": "employee", 39 | "UseServiceDiscovery": true, 40 | "LoadBalancerOptions": { 41 | "Type": "LeastConnection", 42 | "Key": null, 43 | "Expiry": 0 44 | }, 45 | "UpstreamPathTemplate": "/employee/{id}", 46 | "UpstreamHttpMethod": [ "Get", "Delete" ], 47 | "QoSOptions": { 48 | "ExceptionsAllowedBeforeBreaking": 3, 49 | "DurationOfBreak": 10, 50 | "TimeoutValue": 5000 51 | }, 52 | "HttpHandlerOptions": { 53 | "AllowAutoRedirect": false, 54 | "UseCookieContainer": false, 55 | "UseTracing": false, 56 | "UseProxy": true 57 | } 58 | } 59 | ] 60 | } -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Vendor/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | using Serilog; 11 | using Serilog.Events; 12 | using Serilog.Sinks.Elasticsearch; 13 | 14 | namespace Nyw.VendorService { 15 | public class Program { 16 | public static void Main(string[] args) { 17 | Log.Logger = new LoggerConfiguration() 18 | .MinimumLevel.Debug() 19 | .MinimumLevel.Override("Microsoft", LogEventLevel.Information) 20 | .Enrich.FromLogContext() 21 | .WriteTo.Console() 22 | .WriteTo.File("logs\\log.txt", rollingInterval: RollingInterval.Day, rollOnFileSizeLimit: true) 23 | .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200")) { 24 | AutoRegisterTemplate = true, 25 | AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv6, 26 | FailureCallback = e => Console.WriteLine("Unable to submit event " + e.MessageTemplate), 27 | EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog | 28 | EmitEventFailureHandling.WriteToFailureSink | 29 | EmitEventFailureHandling.RaiseCallback 30 | }) 31 | .CreateLogger(); 32 | 33 | try { 34 | Log.Information("Starting web host"); 35 | CreateWebHostBuilder(args).Build().Run(); 36 | } 37 | catch (Exception ex) { 38 | Log.Fatal(ex, "Host terminated unexpectedly"); 39 | } 40 | finally { 41 | Log.CloseAndFlush(); 42 | } 43 | } 44 | 45 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 46 | WebHost.CreateDefaultBuilder(args) 47 | .ConfigureAppConfiguration(Startup.ConfigureAppConfiguration) 48 | .UseStartup() 49 | .UseSerilog(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/Controllers/RerouteController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Authorization; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Extensions.Logging; 6 | using Ocelot.Configuration.File; 7 | using Ocelot.Configuration.Repository; 8 | using Ocelot.Configuration.Setter; 9 | 10 | namespace NSB.ApiManagement.ApiMgtService.Controllers { 11 | [Route("admin/[controller]")] 12 | [ApiController] 13 | [Authorize] 14 | public class RerouteController : ControllerBase { 15 | private readonly IFileConfigurationRepository _repo; 16 | private readonly IFileConfigurationSetter _setter; 17 | private readonly IServiceProvider _provider; 18 | private readonly ILogger _logger; 19 | public RerouteController(IFileConfigurationRepository repo, IFileConfigurationSetter setter, IServiceProvider provider, ILogger logger) { 20 | _repo = repo; 21 | _setter = setter; 22 | _provider = provider; 23 | _logger = logger; 24 | } 25 | //读取所有ReRoutes 26 | [HttpGet] 27 | public async Task Get() { 28 | _logger.LogInformation("get demo log"); 29 | //对ReRoute对象操作是对FileConfiguration.ReRoutes属性的操作 30 | var response = await _repo.Get(); 31 | if (response.IsError) { 32 | return new BadRequestObjectResult(response.Errors); 33 | } 34 | return new OkObjectResult(response.Data.ReRoutes); 35 | } 36 | //更新某一个ReRoute 37 | [HttpPost] 38 | public async Task Post([FromBody]FileReRoute fileReRoute) { 39 | try { 40 | var fileConfiguration= _repo.Get().Result.Data; 41 | //根据FileReRoute.Key找到要更新的FileReRoute 42 | //更新FileReRoute 43 | 44 | var response = await _setter.Set(fileConfiguration); 45 | 46 | if (response.IsError) { 47 | return new BadRequestObjectResult(response.Errors); 48 | } 49 | 50 | return new OkObjectResult(fileReRoute); 51 | } 52 | catch (Exception e) { 53 | return new BadRequestObjectResult($"{e.Message}:{e.StackTrace}"); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ExchangeRateTask/Program.cs: -------------------------------------------------------------------------------- 1 | using Quartz; 2 | using Quartz.Impl; 3 | using Serilog; 4 | using System; 5 | using System.Collections.Specialized; 6 | using System.Threading.Tasks; 7 | 8 | namespace Nyw.ExchangeRateTask { 9 | class Program { 10 | static void Main(string[] args) { 11 | 12 | Log.Logger = new LoggerConfiguration() 13 | .MinimumLevel.Debug() 14 | .WriteTo.Console() 15 | .WriteTo.File("logs\\log.txt", rollingInterval: RollingInterval.Day) 16 | .CreateLogger(); 17 | 18 | Log.Information("Hello, world!"); 19 | 20 | RunTask().GetAwaiter().GetResult(); 21 | 22 | Console.WriteLine("Press any key to close the application"); 23 | Console.ReadKey(); 24 | } 25 | private static async Task RunTask() { 26 | try { 27 | //NameValueCollection props = new NameValueCollection { 28 | // { "quartz.serializer.type", "binary" } 29 | //}; 30 | //StdSchedulerFactory factory = new StdSchedulerFactory(props); 31 | //IScheduler scheduler = await factory.GetScheduler(); 32 | 33 | IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler(); 34 | await scheduler.Start(); 35 | 36 | IJobDetail jobDetail = JobBuilder.Create() 37 | .WithIdentity("helloJob1","group1") 38 | .Build(); 39 | ITrigger trigger = TriggerBuilder.Create() 40 | .WithIdentity("trigger1", "group1") 41 | .StartNow() 42 | .WithSimpleSchedule(x => x 43 | .WithIntervalInSeconds(10) 44 | .WithRepeatCount(5) 45 | //.RepeatForever() 46 | ) 47 | .Build(); 48 | 49 | await scheduler.ScheduleJob(jobDetail,trigger); 50 | 51 | await Task.Delay(TimeSpan.FromSeconds(60)); 52 | await scheduler.Shutdown(); 53 | } 54 | catch (SchedulerException sex) { 55 | await Console.Error.WriteLineAsync(sex.ToString()); 56 | } 57 | catch (Exception ex) { 58 | await Console.Error.WriteLineAsync(ex.ToString()); 59 | } 60 | } 61 | } 62 | public class HelloJob : IJob { 63 | public async Task Execute(IJobExecutionContext context) { 64 | await Console.Out.WriteLineAsync("Greetings from Hello Job."); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/User/UserProfileService.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer4.Extensions; 2 | using IdentityServer4.Models; 3 | using IdentityServer4.Services; 4 | using Microsoft.Extensions.Logging; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | 9 | namespace Nyw.IdentityServer.User { 10 | public class UserProfileService : IProfileService { 11 | /// 12 | /// The logger 13 | /// 14 | protected readonly ILogger Logger; 15 | 16 | /// 17 | /// The users 18 | /// 19 | protected readonly UserStore Users; 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// The users. 25 | /// The logger. 26 | public UserProfileService(UserStore users, ILogger logger) { 27 | Users = users; 28 | Logger = logger; 29 | } 30 | 31 | /// 32 | /// This method is called whenever claims about the user are requested (e.g. during token creation or via the userinfo endpoint) 33 | /// 34 | /// The context. 35 | /// 36 | public virtual Task GetProfileDataAsync(ProfileDataRequestContext context) { 37 | context.LogProfileRequest(Logger); 38 | 39 | if (context.RequestedClaimTypes.Any()) { 40 | var user = Users.FindBySubjectId(context.Subject.GetSubjectId()); 41 | if (user != null) { 42 | context.AddRequestedClaims(user.Claims); 43 | } 44 | } 45 | 46 | context.LogIssuedClaims(Logger); 47 | 48 | return Task.CompletedTask; 49 | } 50 | 51 | /// 52 | /// This method gets called whenever identity server needs to determine if the user is valid or active (e.g. if the user's account has been deactivated since they logged in). 53 | /// (e.g. during token issuance or validation). 54 | /// 55 | /// The context. 56 | /// 57 | public virtual Task IsActiveAsync(IsActiveContext context) { 58 | Logger.LogDebug("IsActive called from: {caller}", context.Caller); 59 | 60 | var user = Users.FindBySubjectId(context.Subject.GetSubjectId()); 61 | context.IsActive = user?.IsActive == true; 62 | 63 | return Task.CompletedTask; 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.ApiGateway/ocelot.json: -------------------------------------------------------------------------------- 1 | {"ReRoutes":[{"DownstreamPathTemplate":"/api/values/{id}","UpstreamPathTemplate":"/vendor/{id}","UpstreamHttpMethod":["Get","Delete"],"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"ReRouteIsCaseSensitive":false,"ServiceName":"vendor","DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":3,"DurationOfBreak":10,"TimeoutValue":5000},"LoadBalancerOptions":{"Type":"LeastConnection","Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":"1s","PeriodTimespan":1.0,"Limit":10},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true},"UseServiceDiscovery":true,"DownstreamHostAndPorts":[],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false},{"DownstreamPathTemplate":"/api/values/{id}","UpstreamPathTemplate":"/employee/{id}","UpstreamHttpMethod":["Get","Delete"],"AddHeadersToRequest":{},"UpstreamHeaderTransform":{},"DownstreamHeaderTransform":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0,"Region":null},"ReRouteIsCaseSensitive":false,"ServiceName":"employee","DownstreamScheme":"http","QoSOptions":{"ExceptionsAllowedBeforeBreaking":3,"DurationOfBreak":10,"TimeoutValue":5000},"LoadBalancerOptions":{"Type":"LeastConnection","Key":null,"Expiry":0},"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0},"AuthenticationOptions":{"AuthenticationProviderKey":null,"AllowedScopes":[]},"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true},"UseServiceDiscovery":true,"DownstreamHostAndPorts":[],"UpstreamHost":null,"Key":null,"DelegatingHandlers":[],"Priority":1,"Timeout":0,"DangerousAcceptAnyServerCertificateValidator":false}],"Aggregates":[],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Host":"localhost","Port":8500,"Type":null,"Token":null,"ConfigurationKey":"Nyw.Oceolot","PollingInterval":0},"RateLimitOptions":{"ClientIdHeader":"ClientId","QuotaExceededMessage":"Exceeded access quota limit","RateLimitCounterPrefix":"ocelot","DisableRateLimitHeaders":false,"HttpStatusCode":429},"QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"BaseUrl":null,"LoadBalancerOptions":{"Type":null,"Key":null,"Expiry":0},"DownstreamScheme":null,"HttpHandlerOptions":{"AllowAutoRedirect":false,"UseCookieContainer":false,"UseTracing":false,"UseProxy":true}}} -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Vendor/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Logging; 11 | using Microsoft.Extensions.Options; 12 | using Winton.Extensions.Configuration.Consul; 13 | using Nyw.AppExtensions; 14 | 15 | namespace Nyw.VendorService { 16 | public class Startup { 17 | public Startup(IConfiguration configuration, IHostingEnvironment env) { 18 | HostingEnvironment = env; 19 | Configuration = configuration; 20 | } 21 | 22 | public IConfiguration Configuration { get; } 23 | public IHostingEnvironment HostingEnvironment { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) { 27 | services.AddMvc(); 28 | } 29 | 30 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 31 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime) { 32 | if (env.IsDevelopment()) { 33 | app.UseDeveloperExceptionPage(); 34 | } 35 | 36 | app.RegisterConsulService(appLifetime, new ConsulServiceOptions { 37 | Address = "localhost", 38 | ConsulAddress = "localhost", 39 | ConsulPort = 8500, 40 | Port = Convert.ToInt32(Configuration["ServicePort"]), 41 | Service = "vendor" 42 | }); 43 | 44 | appLifetime.ApplicationStopping.Register(cancellationTokenSource.Cancel); 45 | app.UseMvc(); 46 | } 47 | private static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); 48 | public static void ConfigureAppConfiguration(WebHostBuilderContext hostingContext, IConfigurationBuilder builder) { 49 | var env = hostingContext.HostingEnvironment; 50 | builder 51 | .AddConsul($"{env.ApplicationName}.{env.EnvironmentName}", 52 | cancellationTokenSource.Token, 53 | options => { 54 | options.ConsulConfigurationOptions = 55 | cco => { 56 | cco.Address = new Uri("http://localhost:8500"); 57 | cco.Datacenter = "dc1"; 58 | }; 59 | options.Optional = true; 60 | options.ReloadOnChange = true; 61 | options.OnLoadException = exceptionContext => { exceptionContext.Ignore = true; }; 62 | }) 63 | .AddEnvironmentVariables(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Employee/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Logging; 11 | using Microsoft.Extensions.Options; 12 | using Nyw.AppExtensions; 13 | using Winton.Extensions.Configuration.Consul; 14 | 15 | namespace Nyw.EmployeeServices { 16 | public class Startup { 17 | public Startup(IConfiguration configuration, IHostingEnvironment env) { 18 | HostingEnvironment = env; 19 | Configuration = configuration; 20 | } 21 | 22 | public IConfiguration Configuration { get; } 23 | public IHostingEnvironment HostingEnvironment { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) { 27 | services.AddMvc(); 28 | } 29 | 30 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 31 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime) { 32 | if (env.IsDevelopment()) { 33 | app.UseDeveloperExceptionPage(); 34 | } 35 | 36 | app.RegisterConsulService(appLifetime, new ConsulServiceOptions { 37 | Address = "localhost", 38 | ConsulAddress = "localhost", 39 | ConsulPort = 8500, 40 | Port = Convert.ToInt32(Configuration["ServicePort"]), 41 | Service = "employee" 42 | }); 43 | 44 | appLifetime.ApplicationStopping.Register(cancellationTokenSource.Cancel); 45 | app.UseMvc(); 46 | } 47 | private static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); 48 | public static void ConfigureAppConfiguration(WebHostBuilderContext hostingContext, IConfigurationBuilder builder) { 49 | var env = hostingContext.HostingEnvironment; 50 | builder 51 | .AddConsul($"{env.ApplicationName}.{env.EnvironmentName}", 52 | cancellationTokenSource.Token, 53 | options => { 54 | options.ConsulConfigurationOptions = 55 | cco => { 56 | cco.Address = new Uri("http://localhost:8500"); 57 | cco.Datacenter = "dc1"; 58 | }; 59 | options.Optional = true; 60 | options.ReloadOnChange = true; 61 | options.OnLoadException = exceptionContext => { exceptionContext.Ignore = true; }; 62 | }) 63 | .AddEnvironmentVariables(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- 1 | [英文](README.md) | 中文 2 | # 蜂巢 3 | 4 | ## 环境说明 5 | - Visual Studio 2017 6 | - .NET Core 2.0 7 | - Windows 10 v1803 8 | - Docker Version 18.03.1-ce-win65 9 | 10 | ## 相关开源项目 11 | - [Ocelot](https://github.com/ThreeMammals/Ocelot) 12 | - [Consul](https://github.com/hashicorp/consul) 13 | - [Winton.Extensions.Configuration.Consul](https://github.com/wintoncode/Winton.Extensions.Configuration.Consul) 14 | - [安装](/Env/Consul/README.md) 15 | - [IdentityServer4](https://github.com/IdentityServer/IdentityServer4) 16 | - [IdentityServer4.EntityFramework](https://github.com/IdentityServer/IdentityServer4.EntityFramework) 17 | - [Serilog](https://github.com/serilog) 18 | - [Serilog.Serilog](https://github.com/serilog/serilog) 19 | - [Serilog-aspnetcore](https://github.com/serilog/serilog-aspnetcore) 20 | - [serilog-sinks-file](https://github.com/serilog/serilog-sinks-file) 21 | - [serilog-sinks-console](https://github.com/serilog/serilog-sinks-console) 22 | - [serilog-sinks-elasticsearch](https://github.com/serilog/serilog-sinks-elasticsearch) 23 | - [ELK](https://github.com/elastic/) 24 | - [elasticsearch](https://github.com/elastic/elasticsearch) 25 | - [logstash](https://github.com/elastic/logstash) 26 | - [kibana](https://github.com/elastic/kibana) 27 | - [安装](/Env/ELK/README.md) 28 | - [Quartz.NET](https://github.com/quartznet/quartznet) 29 | - [Documents](https://www.quartz-scheduler.net/documentation/index.html) 30 | - [skywalking](https://github.com/apache/incubator-skywalking) 31 | - [Client:dotnetcore](https://github.com/OpenSkywalking/skywalking-netcore) 32 | - [Redis](https://github.com/antirez/redis) 33 | - [StackExchange.Redis](https://github.com/StackExchange/StackExchange.Redis/) 34 | - [安装](/Env/Redis/README.md) 35 | - [Sonarqube](/DevOps/Sonarqube/README.md) 36 | - [Jenkins](/DevOps/Jenkins/README.md) 37 | 38 | ## 项目说明 39 | - Nyw.ApiGateway:基于Ocelot构建的ApiGateway,配置从Consul获取 40 | - Nyw.Employee:测试项目 41 | - Consul作为配置源 42 | - 启动时向Consul注册自己 43 | - Nyw.Vendor:测试项目 44 | - Consul作为配置源 45 | - 启动时向Consul注册自己 46 | - 使用serilog,日志输出到Console, File, Elasticsearch 47 | - Nyw.AppExtensions:扩展项目 48 | - Consul扩展,实现项目启动时自动向Consul注册服务 49 | - Nyw.IdentityServer:认证服务项目 50 | - 使用IdentityServer4.EntityFramework保存数据到数据库中 51 | - 使用自定义用户模型 52 | - Nyw.ExchangeRateTask:定期查询汇率任务(计划任务) 53 | - 控制台程序使用Serilog记录日志 54 | - 使用Quartz.NET构建计划任务 55 | - Quartz.NET和Serilog协同工作 56 | - Nyw.Portal:定义门户,计划用于调用API 57 | - 添加skywalking netcore 58 | - 添加Redis缓存 59 | - Nyw.Configuration.SqlServer: 数据库配置提供程序中间件 60 | - 将SQL Server作为IConfiguration的配置提供程序,能够从数据库读取配置 61 | 62 | ## 已验证功能 63 | - Ocelot: 64 | 1. 路由 65 | 1. 服务质量 66 | 1. 使用限制 67 | 1. 服务发现,使用consul 68 | 1. 添加网关管理API框架 69 | 1. 添加Nlog支持 70 | - Consul 71 | 1. K/V存储 72 | 1. Dotnetcore 配置提供程序 73 | 1. 服务注册 74 | 1. 健康检查 75 | - IdentityServer: 76 | 1. 使用IdentityServer4.EntityFramework存储数据到数据库 77 | 1. 自定义用户模型 78 | - Serilog: 79 | 1. ASP.NET Core 2.x使用Serilog记录日志 80 | 1. 输出日志到控制台 81 | 1. 输出日志到文件 82 | 1. 输出日志到Elasticsearch 83 | - ELK: 84 | 1. 使用ELK Docker Compose快速构建环境 85 | 1. 输出日志到Elk 86 | 1. 创建基本索引和查询 87 | - Quartz.NET: 88 | 1. 构建简单的计划任务,重复有限次数和无限次重复 89 | 1. 和Serilog协同工作 90 | 1. 使用控制台运行 91 | - Skywalking 92 | 1. ASP.NET Core 的APM和应用程序拓扑图 93 | - Redis 94 | 1. 基本操作:连接,添加字符串,读取字符串 95 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - Nyw.Portal 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 41 |
42 | @RenderBody() 43 |
44 |
45 |

© 2018 - Nyw.Portal

46 |
47 |
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 61 | 67 | 68 | 69 | 70 | @RenderSection("Scripts", required: false) 71 | 72 | 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 英文 | [中文](README.zh-CN.md) 2 | # honeycomb 3 | 4 | ## Requirements 5 | - Visual Studio 2017 6 | - .NET Core 2.0/2.1 7 | - Windows 10 v1803 8 | - Docker Version 18.03.1-ce-win65 9 | 10 | ## Open Source Projects 11 | - [Ocelot](https://github.com/ThreeMammals/Ocelot) 12 | - [Consul](https://github.com/hashicorp/consul) 13 | - [Winton.Extensions.Configuration.Consul](https://github.com/wintoncode/Winton.Extensions.Configuration.Consul) 14 | - [Setup](/Env/Consul/README.md) 15 | - [IdentityServer4](https://github.com/IdentityServer/IdentityServer4) 16 | - [IdentityServer4.EntityFramework](https://github.com/IdentityServer/IdentityServer4.EntityFramework) 17 | - [Serilog](https://github.com/serilog) 18 | - [Serilog.Serilog](https://github.com/serilog/serilog) 19 | - [Serilog-aspnetcore](https://github.com/serilog/serilog-aspnetcore) 20 | - [serilog-sinks-file](https://github.com/serilog/serilog-sinks-file) 21 | - [serilog-sinks-console](https://github.com/serilog/serilog-sinks-console) 22 | - [serilog-sinks-elasticsearch](https://github.com/serilog/serilog-sinks-elasticsearch) 23 | - [ELK](https://github.com/elastic/) 24 | - [elasticsearch](https://github.com/elastic/elasticsearch) 25 | - [logstash](https://github.com/elastic/logstash) 26 | - [kibana](https://github.com/elastic/kibana) 27 | - [Setup](/Env/ELK/README.md) 28 | - [Quartz.NET](https://github.com/quartznet/quartznet) 29 | - [Documents](https://www.quartz-scheduler.net/documentation/index.html) 30 | - [skywalking](https://github.com/apache/incubator-skywalking) 31 | - [Client:dotnetcore](https://github.com/OpenSkywalking/skywalking-netcore) 32 | - [Redis](https://github.com/antirez/redis) 33 | - [StackExchange.Redis](https://github.com/StackExchange/StackExchange.Redis/) 34 | - [Setup](/Env/Redis/README.md) 35 | - [Sonarqube](/DevOps/Sonarqube/README.md) 36 | - [Jenkins](/DevOps/Jenkins/README.md) 37 | 38 | ## Projects Illustrate 39 | - Nyw.ApiGateway: 40 | - ApiGatewat service, base **Ocelot** and load configuration from **Consul** 41 | - Nyw.Employee:Web API Test Project 42 | - Consul as configuration source provider 43 | - Register itself to consul as a service when lunch 44 | - Nyw.Vendor:Web API Test Project 45 | - Consul as configuration source provider 46 | - Register itself to consul as a service when lunch 47 | - Using serilog,write log to Console, File, Elasticsearch 48 | - Nyw.AppExtensions:Class Library 49 | - .et core middlerware, Consul extension,the app could registry itself to Consul when lunch 50 | - Nyw.IdentityServer:Web API Project for IdentityServer 51 | - Persisent data to sqlserver using IdentityServer4.EntityFramework 52 | - Using customize user model 53 | - Nyw.ExchangeRateTask:Console app as Schedule Task, mock to query Exchange Rage Schdulely 54 | - Use serilog to output log 55 | - Build simple schedule task using Quartz.NET 56 | - Quartz.NET work with Serilog 57 | - Nyw.Portal:Customzie USer Protal, plan to consum API 58 | - add skywalking netcore 59 | - add redis cache 60 | - Nyw.Configuration.SqlServer: IConfiguration SQL Server Provider Middlerware 61 | - Use SQL Server as IConfigguration Provider, it can load appsettings from sqlserver now 62 | 63 | ## Proofed Functions 64 | - Ocelot: 65 | 1. Rounting 66 | 1. Quality of Service 67 | 1. Rate Limiting 68 | 1. Service Discovery, work with consul 69 | 1. Add ApiGateway Admin API craft 70 | 1. Add nlog support; 71 | - Consul 72 | 1. Key/Value 73 | 1. Dotnetcore Configuration Provider 74 | 1. Service Registry 75 | 1. Health Check 76 | - IdentityServer: 77 | 1. IdentityServer4.EntityFramework 78 | 1. Customize User Model 79 | - Serilog: 80 | 1. ASP.NET Core 2.x log using Serilog 81 | 1. Output log to console 82 | 1. Output log to file 83 | 1. Output log to Elasticsearch 84 | - ELK: 85 | 1. ELK Docker Compose build quickly 86 | 1. Write log to Elk 87 | 1. Basicly create index and search 88 | - Quartz.NET: 89 | 1. Simple Schedule with Repeat Count or Forever 90 | 1. Work with Serilog 91 | 1. Console host 92 | - Skywalking 93 | 1. Basicly .net core apm and application topology map 94 | - Redis 95 | 1. Basic Usage:connect, add string, read string 96 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.EntityFrameworkCore; 6 | using System.Reflection; 7 | using Microsoft.Extensions.Configuration; 8 | using IdentityServer4.EntityFramework.DbContexts; 9 | using IdentityServer4.Models; 10 | using IdentityServer4.EntityFramework.Mappers; 11 | using System.Linq; 12 | 13 | namespace Nyw.IdentityServer { 14 | public class Startup { 15 | public Startup(IConfiguration configuration) { 16 | Configuration = configuration; 17 | } 18 | 19 | public IConfiguration Configuration { get; } 20 | // This method gets called by the runtime. Use this method to add services to the container. 21 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 22 | public void ConfigureServices(IServiceCollection services) { 23 | ConfigureIdentityServerServices(services); 24 | services.AddMvc(); 25 | } 26 | 27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 28 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) { 29 | if (env.IsDevelopment()) { 30 | app.UseDeveloperExceptionPage(); 31 | InitializeIdentityServerDatabase(app); 32 | } 33 | app.UseMvc(); 34 | } 35 | private void ConfigureIdentityServerServices(IServiceCollection services) { 36 | var idpDbConnStr = Configuration.GetConnectionString("IdpDbConnStr"); 37 | var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; 38 | services.AddIdentityServer() 39 | .AddDeveloperSigningCredential() 40 | .AddUserModel() 41 | .AddConfigurationStore(options => { 42 | options.ConfigureDbContext = builder => 43 | builder.UseSqlServer(idpDbConnStr, 44 | sql => sql.MigrationsAssembly(migrationsAssembly)); 45 | }) 46 | .AddOperationalStore(options => { 47 | options.ConfigureDbContext = builder => 48 | builder.UseSqlServer(idpDbConnStr, 49 | sql => sql.MigrationsAssembly(migrationsAssembly)); 50 | options.EnableTokenCleanup = true; 51 | options.TokenCleanupInterval = 30; 52 | }); 53 | 54 | } 55 | private void InitializeIdentityServerDatabase(IApplicationBuilder app) { 56 | using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) { 57 | serviceScope.ServiceProvider.GetRequiredService().Database.Migrate(); 58 | var context = serviceScope.ServiceProvider.GetRequiredService(); 59 | context.Database.Migrate(); 60 | if (!context.Clients.Any()) { 61 | var client1 = new IdentityServer4.Models.Client { 62 | ClientId = "demo.client1", 63 | AllowedGrantTypes = GrantTypes.ClientCredentials, 64 | ClientSecrets = { 65 | new IdentityServer4.Models.Secret("secret".Sha256()) 66 | }, 67 | AllowedScopes = { "demo.api1" }, 68 | ClientName = "Demo Client1" 69 | }; 70 | context.Clients.Add(client1.ToEntity()); 71 | context.SaveChanges(); 72 | } 73 | 74 | if (!context.ApiResources.Any()) { 75 | var api1 = new IdentityServer4.Models.ApiResource { 76 | Name = "demo.api1", 77 | DisplayName = "demo api", 78 | Description = "this is just for demo" 79 | }; 80 | context.ApiResources.Add(api1.ToEntity()); 81 | context.SaveChanges(); 82 | } 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | !function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Microservice.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2000 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nyw.ApiGateway", "Nyw.ApiGateway\Nyw.ApiGateway.csproj", "{3DF9D910-5A2D-4038-91E8-E136C56E6918}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nyw.Vendor", "Nyw.Vendor\Nyw.Vendor.csproj", "{4E0CBE39-3A13-421D-A605-56C46610883B}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nyw.Employee", "Nyw.Employee\Nyw.Employee.csproj", "{CC65BB47-20FD-4B4F-8B2E-39438381084B}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02.Apps", "02.Apps", "{320A36EE-8052-433D-B007-9DE3A2C439BF}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01.Common", "01.Common", "{90E9C700-3C64-4F15-9406-F31BAC440D8B}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nyw.AppExtensions", "Nyw.AppExtensions\Nyw.AppExtensions.csproj", "{F07B5EB9-5FC0-4969-8F69-3B19186EC9D0}" 17 | EndProject 18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "00.Services", "00.Services", "{F1422284-13A6-4C40-89B3-3558D7AD042C}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nyw.IdentityServer", "Nyw.IdentityServer\Nyw.IdentityServer.csproj", "{41D909B7-8319-4261-85B9-78DC79376C9E}" 21 | EndProject 22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03.Tasks", "03.Tasks", "{6823DB3A-7A63-48CF-91C4-5B42DEAE19F8}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nyw.ExchangeRateTask", "Nyw.ExchangeRateTask\Nyw.ExchangeRateTask.csproj", "{ABF99209-048D-417F-A6C0-AD7F1E4BA46A}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nyw.Portal", "Nyw.Portal\Nyw.Portal.csproj", "{CAB44AD9-7A47-4AFC-BBB2-84085AC27BEE}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | Debug|Any CPU = Debug|Any CPU 31 | Release|Any CPU = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {3DF9D910-5A2D-4038-91E8-E136C56E6918}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {3DF9D910-5A2D-4038-91E8-E136C56E6918}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {3DF9D910-5A2D-4038-91E8-E136C56E6918}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {3DF9D910-5A2D-4038-91E8-E136C56E6918}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {4E0CBE39-3A13-421D-A605-56C46610883B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {4E0CBE39-3A13-421D-A605-56C46610883B}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {4E0CBE39-3A13-421D-A605-56C46610883B}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {4E0CBE39-3A13-421D-A605-56C46610883B}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {CC65BB47-20FD-4B4F-8B2E-39438381084B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {CC65BB47-20FD-4B4F-8B2E-39438381084B}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {CC65BB47-20FD-4B4F-8B2E-39438381084B}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {CC65BB47-20FD-4B4F-8B2E-39438381084B}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {F07B5EB9-5FC0-4969-8F69-3B19186EC9D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {F07B5EB9-5FC0-4969-8F69-3B19186EC9D0}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {F07B5EB9-5FC0-4969-8F69-3B19186EC9D0}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {F07B5EB9-5FC0-4969-8F69-3B19186EC9D0}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {41D909B7-8319-4261-85B9-78DC79376C9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {41D909B7-8319-4261-85B9-78DC79376C9E}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {41D909B7-8319-4261-85B9-78DC79376C9E}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {41D909B7-8319-4261-85B9-78DC79376C9E}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {ABF99209-048D-417F-A6C0-AD7F1E4BA46A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {ABF99209-048D-417F-A6C0-AD7F1E4BA46A}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {ABF99209-048D-417F-A6C0-AD7F1E4BA46A}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {ABF99209-048D-417F-A6C0-AD7F1E4BA46A}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {CAB44AD9-7A47-4AFC-BBB2-84085AC27BEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {CAB44AD9-7A47-4AFC-BBB2-84085AC27BEE}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {CAB44AD9-7A47-4AFC-BBB2-84085AC27BEE}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {CAB44AD9-7A47-4AFC-BBB2-84085AC27BEE}.Release|Any CPU.Build.0 = Release|Any CPU 62 | EndGlobalSection 63 | GlobalSection(SolutionProperties) = preSolution 64 | HideSolutionNode = FALSE 65 | EndGlobalSection 66 | GlobalSection(NestedProjects) = preSolution 67 | {3DF9D910-5A2D-4038-91E8-E136C56E6918} = {F1422284-13A6-4C40-89B3-3558D7AD042C} 68 | {4E0CBE39-3A13-421D-A605-56C46610883B} = {320A36EE-8052-433D-B007-9DE3A2C439BF} 69 | {CC65BB47-20FD-4B4F-8B2E-39438381084B} = {320A36EE-8052-433D-B007-9DE3A2C439BF} 70 | {F07B5EB9-5FC0-4969-8F69-3B19186EC9D0} = {90E9C700-3C64-4F15-9406-F31BAC440D8B} 71 | {41D909B7-8319-4261-85B9-78DC79376C9E} = {F1422284-13A6-4C40-89B3-3558D7AD042C} 72 | {ABF99209-048D-417F-A6C0-AD7F1E4BA46A} = {6823DB3A-7A63-48CF-91C4-5B42DEAE19F8} 73 | {CAB44AD9-7A47-4AFC-BBB2-84085AC27BEE} = {320A36EE-8052-433D-B007-9DE3A2C439BF} 74 | EndGlobalSection 75 | GlobalSection(ExtensibilityGlobals) = postSolution 76 | SolutionGuid = {D3749782-165A-47C9-A8BA-C007F17F3AD9} 77 | EndGlobalSection 78 | EndGlobal 79 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Home Page"; 3 | } 4 | 5 | 67 | 68 | 107 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.IdentityServer/User/UserStore.cs: -------------------------------------------------------------------------------- 1 | using IdentityModel; 2 | using System.Collections.Generic; 3 | using System.IdentityModel.Tokens.Jwt; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System; 7 | 8 | 9 | namespace Nyw.IdentityServer.User { 10 | public class UserStore { 11 | private readonly List _users = null; 12 | 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The users. 17 | public UserStore(/*List users*/) { 18 | //_users = users; 19 | if (_users == null) { 20 | _users = new List { 21 | new UserModel{ SubjectId="1", Username="test1", Usermail="test1@qq.com", MobilePhone="13900000001", Password="P2ssw0rd", Claims=new List{ new Claim("name", "test1"),new Claim("website", "https://test1.com") } }, 22 | new UserModel{ SubjectId="2", Username="test2", Usermail="test2@qq.com", MobilePhone="13900000002", Password="P2ssw0rd", Claims=new List{ new Claim("name", "test2"),new Claim("website", "https://test2.com") } }, 23 | new UserModel{ SubjectId="3", Username="test3", Usermail="test3@qq.com", MobilePhone="13900000003", Password="P2ssw0rd", Claims=new List{ new Claim("name", "test3"),new Claim("website", "https://test3.com") } }, 24 | new UserModel{ SubjectId="4", Username="test4", Usermail="test4@qq.com", MobilePhone="13900000004", Password="P2ssw0rd", Claims=new List{ new Claim("name", "test4"),new Claim("website", "https://test4.com") } }, 25 | new UserModel{ SubjectId="5", Username="test5", Usermail="test5@qq.com", MobilePhone="13900000005", Password="P2ssw0rd", Claims=new List{ new Claim("name", "test5"),new Claim("website", "https://test5.com") } } 26 | }; 27 | } 28 | } 29 | 30 | /// 31 | /// Validates the credentials. 32 | /// 33 | /// The username. 34 | /// The password. 35 | /// 36 | public bool ValidateCredentials(string username, string password) { 37 | var user = FindByUsername(username); 38 | if (user != null) { 39 | return user.Password.Equals(password); 40 | } 41 | 42 | return false; 43 | } 44 | 45 | /// 46 | /// Finds the user by subject identifier. 47 | /// 48 | /// The subject identifier. 49 | /// 50 | public UserModel FindBySubjectId(string subjectId) { 51 | return _users.FirstOrDefault(x => x.SubjectId == subjectId); 52 | } 53 | 54 | /// 55 | /// Finds the user by username. 56 | /// 57 | /// The username. 58 | /// 59 | public UserModel FindByUsername(string username) { 60 | return _users.FirstOrDefault(x => x.Username.Equals(username, StringComparison.OrdinalIgnoreCase)); 61 | } 62 | 63 | /// 64 | /// Finds the user by external provider. 65 | /// 66 | /// The provider. 67 | /// The user identifier. 68 | /// 69 | public UserModel FindByExternalProvider(string provider, string userId) { 70 | /*return _users.FirstOrDefault(x => 71 | x.ProviderName == provider && 72 | x.ProviderSubjectId == userId);*/ 73 | return null; 74 | } 75 | 76 | /// 77 | /// Automatically provisions a user. 78 | /// 79 | /// The provider. 80 | /// The user identifier. 81 | /// The claims. 82 | /// 83 | public UserModel AutoProvisionUser(string provider, string userId, List claims) { 84 | // create a list of claims that we want to transfer into our store 85 | var filtered = new List(); 86 | 87 | foreach (var claim in claims) { 88 | // if the external system sends a display name - translate that to the standard OIDC name claim 89 | if (claim.Type == ClaimTypes.Name) { 90 | filtered.Add(new Claim(JwtClaimTypes.Name, claim.Value)); 91 | } 92 | // if the JWT handler has an outbound mapping to an OIDC claim use that 93 | else if (JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.ContainsKey(claim.Type)) { 94 | filtered.Add(new Claim(JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap[claim.Type], claim.Value)); 95 | } 96 | // copy the claim as-is 97 | else { 98 | filtered.Add(claim); 99 | } 100 | } 101 | 102 | // if no display name was provided, try to construct by first and/or last name 103 | if (!filtered.Any(x => x.Type == JwtClaimTypes.Name)) { 104 | var first = filtered.FirstOrDefault(x => x.Type == JwtClaimTypes.GivenName)?.Value; 105 | var last = filtered.FirstOrDefault(x => x.Type == JwtClaimTypes.FamilyName)?.Value; 106 | if (first != null && last != null) { 107 | filtered.Add(new Claim(JwtClaimTypes.Name, first + " " + last)); 108 | } 109 | else if (first != null) { 110 | filtered.Add(new Claim(JwtClaimTypes.Name, first)); 111 | } 112 | else if (last != null) { 113 | filtered.Add(new Claim(JwtClaimTypes.Name, last)); 114 | } 115 | } 116 | 117 | // create a new unique subject id 118 | var sub = CryptoRandom.CreateUniqueId(); 119 | 120 | // check if a display name is available, otherwise fallback to subject id 121 | var name = filtered.FirstOrDefault(c => c.Type == JwtClaimTypes.Name)?.Value ?? sub; 122 | 123 | // create new user 124 | var user = new UserModel { 125 | SubjectId = sub, 126 | Username = name, 127 | /*ProviderName = provider, 128 | ProviderSubjectId = userId,*/ 129 | Claims = filtered 130 | }; 131 | 132 | // add user to in-memory store 133 | _users.Add(user); 134 | 135 | return user; 136 | } 137 | 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | .vscode/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # Visual Studio 2017 auto generated files 34 | Generated\ Files/ 35 | 36 | # MSTest test Results 37 | [Tt]est[Rr]esult*/ 38 | [Bb]uild[Ll]og.* 39 | 40 | # NUNIT 41 | *.VisualState.xml 42 | TestResult.xml 43 | 44 | # Build Results of an ATL Project 45 | [Dd]ebugPS/ 46 | [Rr]eleasePS/ 47 | dlldata.c 48 | 49 | # Benchmark Results 50 | BenchmarkDotNet.Artifacts/ 51 | 52 | # .NET Core 53 | project.lock.json 54 | project.fragment.lock.json 55 | artifacts/ 56 | **/Properties/launchSettings.json 57 | 58 | # StyleCop 59 | StyleCopReport.xml 60 | 61 | # Files built by Visual Studio 62 | *_i.c 63 | *_p.c 64 | *_i.h 65 | *.ilk 66 | *.meta 67 | *.obj 68 | *.iobj 69 | *.pch 70 | *.pdb 71 | *.ipdb 72 | *.pgc 73 | *.pgd 74 | *.rsp 75 | *.sbr 76 | *.tlb 77 | *.tli 78 | *.tlh 79 | *.tmp 80 | *.tmp_proj 81 | *.log 82 | *.vspscc 83 | *.vssscc 84 | .builds 85 | *.pidb 86 | *.svclog 87 | *.scc 88 | 89 | # Chutzpah Test files 90 | _Chutzpah* 91 | 92 | # Visual C++ cache files 93 | ipch/ 94 | *.aps 95 | *.ncb 96 | *.opendb 97 | *.opensdf 98 | *.sdf 99 | *.cachefile 100 | *.VC.db 101 | *.VC.VC.opendb 102 | 103 | # Visual Studio profiler 104 | *.psess 105 | *.vsp 106 | *.vspx 107 | *.sap 108 | 109 | # Visual Studio Trace Files 110 | *.e2e 111 | 112 | # TFS 2012 Local Workspace 113 | $tf/ 114 | 115 | # Guidance Automation Toolkit 116 | *.gpState 117 | 118 | # ReSharper is a .NET coding add-in 119 | _ReSharper*/ 120 | *.[Rr]e[Ss]harper 121 | *.DotSettings.user 122 | 123 | # JustCode is a .NET coding add-in 124 | .JustCode 125 | 126 | # TeamCity is a build add-in 127 | _TeamCity* 128 | 129 | # DotCover is a Code Coverage Tool 130 | *.dotCover 131 | 132 | # AxoCover is a Code Coverage Tool 133 | .axoCover/* 134 | !.axoCover/settings.json 135 | 136 | # Visual Studio code coverage results 137 | *.coverage 138 | *.coveragexml 139 | 140 | # NCrunch 141 | _NCrunch_* 142 | .*crunch*.local.xml 143 | nCrunchTemp_* 144 | 145 | # MightyMoose 146 | *.mm.* 147 | AutoTest.Net/ 148 | 149 | # Web workbench (sass) 150 | .sass-cache/ 151 | 152 | # Installshield output folder 153 | [Ee]xpress/ 154 | 155 | # DocProject is a documentation generator add-in 156 | DocProject/buildhelp/ 157 | DocProject/Help/*.HxT 158 | DocProject/Help/*.HxC 159 | DocProject/Help/*.hhc 160 | DocProject/Help/*.hhk 161 | DocProject/Help/*.hhp 162 | DocProject/Help/Html2 163 | DocProject/Help/html 164 | 165 | # Click-Once directory 166 | publish/ 167 | 168 | # Publish Web Output 169 | *.[Pp]ublish.xml 170 | *.azurePubxml 171 | # Note: Comment the next line if you want to checkin your web deploy settings, 172 | # but database connection strings (with potential passwords) will be unencrypted 173 | *.pubxml 174 | *.publishproj 175 | 176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 177 | # checkin your Azure Web App publish settings, but sensitive information contained 178 | # in these scripts will be unencrypted 179 | PublishScripts/ 180 | 181 | # NuGet Packages 182 | *.nupkg 183 | # The packages folder can be ignored because of Package Restore 184 | **/[Pp]ackages/* 185 | # except build/, which is used as an MSBuild target. 186 | !**/[Pp]ackages/build/ 187 | # Uncomment if necessary however generally it will be regenerated when needed 188 | #!**/[Pp]ackages/repositories.config 189 | # NuGet v3's project.json files produces more ignorable files 190 | *.nuget.props 191 | *.nuget.targets 192 | 193 | # Microsoft Azure Build Output 194 | csx/ 195 | *.build.csdef 196 | 197 | # Microsoft Azure Emulator 198 | ecf/ 199 | rcf/ 200 | 201 | # Windows Store app package directories and files 202 | AppPackages/ 203 | BundleArtifacts/ 204 | Package.StoreAssociation.xml 205 | _pkginfo.txt 206 | *.appx 207 | 208 | # Visual Studio cache files 209 | # files ending in .cache can be ignored 210 | *.[Cc]ache 211 | # but keep track of directories ending in .cache 212 | !*.[Cc]ache/ 213 | 214 | # Others 215 | ClientBin/ 216 | ~$* 217 | *~ 218 | *.dbmdl 219 | *.dbproj.schemaview 220 | *.jfm 221 | *.pfx 222 | *.publishsettings 223 | orleans.codegen.cs 224 | 225 | # Including strong name files can present a security risk 226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 227 | #*.snk 228 | 229 | # Since there are multiple workflows, uncomment next line to ignore bower_components 230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 231 | #bower_components/ 232 | 233 | # RIA/Silverlight projects 234 | Generated_Code/ 235 | 236 | # Backup & report files from converting an old project file 237 | # to a newer Visual Studio version. Backup files are not needed, 238 | # because we have git ;-) 239 | _UpgradeReport_Files/ 240 | Backup*/ 241 | UpgradeLog*.XML 242 | UpgradeLog*.htm 243 | ServiceFabricBackup/ 244 | *.rptproj.bak 245 | 246 | # SQL Server files 247 | *.mdf 248 | *.ldf 249 | *.ndf 250 | 251 | # Business Intelligence projects 252 | *.rdl.data 253 | *.bim.layout 254 | *.bim_*.settings 255 | *.rptproj.rsuser 256 | 257 | # Microsoft Fakes 258 | FakesAssemblies/ 259 | 260 | # GhostDoc plugin setting file 261 | *.GhostDoc.xml 262 | 263 | # Node.js Tools for Visual Studio 264 | .ntvs_analysis.dat 265 | node_modules/ 266 | 267 | # Visual Studio 6 build log 268 | *.plg 269 | 270 | # Visual Studio 6 workspace options file 271 | *.opt 272 | 273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 274 | *.vbw 275 | 276 | # Visual Studio LightSwitch build output 277 | **/*.HTMLClient/GeneratedArtifacts 278 | **/*.DesktopClient/GeneratedArtifacts 279 | **/*.DesktopClient/ModelManifest.xml 280 | **/*.Server/GeneratedArtifacts 281 | **/*.Server/ModelManifest.xml 282 | _Pvt_Extensions 283 | 284 | # Paket dependency manager 285 | .paket/paket.exe 286 | paket-files/ 287 | 288 | # FAKE - F# Make 289 | .fake/ 290 | 291 | # JetBrains Rider 292 | .idea/ 293 | *.sln.iml 294 | 295 | # CodeRush 296 | .cr/ 297 | 298 | # Python Tools for Visual Studio (PTVS) 299 | __pycache__/ 300 | *.pyc 301 | 302 | # Cake - Uncomment if you are using it 303 | # tools/** 304 | # !tools/packages.config 305 | 306 | # Tabs Studio 307 | *.tss 308 | 309 | # Telerik's JustMock configuration file 310 | *.jmconfig 311 | 312 | # BizTalk build output 313 | *.btp.cs 314 | *.btm.cs 315 | *.odx.cs 316 | *.xsd.cs 317 | 318 | # OpenCover UI analysis results 319 | OpenCover/ 320 | 321 | # Azure Stream Analytics local run output 322 | ASALocalRun/ 323 | 324 | # MSBuild Binary and Structured Log 325 | *.binlog 326 | 327 | # NVidia Nsight GPU debugger configuration file 328 | *.nvuser 329 | 330 | # MFractors (Xamarin productivity tool) working folder 331 | .mfractor/ 332 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/images/banner2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/images/banner1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/images/banner3.svg: -------------------------------------------------------------------------------- 1 | banner3b -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/images/banner4.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /POC/nyw.microservice/Nyw.Portal/wwwroot/lib/jquery-validation/dist/additional-methods.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.14.0 - 6/30/2015 2 | * http://jqueryvalidation.org/ 3 | * Copyright (c) 2015 Jörn Zaefferer; Licensed MIT */ 4 | !function(a){"function"==typeof define&&define.amd?define(["jquery","./jquery.validate.min"],a):a(jQuery)}(function(a){!function(){function b(a){return a.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," ").replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g,"")}a.validator.addMethod("maxWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length<=d},a.validator.format("Please enter {0} words or less.")),a.validator.addMethod("minWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length>=d},a.validator.format("Please enter at least {0} words.")),a.validator.addMethod("rangeWords",function(a,c,d){var e=b(a),f=/\b\w+\b/g;return this.optional(c)||e.match(f).length>=d[0]&&e.match(f).length<=d[1]},a.validator.format("Please enter between {0} and {1} words."))}(),a.validator.addMethod("accept",function(b,c,d){var e,f,g="string"==typeof d?d.replace(/\s/g,"").replace(/,/g,"|"):"image/*",h=this.optional(c);if(h)return h;if("file"===a(c).attr("type")&&(g=g.replace(/\*/g,".*"),c.files&&c.files.length))for(e=0;ec;c++)d=h-c,e=f.substring(c,c+1),g+=d*e;return g%11===0},"Please specify a valid bank account number"),a.validator.addMethod("bankorgiroaccountNL",function(b,c){return this.optional(c)||a.validator.methods.bankaccountNL.call(this,b,c)||a.validator.methods.giroaccountNL.call(this,b,c)},"Please specify a valid bank or giro account number"),a.validator.addMethod("bic",function(a,b){return this.optional(b)||/^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test(a)},"Please specify a valid BIC code"),a.validator.addMethod("cifES",function(a){"use strict";var b,c,d,e,f,g,h=[];if(a=a.toUpperCase(),!a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)"))return!1;for(d=0;9>d;d++)h[d]=parseInt(a.charAt(d),10);for(c=h[2]+h[4]+h[6],e=1;8>e;e+=2)f=(2*h[e]).toString(),g=f.charAt(1),c+=parseInt(f.charAt(0),10)+(""===g?0:parseInt(g,10));return/^[ABCDEFGHJNPQRSUVW]{1}/.test(a)?(c+="",b=10-parseInt(c.charAt(c.length-1),10),a+=b,h[8].toString()===String.fromCharCode(64+b)||h[8].toString()===a.charAt(a.length-1)):!1},"Please specify a valid CIF number."),a.validator.addMethod("cpfBR",function(a){if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;var b,c,d,e,f=0;if(b=parseInt(a.substring(9,10),10),c=parseInt(a.substring(10,11),10),d=function(a,b){var c=10*a%11;return(10===c||11===c)&&(c=0),c===b},""===a||"00000000000"===a||"11111111111"===a||"22222222222"===a||"33333333333"===a||"44444444444"===a||"55555555555"===a||"66666666666"===a||"77777777777"===a||"88888888888"===a||"99999999999"===a)return!1;for(e=1;9>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(11-e);if(d(f,b)){for(f=0,e=1;10>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(12-e);return d(f,c)}return!1},"Please specify a valid CPF number"),a.validator.addMethod("creditcardtypes",function(a,b,c){if(/[^0-9\-]+/.test(a))return!1;a=a.replace(/\D/g,"");var d=0;return c.mastercard&&(d|=1),c.visa&&(d|=2),c.amex&&(d|=4),c.dinersclub&&(d|=8),c.enroute&&(d|=16),c.discover&&(d|=32),c.jcb&&(d|=64),c.unknown&&(d|=128),c.all&&(d=255),1&d&&/^(5[12345])/.test(a)?16===a.length:2&d&&/^(4)/.test(a)?16===a.length:4&d&&/^(3[47])/.test(a)?15===a.length:8&d&&/^(3(0[012345]|[68]))/.test(a)?14===a.length:16&d&&/^(2(014|149))/.test(a)?15===a.length:32&d&&/^(6011)/.test(a)?16===a.length:64&d&&/^(3)/.test(a)?16===a.length:64&d&&/^(2131|1800)/.test(a)?15===a.length:128&d?!0:!1},"Please enter a valid credit card number."),a.validator.addMethod("currency",function(a,b,c){var d,e="string"==typeof c,f=e?c:c[0],g=e?!0:c[1];return f=f.replace(/,/g,""),f=g?f+"]":f+"]?",d="^["+f+"([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$",d=new RegExp(d),this.optional(b)||d.test(a)},"Please specify a valid currency"),a.validator.addMethod("dateFA",function(a,b){return this.optional(b)||/^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(a)},a.validator.messages.date),a.validator.addMethod("dateITA",function(a,b){var c,d,e,f,g,h=!1,i=/^\d{1,2}\/\d{1,2}\/\d{4}$/;return i.test(a)?(c=a.split("/"),d=parseInt(c[0],10),e=parseInt(c[1],10),f=parseInt(c[2],10),g=new Date(Date.UTC(f,e-1,d,12,0,0,0)),h=g.getUTCFullYear()===f&&g.getUTCMonth()===e-1&&g.getUTCDate()===d?!0:!1):h=!1,this.optional(b)||h},a.validator.messages.date),a.validator.addMethod("dateNL",function(a,b){return this.optional(b)||/^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(a)},a.validator.messages.date),a.validator.addMethod("extension",function(a,b,c){return c="string"==typeof c?c.replace(/,/g,"|"):"png|jpe?g|gif",this.optional(b)||a.match(new RegExp("\\.("+c+")$","i"))},a.validator.format("Please enter a value with a valid extension.")),a.validator.addMethod("giroaccountNL",function(a,b){return this.optional(b)||/^[0-9]{1,7}$/.test(a)},"Please specify a valid giro account number"),a.validator.addMethod("iban",function(a,b){if(this.optional(b))return!0;var c,d,e,f,g,h,i,j,k,l=a.replace(/ /g,"").toUpperCase(),m="",n=!0,o="",p="";if(c=l.substring(0,2),h={AL:"\\d{8}[\\dA-Z]{16}",AD:"\\d{8}[\\dA-Z]{12}",AT:"\\d{16}",AZ:"[\\dA-Z]{4}\\d{20}",BE:"\\d{12}",BH:"[A-Z]{4}[\\dA-Z]{14}",BA:"\\d{16}",BR:"\\d{23}[A-Z][\\dA-Z]",BG:"[A-Z]{4}\\d{6}[\\dA-Z]{8}",CR:"\\d{17}",HR:"\\d{17}",CY:"\\d{8}[\\dA-Z]{16}",CZ:"\\d{20}",DK:"\\d{14}",DO:"[A-Z]{4}\\d{20}",EE:"\\d{16}",FO:"\\d{14}",FI:"\\d{14}",FR:"\\d{10}[\\dA-Z]{11}\\d{2}",GE:"[\\dA-Z]{2}\\d{16}",DE:"\\d{18}",GI:"[A-Z]{4}[\\dA-Z]{15}",GR:"\\d{7}[\\dA-Z]{16}",GL:"\\d{14}",GT:"[\\dA-Z]{4}[\\dA-Z]{20}",HU:"\\d{24}",IS:"\\d{22}",IE:"[\\dA-Z]{4}\\d{14}",IL:"\\d{19}",IT:"[A-Z]\\d{10}[\\dA-Z]{12}",KZ:"\\d{3}[\\dA-Z]{13}",KW:"[A-Z]{4}[\\dA-Z]{22}",LV:"[A-Z]{4}[\\dA-Z]{13}",LB:"\\d{4}[\\dA-Z]{20}",LI:"\\d{5}[\\dA-Z]{12}",LT:"\\d{16}",LU:"\\d{3}[\\dA-Z]{13}",MK:"\\d{3}[\\dA-Z]{10}\\d{2}",MT:"[A-Z]{4}\\d{5}[\\dA-Z]{18}",MR:"\\d{23}",MU:"[A-Z]{4}\\d{19}[A-Z]{3}",MC:"\\d{10}[\\dA-Z]{11}\\d{2}",MD:"[\\dA-Z]{2}\\d{18}",ME:"\\d{18}",NL:"[A-Z]{4}\\d{10}",NO:"\\d{11}",PK:"[\\dA-Z]{4}\\d{16}",PS:"[\\dA-Z]{4}\\d{21}",PL:"\\d{24}",PT:"\\d{21}",RO:"[A-Z]{4}[\\dA-Z]{16}",SM:"[A-Z]\\d{10}[\\dA-Z]{12}",SA:"\\d{2}[\\dA-Z]{18}",RS:"\\d{18}",SK:"\\d{20}",SI:"\\d{15}",ES:"\\d{20}",SE:"\\d{20}",CH:"\\d{5}[\\dA-Z]{12}",TN:"\\d{20}",TR:"\\d{5}[\\dA-Z]{17}",AE:"\\d{3}\\d{16}",GB:"[A-Z]{4}\\d{14}",VG:"[\\dA-Z]{4}\\d{16}"},g=h[c],"undefined"!=typeof g&&(i=new RegExp("^[A-Z]{2}\\d{2}"+g+"$",""),!i.test(l)))return!1;for(d=l.substring(4,l.length)+l.substring(0,4),j=0;j9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),a.validator.addMethod("nieES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[T]{1}/.test(a)?a[8]===/^[T]{1}[A-Z0-9]{8}$/.test(a):/^[XYZ]{1}/.test(a)?a[8]==="TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.replace("X","0").replace("Y","1").replace("Z","2").substring(0,8)%23):!1:!1},"Please specify a valid NIE number."),a.validator.addMethod("nifES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[0-9]{8}[A-Z]{1}$/.test(a)?"TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,0)%23)===a.charAt(8):/^[KLM]{1}/.test(a)?a[8]===String.fromCharCode(64):!1:!1},"Please specify a valid NIF number."),jQuery.validator.addMethod("notEqualTo",function(b,c,d){return this.optional(c)||!a.validator.methods.equalTo.call(this,b,c,d)},"Please enter a different value, values must not be the same."),a.validator.addMethod("nowhitespace",function(a,b){return this.optional(b)||/^\S+$/i.test(a)},"No white space please"),a.validator.addMethod("pattern",function(a,b,c){return this.optional(b)?!0:("string"==typeof c&&(c=new RegExp("^(?:"+c+")$")),c.test(a))},"Invalid format."),a.validator.addMethod("phoneNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid phone number."),a.validator.addMethod("phoneUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),a.validator.addMethod("phoneUS",function(a,b){return a=a.replace(/\s+/g,""),this.optional(b)||a.length>9&&a.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/)},"Please specify a valid phone number"),a.validator.addMethod("phonesUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),a.validator.addMethod("postalCodeCA",function(a,b){return this.optional(b)||/^[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeBR",function(a,b){return this.optional(b)||/^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test(a)},"Informe um CEP válido."),a.validator.addMethod("postalcodeIT",function(a,b){return this.optional(b)||/^\d{5}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeNL",function(a,b){return this.optional(b)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postcodeUK",function(a,b){return this.optional(b)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(a)},"Please specify a valid UK postcode"),a.validator.addMethod("require_from_group",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_req_grp")?f.data("valid_req_grp"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length>=d[0];return f.data("valid_req_grp",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),h},a.validator.format("Please fill at least {0} of these fields.")),a.validator.addMethod("skip_or_fill_minimum",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_skip")?f.data("valid_skip"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length,i=0===h||h>=d[0];return f.data("valid_skip",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),i},a.validator.format("Please either skip these fields or fill at least {0} of them.")),a.validator.addMethod("stateUS",function(a,b,c){var d,e="undefined"==typeof c,f=e||"undefined"==typeof c.caseSensitive?!1:c.caseSensitive,g=e||"undefined"==typeof c.includeTerritories?!1:c.includeTerritories,h=e||"undefined"==typeof c.includeMilitary?!1:c.includeMilitary;return d=g||h?g&&h?"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":g?"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$":"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$",d=f?new RegExp(d):new RegExp(d,"i"),this.optional(b)||d.test(a)},"Please specify a valid state"),a.validator.addMethod("strippedminlength",function(b,c,d){return a(b).text().length>=d},a.validator.format("Please enter at least {0} characters")),a.validator.addMethod("time",function(a,b){return this.optional(b)||/^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(a)},"Please enter a valid time, between 00:00 and 23:59"),a.validator.addMethod("time12h",function(a,b){return this.optional(b)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(a)},"Please enter a valid time in 12-hour am/pm format"),a.validator.addMethod("url2",function(a,b){return this.optional(b)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},a.validator.messages.url),a.validator.addMethod("vinUS",function(a){if(17!==a.length)return!1;var b,c,d,e,f,g,h=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],i=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],j=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],k=0;for(b=0;17>b;b++){if(e=j[b],d=a.slice(b,b+1),8===b&&(g=d),isNaN(d)){for(c=0;c").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),e=c.settings.submitHandler.call(c,c.currentForm,b),c.submitButton&&d.remove(),void 0!==e?e:!1):!0}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,d=d.concat(c.errorList)}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(b,c){i[c]=f[c],delete f[c],"required"===c&&a(j).removeAttr("aria-required")}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g),a(j).attr("aria-required","true")),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}),a.extend(a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){return!!a.trim(""+a(b).val())},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||-1!==a.inArray(c.keyCode,d)||(b.name in this.submitted||b===this.lastElement)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date ( ISO ).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c=a.data(this.form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!a(this).is(e.ignore)&&e[d].call(c,this,b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler),a(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required","true")},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c=this.clean(b),d=this.validationTargetFor(c),e=!0;return this.lastElement=d,void 0===d?delete this.invalid[c.name]:(this.prepareElement(d),this.currentElements=a(d),e=this.check(d)!==!1,e?delete this.invalid[d.name]:this.invalid[d.name]=!0),a(b).attr("aria-invalid",!e),this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),e},showErrors:function(b){if(b){a.extend(this.errorMap,b),this.errorList=[];for(var c in b)this.errorList.push({message:b[c],element:this.findByName(c)[0]});this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors();var b,c=this.elements().removeData("previousValue").removeAttr("aria-invalid");if(this.settings.unhighlight)for(b=0;c[b];b++)this.settings.unhighlight.call(this,c[b],this.settings.errorClass,"");else c.removeClass(this.settings.errorClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){return!this.name&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in c||!b.objectLength(a(this).rules())?!1:(c[this.name]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([]),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d=a(b),e=b.type;return"radio"===e||"checkbox"===e?this.findByName(b.name).filter(":checked").val():"number"===e&&"undefined"!=typeof b.validity?b.validity.badInput?!1:d.val():(c=d.val(),"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f=a(b).rules(),g=a.map(f,function(a,b){return b}).length,h=!1,i=this.elementValue(b);for(d in f){e={method:d,parameters:f[d]};try{if(c=a.validator.methods[d].call(this,i,b,e.parameters),"dependency-mismatch"===c&&1===g){h=!0;continue}if(h=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(j){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",j),j instanceof TypeError&&(j.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),j}}if(!h)return this.objectLength(f)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;aWarning: No message defined for "+b.name+"")},formatAndAdd:function(b,c){var d=this.defaultMessage(b,c.method),e=/\$?\{(\d+)\}/g;"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),this.errorList.push({message:d,element:b,method:c.method}),this.errorMap[b.name]=d,this.submitted[b.name]=d},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g=this.errorsFor(b),h=this.idOrName(b),i=a(b).attr("aria-describedby");g.length?(g.removeClass(this.settings.validClass).addClass(this.settings.errorClass),g.html(c)):(g=a("<"+this.settings.errorElement+">").attr("id",h+"-error").addClass(this.settings.errorClass).html(c||""),d=g,this.settings.wrapper&&(d=g.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement(d,a(b)):d.insertAfter(b),g.is("label")?g.attr("for",h):0===g.parents("label[for='"+h+"']").length&&(f=g.attr("id").replace(/(:|\.|\[|\]|\$)/g,"\\$1"),i?i.match(new RegExp("\\b"+f+"\\b"))||(i+=" "+f):i=f,a(b).attr("aria-describedby",i),e=this.groups[b.name],e&&a.each(this.groups,function(b,c){c===e&&a("[name='"+b+"']",this.currentForm).attr("aria-describedby",g.attr("id"))}))),!c&&this.settings.success&&(g.text(""),"string"==typeof this.settings.success?g.addClass(this.settings.success):this.settings.success(g,b)),this.toShow=this.toShow.add(g)},errorsFor:function(b){var c=this.idOrName(b),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+d.replace(/\s+/g,", #")),this.errors().filter(e)},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+b+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return this.dependTypes[typeof a]?this.dependTypes[typeof a](a,b):!0},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(a){this.pending[a.name]||(this.pendingRequest++,this.pending[a.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b){return a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,"remote")})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0!==e.param?e.param:!0:delete b[d]}}),a.each(b,function(d,e){b[d]=a.isFunction(e)?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},creditcard:function(a,b){if(this.optional(b))return"dependency-mismatch";if(/[^0-9 \-]+/.test(a))return!1;var c,d,e=0,f=0,g=!1;if(a=a.replace(/\D/g,""),a.length<13||a.length>19)return!1;for(c=a.length-1;c>=0;c--)d=a.charAt(c),f=parseInt(d,10),g&&(f*=2)>9&&(f-=9),e+=f,g=!g;return e%10===0},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||d>=e},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||c>=a},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.off(".validate-equalTo").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d){if(this.optional(c))return"dependency-mismatch";var e,f,g=this.previousValue(c);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),g.originalMessage=this.settings.messages[c.name].remote,this.settings.messages[c.name].remote=g.message,d="string"==typeof d&&{url:d}||d,g.old===b?g.valid:(g.old=b,e=this,this.startRequest(c),f={},f[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:f,context:e.currentForm,success:function(d){var f,h,i,j=d===!0||"true"===d;e.settings.messages[c.name].remote=g.originalMessage,j?(i=e.formSubmitted,e.prepareElement(c),e.formSubmitted=i,e.successList.push(c),delete e.invalid[c.name],e.showErrors()):(f={},h=d||e.defaultMessage(c,"remote"),f[c.name]=g.message=a.isFunction(h)?h(b):h,e.invalid[c.name]=!0,e.showErrors(f)),g.valid=j,e.stopRequest(c,j)}},d)),"pending")}}});var b,c={};a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)})}); --------------------------------------------------------------------------------