├── .dockerignore ├── .gitignore ├── .idea └── .idea.ASPWebApp │ └── .idea │ ├── .gitignore │ ├── encodings.xml │ ├── git_toolbox_prj.xml │ ├── indexLayout.xml │ └── vcs.xml ├── .vs └── ASPWebApp │ └── v17 │ └── .suo ├── ASPWebApp.csproj ├── ASPWebApp.sln ├── ClientApp ├── .browserslistrc ├── .editorconfig ├── .gitignore ├── README.md ├── angular.json ├── aspnetcore-https.js ├── karma.conf.js ├── package-lock.json ├── package.json ├── proxy.conf.js ├── src │ ├── api-authorization │ │ ├── api-authorization.constants.ts │ │ ├── api-authorization.module.spec.ts │ │ ├── api-authorization.module.ts │ │ ├── authorize.guard.spec.ts │ │ ├── authorize.guard.ts │ │ ├── authorize.interceptor.spec.ts │ │ ├── authorize.interceptor.ts │ │ ├── authorize.service.spec.ts │ │ ├── authorize.service.ts │ │ ├── login-menu │ │ │ ├── login-menu.component.css │ │ │ ├── login-menu.component.html │ │ │ ├── login-menu.component.spec.ts │ │ │ └── login-menu.component.ts │ │ ├── login │ │ │ ├── login.component.css │ │ │ ├── login.component.html │ │ │ ├── login.component.spec.ts │ │ │ └── login.component.ts │ │ └── logout │ │ │ ├── logout.component.css │ │ │ ├── logout.component.html │ │ │ ├── logout.component.spec.ts │ │ │ └── logout.component.ts │ ├── app │ │ ├── app.component.html │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.server.module.ts │ │ ├── counter │ │ │ ├── counter.component.html │ │ │ ├── counter.component.spec.ts │ │ │ └── counter.component.ts │ │ ├── fetch-data │ │ │ ├── fetch-data.component.html │ │ │ └── fetch-data.component.ts │ │ ├── home │ │ │ ├── home.component.html │ │ │ └── home.component.ts │ │ └── nav-menu │ │ │ ├── nav-menu.component.css │ │ │ ├── nav-menu.component.html │ │ │ └── nav-menu.component.ts │ ├── assets │ │ └── .gitkeep │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── styles.css │ └── test.ts ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json ├── Controllers ├── OidcConfigurationController.cs └── WeatherForecastController.cs ├── Data ├── ApplicationDbContext.cs └── Migrations │ ├── 00000000000000_CreateIdentitySchema.Designer.cs │ ├── 00000000000000_CreateIdentitySchema.cs │ ├── 20211231110352_inita.Designer.cs │ ├── 20211231110352_inita.cs │ └── ApplicationDbContextModelSnapshot.cs ├── Dockerfile ├── Models └── ApplicationUser.cs ├── Program.cs ├── Properties └── launchSettings.json ├── WeatherForecast.cs ├── app.db ├── app.db-shm ├── app.db-wal ├── appsettings.Development.json ├── appsettings.json └── wwwroot └── favicon.ico /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.dockerignore 2 | **/.env 3 | **/.git 4 | **/.gitignore 5 | **/.project 6 | **/.settings 7 | **/.toolstarget 8 | **/.vs 9 | **/.vscode 10 | **/.idea 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | /packages/ 4 | riderModule.iml 5 | /_ReSharper.Caches/ -------------------------------------------------------------------------------- /.idea/.idea.ASPWebApp/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Rider ignored files 5 | /.idea.ASPWebApp.iml 6 | /contentModel.xml 7 | /modules.xml 8 | /projectSettingsUpdater.xml 9 | # Editor-based HTTP Client requests 10 | /httpRequests/ 11 | # Datasource local storage ignored files 12 | /dataSources/ 13 | /dataSources.local.xml 14 | -------------------------------------------------------------------------------- /.idea/.idea.ASPWebApp/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/.idea.ASPWebApp/.idea/git_toolbox_prj.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/.idea.ASPWebApp/.idea/indexLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/.idea.ASPWebApp/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.vs/ASPWebApp/v17/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/ASPWebAppWithDocker/1e5f4526b3424be67a198ea9f3a4f63549a13c30/.vs/ASPWebApp/v17/.suo -------------------------------------------------------------------------------- /ASPWebApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | false 7 | ClientApp\ 8 | https://localhost:44479 9 | npm start 10 | enable 11 | Linux 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | wwwroot\%(RecursiveDir)%(FileName)%(Extension) 58 | PreserveNewest 59 | true 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /ASPWebApp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASPWebApp", "ASPWebApp.csproj", "{D981FE79-CEC5-4F4A-B762-8C11981892B6}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | Release|Any CPU = Release|Any CPU 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {D981FE79-CEC5-4F4A-B762-8C11981892B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 12 | {D981FE79-CEC5-4F4A-B762-8C11981892B6}.Debug|Any CPU.Build.0 = Debug|Any CPU 13 | {D981FE79-CEC5-4F4A-B762-8C11981892B6}.Release|Any CPU.ActiveCfg = Release|Any CPU 14 | {D981FE79-CEC5-4F4A-B762-8C11981892B6}.Release|Any CPU.Build.0 = Release|Any CPU 15 | EndGlobalSection 16 | EndGlobal 17 | -------------------------------------------------------------------------------- /ClientApp/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /ClientApp/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | 18 | [*.{razor,cshtml}] 19 | charset = utf-8-bom 20 | -------------------------------------------------------------------------------- /ClientApp/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /dist-server 6 | /tmp 7 | /out-tsc 8 | 9 | # dependencies 10 | /node_modules 11 | 12 | # IDEs and editors 13 | /.idea 14 | .project 15 | .classpath 16 | .c9/ 17 | *.launch 18 | .settings/ 19 | *.sublime-workspace 20 | 21 | # IDE - VSCode 22 | .vscode/* 23 | !.vscode/settings.json 24 | !.vscode/tasks.json 25 | !.vscode/launch.json 26 | !.vscode/extensions.json 27 | 28 | # misc 29 | /.sass-cache 30 | /connect.lock 31 | /coverage 32 | /libpeerconnection.log 33 | npm-debug.log 34 | yarn-error.log 35 | testem.log 36 | /typings 37 | 38 | # System Files 39 | .DS_Store 40 | Thumbs.db 41 | -------------------------------------------------------------------------------- /ClientApp/README.md: -------------------------------------------------------------------------------- 1 | # ASPWebApp 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 28 | -------------------------------------------------------------------------------- /ClientApp/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "cli": { 4 | "analytics": "71ecee38-180a-495a-a335-434e4b5db2b8" 5 | }, 6 | "version": 1, 7 | "newProjectRoot": "projects", 8 | "projects": { 9 | "ASPWebApp": { 10 | "projectType": "application", 11 | "schematics": { 12 | "@schematics/angular:application": { 13 | "strict": true 14 | } 15 | }, 16 | "root": "", 17 | "sourceRoot": "src", 18 | "prefix": "app", 19 | "architect": { 20 | "build": { 21 | "builder": "@angular-devkit/build-angular:browser", 22 | "options": { 23 | "progress": false, 24 | "outputPath": "dist", 25 | "index": "src/index.html", 26 | "main": "src/main.ts", 27 | "polyfills": "src/polyfills.ts", 28 | "tsConfig": "tsconfig.app.json", 29 | "assets": [ 30 | "src/assets" 31 | ], 32 | "styles": [ 33 | "node_modules/bootstrap/dist/css/bootstrap.min.css", 34 | "src/styles.css" 35 | ], 36 | "scripts": [] 37 | }, 38 | "configurations": { 39 | "production": { 40 | "budgets": [ 41 | { 42 | "type": "initial", 43 | "maximumWarning": "500kb", 44 | "maximumError": "1mb" 45 | }, 46 | { 47 | "type": "anyComponentStyle", 48 | "maximumWarning": "2kb", 49 | "maximumError": "4kb" 50 | } 51 | ], 52 | "fileReplacements": [ 53 | { 54 | "replace": "src/environments/environment.ts", 55 | "with": "src/environments/environment.prod.ts" 56 | } 57 | ], 58 | "outputHashing": "all" 59 | }, 60 | "development": { 61 | "buildOptimizer": false, 62 | "optimization": false, 63 | "vendorChunk": true, 64 | "extractLicenses": false, 65 | "sourceMap": true, 66 | "namedChunks": true 67 | } 68 | }, 69 | "defaultConfiguration": "production" 70 | }, 71 | "serve": { 72 | "builder": "@angular-devkit/build-angular:dev-server", 73 | "configurations": { 74 | "production": { 75 | "browserTarget": "ASPWebApp:build:production" 76 | }, 77 | "development": { 78 | "browserTarget": "ASPWebApp:build:development", 79 | "proxyConfig": "proxy.conf.js" 80 | } 81 | }, 82 | "defaultConfiguration": "development" 83 | }, 84 | "extract-i18n": { 85 | "builder": "@angular-devkit/build-angular:extract-i18n", 86 | "options": { 87 | "browserTarget": "ASPWebApp:build" 88 | } 89 | }, 90 | "test": { 91 | "builder": "@angular-devkit/build-angular:karma", 92 | "options": { 93 | "main": "src/test.ts", 94 | "polyfills": "src/polyfills.ts", 95 | "tsConfig": "tsconfig.spec.json", 96 | "karmaConfig": "karma.conf.js", 97 | "assets": [ 98 | "src/assets" 99 | ], 100 | "styles": [ 101 | "src/styles.css" 102 | ], 103 | "scripts": [] 104 | } 105 | }, 106 | "server": { 107 | "builder": "@angular-devkit/build-angular:server", 108 | "options": { 109 | "outputPath": "dist-server", 110 | "main": "src/main.ts", 111 | "tsConfig": "tsconfig.server.json" 112 | }, 113 | "configurations": { 114 | "dev": { 115 | "optimization": true, 116 | "outputHashing": "all", 117 | "sourceMap": false, 118 | "namedChunks": false, 119 | "extractLicenses": true, 120 | "vendorChunk": true 121 | }, 122 | "production": { 123 | "optimization": true, 124 | "outputHashing": "all", 125 | "sourceMap": false, 126 | "namedChunks": false, 127 | "extractLicenses": true, 128 | "vendorChunk": false 129 | } 130 | } 131 | } 132 | } 133 | } 134 | }, 135 | "defaultProject": "ASPWebApp" 136 | } 137 | -------------------------------------------------------------------------------- /ClientApp/aspnetcore-https.js: -------------------------------------------------------------------------------- 1 | // This script sets up HTTPS for the application using the ASP.NET Core HTTPS certificate 2 | const fs = require('fs'); 3 | const spawn = require('child_process').spawn; 4 | const path = require('path'); 5 | 6 | const baseFolder = 7 | process.env.APPDATA !== undefined && process.env.APPDATA !== '' 8 | ? `${process.env.APPDATA}/ASP.NET/https` 9 | : `${process.env.HOME}/.aspnet/https`; 10 | 11 | const certificateArg = process.argv.map(arg => arg.match(/--name=(?.+)/i)).filter(Boolean)[0]; 12 | const certificateName = certificateArg ? certificateArg.groups.value : process.env.npm_package_name; 13 | 14 | if (!certificateName) { 15 | console.error('Invalid certificate name. Run this script in the context of an npm/yarn script or pass --name=<> explicitly.') 16 | process.exit(-1); 17 | } 18 | 19 | const certFilePath = path.join(baseFolder, `${certificateName}.pem`); 20 | const keyFilePath = path.join(baseFolder, `${certificateName}.key`); 21 | 22 | if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) { 23 | spawn('dotnet', [ 24 | 'dev-certs', 25 | 'https', 26 | '--export-path', 27 | certFilePath, 28 | '--format', 29 | 'Pem', 30 | '--no-password', 31 | ], { stdio: 'inherit', }) 32 | .on('exit', (code) => process.exit(code)); 33 | } 34 | -------------------------------------------------------------------------------- /ClientApp/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, './coverage/angularapp'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /ClientApp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aspwebapp", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "prestart": "node aspnetcore-https", 7 | "start": "run-script-os", 8 | "start:windows": "ng serve --port 44479 --ssl --ssl-cert %APPDATA%\\ASP.NET\\https\\%npm_package_name%.pem --ssl-key %APPDATA%\\ASP.NET\\https\\%npm_package_name%.key", 9 | "start:default": "ng serve --port 44479 --ssl --ssl-cert $HOME/.aspnet/https/${npm_package_name}.pem --ssl-key $HOME/.aspnet/https/${npm_package_name}.key", 10 | "build": "ng build", 11 | "build:ssr": "ng run ASPWebApp:server:dev", 12 | "watch": "ng build --watch --configuration development", 13 | "test": "ng test" 14 | }, 15 | "private": true, 16 | "dependencies": { 17 | "@angular/animations": "~12.2.2", 18 | "@angular/common": "~12.2.2", 19 | "@angular/compiler": "~12.2.2", 20 | "@angular/core": "~12.2.2", 21 | "@angular/forms": "~12.2.2", 22 | "@angular/platform-browser": "~12.2.2", 23 | "@angular/platform-browser-dynamic": "~12.2.2", 24 | "@angular/platform-server": "~12.2.2", 25 | "@angular/router": "~12.2.2", 26 | "bootstrap": "^5.1.0", 27 | "jquery": "^3.5.1", 28 | "oidc-client": "^1.11.5", 29 | "popper.js": "^1.16.0", 30 | "run-script-os": "^1.1.6", 31 | "rxjs": "~6.6.0", 32 | "tslib": "^2.1.0", 33 | "zone.js": "~0.11.4" 34 | }, 35 | "devDependencies": { 36 | "@angular-devkit/build-angular": "~12.2.2", 37 | "@angular/cli": "~12.2.2", 38 | "@angular/compiler-cli": "~12.2.2", 39 | "@types/jasmine": "~3.6.0", 40 | "@types/jasminewd2": "~2.0.8", 41 | "@types/node": "^12.11.1", 42 | "jasmine-core": "~3.8.0", 43 | "karma": "~6.3.0", 44 | "karma-chrome-launcher": "~3.1.0", 45 | "karma-coverage": "~2.0.3", 46 | "karma-jasmine": "~4.0.0", 47 | "karma-jasmine-html-reporter": "^1.5.0", 48 | "typescript": "~4.2.3" 49 | }, 50 | "optionalDependencies": {} 51 | } 52 | -------------------------------------------------------------------------------- /ClientApp/proxy.conf.js: -------------------------------------------------------------------------------- 1 | const { env } = require('process'); 2 | 3 | const target = env.ASPNETCORE_HTTPS_PORT ? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}` : 4 | env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:53118'; 5 | 6 | const PROXY_CONFIG = [ 7 | { 8 | context: [ 9 | "/weatherforecast", 10 | "/_configuration", 11 | "/.well-known", 12 | "/Identity", 13 | "/connect", 14 | "/ApplyDatabaseMigrations", 15 | "/_framework" 16 | ], 17 | target: target, 18 | secure: false 19 | } 20 | ] 21 | 22 | module.exports = PROXY_CONFIG; 23 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/api-authorization.constants.ts: -------------------------------------------------------------------------------- 1 | export const ApplicationName = 'ASPWebApp'; 2 | 3 | export const ReturnUrlType = 'returnUrl'; 4 | 5 | export const QueryParameterNames = { 6 | ReturnUrl: ReturnUrlType, 7 | Message: 'message' 8 | }; 9 | 10 | export const LogoutActions = { 11 | LogoutCallback: 'logout-callback', 12 | Logout: 'logout', 13 | LoggedOut: 'logged-out' 14 | }; 15 | 16 | export const LoginActions = { 17 | Login: 'login', 18 | LoginCallback: 'login-callback', 19 | LoginFailed: 'login-failed', 20 | Profile: 'profile', 21 | Register: 'register' 22 | }; 23 | 24 | let applicationPaths: ApplicationPathsType = { 25 | DefaultLoginRedirectPath: '/', 26 | ApiAuthorizationClientConfigurationUrl: `_configuration/${ApplicationName}`, 27 | Login: `authentication/${LoginActions.Login}`, 28 | LoginFailed: `authentication/${LoginActions.LoginFailed}`, 29 | LoginCallback: `authentication/${LoginActions.LoginCallback}`, 30 | Register: `authentication/${LoginActions.Register}`, 31 | Profile: `authentication/${LoginActions.Profile}`, 32 | LogOut: `authentication/${LogoutActions.Logout}`, 33 | LoggedOut: `authentication/${LogoutActions.LoggedOut}`, 34 | LogOutCallback: `authentication/${LogoutActions.LogoutCallback}`, 35 | LoginPathComponents: [], 36 | LoginFailedPathComponents: [], 37 | LoginCallbackPathComponents: [], 38 | RegisterPathComponents: [], 39 | ProfilePathComponents: [], 40 | LogOutPathComponents: [], 41 | LoggedOutPathComponents: [], 42 | LogOutCallbackPathComponents: [], 43 | IdentityRegisterPath: 'Identity/Account/Register', 44 | IdentityManagePath: 'Identity/Account/Manage' 45 | }; 46 | 47 | applicationPaths = { 48 | ...applicationPaths, 49 | LoginPathComponents: applicationPaths.Login.split('/'), 50 | LoginFailedPathComponents: applicationPaths.LoginFailed.split('/'), 51 | RegisterPathComponents: applicationPaths.Register.split('/'), 52 | ProfilePathComponents: applicationPaths.Profile.split('/'), 53 | LogOutPathComponents: applicationPaths.LogOut.split('/'), 54 | LoggedOutPathComponents: applicationPaths.LoggedOut.split('/'), 55 | LogOutCallbackPathComponents: applicationPaths.LogOutCallback.split('/') 56 | }; 57 | 58 | interface ApplicationPathsType { 59 | readonly DefaultLoginRedirectPath: string; 60 | readonly ApiAuthorizationClientConfigurationUrl: string; 61 | readonly Login: string; 62 | readonly LoginFailed: string; 63 | readonly LoginCallback: string; 64 | readonly Register: string; 65 | readonly Profile: string; 66 | readonly LogOut: string; 67 | readonly LoggedOut: string; 68 | readonly LogOutCallback: string; 69 | readonly LoginPathComponents: string []; 70 | readonly LoginFailedPathComponents: string []; 71 | readonly LoginCallbackPathComponents: string []; 72 | readonly RegisterPathComponents: string []; 73 | readonly ProfilePathComponents: string []; 74 | readonly LogOutPathComponents: string []; 75 | readonly LoggedOutPathComponents: string []; 76 | readonly LogOutCallbackPathComponents: string []; 77 | readonly IdentityRegisterPath: string; 78 | readonly IdentityManagePath: string; 79 | } 80 | 81 | export const ApplicationPaths: ApplicationPathsType = applicationPaths; 82 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/api-authorization.module.spec.ts: -------------------------------------------------------------------------------- 1 | import { ApiAuthorizationModule } from './api-authorization.module'; 2 | 3 | describe('ApiAuthorizationModule', () => { 4 | let apiAuthorizationModule: ApiAuthorizationModule; 5 | 6 | beforeEach(() => { 7 | apiAuthorizationModule = new ApiAuthorizationModule(); 8 | }); 9 | 10 | it('should create an instance', () => { 11 | expect(apiAuthorizationModule).toBeTruthy(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/api-authorization.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { LoginMenuComponent } from './login-menu/login-menu.component'; 4 | import { LoginComponent } from './login/login.component'; 5 | import { LogoutComponent } from './logout/logout.component'; 6 | import { RouterModule } from '@angular/router'; 7 | import { ApplicationPaths } from './api-authorization.constants'; 8 | import { HttpClientModule } from '@angular/common/http'; 9 | 10 | @NgModule({ 11 | imports: [ 12 | CommonModule, 13 | HttpClientModule, 14 | RouterModule.forChild( 15 | [ 16 | { path: ApplicationPaths.Register, component: LoginComponent }, 17 | { path: ApplicationPaths.Profile, component: LoginComponent }, 18 | { path: ApplicationPaths.Login, component: LoginComponent }, 19 | { path: ApplicationPaths.LoginFailed, component: LoginComponent }, 20 | { path: ApplicationPaths.LoginCallback, component: LoginComponent }, 21 | { path: ApplicationPaths.LogOut, component: LogoutComponent }, 22 | { path: ApplicationPaths.LoggedOut, component: LogoutComponent }, 23 | { path: ApplicationPaths.LogOutCallback, component: LogoutComponent } 24 | ] 25 | ) 26 | ], 27 | declarations: [LoginMenuComponent, LoginComponent, LogoutComponent], 28 | exports: [LoginMenuComponent, LoginComponent, LogoutComponent] 29 | }) 30 | export class ApiAuthorizationModule { } 31 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/authorize.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AuthorizeGuard } from './authorize.guard'; 4 | 5 | describe('AuthorizeGuard', () => { 6 | beforeEach(() => { 7 | TestBed.configureTestingModule({ 8 | imports: [RouterTestingModule], 9 | providers: [AuthorizeGuard] 10 | }); 11 | }); 12 | 13 | it('should ...', inject([AuthorizeGuard], (guard: AuthorizeGuard) => { 14 | expect(guard).toBeTruthy(); 15 | })); 16 | }); 17 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/authorize.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; 3 | import { Observable } from 'rxjs'; 4 | import { AuthorizeService } from './authorize.service'; 5 | import { tap } from 'rxjs/operators'; 6 | import { ApplicationPaths, QueryParameterNames } from './api-authorization.constants'; 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class AuthorizeGuard implements CanActivate { 12 | constructor(private authorize: AuthorizeService, private router: Router) { 13 | } 14 | canActivate( 15 | _next: ActivatedRouteSnapshot, 16 | state: RouterStateSnapshot): Observable | Promise | boolean { 17 | return this.authorize.isAuthenticated() 18 | .pipe(tap(isAuthenticated => this.handleAuthorization(isAuthenticated, state))); 19 | } 20 | 21 | private handleAuthorization(isAuthenticated: boolean, state: RouterStateSnapshot) { 22 | if (!isAuthenticated) { 23 | this.router.navigate(ApplicationPaths.LoginPathComponents, { 24 | queryParams: { 25 | [QueryParameterNames.ReturnUrl]: state.url 26 | } 27 | }); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/authorize.interceptor.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from '@angular/core/testing'; 2 | 3 | import { AuthorizeInterceptor } from './authorize.interceptor'; 4 | 5 | describe('AuthorizeInterceptor', () => { 6 | beforeEach(() => { 7 | TestBed.configureTestingModule({ 8 | providers: [AuthorizeInterceptor] 9 | }); 10 | }); 11 | 12 | it('should be created', inject([AuthorizeInterceptor], (service: AuthorizeInterceptor) => { 13 | expect(service).toBeTruthy(); 14 | })); 15 | }); 16 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/authorize.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; 3 | import { Observable } from 'rxjs'; 4 | import { AuthorizeService } from './authorize.service'; 5 | import { mergeMap } from 'rxjs/operators'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class AuthorizeInterceptor implements HttpInterceptor { 11 | constructor(private authorize: AuthorizeService) { } 12 | 13 | intercept(req: HttpRequest, next: HttpHandler): Observable> { 14 | return this.authorize.getAccessToken() 15 | .pipe(mergeMap(token => this.processRequestWithToken(token, req, next))); 16 | } 17 | 18 | // Checks if there is an access_token available in the authorize service 19 | // and adds it to the request in case it's targeted at the same origin as the 20 | // single page application. 21 | private processRequestWithToken(token: string | null, req: HttpRequest, next: HttpHandler) { 22 | if (!!token && this.isSameOriginUrl(req)) { 23 | req = req.clone({ 24 | setHeaders: { 25 | Authorization: `Bearer ${token}` 26 | } 27 | }); 28 | } 29 | 30 | return next.handle(req); 31 | } 32 | 33 | private isSameOriginUrl(req: any) { 34 | // It's an absolute url with the same origin. 35 | if (req.url.startsWith(`${window.location.origin}/`)) { 36 | return true; 37 | } 38 | 39 | // It's a protocol relative url with the same origin. 40 | // For example: //www.example.com/api/Products 41 | if (req.url.startsWith(`//${window.location.host}/`)) { 42 | return true; 43 | } 44 | 45 | // It's a relative url like /api/Products 46 | if (/^\/[^\/].*/.test(req.url)) { 47 | return true; 48 | } 49 | 50 | // It's an absolute or protocol relative url that 51 | // doesn't have the same origin. 52 | return false; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/authorize.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from '@angular/core/testing'; 2 | 3 | import { AuthorizeService } from './authorize.service'; 4 | 5 | describe('AuthorizeService', () => { 6 | beforeEach(() => { 7 | TestBed.configureTestingModule({ 8 | providers: [AuthorizeService] 9 | }); 10 | }); 11 | 12 | it('should be created', inject([AuthorizeService], (service: AuthorizeService) => { 13 | expect(service).toBeTruthy(); 14 | })); 15 | }); 16 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/authorize.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { User, UserManager } from 'oidc-client'; 3 | import { BehaviorSubject, concat, from, Observable } from 'rxjs'; 4 | import { filter, map, mergeMap, take, tap } from 'rxjs/operators'; 5 | import { ApplicationPaths, ApplicationName } from './api-authorization.constants'; 6 | 7 | export type IAuthenticationResult = 8 | SuccessAuthenticationResult | 9 | FailureAuthenticationResult | 10 | RedirectAuthenticationResult; 11 | 12 | export interface SuccessAuthenticationResult { 13 | status: AuthenticationResultStatus.Success; 14 | state: any; 15 | } 16 | 17 | export interface FailureAuthenticationResult { 18 | status: AuthenticationResultStatus.Fail; 19 | message: string; 20 | } 21 | 22 | export interface RedirectAuthenticationResult { 23 | status: AuthenticationResultStatus.Redirect; 24 | } 25 | 26 | export enum AuthenticationResultStatus { 27 | Success, 28 | Redirect, 29 | Fail 30 | } 31 | 32 | export interface IUser { 33 | name?: string; 34 | } 35 | 36 | @Injectable({ 37 | providedIn: 'root' 38 | }) 39 | export class AuthorizeService { 40 | // By default pop ups are disabled because they don't work properly on Edge. 41 | // If you want to enable pop up authentication simply set this flag to false. 42 | 43 | private popUpDisabled = true; 44 | private userManager?: UserManager; 45 | private userSubject: BehaviorSubject = new BehaviorSubject(null); 46 | 47 | public isAuthenticated(): Observable { 48 | return this.getUser().pipe(map(u => !!u)); 49 | } 50 | 51 | public getUser(): Observable { 52 | return concat( 53 | this.userSubject.pipe(take(1), filter(u => !!u)), 54 | this.getUserFromStorage().pipe(filter(u => !!u), tap(u => this.userSubject.next(u))), 55 | this.userSubject.asObservable()); 56 | } 57 | 58 | public getAccessToken(): Observable { 59 | return from(this.ensureUserManagerInitialized()) 60 | .pipe(mergeMap(() => from(this.userManager!.getUser())), 61 | map(user => user && user.access_token)); 62 | } 63 | 64 | // We try to authenticate the user in three different ways: 65 | // 1) We try to see if we can authenticate the user silently. This happens 66 | // when the user is already logged in on the IdP and is done using a hidden iframe 67 | // on the client. 68 | // 2) We try to authenticate the user using a PopUp Window. This might fail if there is a 69 | // Pop-Up blocker or the user has disabled PopUps. 70 | // 3) If the two methods above fail, we redirect the browser to the IdP to perform a traditional 71 | // redirect flow. 72 | public async signIn(state: any): Promise { 73 | await this.ensureUserManagerInitialized(); 74 | let user: User | null = null; 75 | try { 76 | user = await this.userManager!.signinSilent(this.createArguments()); 77 | this.userSubject.next(user.profile); 78 | return this.success(state); 79 | } catch (silentError) { 80 | // User might not be authenticated, fallback to popup authentication 81 | console.log('Silent authentication error: ', silentError); 82 | 83 | try { 84 | if (this.popUpDisabled) { 85 | throw new Error('Popup disabled. Change \'authorize.service.ts:AuthorizeService.popupDisabled\' to false to enable it.'); 86 | } 87 | user = await this.userManager!.signinPopup(this.createArguments()); 88 | this.userSubject.next(user.profile); 89 | return this.success(state); 90 | } catch (popupError) { 91 | if (popupError.message === 'Popup window closed') { 92 | // The user explicitly cancelled the login action by closing an opened popup. 93 | return this.error('The user closed the window.'); 94 | } else if (!this.popUpDisabled) { 95 | console.log('Popup authentication error: ', popupError); 96 | } 97 | 98 | // PopUps might be blocked by the user, fallback to redirect 99 | try { 100 | await this.userManager!.signinRedirect(this.createArguments(state)); 101 | return this.redirect(); 102 | } catch (redirectError) { 103 | console.log('Redirect authentication error: ', redirectError); 104 | return this.error(redirectError); 105 | } 106 | } 107 | } 108 | } 109 | 110 | public async completeSignIn(url: string): Promise { 111 | try { 112 | await this.ensureUserManagerInitialized(); 113 | const user = await this.userManager!.signinCallback(url); 114 | this.userSubject.next(user && user.profile); 115 | return this.success(user && user.state); 116 | } catch (error) { 117 | console.log('There was an error signing in: ', error); 118 | return this.error('There was an error signing in.'); 119 | } 120 | } 121 | 122 | public async signOut(state: any): Promise { 123 | try { 124 | if (this.popUpDisabled) { 125 | throw new Error('Popup disabled. Change \'authorize.service.ts:AuthorizeService.popupDisabled\' to false to enable it.'); 126 | } 127 | 128 | await this.ensureUserManagerInitialized(); 129 | await this.userManager!.signoutPopup(this.createArguments()); 130 | this.userSubject.next(null); 131 | return this.success(state); 132 | } catch (popupSignOutError) { 133 | console.log('Popup signout error: ', popupSignOutError); 134 | try { 135 | await this.userManager!.signoutRedirect(this.createArguments(state)); 136 | return this.redirect(); 137 | } catch (redirectSignOutError) { 138 | console.log('Redirect signout error: ', redirectSignOutError); 139 | return this.error(redirectSignOutError); 140 | } 141 | } 142 | } 143 | 144 | public async completeSignOut(url: string): Promise { 145 | await this.ensureUserManagerInitialized(); 146 | try { 147 | const response = await this.userManager!.signoutCallback(url); 148 | this.userSubject.next(null); 149 | return this.success(response && response.state); 150 | } catch (error) { 151 | console.log(`There was an error trying to log out '${error}'.`); 152 | return this.error(error); 153 | } 154 | } 155 | 156 | private createArguments(state?: any): any { 157 | return { useReplaceToNavigate: true, data: state }; 158 | } 159 | 160 | private error(message: string): IAuthenticationResult { 161 | return { status: AuthenticationResultStatus.Fail, message }; 162 | } 163 | 164 | private success(state: any): IAuthenticationResult { 165 | return { status: AuthenticationResultStatus.Success, state }; 166 | } 167 | 168 | private redirect(): IAuthenticationResult { 169 | return { status: AuthenticationResultStatus.Redirect }; 170 | } 171 | 172 | private async ensureUserManagerInitialized(): Promise { 173 | if (this.userManager !== undefined) { 174 | return; 175 | } 176 | 177 | const response = await fetch(ApplicationPaths.ApiAuthorizationClientConfigurationUrl); 178 | if (!response.ok) { 179 | throw new Error(`Could not load settings for '${ApplicationName}'`); 180 | } 181 | 182 | const settings: any = await response.json(); 183 | settings.automaticSilentRenew = true; 184 | settings.includeIdTokenInSilentRenew = true; 185 | this.userManager = new UserManager(settings); 186 | 187 | this.userManager.events.addUserSignedOut(async () => { 188 | await this.userManager!.removeUser(); 189 | this.userSubject.next(null); 190 | }); 191 | } 192 | 193 | private getUserFromStorage(): Observable { 194 | return from(this.ensureUserManagerInitialized()) 195 | .pipe( 196 | mergeMap(() => this.userManager!.getUser()), 197 | map(u => u && u.profile)); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/login-menu/login-menu.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/ASPWebAppWithDocker/1e5f4526b3424be67a198ea9f3a4f63549a13c30/ClientApp/src/api-authorization/login-menu/login-menu.component.css -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/login-menu/login-menu.component.html: -------------------------------------------------------------------------------- 1 | 9 | 17 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/login-menu/login-menu.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { LoginMenuComponent } from './login-menu.component'; 4 | import { AuthorizeService } from '../authorize.service'; 5 | import { of } from 'rxjs'; 6 | 7 | describe('LoginMenuComponent', () => { 8 | let component: LoginMenuComponent; 9 | let fixture: ComponentFixture; 10 | 11 | beforeEach(async(() => { 12 | TestBed.configureTestingModule({ 13 | imports: [RouterTestingModule], 14 | declarations: [ LoginMenuComponent ] 15 | }) 16 | .compileComponents(); 17 | })); 18 | 19 | beforeEach(() => { 20 | let authService = TestBed.get(AuthorizeService); 21 | 22 | spyOn(authService, 'ensureUserManagerInitialized').and.returnValue( 23 | Promise.resolve()); 24 | spyOn(authService, 'getUserFromStorage').and.returnValue( 25 | of(null)); 26 | 27 | fixture = TestBed.createComponent(LoginMenuComponent); 28 | component = fixture.componentInstance; 29 | fixture.detectChanges(); 30 | }); 31 | 32 | it('should create', () => { 33 | expect(component).toBeTruthy(); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/login-menu/login-menu.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { AuthorizeService } from '../authorize.service'; 3 | import { Observable } from 'rxjs'; 4 | import { map } from 'rxjs/operators'; 5 | 6 | @Component({ 7 | selector: 'app-login-menu', 8 | templateUrl: './login-menu.component.html', 9 | styleUrls: ['./login-menu.component.css'] 10 | }) 11 | export class LoginMenuComponent implements OnInit { 12 | public isAuthenticated?: Observable; 13 | public userName?: Observable; 14 | 15 | constructor(private authorizeService: AuthorizeService) { } 16 | 17 | ngOnInit() { 18 | this.isAuthenticated = this.authorizeService.isAuthenticated(); 19 | this.userName = this.authorizeService.getUser().pipe(map(u => u && u.name)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/login/login.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/ASPWebAppWithDocker/1e5f4526b3424be67a198ea9f3a4f63549a13c30/ClientApp/src/api-authorization/login/login.component.css -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/login/login.component.html: -------------------------------------------------------------------------------- 1 |

{{ message | async }}

-------------------------------------------------------------------------------- /ClientApp/src/api-authorization/login/login.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { LoginComponent } from './login.component'; 4 | import { ActivatedRoute, ActivatedRouteSnapshot, UrlSegment, convertToParamMap, Params, Router } from '@angular/router'; 5 | import { of } from 'rxjs'; 6 | import { LoginActions } from '../api-authorization.constants'; 7 | import { HttpParams } from '@angular/common/http'; 8 | import { AuthorizeService } from '../authorize.service'; 9 | import { HomeComponent } from 'src/app/home/home.component'; 10 | 11 | class RouterStub { 12 | url = ''; 13 | navigate(commands: any[], extras?: any) {} 14 | } 15 | 16 | describe('LoginComponent', () => { 17 | let component: LoginComponent; 18 | let fixture: ComponentFixture; 19 | let router: Router; 20 | 21 | beforeEach(async(() => { 22 | let tempParams: Params = { id: '1234' }; 23 | 24 | let segment0: UrlSegment = new UrlSegment('segment0', {}); 25 | let segment1: UrlSegment = new UrlSegment(LoginActions.Login, {}); 26 | 27 | let urlSegments: UrlSegment[] = [segment0, segment1]; 28 | 29 | TestBed.configureTestingModule({ 30 | imports: [ 31 | RouterTestingModule.withRoutes([ 32 | { path: 'authentication/login-failed', component: HomeComponent } 33 | ])], 34 | declarations: [LoginComponent, HomeComponent], 35 | providers: [{ 36 | provide: ActivatedRoute, useValue: { 37 | snapshot: { 38 | paramMap: convertToParamMap(tempParams), 39 | url: urlSegments, 40 | queryParams: tempParams 41 | } 42 | } 43 | }] 44 | }).compileComponents(); 45 | 46 | router = TestBed.get(Router); 47 | spyOn(router, 'navigate').and.returnValue(Promise.resolve(true)); 48 | })); 49 | 50 | beforeEach(() => { 51 | let authService = TestBed.get(AuthorizeService); 52 | 53 | spyOn(authService, 'ensureUserManagerInitialized').and.returnValue( 54 | Promise.resolve()); 55 | 56 | fixture = TestBed.createComponent(LoginComponent); 57 | component = fixture.componentInstance; 58 | fixture.detectChanges(); 59 | }); 60 | 61 | it('should create', () => { 62 | expect(component).toBeTruthy(); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/login/login.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { AuthorizeService, AuthenticationResultStatus } from '../authorize.service'; 3 | import { ActivatedRoute, Router } from '@angular/router'; 4 | import { BehaviorSubject } from 'rxjs'; 5 | import { LoginActions, QueryParameterNames, ApplicationPaths, ReturnUrlType } from '../api-authorization.constants'; 6 | 7 | // The main responsibility of this component is to handle the user's login process. 8 | // This is the starting point for the login process. Any component that needs to authenticate 9 | // a user can simply perform a redirect to this component with a returnUrl query parameter and 10 | // let the component perform the login and return back to the return url. 11 | @Component({ 12 | selector: 'app-login', 13 | templateUrl: './login.component.html', 14 | styleUrls: ['./login.component.css'] 15 | }) 16 | export class LoginComponent implements OnInit { 17 | public message = new BehaviorSubject(null); 18 | 19 | constructor( 20 | private authorizeService: AuthorizeService, 21 | private activatedRoute: ActivatedRoute, 22 | private router: Router) { } 23 | 24 | async ngOnInit() { 25 | const action = this.activatedRoute.snapshot.url[1]; 26 | switch (action.path) { 27 | case LoginActions.Login: 28 | await this.login(this.getReturnUrl()); 29 | break; 30 | case LoginActions.LoginCallback: 31 | await this.processLoginCallback(); 32 | break; 33 | case LoginActions.LoginFailed: 34 | const message = this.activatedRoute.snapshot.queryParamMap.get(QueryParameterNames.Message); 35 | this.message.next(message); 36 | break; 37 | case LoginActions.Profile: 38 | this.redirectToProfile(); 39 | break; 40 | case LoginActions.Register: 41 | this.redirectToRegister(); 42 | break; 43 | default: 44 | throw new Error(`Invalid action '${action}'`); 45 | } 46 | } 47 | 48 | 49 | private async login(returnUrl: string): Promise { 50 | const state: INavigationState = { returnUrl }; 51 | const result = await this.authorizeService.signIn(state); 52 | this.message.next(undefined); 53 | switch (result.status) { 54 | case AuthenticationResultStatus.Redirect: 55 | break; 56 | case AuthenticationResultStatus.Success: 57 | await this.navigateToReturnUrl(returnUrl); 58 | break; 59 | case AuthenticationResultStatus.Fail: 60 | await this.router.navigate(ApplicationPaths.LoginFailedPathComponents, { 61 | queryParams: { [QueryParameterNames.Message]: result.message } 62 | }); 63 | break; 64 | default: 65 | throw new Error(`Invalid status result ${(result as any).status}.`); 66 | } 67 | } 68 | 69 | private async processLoginCallback(): Promise { 70 | const url = window.location.href; 71 | const result = await this.authorizeService.completeSignIn(url); 72 | switch (result.status) { 73 | case AuthenticationResultStatus.Redirect: 74 | // There should not be any redirects as completeSignIn never redirects. 75 | throw new Error('Should not redirect.'); 76 | case AuthenticationResultStatus.Success: 77 | await this.navigateToReturnUrl(this.getReturnUrl(result.state)); 78 | break; 79 | case AuthenticationResultStatus.Fail: 80 | this.message.next(result.message); 81 | break; 82 | } 83 | } 84 | 85 | private redirectToRegister(): any { 86 | this.redirectToApiAuthorizationPath( 87 | `${ApplicationPaths.IdentityRegisterPath}?returnUrl=${encodeURI('/' + ApplicationPaths.Login)}`); 88 | } 89 | 90 | private redirectToProfile(): void { 91 | this.redirectToApiAuthorizationPath(ApplicationPaths.IdentityManagePath); 92 | } 93 | 94 | private async navigateToReturnUrl(returnUrl: string) { 95 | // It's important that we do a replace here so that we remove the callback uri with the 96 | // fragment containing the tokens from the browser history. 97 | await this.router.navigateByUrl(returnUrl, { 98 | replaceUrl: true 99 | }); 100 | } 101 | 102 | private getReturnUrl(state?: INavigationState): string { 103 | const fromQuery = (this.activatedRoute.snapshot.queryParams as INavigationState).returnUrl; 104 | // If the url is coming from the query string, check that is either 105 | // a relative url or an absolute url 106 | if (fromQuery && 107 | !(fromQuery.startsWith(`${window.location.origin}/`) || 108 | /\/[^\/].*/.test(fromQuery))) { 109 | // This is an extra check to prevent open redirects. 110 | throw new Error('Invalid return url. The return url needs to have the same origin as the current page.'); 111 | } 112 | return (state && state.returnUrl) || 113 | fromQuery || 114 | ApplicationPaths.DefaultLoginRedirectPath; 115 | } 116 | 117 | private redirectToApiAuthorizationPath(apiAuthorizationPath: string) { 118 | // It's important that we do a replace here so that when the user hits the back arrow on the 119 | // browser they get sent back to where it was on the app instead of to an endpoint on this 120 | // component. 121 | const redirectUrl = `${window.location.origin}/${apiAuthorizationPath}`; 122 | window.location.replace(redirectUrl); 123 | } 124 | } 125 | 126 | interface INavigationState { 127 | [ReturnUrlType]: string; 128 | } 129 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/logout/logout.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/ASPWebAppWithDocker/1e5f4526b3424be67a198ea9f3a4f63549a13c30/ClientApp/src/api-authorization/logout/logout.component.css -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/logout/logout.component.html: -------------------------------------------------------------------------------- 1 |

{{ message | async }}

-------------------------------------------------------------------------------- /ClientApp/src/api-authorization/logout/logout.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { LogoutComponent } from './logout.component'; 4 | import { HomeComponent } from 'src/app/home/home.component'; 5 | import { ActivatedRoute, convertToParamMap, Params, UrlSegment } from '@angular/router'; 6 | import { LogoutActions } from '../api-authorization.constants'; 7 | 8 | describe('LogoutComponent', () => { 9 | let component: LogoutComponent; 10 | let fixture: ComponentFixture; 11 | 12 | beforeEach(async(() => { 13 | let tempParams: Params = { id: '1234' }; 14 | 15 | let segment0: UrlSegment = new UrlSegment('segment0', {}); 16 | let segment1: UrlSegment = new UrlSegment(LogoutActions.LoggedOut, {}); 17 | 18 | let urlSegments: UrlSegment[] = [segment0, segment1]; 19 | 20 | TestBed.configureTestingModule({ 21 | imports: [ 22 | RouterTestingModule.withRoutes([ 23 | { path: 'authentication/login-failed', component: HomeComponent } 24 | ])], 25 | declarations: [LogoutComponent, HomeComponent], 26 | providers: [{ 27 | provide: ActivatedRoute, useValue: { 28 | snapshot: { 29 | paramMap: convertToParamMap(tempParams), 30 | url: urlSegments, 31 | queryParams: tempParams 32 | } 33 | } 34 | }] 35 | }) 36 | .compileComponents(); 37 | })); 38 | 39 | beforeEach(() => { 40 | fixture = TestBed.createComponent(LogoutComponent); 41 | component = fixture.componentInstance; 42 | fixture.detectChanges(); 43 | }); 44 | 45 | it('should create', () => { 46 | expect(component).toBeTruthy(); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /ClientApp/src/api-authorization/logout/logout.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { AuthenticationResultStatus, AuthorizeService } from '../authorize.service'; 3 | import { BehaviorSubject } from 'rxjs'; 4 | import { ActivatedRoute, Router } from '@angular/router'; 5 | import { take } from 'rxjs/operators'; 6 | import { LogoutActions, ApplicationPaths, ReturnUrlType } from '../api-authorization.constants'; 7 | 8 | // The main responsibility of this component is to handle the user's logout process. 9 | // This is the starting point for the logout process, which is usually initiated when a 10 | // user clicks on the logout button on the LoginMenu component. 11 | @Component({ 12 | selector: 'app-logout', 13 | templateUrl: './logout.component.html', 14 | styleUrls: ['./logout.component.css'] 15 | }) 16 | export class LogoutComponent implements OnInit { 17 | public message = new BehaviorSubject(null); 18 | 19 | constructor( 20 | private authorizeService: AuthorizeService, 21 | private activatedRoute: ActivatedRoute, 22 | private router: Router) { } 23 | 24 | async ngOnInit() { 25 | const action = this.activatedRoute.snapshot.url[1]; 26 | switch (action.path) { 27 | case LogoutActions.Logout: 28 | if (!!window.history.state.local) { 29 | await this.logout(this.getReturnUrl()); 30 | } else { 31 | // This prevents regular links to /authentication/logout from triggering a logout 32 | this.message.next('The logout was not initiated from within the page.'); 33 | } 34 | 35 | break; 36 | case LogoutActions.LogoutCallback: 37 | await this.processLogoutCallback(); 38 | break; 39 | case LogoutActions.LoggedOut: 40 | this.message.next('You successfully logged out!'); 41 | break; 42 | default: 43 | throw new Error(`Invalid action '${action}'`); 44 | } 45 | } 46 | 47 | private async logout(returnUrl: string): Promise { 48 | const state: INavigationState = { returnUrl }; 49 | const isauthenticated = await this.authorizeService.isAuthenticated().pipe( 50 | take(1) 51 | ).toPromise(); 52 | if (isauthenticated) { 53 | const result = await this.authorizeService.signOut(state); 54 | switch (result.status) { 55 | case AuthenticationResultStatus.Redirect: 56 | break; 57 | case AuthenticationResultStatus.Success: 58 | await this.navigateToReturnUrl(returnUrl); 59 | break; 60 | case AuthenticationResultStatus.Fail: 61 | this.message.next(result.message); 62 | break; 63 | default: 64 | throw new Error('Invalid authentication result status.'); 65 | } 66 | } else { 67 | this.message.next('You successfully logged out!'); 68 | } 69 | } 70 | 71 | private async processLogoutCallback(): Promise { 72 | const url = window.location.href; 73 | const result = await this.authorizeService.completeSignOut(url); 74 | switch (result.status) { 75 | case AuthenticationResultStatus.Redirect: 76 | // There should not be any redirects as the only time completeAuthentication finishes 77 | // is when we are doing a redirect sign in flow. 78 | throw new Error('Should not redirect.'); 79 | case AuthenticationResultStatus.Success: 80 | await this.navigateToReturnUrl(this.getReturnUrl(result.state)); 81 | break; 82 | case AuthenticationResultStatus.Fail: 83 | this.message.next(result.message); 84 | break; 85 | default: 86 | throw new Error('Invalid authentication result status.'); 87 | } 88 | } 89 | 90 | private async navigateToReturnUrl(returnUrl: string) { 91 | await this.router.navigateByUrl(returnUrl, { 92 | replaceUrl: true 93 | }); 94 | } 95 | 96 | private getReturnUrl(state?: INavigationState): string { 97 | const fromQuery = (this.activatedRoute.snapshot.queryParams as INavigationState).returnUrl; 98 | // If the url is coming from the query string, check that is either 99 | // a relative url or an absolute url 100 | if (fromQuery && 101 | !(fromQuery.startsWith(`${window.location.origin}/`) || 102 | /\/[^\/].*/.test(fromQuery))) { 103 | // This is an extra check to prevent open redirects. 104 | throw new Error('Invalid return url. The return url needs to have the same origin as the current page.'); 105 | } 106 | return (state && state.returnUrl) || 107 | fromQuery || 108 | ApplicationPaths.LoggedOut; 109 | } 110 | } 111 | 112 | interface INavigationState { 113 | [ReturnUrlType]: string; 114 | } 115 | -------------------------------------------------------------------------------- /ClientApp/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | -------------------------------------------------------------------------------- /ClientApp/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html' 6 | }) 7 | export class AppComponent { 8 | title = 'app'; 9 | } 10 | -------------------------------------------------------------------------------- /ClientApp/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; 5 | import { RouterModule } from '@angular/router'; 6 | 7 | import { AppComponent } from './app.component'; 8 | import { NavMenuComponent } from './nav-menu/nav-menu.component'; 9 | import { HomeComponent } from './home/home.component'; 10 | import { CounterComponent } from './counter/counter.component'; 11 | import { FetchDataComponent } from './fetch-data/fetch-data.component'; 12 | import { ApiAuthorizationModule } from 'src/api-authorization/api-authorization.module'; 13 | import { AuthorizeGuard } from 'src/api-authorization/authorize.guard'; 14 | import { AuthorizeInterceptor } from 'src/api-authorization/authorize.interceptor'; 15 | 16 | @NgModule({ 17 | declarations: [ 18 | AppComponent, 19 | NavMenuComponent, 20 | HomeComponent, 21 | CounterComponent, 22 | FetchDataComponent 23 | ], 24 | imports: [ 25 | BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }), 26 | HttpClientModule, 27 | FormsModule, 28 | ApiAuthorizationModule, 29 | RouterModule.forRoot([ 30 | { path: '', component: HomeComponent, pathMatch: 'full' }, 31 | { path: 'counter', component: CounterComponent }, 32 | { path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] }, 33 | ]) 34 | ], 35 | providers: [ 36 | { provide: HTTP_INTERCEPTORS, useClass: AuthorizeInterceptor, multi: true } 37 | ], 38 | bootstrap: [AppComponent] 39 | }) 40 | export class AppModule { } 41 | -------------------------------------------------------------------------------- /ClientApp/src/app/app.server.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { ServerModule } from '@angular/platform-server'; 3 | import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader'; 4 | import { AppComponent } from './app.component'; 5 | import { AppModule } from './app.module'; 6 | 7 | @NgModule({ 8 | imports: [AppModule, ServerModule, ModuleMapLoaderModule], 9 | bootstrap: [AppComponent] 10 | }) 11 | export class AppServerModule { } 12 | -------------------------------------------------------------------------------- /ClientApp/src/app/counter/counter.component.html: -------------------------------------------------------------------------------- 1 |

Counter

2 | 3 |

This is a simple example of an Angular component.

4 | 5 |

Current count: {{ currentCount }}

6 | 7 | 8 | -------------------------------------------------------------------------------- /ClientApp/src/app/counter/counter.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CounterComponent } from './counter.component'; 4 | 5 | describe('CounterComponent', () => { 6 | let fixture: ComponentFixture; 7 | 8 | beforeEach(async(() => { 9 | TestBed.configureTestingModule({ 10 | declarations: [ CounterComponent ] 11 | }) 12 | .compileComponents(); 13 | })); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(CounterComponent); 17 | fixture.detectChanges(); 18 | }); 19 | 20 | it('should display a title', async(() => { 21 | const titleText = fixture.nativeElement.querySelector('h1').textContent; 22 | expect(titleText).toEqual('Counter'); 23 | })); 24 | 25 | it('should start with count 0, then increments by 1 when clicked', async(() => { 26 | const countElement = fixture.nativeElement.querySelector('strong'); 27 | expect(countElement.textContent).toEqual('0'); 28 | 29 | const incrementButton = fixture.nativeElement.querySelector('button'); 30 | incrementButton.click(); 31 | fixture.detectChanges(); 32 | expect(countElement.textContent).toEqual('1'); 33 | })); 34 | }); 35 | -------------------------------------------------------------------------------- /ClientApp/src/app/counter/counter.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-counter-component', 5 | templateUrl: './counter.component.html' 6 | }) 7 | export class CounterComponent { 8 | public currentCount = 0; 9 | 10 | public incrementCounter() { 11 | this.currentCount++; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ClientApp/src/app/fetch-data/fetch-data.component.html: -------------------------------------------------------------------------------- 1 |

Weather forecast

2 | 3 |

This component demonstrates fetching data from the server.

4 | 5 |

Loading...

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
DateTemp. (C)Temp. (F)Summary
{{ forecast.date }}{{ forecast.temperatureC }}{{ forecast.temperatureF }}{{ forecast.summary }}
25 | -------------------------------------------------------------------------------- /ClientApp/src/app/fetch-data/fetch-data.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Inject } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | 4 | @Component({ 5 | selector: 'app-fetch-data', 6 | templateUrl: './fetch-data.component.html' 7 | }) 8 | export class FetchDataComponent { 9 | public forecasts: WeatherForecast[] = []; 10 | 11 | constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) { 12 | http.get(baseUrl + 'weatherforecast').subscribe(result => { 13 | this.forecasts = result; 14 | }, error => console.error(error)); 15 | } 16 | } 17 | 18 | interface WeatherForecast { 19 | date: string; 20 | temperatureC: number; 21 | temperatureF: number; 22 | summary: string; 23 | } 24 | -------------------------------------------------------------------------------- /ClientApp/src/app/home/home.component.html: -------------------------------------------------------------------------------- 1 |

Hello, world!

2 |

Welcome to your new single-page application, built with:

3 | 8 |

To help you get started, we've also set up:

9 |
    10 |
  • Client-side navigation. For example, click Counter then Back to return here.
  • 11 |
  • Angular CLI integration. In development mode, there's no need to run ng serve. It runs in the background automatically, so your client-side resources are dynamically built on demand and the page refreshes when you modify any file.
  • 12 |
  • Efficient production builds. In production mode, development-time features are disabled, and your dotnet publish configuration automatically invokes ng build to produce minified, ahead-of-time compiled JavaScript files.
  • 13 |
14 |

The ClientApp subdirectory is a standard Angular CLI application. If you open a command prompt in that directory, you can run any ng command (e.g., ng test), or use npm to install extra packages into it.

15 | -------------------------------------------------------------------------------- /ClientApp/src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-home', 5 | templateUrl: './home.component.html', 6 | }) 7 | export class HomeComponent { 8 | } 9 | -------------------------------------------------------------------------------- /ClientApp/src/app/nav-menu/nav-menu.component.css: -------------------------------------------------------------------------------- 1 | a.navbar-brand { 2 | white-space: normal; 3 | text-align: center; 4 | word-break: break-all; 5 | } 6 | 7 | html { 8 | font-size: 14px; 9 | } 10 | @media (min-width: 768px) { 11 | html { 12 | font-size: 16px; 13 | } 14 | } 15 | 16 | .box-shadow { 17 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 18 | } 19 | -------------------------------------------------------------------------------- /ClientApp/src/app/nav-menu/nav-menu.component.html: -------------------------------------------------------------------------------- 1 |
2 | 45 |
46 | -------------------------------------------------------------------------------- /ClientApp/src/app/nav-menu/nav-menu.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-nav-menu', 5 | templateUrl: './nav-menu.component.html', 6 | styleUrls: ['./nav-menu.component.css'] 7 | }) 8 | export class NavMenuComponent { 9 | isExpanded = false; 10 | 11 | collapse() { 12 | this.isExpanded = false; 13 | } 14 | 15 | toggle() { 16 | this.isExpanded = !this.isExpanded; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ClientApp/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/ASPWebAppWithDocker/1e5f4526b3424be67a198ea9f3a4f63549a13c30/ClientApp/src/assets/.gitkeep -------------------------------------------------------------------------------- /ClientApp/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /ClientApp/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /ClientApp/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ASPWebApp 6 | 7 | 8 | 9 | 10 | 11 | 12 | Loading... 13 | 14 | 15 | -------------------------------------------------------------------------------- /ClientApp/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | export function getBaseUrl() { 8 | return document.getElementsByTagName('base')[0].href; 9 | } 10 | 11 | const providers = [ 12 | { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] } 13 | ]; 14 | 15 | if (environment.production) { 16 | enableProdMode(); 17 | } 18 | 19 | platformBrowserDynamic(providers).bootstrapModule(AppModule) 20 | .catch(err => console.log(err)); 21 | -------------------------------------------------------------------------------- /ClientApp/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js'; // Included with Angular CLI. 61 | 62 | 63 | /*************************************************************************************************** 64 | * APPLICATION IMPORTS 65 | */ 66 | -------------------------------------------------------------------------------- /ClientApp/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | /* Provide sufficient contrast against white background */ 4 | a { 5 | color: #0366d6; 6 | } 7 | 8 | code { 9 | color: #e01a76; 10 | } 11 | 12 | .btn-primary { 13 | color: #fff; 14 | background-color: #1b6ec2; 15 | border-color: #1861ac; 16 | } 17 | -------------------------------------------------------------------------------- /ClientApp/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context(path: string, deep?: boolean, filter?: RegExp): { 12 | keys(): string[]; 13 | (id: string): T; 14 | }; 15 | }; 16 | 17 | // First, initialize the Angular testing environment. 18 | getTestBed().initTestEnvironment( 19 | BrowserDynamicTestingModule, 20 | platformBrowserDynamicTesting() 21 | ); 22 | // Then we find all the tests. 23 | const context = require.context('./', true, /\.spec\.ts$/); 24 | // And load the modules. 25 | context.keys().map(context); 26 | -------------------------------------------------------------------------------- /ClientApp/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /ClientApp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "noImplicitReturns": true, 9 | "noFallthroughCasesInSwitch": true, 10 | "sourceMap": true, 11 | "declaration": false, 12 | "downlevelIteration": true, 13 | "experimentalDecorators": true, 14 | "moduleResolution": "node", 15 | "importHelpers": true, 16 | "target": "es2017", 17 | "module": "es2020", 18 | "lib": [ 19 | "es2018", 20 | "dom" 21 | ] 22 | }, 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ClientApp/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine", 8 | "node" 9 | ] 10 | }, 11 | "files": [ 12 | "src/test.ts", 13 | "src/polyfills.ts" 14 | ], 15 | "include": [ 16 | "src/**/*.spec.ts", 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /Controllers/OidcConfigurationController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.ApiAuthorization.IdentityServer; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace ASPWebApp.Controllers; 5 | 6 | public class OidcConfigurationController : Controller 7 | { 8 | private readonly ILogger _logger; 9 | 10 | public OidcConfigurationController( 11 | IClientRequestParametersProvider clientRequestParametersProvider, 12 | ILogger logger) 13 | { 14 | ClientRequestParametersProvider = clientRequestParametersProvider; 15 | _logger = logger; 16 | } 17 | 18 | public IClientRequestParametersProvider ClientRequestParametersProvider { get; } 19 | 20 | [HttpGet("_configuration/{clientId}")] 21 | public IActionResult GetClientRequestParameters([FromRoute] string clientId) 22 | { 23 | var parameters = ClientRequestParametersProvider.GetClientParameters(HttpContext, clientId); 24 | return Ok(parameters); 25 | } 26 | } -------------------------------------------------------------------------------- /Controllers/WeatherForecastController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace ASPWebApp.Controllers; 5 | 6 | [Authorize] 7 | [ApiController] 8 | [Route("[controller]")] 9 | public class WeatherForecastController : ControllerBase 10 | { 11 | private static readonly string[] Summaries = new[] 12 | { 13 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 14 | }; 15 | 16 | private readonly ILogger _logger; 17 | 18 | public WeatherForecastController(ILogger logger) 19 | { 20 | _logger = logger; 21 | } 22 | 23 | [HttpGet] 24 | public IEnumerable Get() 25 | { 26 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 27 | { 28 | Date = DateTime.Now.AddDays(index), 29 | TemperatureC = Random.Shared.Next(-20, 55), 30 | Summary = Summaries[Random.Shared.Next(Summaries.Length)] 31 | }) 32 | .ToArray(); 33 | } 34 | } -------------------------------------------------------------------------------- /Data/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.ApiAuthorization.IdentityServer; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.Extensions.Options; 4 | using Duende.IdentityServer.EntityFramework.Options; 5 | using ASPWebApp.Models; 6 | 7 | namespace ASPWebApp.Data; 8 | 9 | public class ApplicationDbContext : ApiAuthorizationDbContext 10 | { 11 | public ApplicationDbContext(DbContextOptions options, IOptions operationalStoreOptions) 12 | : base(options, operationalStoreOptions) 13 | { 14 | } 15 | } -------------------------------------------------------------------------------- /Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | using System; 4 | using ASPWebApp.Data; 5 | using Microsoft.EntityFrameworkCore; 6 | using Microsoft.EntityFrameworkCore.Infrastructure; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | namespace ASPWebApp.Data.Migrations 11 | { 12 | [DbContext(typeof(ApplicationDbContext))] 13 | [Migration("00000000000000_CreateIdentitySchema")] 14 | partial class CreateIdentitySchema 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "5.0.0-rc.1.20417.2"); 21 | 22 | modelBuilder.Entity("ASPWebApp.Models.ApplicationUser", b => 23 | { 24 | b.Property("Id") 25 | .HasColumnType("TEXT"); 26 | 27 | b.Property("AccessFailedCount") 28 | .HasColumnType("INTEGER"); 29 | 30 | b.Property("ConcurrencyStamp") 31 | .IsConcurrencyToken() 32 | .HasColumnType("TEXT"); 33 | 34 | b.Property("Email") 35 | .HasMaxLength(256) 36 | .HasColumnType("TEXT"); 37 | 38 | b.Property("EmailConfirmed") 39 | .HasColumnType("INTEGER"); 40 | 41 | b.Property("LockoutEnabled") 42 | .HasColumnType("INTEGER"); 43 | 44 | b.Property("LockoutEnd") 45 | .HasColumnType("TEXT"); 46 | 47 | b.Property("NormalizedEmail") 48 | .HasMaxLength(256) 49 | .HasColumnType("TEXT"); 50 | 51 | b.Property("NormalizedUserName") 52 | .HasMaxLength(256) 53 | .HasColumnType("TEXT"); 54 | 55 | b.Property("PasswordHash") 56 | .HasColumnType("TEXT"); 57 | 58 | b.Property("PhoneNumber") 59 | .HasColumnType("TEXT"); 60 | 61 | b.Property("PhoneNumberConfirmed") 62 | .HasColumnType("INTEGER"); 63 | 64 | b.Property("SecurityStamp") 65 | .HasColumnType("TEXT"); 66 | 67 | b.Property("TwoFactorEnabled") 68 | .HasColumnType("INTEGER"); 69 | 70 | b.Property("UserName") 71 | .HasMaxLength(256) 72 | .HasColumnType("TEXT"); 73 | 74 | b.HasKey("Id"); 75 | 76 | b.HasIndex("NormalizedEmail") 77 | .HasDatabaseName("EmailIndex"); 78 | 79 | b.HasIndex("NormalizedUserName") 80 | .IsUnique() 81 | .HasDatabaseName("UserNameIndex"); 82 | 83 | b.ToTable("AspNetUsers"); 84 | }); 85 | 86 | modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => 87 | { 88 | b.Property("UserCode") 89 | .HasMaxLength(200) 90 | .HasColumnType("TEXT"); 91 | 92 | b.Property("ClientId") 93 | .IsRequired() 94 | .HasMaxLength(200) 95 | .HasColumnType("TEXT"); 96 | 97 | b.Property("CreationTime") 98 | .HasColumnType("TEXT"); 99 | 100 | b.Property("Data") 101 | .IsRequired() 102 | .HasMaxLength(52420) 103 | .HasColumnType("TEXT"); 104 | 105 | b.Property("Description") 106 | .HasMaxLength(200) 107 | .HasColumnType("TEXT"); 108 | 109 | b.Property("DeviceCode") 110 | .IsRequired() 111 | .HasMaxLength(200) 112 | .HasColumnType("TEXT"); 113 | 114 | b.Property("Expiration") 115 | .IsRequired() 116 | .HasColumnType("TEXT"); 117 | 118 | b.Property("SessionId") 119 | .HasMaxLength(100) 120 | .HasColumnType("TEXT"); 121 | 122 | b.Property("SubjectId") 123 | .HasMaxLength(200) 124 | .HasColumnType("TEXT"); 125 | 126 | b.HasKey("UserCode"); 127 | 128 | b.HasIndex("DeviceCode") 129 | .IsUnique(); 130 | 131 | b.HasIndex("Expiration"); 132 | 133 | b.ToTable("DeviceCodes"); 134 | }); 135 | 136 | modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => 137 | { 138 | b.Property("Id") 139 | .HasColumnType("TEXT"); 140 | 141 | b.Property("Algorithm") 142 | .IsRequired() 143 | .HasMaxLength(100) 144 | .HasColumnType("TEXT"); 145 | 146 | b.Property("Created") 147 | .HasColumnType("TEXT"); 148 | 149 | b.Property("Data") 150 | .IsRequired() 151 | .HasMaxLength(52420) 152 | .HasColumnType("TEXT"); 153 | 154 | b.Property("DataProtected") 155 | .HasColumnType("INTEGER"); 156 | 157 | b.Property("IsX509Certificate") 158 | .HasColumnType("INTEGER"); 159 | 160 | b.Property("Use") 161 | .HasMaxLength(450) 162 | .HasColumnType("TEXT"); 163 | 164 | b.Property("Version") 165 | .HasColumnType("INTEGER"); 166 | 167 | b.HasKey("Id"); 168 | 169 | b.HasIndex("Use"); 170 | 171 | b.ToTable("Keys"); 172 | }); 173 | 174 | modelBuilder.Entity("Duende.EntityFramework.Entities.PersistedGrant", b => 175 | { 176 | b.Property("Key") 177 | .HasMaxLength(200) 178 | .HasColumnType("TEXT"); 179 | 180 | b.Property("ClientId") 181 | .IsRequired() 182 | .HasMaxLength(200) 183 | .HasColumnType("TEXT"); 184 | 185 | b.Property("ConsumedTime") 186 | .HasColumnType("TEXT"); 187 | 188 | b.Property("CreationTime") 189 | .HasColumnType("TEXT"); 190 | 191 | b.Property("Data") 192 | .IsRequired() 193 | .HasMaxLength(52420) 194 | .HasColumnType("TEXT"); 195 | 196 | b.Property("Description") 197 | .HasMaxLength(200) 198 | .HasColumnType("TEXT"); 199 | 200 | b.Property("Expiration") 201 | .HasColumnType("TEXT"); 202 | 203 | b.Property("SessionId") 204 | .HasMaxLength(100) 205 | .HasColumnType("TEXT"); 206 | 207 | b.Property("SubjectId") 208 | .HasMaxLength(200) 209 | .HasColumnType("TEXT"); 210 | 211 | b.Property("Type") 212 | .IsRequired() 213 | .HasMaxLength(50) 214 | .HasColumnType("TEXT"); 215 | 216 | b.HasKey("Key"); 217 | 218 | b.HasIndex("ConsumedTime"); 219 | 220 | b.HasIndex("Expiration"); 221 | 222 | b.HasIndex("SubjectId", "ClientId", "Type"); 223 | 224 | b.HasIndex("SubjectId", "SessionId", "Type"); 225 | 226 | b.ToTable("PersistedGrants"); 227 | }); 228 | 229 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 230 | { 231 | b.Property("Id") 232 | .HasColumnType("TEXT"); 233 | 234 | b.Property("ConcurrencyStamp") 235 | .IsConcurrencyToken() 236 | .HasColumnType("TEXT"); 237 | 238 | b.Property("Name") 239 | .HasMaxLength(256) 240 | .HasColumnType("TEXT"); 241 | 242 | b.Property("NormalizedName") 243 | .HasMaxLength(256) 244 | .HasColumnType("TEXT"); 245 | 246 | b.HasKey("Id"); 247 | 248 | b.HasIndex("NormalizedName") 249 | .IsUnique() 250 | .HasDatabaseName("RoleNameIndex"); 251 | 252 | b.ToTable("AspNetRoles"); 253 | }); 254 | 255 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 256 | { 257 | b.Property("Id") 258 | .ValueGeneratedOnAdd() 259 | .HasColumnType("INTEGER"); 260 | 261 | b.Property("ClaimType") 262 | .HasColumnType("TEXT"); 263 | 264 | b.Property("ClaimValue") 265 | .HasColumnType("TEXT"); 266 | 267 | b.Property("RoleId") 268 | .IsRequired() 269 | .HasColumnType("TEXT"); 270 | 271 | b.HasKey("Id"); 272 | 273 | b.HasIndex("RoleId"); 274 | 275 | b.ToTable("AspNetRoleClaims"); 276 | }); 277 | 278 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 279 | { 280 | b.Property("Id") 281 | .ValueGeneratedOnAdd() 282 | .HasColumnType("INTEGER"); 283 | 284 | b.Property("ClaimType") 285 | .HasColumnType("TEXT"); 286 | 287 | b.Property("ClaimValue") 288 | .HasColumnType("TEXT"); 289 | 290 | b.Property("UserId") 291 | .IsRequired() 292 | .HasColumnType("TEXT"); 293 | 294 | b.HasKey("Id"); 295 | 296 | b.HasIndex("UserId"); 297 | 298 | b.ToTable("AspNetUserClaims"); 299 | }); 300 | 301 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 302 | { 303 | b.Property("LoginProvider") 304 | .HasMaxLength(128) 305 | .HasColumnType("TEXT"); 306 | 307 | b.Property("ProviderKey") 308 | .HasMaxLength(128) 309 | .HasColumnType("TEXT"); 310 | 311 | b.Property("ProviderDisplayName") 312 | .HasColumnType("TEXT"); 313 | 314 | b.Property("UserId") 315 | .IsRequired() 316 | .HasColumnType("TEXT"); 317 | 318 | b.HasKey("LoginProvider", "ProviderKey"); 319 | 320 | b.HasIndex("UserId"); 321 | 322 | b.ToTable("AspNetUserLogins"); 323 | }); 324 | 325 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 326 | { 327 | b.Property("UserId") 328 | .HasColumnType("TEXT"); 329 | 330 | b.Property("RoleId") 331 | .HasColumnType("TEXT"); 332 | 333 | b.HasKey("UserId", "RoleId"); 334 | 335 | b.HasIndex("RoleId"); 336 | 337 | b.ToTable("AspNetUserRoles"); 338 | }); 339 | 340 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 341 | { 342 | b.Property("UserId") 343 | .HasColumnType("TEXT"); 344 | 345 | b.Property("LoginProvider") 346 | .HasMaxLength(128) 347 | .HasColumnType("TEXT"); 348 | 349 | b.Property("Name") 350 | .HasMaxLength(128) 351 | .HasColumnType("TEXT"); 352 | 353 | b.Property("Value") 354 | .HasColumnType("TEXT"); 355 | 356 | b.HasKey("UserId", "LoginProvider", "Name"); 357 | 358 | b.ToTable("AspNetUserTokens"); 359 | }); 360 | 361 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 362 | { 363 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 364 | .WithMany() 365 | .HasForeignKey("RoleId") 366 | .OnDelete(DeleteBehavior.Cascade) 367 | .IsRequired(); 368 | }); 369 | 370 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 371 | { 372 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 373 | .WithMany() 374 | .HasForeignKey("UserId") 375 | .OnDelete(DeleteBehavior.Cascade) 376 | .IsRequired(); 377 | }); 378 | 379 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 380 | { 381 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 382 | .WithMany() 383 | .HasForeignKey("UserId") 384 | .OnDelete(DeleteBehavior.Cascade) 385 | .IsRequired(); 386 | }); 387 | 388 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 389 | { 390 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 391 | .WithMany() 392 | .HasForeignKey("RoleId") 393 | .OnDelete(DeleteBehavior.Cascade) 394 | .IsRequired(); 395 | 396 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 397 | .WithMany() 398 | .HasForeignKey("UserId") 399 | .OnDelete(DeleteBehavior.Cascade) 400 | .IsRequired(); 401 | }); 402 | 403 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 404 | { 405 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 406 | .WithMany() 407 | .HasForeignKey("UserId") 408 | .OnDelete(DeleteBehavior.Cascade) 409 | .IsRequired(); 410 | }); 411 | #pragma warning restore 612, 618 412 | } 413 | } 414 | } -------------------------------------------------------------------------------- /Data/Migrations/00000000000000_CreateIdentitySchema.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace ASPWebApp.Data.Migrations 5 | { 6 | public partial class CreateIdentitySchema : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "AspNetRoles", 12 | columns: table => new 13 | { 14 | Id = table.Column(type: "TEXT", nullable: false), 15 | Name = table.Column(type: "TEXT", maxLength: 256, nullable: true), 16 | NormalizedName = table.Column(type: "TEXT", maxLength: 256, nullable: true), 17 | ConcurrencyStamp = table.Column(type: "TEXT", nullable: true) 18 | }, 19 | constraints: table => { table.PrimaryKey("PK_AspNetRoles", x => x.Id); }); 20 | 21 | migrationBuilder.CreateTable( 22 | name: "AspNetUsers", 23 | columns: table => new 24 | { 25 | Id = table.Column(type: "TEXT", nullable: false), 26 | UserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), 27 | NormalizedUserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), 28 | Email = table.Column(type: "TEXT", maxLength: 256, nullable: true), 29 | NormalizedEmail = table.Column(type: "TEXT", maxLength: 256, nullable: true), 30 | EmailConfirmed = table.Column(type: "INTEGER", nullable: false), 31 | PasswordHash = table.Column(type: "TEXT", nullable: true), 32 | SecurityStamp = table.Column(type: "TEXT", nullable: true), 33 | ConcurrencyStamp = table.Column(type: "TEXT", nullable: true), 34 | PhoneNumber = table.Column(type: "TEXT", nullable: true), 35 | PhoneNumberConfirmed = table.Column(type: "INTEGER", nullable: false), 36 | TwoFactorEnabled = table.Column(type: "INTEGER", nullable: false), 37 | LockoutEnd = table.Column(type: "TEXT", nullable: true), 38 | LockoutEnabled = table.Column(type: "INTEGER", nullable: false), 39 | AccessFailedCount = table.Column(type: "INTEGER", nullable: false) 40 | }, 41 | constraints: table => { table.PrimaryKey("PK_AspNetUsers", x => x.Id); }); 42 | 43 | migrationBuilder.CreateTable( 44 | name: "DeviceCodes", 45 | columns: table => new 46 | { 47 | UserCode = table.Column(type: "TEXT", maxLength: 200, nullable: false), 48 | DeviceCode = table.Column(type: "TEXT", maxLength: 200, nullable: false), 49 | SubjectId = table.Column(type: "TEXT", maxLength: 200, nullable: true), 50 | SessionId = table.Column(type: "TEXT", maxLength: 100, nullable: true), 51 | ClientId = table.Column(type: "TEXT", maxLength: 200, nullable: false), 52 | Description = table.Column(type: "TEXT", maxLength: 200, nullable: true), 53 | CreationTime = table.Column(type: "TEXT", nullable: false), 54 | Expiration = table.Column(type: "TEXT", nullable: false), 55 | Data = table.Column(type: "TEXT", maxLength: 52420, nullable: false) 56 | }, 57 | constraints: table => { table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); }); 58 | 59 | migrationBuilder.CreateTable( 60 | name: "Keys", 61 | columns: table => new 62 | { 63 | Id = table.Column(type: "TEXT", nullable: false), 64 | Version = table.Column(type: "INTEGER", nullable: false), 65 | Created = table.Column(type: "TEXT", nullable: false), 66 | Use = table.Column(type: "TEXT", maxLength: 450, nullable: true), 67 | Algorithm = table.Column(type: "TEXT", maxLength: 100, nullable: false), 68 | IsX509Certificate = table.Column(type: "INTEGER", nullable: false), 69 | DataProtected = table.Column(type: "INTEGER", nullable: false), 70 | Data = table.Column(type: "TEXT", maxLength: 52420, nullable: false) 71 | }, 72 | constraints: table => { table.PrimaryKey("PK_Keys", x => x.Id); }); 73 | 74 | migrationBuilder.CreateTable( 75 | name: "PersistedGrants", 76 | columns: table => new 77 | { 78 | Key = table.Column(type: "TEXT", maxLength: 200, nullable: false), 79 | Type = table.Column(type: "TEXT", maxLength: 50, nullable: false), 80 | SubjectId = table.Column(type: "TEXT", maxLength: 200, nullable: true), 81 | SessionId = table.Column(type: "TEXT", maxLength: 100, nullable: true), 82 | ClientId = table.Column(type: "TEXT", maxLength: 200, nullable: false), 83 | Description = table.Column(type: "TEXT", maxLength: 200, nullable: true), 84 | CreationTime = table.Column(type: "TEXT", nullable: false), 85 | Expiration = table.Column(type: "TEXT", nullable: true), 86 | ConsumedTime = table.Column(type: "TEXT", nullable: true), 87 | Data = table.Column(type: "TEXT", maxLength: 52420, nullable: false) 88 | }, 89 | constraints: table => { table.PrimaryKey("PK_PersistedGrants", x => x.Key); }); 90 | 91 | migrationBuilder.CreateTable( 92 | name: "AspNetRoleClaims", 93 | columns: table => new 94 | { 95 | Id = table.Column(type: "INTEGER", nullable: false) 96 | .Annotation("Sqlite:Autoincrement", true), 97 | RoleId = table.Column(type: "TEXT", nullable: false), 98 | ClaimType = table.Column(type: "TEXT", nullable: true), 99 | ClaimValue = table.Column(type: "TEXT", nullable: true) 100 | }, 101 | constraints: table => 102 | { 103 | table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); 104 | table.ForeignKey( 105 | name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", 106 | column: x => x.RoleId, 107 | principalTable: "AspNetRoles", 108 | principalColumn: "Id", 109 | onDelete: ReferentialAction.Cascade); 110 | }); 111 | 112 | migrationBuilder.CreateTable( 113 | name: "AspNetUserClaims", 114 | columns: table => new 115 | { 116 | Id = table.Column(type: "INTEGER", nullable: false) 117 | .Annotation("Sqlite:Autoincrement", true), 118 | UserId = table.Column(type: "TEXT", nullable: false), 119 | ClaimType = table.Column(type: "TEXT", nullable: true), 120 | ClaimValue = table.Column(type: "TEXT", nullable: true) 121 | }, 122 | constraints: table => 123 | { 124 | table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); 125 | table.ForeignKey( 126 | name: "FK_AspNetUserClaims_AspNetUsers_UserId", 127 | column: x => x.UserId, 128 | principalTable: "AspNetUsers", 129 | principalColumn: "Id", 130 | onDelete: ReferentialAction.Cascade); 131 | }); 132 | 133 | migrationBuilder.CreateTable( 134 | name: "AspNetUserLogins", 135 | columns: table => new 136 | { 137 | LoginProvider = table.Column(type: "TEXT", maxLength: 128, nullable: false), 138 | ProviderKey = table.Column(type: "TEXT", maxLength: 128, nullable: false), 139 | ProviderDisplayName = table.Column(type: "TEXT", nullable: true), 140 | UserId = table.Column(type: "TEXT", nullable: false) 141 | }, 142 | constraints: table => 143 | { 144 | table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); 145 | table.ForeignKey( 146 | name: "FK_AspNetUserLogins_AspNetUsers_UserId", 147 | column: x => x.UserId, 148 | principalTable: "AspNetUsers", 149 | principalColumn: "Id", 150 | onDelete: ReferentialAction.Cascade); 151 | }); 152 | 153 | migrationBuilder.CreateTable( 154 | name: "AspNetUserRoles", 155 | columns: table => new 156 | { 157 | UserId = table.Column(type: "TEXT", nullable: false), 158 | RoleId = table.Column(type: "TEXT", nullable: false) 159 | }, 160 | constraints: table => 161 | { 162 | table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); 163 | table.ForeignKey( 164 | name: "FK_AspNetUserRoles_AspNetRoles_RoleId", 165 | column: x => x.RoleId, 166 | principalTable: "AspNetRoles", 167 | principalColumn: "Id", 168 | onDelete: ReferentialAction.Cascade); 169 | table.ForeignKey( 170 | name: "FK_AspNetUserRoles_AspNetUsers_UserId", 171 | column: x => x.UserId, 172 | principalTable: "AspNetUsers", 173 | principalColumn: "Id", 174 | onDelete: ReferentialAction.Cascade); 175 | }); 176 | 177 | migrationBuilder.CreateTable( 178 | name: "AspNetUserTokens", 179 | columns: table => new 180 | { 181 | UserId = table.Column(type: "TEXT", nullable: false), 182 | LoginProvider = table.Column(type: "TEXT", maxLength: 128, nullable: false), 183 | Name = table.Column(type: "TEXT", maxLength: 128, nullable: false), 184 | Value = table.Column(type: "TEXT", nullable: true) 185 | }, 186 | constraints: table => 187 | { 188 | table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); 189 | table.ForeignKey( 190 | name: "FK_AspNetUserTokens_AspNetUsers_UserId", 191 | column: x => x.UserId, 192 | principalTable: "AspNetUsers", 193 | principalColumn: "Id", 194 | onDelete: ReferentialAction.Cascade); 195 | }); 196 | 197 | migrationBuilder.CreateIndex( 198 | name: "IX_AspNetRoleClaims_RoleId", 199 | table: "AspNetRoleClaims", 200 | column: "RoleId"); 201 | 202 | migrationBuilder.CreateIndex( 203 | name: "RoleNameIndex", 204 | table: "AspNetRoles", 205 | column: "NormalizedName", 206 | unique: true); 207 | 208 | migrationBuilder.CreateIndex( 209 | name: "IX_AspNetUserClaims_UserId", 210 | table: "AspNetUserClaims", 211 | column: "UserId"); 212 | 213 | migrationBuilder.CreateIndex( 214 | name: "IX_AspNetUserLogins_UserId", 215 | table: "AspNetUserLogins", 216 | column: "UserId"); 217 | 218 | migrationBuilder.CreateIndex( 219 | name: "IX_AspNetUserRoles_RoleId", 220 | table: "AspNetUserRoles", 221 | column: "RoleId"); 222 | 223 | migrationBuilder.CreateIndex( 224 | name: "EmailIndex", 225 | table: "AspNetUsers", 226 | column: "NormalizedEmail"); 227 | 228 | migrationBuilder.CreateIndex( 229 | name: "UserNameIndex", 230 | table: "AspNetUsers", 231 | column: "NormalizedUserName", 232 | unique: true); 233 | 234 | migrationBuilder.CreateIndex( 235 | name: "IX_DeviceCodes_DeviceCode", 236 | table: "DeviceCodes", 237 | column: "DeviceCode", 238 | unique: true); 239 | 240 | migrationBuilder.CreateIndex( 241 | name: "IX_DeviceCodes_Expiration", 242 | table: "DeviceCodes", 243 | column: "Expiration"); 244 | 245 | migrationBuilder.CreateIndex( 246 | name: "IX_Keys_Use", 247 | table: "Keys", 248 | column: "Use"); 249 | 250 | migrationBuilder.CreateIndex( 251 | name: "IX_PersistedGrants_ConsumedTime", 252 | table: "PersistedGrants", 253 | column: "ConsumedTime"); 254 | 255 | migrationBuilder.CreateIndex( 256 | name: "IX_PersistedGrants_Expiration", 257 | table: "PersistedGrants", 258 | column: "Expiration"); 259 | 260 | migrationBuilder.CreateIndex( 261 | name: "IX_PersistedGrants_SubjectId_ClientId_Type", 262 | table: "PersistedGrants", 263 | columns: new[] { "SubjectId", "ClientId", "Type" }); 264 | 265 | migrationBuilder.CreateIndex( 266 | name: "IX_PersistedGrants_SubjectId_SessionId_Type", 267 | table: "PersistedGrants", 268 | columns: new[] { "SubjectId", "SessionId", "Type" }); 269 | } 270 | 271 | protected override void Down(MigrationBuilder migrationBuilder) 272 | { 273 | migrationBuilder.DropTable( 274 | name: "AspNetRoleClaims"); 275 | 276 | migrationBuilder.DropTable( 277 | name: "AspNetUserClaims"); 278 | 279 | migrationBuilder.DropTable( 280 | name: "AspNetUserLogins"); 281 | 282 | migrationBuilder.DropTable( 283 | name: "AspNetUserRoles"); 284 | 285 | migrationBuilder.DropTable( 286 | name: "AspNetUserTokens"); 287 | 288 | migrationBuilder.DropTable( 289 | name: "DeviceCodes"); 290 | 291 | migrationBuilder.DropTable( 292 | name: "Keys"); 293 | 294 | migrationBuilder.DropTable( 295 | name: "PersistedGrants"); 296 | 297 | migrationBuilder.DropTable( 298 | name: "AspNetRoles"); 299 | 300 | migrationBuilder.DropTable( 301 | name: "AspNetUsers"); 302 | } 303 | } 304 | } -------------------------------------------------------------------------------- /Data/Migrations/20211231110352_inita.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using ASPWebApp.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace ASPWebApp.Data.Migrations 13 | { 14 | [DbContext(typeof(ApplicationDbContext))] 15 | [Migration("20211231110352_inita")] 16 | partial class inita 17 | { 18 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 19 | { 20 | #pragma warning disable 612, 618 21 | modelBuilder 22 | .HasAnnotation("ProductVersion", "6.0.1") 23 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 24 | 25 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 26 | 27 | modelBuilder.Entity("ASPWebApp.Models.ApplicationUser", b => 28 | { 29 | b.Property("Id") 30 | .HasColumnType("nvarchar(450)"); 31 | 32 | b.Property("AccessFailedCount") 33 | .HasColumnType("int"); 34 | 35 | b.Property("ConcurrencyStamp") 36 | .IsConcurrencyToken() 37 | .HasColumnType("nvarchar(max)"); 38 | 39 | b.Property("Email") 40 | .HasMaxLength(256) 41 | .HasColumnType("nvarchar(256)"); 42 | 43 | b.Property("EmailConfirmed") 44 | .HasColumnType("bit"); 45 | 46 | b.Property("LockoutEnabled") 47 | .HasColumnType("bit"); 48 | 49 | b.Property("LockoutEnd") 50 | .HasColumnType("datetimeoffset"); 51 | 52 | b.Property("NormalizedEmail") 53 | .HasMaxLength(256) 54 | .HasColumnType("nvarchar(256)"); 55 | 56 | b.Property("NormalizedUserName") 57 | .HasMaxLength(256) 58 | .HasColumnType("nvarchar(256)"); 59 | 60 | b.Property("PasswordHash") 61 | .HasColumnType("nvarchar(max)"); 62 | 63 | b.Property("PhoneNumber") 64 | .HasColumnType("nvarchar(max)"); 65 | 66 | b.Property("PhoneNumberConfirmed") 67 | .HasColumnType("bit"); 68 | 69 | b.Property("SecurityStamp") 70 | .HasColumnType("nvarchar(max)"); 71 | 72 | b.Property("TwoFactorEnabled") 73 | .HasColumnType("bit"); 74 | 75 | b.Property("UserName") 76 | .HasMaxLength(256) 77 | .HasColumnType("nvarchar(256)"); 78 | 79 | b.HasKey("Id"); 80 | 81 | b.HasIndex("NormalizedEmail") 82 | .HasDatabaseName("EmailIndex"); 83 | 84 | b.HasIndex("NormalizedUserName") 85 | .IsUnique() 86 | .HasDatabaseName("UserNameIndex") 87 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 88 | 89 | b.ToTable("AspNetUsers", (string)null); 90 | }); 91 | 92 | modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => 93 | { 94 | b.Property("UserCode") 95 | .HasMaxLength(200) 96 | .HasColumnType("nvarchar(200)"); 97 | 98 | b.Property("ClientId") 99 | .IsRequired() 100 | .HasMaxLength(200) 101 | .HasColumnType("nvarchar(200)"); 102 | 103 | b.Property("CreationTime") 104 | .HasColumnType("datetime2"); 105 | 106 | b.Property("Data") 107 | .IsRequired() 108 | .HasMaxLength(50000) 109 | .HasColumnType("nvarchar(max)"); 110 | 111 | b.Property("Description") 112 | .HasMaxLength(200) 113 | .HasColumnType("nvarchar(200)"); 114 | 115 | b.Property("DeviceCode") 116 | .IsRequired() 117 | .HasMaxLength(200) 118 | .HasColumnType("nvarchar(200)"); 119 | 120 | b.Property("Expiration") 121 | .IsRequired() 122 | .HasColumnType("datetime2"); 123 | 124 | b.Property("SessionId") 125 | .HasMaxLength(100) 126 | .HasColumnType("nvarchar(100)"); 127 | 128 | b.Property("SubjectId") 129 | .HasMaxLength(200) 130 | .HasColumnType("nvarchar(200)"); 131 | 132 | b.HasKey("UserCode"); 133 | 134 | b.HasIndex("DeviceCode") 135 | .IsUnique(); 136 | 137 | b.HasIndex("Expiration"); 138 | 139 | b.ToTable("DeviceCodes", (string)null); 140 | }); 141 | 142 | modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => 143 | { 144 | b.Property("Id") 145 | .HasColumnType("nvarchar(450)"); 146 | 147 | b.Property("Algorithm") 148 | .IsRequired() 149 | .HasMaxLength(100) 150 | .HasColumnType("nvarchar(100)"); 151 | 152 | b.Property("Created") 153 | .HasColumnType("datetime2"); 154 | 155 | b.Property("Data") 156 | .IsRequired() 157 | .HasColumnType("nvarchar(max)"); 158 | 159 | b.Property("DataProtected") 160 | .HasColumnType("bit"); 161 | 162 | b.Property("IsX509Certificate") 163 | .HasColumnType("bit"); 164 | 165 | b.Property("Use") 166 | .HasColumnType("nvarchar(450)"); 167 | 168 | b.Property("Version") 169 | .HasColumnType("int"); 170 | 171 | b.HasKey("Id"); 172 | 173 | b.HasIndex("Use"); 174 | 175 | b.ToTable("Keys"); 176 | }); 177 | 178 | modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => 179 | { 180 | b.Property("Key") 181 | .HasMaxLength(200) 182 | .HasColumnType("nvarchar(200)"); 183 | 184 | b.Property("ClientId") 185 | .IsRequired() 186 | .HasMaxLength(200) 187 | .HasColumnType("nvarchar(200)"); 188 | 189 | b.Property("ConsumedTime") 190 | .HasColumnType("datetime2"); 191 | 192 | b.Property("CreationTime") 193 | .HasColumnType("datetime2"); 194 | 195 | b.Property("Data") 196 | .IsRequired() 197 | .HasMaxLength(50000) 198 | .HasColumnType("nvarchar(max)"); 199 | 200 | b.Property("Description") 201 | .HasMaxLength(200) 202 | .HasColumnType("nvarchar(200)"); 203 | 204 | b.Property("Expiration") 205 | .HasColumnType("datetime2"); 206 | 207 | b.Property("SessionId") 208 | .HasMaxLength(100) 209 | .HasColumnType("nvarchar(100)"); 210 | 211 | b.Property("SubjectId") 212 | .HasMaxLength(200) 213 | .HasColumnType("nvarchar(200)"); 214 | 215 | b.Property("Type") 216 | .IsRequired() 217 | .HasMaxLength(50) 218 | .HasColumnType("nvarchar(50)"); 219 | 220 | b.HasKey("Key"); 221 | 222 | b.HasIndex("ConsumedTime"); 223 | 224 | b.HasIndex("Expiration"); 225 | 226 | b.HasIndex("SubjectId", "ClientId", "Type"); 227 | 228 | b.HasIndex("SubjectId", "SessionId", "Type"); 229 | 230 | b.ToTable("PersistedGrants", (string)null); 231 | }); 232 | 233 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 234 | { 235 | b.Property("Id") 236 | .HasColumnType("nvarchar(450)"); 237 | 238 | b.Property("ConcurrencyStamp") 239 | .IsConcurrencyToken() 240 | .HasColumnType("nvarchar(max)"); 241 | 242 | b.Property("Name") 243 | .HasMaxLength(256) 244 | .HasColumnType("nvarchar(256)"); 245 | 246 | b.Property("NormalizedName") 247 | .HasMaxLength(256) 248 | .HasColumnType("nvarchar(256)"); 249 | 250 | b.HasKey("Id"); 251 | 252 | b.HasIndex("NormalizedName") 253 | .IsUnique() 254 | .HasDatabaseName("RoleNameIndex") 255 | .HasFilter("[NormalizedName] IS NOT NULL"); 256 | 257 | b.ToTable("AspNetRoles", (string)null); 258 | }); 259 | 260 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 261 | { 262 | b.Property("Id") 263 | .ValueGeneratedOnAdd() 264 | .HasColumnType("int"); 265 | 266 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 267 | 268 | b.Property("ClaimType") 269 | .HasColumnType("nvarchar(max)"); 270 | 271 | b.Property("ClaimValue") 272 | .HasColumnType("nvarchar(max)"); 273 | 274 | b.Property("RoleId") 275 | .IsRequired() 276 | .HasColumnType("nvarchar(450)"); 277 | 278 | b.HasKey("Id"); 279 | 280 | b.HasIndex("RoleId"); 281 | 282 | b.ToTable("AspNetRoleClaims", (string)null); 283 | }); 284 | 285 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 286 | { 287 | b.Property("Id") 288 | .ValueGeneratedOnAdd() 289 | .HasColumnType("int"); 290 | 291 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 292 | 293 | b.Property("ClaimType") 294 | .HasColumnType("nvarchar(max)"); 295 | 296 | b.Property("ClaimValue") 297 | .HasColumnType("nvarchar(max)"); 298 | 299 | b.Property("UserId") 300 | .IsRequired() 301 | .HasColumnType("nvarchar(450)"); 302 | 303 | b.HasKey("Id"); 304 | 305 | b.HasIndex("UserId"); 306 | 307 | b.ToTable("AspNetUserClaims", (string)null); 308 | }); 309 | 310 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 311 | { 312 | b.Property("LoginProvider") 313 | .HasMaxLength(128) 314 | .HasColumnType("nvarchar(128)"); 315 | 316 | b.Property("ProviderKey") 317 | .HasMaxLength(128) 318 | .HasColumnType("nvarchar(128)"); 319 | 320 | b.Property("ProviderDisplayName") 321 | .HasColumnType("nvarchar(max)"); 322 | 323 | b.Property("UserId") 324 | .IsRequired() 325 | .HasColumnType("nvarchar(450)"); 326 | 327 | b.HasKey("LoginProvider", "ProviderKey"); 328 | 329 | b.HasIndex("UserId"); 330 | 331 | b.ToTable("AspNetUserLogins", (string)null); 332 | }); 333 | 334 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 335 | { 336 | b.Property("UserId") 337 | .HasColumnType("nvarchar(450)"); 338 | 339 | b.Property("RoleId") 340 | .HasColumnType("nvarchar(450)"); 341 | 342 | b.HasKey("UserId", "RoleId"); 343 | 344 | b.HasIndex("RoleId"); 345 | 346 | b.ToTable("AspNetUserRoles", (string)null); 347 | }); 348 | 349 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 350 | { 351 | b.Property("UserId") 352 | .HasColumnType("nvarchar(450)"); 353 | 354 | b.Property("LoginProvider") 355 | .HasMaxLength(128) 356 | .HasColumnType("nvarchar(128)"); 357 | 358 | b.Property("Name") 359 | .HasMaxLength(128) 360 | .HasColumnType("nvarchar(128)"); 361 | 362 | b.Property("Value") 363 | .HasColumnType("nvarchar(max)"); 364 | 365 | b.HasKey("UserId", "LoginProvider", "Name"); 366 | 367 | b.ToTable("AspNetUserTokens", (string)null); 368 | }); 369 | 370 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 371 | { 372 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 373 | .WithMany() 374 | .HasForeignKey("RoleId") 375 | .OnDelete(DeleteBehavior.Cascade) 376 | .IsRequired(); 377 | }); 378 | 379 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 380 | { 381 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 382 | .WithMany() 383 | .HasForeignKey("UserId") 384 | .OnDelete(DeleteBehavior.Cascade) 385 | .IsRequired(); 386 | }); 387 | 388 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 389 | { 390 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 391 | .WithMany() 392 | .HasForeignKey("UserId") 393 | .OnDelete(DeleteBehavior.Cascade) 394 | .IsRequired(); 395 | }); 396 | 397 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 398 | { 399 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 400 | .WithMany() 401 | .HasForeignKey("RoleId") 402 | .OnDelete(DeleteBehavior.Cascade) 403 | .IsRequired(); 404 | 405 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 406 | .WithMany() 407 | .HasForeignKey("UserId") 408 | .OnDelete(DeleteBehavior.Cascade) 409 | .IsRequired(); 410 | }); 411 | 412 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 413 | { 414 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 415 | .WithMany() 416 | .HasForeignKey("UserId") 417 | .OnDelete(DeleteBehavior.Cascade) 418 | .IsRequired(); 419 | }); 420 | #pragma warning restore 612, 618 421 | } 422 | } 423 | } 424 | -------------------------------------------------------------------------------- /Data/Migrations/20211231110352_inita.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace ASPWebApp.Data.Migrations 7 | { 8 | public partial class inita : Migration 9 | { 10 | protected override void Up(MigrationBuilder migrationBuilder) 11 | { 12 | migrationBuilder.DropIndex( 13 | name: "UserNameIndex", 14 | table: "AspNetUsers"); 15 | 16 | migrationBuilder.DropIndex( 17 | name: "RoleNameIndex", 18 | table: "AspNetRoles"); 19 | 20 | migrationBuilder.AlterColumn( 21 | name: "Type", 22 | table: "PersistedGrants", 23 | type: "nvarchar(50)", 24 | maxLength: 50, 25 | nullable: false, 26 | oldClrType: typeof(string), 27 | oldType: "TEXT", 28 | oldMaxLength: 50); 29 | 30 | migrationBuilder.AlterColumn( 31 | name: "SubjectId", 32 | table: "PersistedGrants", 33 | type: "nvarchar(200)", 34 | maxLength: 200, 35 | nullable: true, 36 | oldClrType: typeof(string), 37 | oldType: "TEXT", 38 | oldMaxLength: 200, 39 | oldNullable: true); 40 | 41 | migrationBuilder.AlterColumn( 42 | name: "SessionId", 43 | table: "PersistedGrants", 44 | type: "nvarchar(100)", 45 | maxLength: 100, 46 | nullable: true, 47 | oldClrType: typeof(string), 48 | oldType: "TEXT", 49 | oldMaxLength: 100, 50 | oldNullable: true); 51 | 52 | migrationBuilder.AlterColumn( 53 | name: "Expiration", 54 | table: "PersistedGrants", 55 | type: "datetime2", 56 | nullable: true, 57 | oldClrType: typeof(string), 58 | oldType: "TEXT", 59 | oldNullable: true); 60 | 61 | migrationBuilder.AlterColumn( 62 | name: "Description", 63 | table: "PersistedGrants", 64 | type: "nvarchar(200)", 65 | maxLength: 200, 66 | nullable: true, 67 | oldClrType: typeof(string), 68 | oldType: "TEXT", 69 | oldMaxLength: 200, 70 | oldNullable: true); 71 | 72 | migrationBuilder.AlterColumn( 73 | name: "Data", 74 | table: "PersistedGrants", 75 | type: "nvarchar(max)", 76 | maxLength: 50000, 77 | nullable: false, 78 | oldClrType: typeof(string), 79 | oldType: "TEXT", 80 | oldMaxLength: 50000); 81 | 82 | migrationBuilder.AlterColumn( 83 | name: "CreationTime", 84 | table: "PersistedGrants", 85 | type: "datetime2", 86 | nullable: false, 87 | oldClrType: typeof(string), 88 | oldType: "TEXT"); 89 | 90 | migrationBuilder.AlterColumn( 91 | name: "ConsumedTime", 92 | table: "PersistedGrants", 93 | type: "datetime2", 94 | nullable: true, 95 | oldClrType: typeof(string), 96 | oldType: "TEXT", 97 | oldNullable: true); 98 | 99 | migrationBuilder.AlterColumn( 100 | name: "ClientId", 101 | table: "PersistedGrants", 102 | type: "nvarchar(200)", 103 | maxLength: 200, 104 | nullable: false, 105 | oldClrType: typeof(string), 106 | oldType: "TEXT", 107 | oldMaxLength: 200); 108 | 109 | migrationBuilder.AlterColumn( 110 | name: "Key", 111 | table: "PersistedGrants", 112 | type: "nvarchar(200)", 113 | maxLength: 200, 114 | nullable: false, 115 | oldClrType: typeof(string), 116 | oldType: "TEXT", 117 | oldMaxLength: 200); 118 | 119 | migrationBuilder.AlterColumn( 120 | name: "Version", 121 | table: "Keys", 122 | type: "int", 123 | nullable: false, 124 | oldClrType: typeof(int), 125 | oldType: "INTEGER"); 126 | 127 | migrationBuilder.AlterColumn( 128 | name: "Use", 129 | table: "Keys", 130 | type: "nvarchar(450)", 131 | nullable: true, 132 | oldClrType: typeof(string), 133 | oldType: "TEXT", 134 | oldNullable: true); 135 | 136 | migrationBuilder.AlterColumn( 137 | name: "IsX509Certificate", 138 | table: "Keys", 139 | type: "bit", 140 | nullable: false, 141 | oldClrType: typeof(bool), 142 | oldType: "INTEGER"); 143 | 144 | migrationBuilder.AlterColumn( 145 | name: "DataProtected", 146 | table: "Keys", 147 | type: "bit", 148 | nullable: false, 149 | oldClrType: typeof(bool), 150 | oldType: "INTEGER"); 151 | 152 | migrationBuilder.AlterColumn( 153 | name: "Data", 154 | table: "Keys", 155 | type: "nvarchar(max)", 156 | nullable: false, 157 | oldClrType: typeof(string), 158 | oldType: "TEXT"); 159 | 160 | migrationBuilder.AlterColumn( 161 | name: "Created", 162 | table: "Keys", 163 | type: "datetime2", 164 | nullable: false, 165 | oldClrType: typeof(string), 166 | oldType: "TEXT"); 167 | 168 | migrationBuilder.AlterColumn( 169 | name: "Algorithm", 170 | table: "Keys", 171 | type: "nvarchar(100)", 172 | maxLength: 100, 173 | nullable: false, 174 | oldClrType: typeof(string), 175 | oldType: "TEXT", 176 | oldMaxLength: 100); 177 | 178 | migrationBuilder.AlterColumn( 179 | name: "Id", 180 | table: "Keys", 181 | type: "nvarchar(450)", 182 | nullable: false, 183 | oldClrType: typeof(string), 184 | oldType: "TEXT"); 185 | 186 | migrationBuilder.AlterColumn( 187 | name: "SubjectId", 188 | table: "DeviceCodes", 189 | type: "nvarchar(200)", 190 | maxLength: 200, 191 | nullable: true, 192 | oldClrType: typeof(string), 193 | oldType: "TEXT", 194 | oldMaxLength: 200, 195 | oldNullable: true); 196 | 197 | migrationBuilder.AlterColumn( 198 | name: "SessionId", 199 | table: "DeviceCodes", 200 | type: "nvarchar(100)", 201 | maxLength: 100, 202 | nullable: true, 203 | oldClrType: typeof(string), 204 | oldType: "TEXT", 205 | oldMaxLength: 100, 206 | oldNullable: true); 207 | 208 | migrationBuilder.AlterColumn( 209 | name: "Expiration", 210 | table: "DeviceCodes", 211 | type: "datetime2", 212 | nullable: false, 213 | oldClrType: typeof(string), 214 | oldType: "TEXT"); 215 | 216 | migrationBuilder.AlterColumn( 217 | name: "DeviceCode", 218 | table: "DeviceCodes", 219 | type: "nvarchar(200)", 220 | maxLength: 200, 221 | nullable: false, 222 | oldClrType: typeof(string), 223 | oldType: "TEXT", 224 | oldMaxLength: 200); 225 | 226 | migrationBuilder.AlterColumn( 227 | name: "Description", 228 | table: "DeviceCodes", 229 | type: "nvarchar(200)", 230 | maxLength: 200, 231 | nullable: true, 232 | oldClrType: typeof(string), 233 | oldType: "TEXT", 234 | oldMaxLength: 200, 235 | oldNullable: true); 236 | 237 | migrationBuilder.AlterColumn( 238 | name: "Data", 239 | table: "DeviceCodes", 240 | type: "nvarchar(max)", 241 | maxLength: 50000, 242 | nullable: false, 243 | oldClrType: typeof(string), 244 | oldType: "TEXT", 245 | oldMaxLength: 50000); 246 | 247 | migrationBuilder.AlterColumn( 248 | name: "CreationTime", 249 | table: "DeviceCodes", 250 | type: "datetime2", 251 | nullable: false, 252 | oldClrType: typeof(string), 253 | oldType: "TEXT"); 254 | 255 | migrationBuilder.AlterColumn( 256 | name: "ClientId", 257 | table: "DeviceCodes", 258 | type: "nvarchar(200)", 259 | maxLength: 200, 260 | nullable: false, 261 | oldClrType: typeof(string), 262 | oldType: "TEXT", 263 | oldMaxLength: 200); 264 | 265 | migrationBuilder.AlterColumn( 266 | name: "UserCode", 267 | table: "DeviceCodes", 268 | type: "nvarchar(200)", 269 | maxLength: 200, 270 | nullable: false, 271 | oldClrType: typeof(string), 272 | oldType: "TEXT", 273 | oldMaxLength: 200); 274 | 275 | migrationBuilder.AlterColumn( 276 | name: "Value", 277 | table: "AspNetUserTokens", 278 | type: "nvarchar(max)", 279 | nullable: true, 280 | oldClrType: typeof(string), 281 | oldType: "TEXT", 282 | oldNullable: true); 283 | 284 | migrationBuilder.AlterColumn( 285 | name: "Name", 286 | table: "AspNetUserTokens", 287 | type: "nvarchar(128)", 288 | maxLength: 128, 289 | nullable: false, 290 | oldClrType: typeof(string), 291 | oldType: "TEXT", 292 | oldMaxLength: 128); 293 | 294 | migrationBuilder.AlterColumn( 295 | name: "LoginProvider", 296 | table: "AspNetUserTokens", 297 | type: "nvarchar(128)", 298 | maxLength: 128, 299 | nullable: false, 300 | oldClrType: typeof(string), 301 | oldType: "TEXT", 302 | oldMaxLength: 128); 303 | 304 | migrationBuilder.AlterColumn( 305 | name: "UserId", 306 | table: "AspNetUserTokens", 307 | type: "nvarchar(450)", 308 | nullable: false, 309 | oldClrType: typeof(string), 310 | oldType: "TEXT"); 311 | 312 | migrationBuilder.AlterColumn( 313 | name: "UserName", 314 | table: "AspNetUsers", 315 | type: "nvarchar(256)", 316 | maxLength: 256, 317 | nullable: true, 318 | oldClrType: typeof(string), 319 | oldType: "TEXT", 320 | oldMaxLength: 256, 321 | oldNullable: true); 322 | 323 | migrationBuilder.AlterColumn( 324 | name: "TwoFactorEnabled", 325 | table: "AspNetUsers", 326 | type: "bit", 327 | nullable: false, 328 | oldClrType: typeof(bool), 329 | oldType: "INTEGER"); 330 | 331 | migrationBuilder.AlterColumn( 332 | name: "SecurityStamp", 333 | table: "AspNetUsers", 334 | type: "nvarchar(max)", 335 | nullable: true, 336 | oldClrType: typeof(string), 337 | oldType: "TEXT", 338 | oldNullable: true); 339 | 340 | migrationBuilder.AlterColumn( 341 | name: "PhoneNumberConfirmed", 342 | table: "AspNetUsers", 343 | type: "bit", 344 | nullable: false, 345 | oldClrType: typeof(bool), 346 | oldType: "INTEGER"); 347 | 348 | migrationBuilder.AlterColumn( 349 | name: "PhoneNumber", 350 | table: "AspNetUsers", 351 | type: "nvarchar(max)", 352 | nullable: true, 353 | oldClrType: typeof(string), 354 | oldType: "TEXT", 355 | oldNullable: true); 356 | 357 | migrationBuilder.AlterColumn( 358 | name: "PasswordHash", 359 | table: "AspNetUsers", 360 | type: "nvarchar(max)", 361 | nullable: true, 362 | oldClrType: typeof(string), 363 | oldType: "TEXT", 364 | oldNullable: true); 365 | 366 | migrationBuilder.AlterColumn( 367 | name: "NormalizedUserName", 368 | table: "AspNetUsers", 369 | type: "nvarchar(256)", 370 | maxLength: 256, 371 | nullable: true, 372 | oldClrType: typeof(string), 373 | oldType: "TEXT", 374 | oldMaxLength: 256, 375 | oldNullable: true); 376 | 377 | migrationBuilder.AlterColumn( 378 | name: "NormalizedEmail", 379 | table: "AspNetUsers", 380 | type: "nvarchar(256)", 381 | maxLength: 256, 382 | nullable: true, 383 | oldClrType: typeof(string), 384 | oldType: "TEXT", 385 | oldMaxLength: 256, 386 | oldNullable: true); 387 | 388 | migrationBuilder.AlterColumn( 389 | name: "LockoutEnd", 390 | table: "AspNetUsers", 391 | type: "datetimeoffset", 392 | nullable: true, 393 | oldClrType: typeof(string), 394 | oldType: "TEXT", 395 | oldNullable: true); 396 | 397 | migrationBuilder.AlterColumn( 398 | name: "LockoutEnabled", 399 | table: "AspNetUsers", 400 | type: "bit", 401 | nullable: false, 402 | oldClrType: typeof(bool), 403 | oldType: "INTEGER"); 404 | 405 | migrationBuilder.AlterColumn( 406 | name: "EmailConfirmed", 407 | table: "AspNetUsers", 408 | type: "bit", 409 | nullable: false, 410 | oldClrType: typeof(bool), 411 | oldType: "INTEGER"); 412 | 413 | migrationBuilder.AlterColumn( 414 | name: "Email", 415 | table: "AspNetUsers", 416 | type: "nvarchar(256)", 417 | maxLength: 256, 418 | nullable: true, 419 | oldClrType: typeof(string), 420 | oldType: "TEXT", 421 | oldMaxLength: 256, 422 | oldNullable: true); 423 | 424 | migrationBuilder.AlterColumn( 425 | name: "ConcurrencyStamp", 426 | table: "AspNetUsers", 427 | type: "nvarchar(max)", 428 | nullable: true, 429 | oldClrType: typeof(string), 430 | oldType: "TEXT", 431 | oldNullable: true); 432 | 433 | migrationBuilder.AlterColumn( 434 | name: "AccessFailedCount", 435 | table: "AspNetUsers", 436 | type: "int", 437 | nullable: false, 438 | oldClrType: typeof(int), 439 | oldType: "INTEGER"); 440 | 441 | migrationBuilder.AlterColumn( 442 | name: "Id", 443 | table: "AspNetUsers", 444 | type: "nvarchar(450)", 445 | nullable: false, 446 | oldClrType: typeof(string), 447 | oldType: "TEXT"); 448 | 449 | migrationBuilder.AlterColumn( 450 | name: "RoleId", 451 | table: "AspNetUserRoles", 452 | type: "nvarchar(450)", 453 | nullable: false, 454 | oldClrType: typeof(string), 455 | oldType: "TEXT"); 456 | 457 | migrationBuilder.AlterColumn( 458 | name: "UserId", 459 | table: "AspNetUserRoles", 460 | type: "nvarchar(450)", 461 | nullable: false, 462 | oldClrType: typeof(string), 463 | oldType: "TEXT"); 464 | 465 | migrationBuilder.AlterColumn( 466 | name: "UserId", 467 | table: "AspNetUserLogins", 468 | type: "nvarchar(450)", 469 | nullable: false, 470 | oldClrType: typeof(string), 471 | oldType: "TEXT"); 472 | 473 | migrationBuilder.AlterColumn( 474 | name: "ProviderDisplayName", 475 | table: "AspNetUserLogins", 476 | type: "nvarchar(max)", 477 | nullable: true, 478 | oldClrType: typeof(string), 479 | oldType: "TEXT", 480 | oldNullable: true); 481 | 482 | migrationBuilder.AlterColumn( 483 | name: "ProviderKey", 484 | table: "AspNetUserLogins", 485 | type: "nvarchar(128)", 486 | maxLength: 128, 487 | nullable: false, 488 | oldClrType: typeof(string), 489 | oldType: "TEXT", 490 | oldMaxLength: 128); 491 | 492 | migrationBuilder.AlterColumn( 493 | name: "LoginProvider", 494 | table: "AspNetUserLogins", 495 | type: "nvarchar(128)", 496 | maxLength: 128, 497 | nullable: false, 498 | oldClrType: typeof(string), 499 | oldType: "TEXT", 500 | oldMaxLength: 128); 501 | 502 | migrationBuilder.AlterColumn( 503 | name: "UserId", 504 | table: "AspNetUserClaims", 505 | type: "nvarchar(450)", 506 | nullable: false, 507 | oldClrType: typeof(string), 508 | oldType: "TEXT"); 509 | 510 | migrationBuilder.AlterColumn( 511 | name: "ClaimValue", 512 | table: "AspNetUserClaims", 513 | type: "nvarchar(max)", 514 | nullable: true, 515 | oldClrType: typeof(string), 516 | oldType: "TEXT", 517 | oldNullable: true); 518 | 519 | migrationBuilder.AlterColumn( 520 | name: "ClaimType", 521 | table: "AspNetUserClaims", 522 | type: "nvarchar(max)", 523 | nullable: true, 524 | oldClrType: typeof(string), 525 | oldType: "TEXT", 526 | oldNullable: true); 527 | 528 | migrationBuilder.AlterColumn( 529 | name: "Id", 530 | table: "AspNetUserClaims", 531 | type: "int", 532 | nullable: false, 533 | oldClrType: typeof(int), 534 | oldType: "INTEGER") 535 | .Annotation("SqlServer:Identity", "1, 1"); 536 | 537 | migrationBuilder.AlterColumn( 538 | name: "NormalizedName", 539 | table: "AspNetRoles", 540 | type: "nvarchar(256)", 541 | maxLength: 256, 542 | nullable: true, 543 | oldClrType: typeof(string), 544 | oldType: "TEXT", 545 | oldMaxLength: 256, 546 | oldNullable: true); 547 | 548 | migrationBuilder.AlterColumn( 549 | name: "Name", 550 | table: "AspNetRoles", 551 | type: "nvarchar(256)", 552 | maxLength: 256, 553 | nullable: true, 554 | oldClrType: typeof(string), 555 | oldType: "TEXT", 556 | oldMaxLength: 256, 557 | oldNullable: true); 558 | 559 | migrationBuilder.AlterColumn( 560 | name: "ConcurrencyStamp", 561 | table: "AspNetRoles", 562 | type: "nvarchar(max)", 563 | nullable: true, 564 | oldClrType: typeof(string), 565 | oldType: "TEXT", 566 | oldNullable: true); 567 | 568 | migrationBuilder.AlterColumn( 569 | name: "Id", 570 | table: "AspNetRoles", 571 | type: "nvarchar(450)", 572 | nullable: false, 573 | oldClrType: typeof(string), 574 | oldType: "TEXT"); 575 | 576 | migrationBuilder.AlterColumn( 577 | name: "RoleId", 578 | table: "AspNetRoleClaims", 579 | type: "nvarchar(450)", 580 | nullable: false, 581 | oldClrType: typeof(string), 582 | oldType: "TEXT"); 583 | 584 | migrationBuilder.AlterColumn( 585 | name: "ClaimValue", 586 | table: "AspNetRoleClaims", 587 | type: "nvarchar(max)", 588 | nullable: true, 589 | oldClrType: typeof(string), 590 | oldType: "TEXT", 591 | oldNullable: true); 592 | 593 | migrationBuilder.AlterColumn( 594 | name: "ClaimType", 595 | table: "AspNetRoleClaims", 596 | type: "nvarchar(max)", 597 | nullable: true, 598 | oldClrType: typeof(string), 599 | oldType: "TEXT", 600 | oldNullable: true); 601 | 602 | migrationBuilder.AlterColumn( 603 | name: "Id", 604 | table: "AspNetRoleClaims", 605 | type: "int", 606 | nullable: false, 607 | oldClrType: typeof(int), 608 | oldType: "INTEGER") 609 | .Annotation("SqlServer:Identity", "1, 1"); 610 | 611 | migrationBuilder.CreateIndex( 612 | name: "UserNameIndex", 613 | table: "AspNetUsers", 614 | column: "NormalizedUserName", 615 | unique: true, 616 | filter: "[NormalizedUserName] IS NOT NULL"); 617 | 618 | migrationBuilder.CreateIndex( 619 | name: "RoleNameIndex", 620 | table: "AspNetRoles", 621 | column: "NormalizedName", 622 | unique: true, 623 | filter: "[NormalizedName] IS NOT NULL"); 624 | } 625 | 626 | protected override void Down(MigrationBuilder migrationBuilder) 627 | { 628 | migrationBuilder.DropIndex( 629 | name: "UserNameIndex", 630 | table: "AspNetUsers"); 631 | 632 | migrationBuilder.DropIndex( 633 | name: "RoleNameIndex", 634 | table: "AspNetRoles"); 635 | 636 | migrationBuilder.AlterColumn( 637 | name: "Type", 638 | table: "PersistedGrants", 639 | type: "TEXT", 640 | maxLength: 50, 641 | nullable: false, 642 | oldClrType: typeof(string), 643 | oldType: "nvarchar(50)", 644 | oldMaxLength: 50); 645 | 646 | migrationBuilder.AlterColumn( 647 | name: "SubjectId", 648 | table: "PersistedGrants", 649 | type: "TEXT", 650 | maxLength: 200, 651 | nullable: true, 652 | oldClrType: typeof(string), 653 | oldType: "nvarchar(200)", 654 | oldMaxLength: 200, 655 | oldNullable: true); 656 | 657 | migrationBuilder.AlterColumn( 658 | name: "SessionId", 659 | table: "PersistedGrants", 660 | type: "TEXT", 661 | maxLength: 100, 662 | nullable: true, 663 | oldClrType: typeof(string), 664 | oldType: "nvarchar(100)", 665 | oldMaxLength: 100, 666 | oldNullable: true); 667 | 668 | migrationBuilder.AlterColumn( 669 | name: "Expiration", 670 | table: "PersistedGrants", 671 | type: "TEXT", 672 | nullable: true, 673 | oldClrType: typeof(DateTime), 674 | oldType: "datetime2", 675 | oldNullable: true); 676 | 677 | migrationBuilder.AlterColumn( 678 | name: "Description", 679 | table: "PersistedGrants", 680 | type: "TEXT", 681 | maxLength: 200, 682 | nullable: true, 683 | oldClrType: typeof(string), 684 | oldType: "nvarchar(200)", 685 | oldMaxLength: 200, 686 | oldNullable: true); 687 | 688 | migrationBuilder.AlterColumn( 689 | name: "Data", 690 | table: "PersistedGrants", 691 | type: "TEXT", 692 | maxLength: 50000, 693 | nullable: false, 694 | oldClrType: typeof(string), 695 | oldType: "nvarchar(max)", 696 | oldMaxLength: 50000); 697 | 698 | migrationBuilder.AlterColumn( 699 | name: "CreationTime", 700 | table: "PersistedGrants", 701 | type: "TEXT", 702 | nullable: false, 703 | oldClrType: typeof(DateTime), 704 | oldType: "datetime2"); 705 | 706 | migrationBuilder.AlterColumn( 707 | name: "ConsumedTime", 708 | table: "PersistedGrants", 709 | type: "TEXT", 710 | nullable: true, 711 | oldClrType: typeof(DateTime), 712 | oldType: "datetime2", 713 | oldNullable: true); 714 | 715 | migrationBuilder.AlterColumn( 716 | name: "ClientId", 717 | table: "PersistedGrants", 718 | type: "TEXT", 719 | maxLength: 200, 720 | nullable: false, 721 | oldClrType: typeof(string), 722 | oldType: "nvarchar(200)", 723 | oldMaxLength: 200); 724 | 725 | migrationBuilder.AlterColumn( 726 | name: "Key", 727 | table: "PersistedGrants", 728 | type: "TEXT", 729 | maxLength: 200, 730 | nullable: false, 731 | oldClrType: typeof(string), 732 | oldType: "nvarchar(200)", 733 | oldMaxLength: 200); 734 | 735 | migrationBuilder.AlterColumn( 736 | name: "Version", 737 | table: "Keys", 738 | type: "INTEGER", 739 | nullable: false, 740 | oldClrType: typeof(int), 741 | oldType: "int"); 742 | 743 | migrationBuilder.AlterColumn( 744 | name: "Use", 745 | table: "Keys", 746 | type: "TEXT", 747 | nullable: true, 748 | oldClrType: typeof(string), 749 | oldType: "nvarchar(450)", 750 | oldNullable: true); 751 | 752 | migrationBuilder.AlterColumn( 753 | name: "IsX509Certificate", 754 | table: "Keys", 755 | type: "INTEGER", 756 | nullable: false, 757 | oldClrType: typeof(bool), 758 | oldType: "bit"); 759 | 760 | migrationBuilder.AlterColumn( 761 | name: "DataProtected", 762 | table: "Keys", 763 | type: "INTEGER", 764 | nullable: false, 765 | oldClrType: typeof(bool), 766 | oldType: "bit"); 767 | 768 | migrationBuilder.AlterColumn( 769 | name: "Data", 770 | table: "Keys", 771 | type: "TEXT", 772 | nullable: false, 773 | oldClrType: typeof(string), 774 | oldType: "nvarchar(max)"); 775 | 776 | migrationBuilder.AlterColumn( 777 | name: "Created", 778 | table: "Keys", 779 | type: "TEXT", 780 | nullable: false, 781 | oldClrType: typeof(DateTime), 782 | oldType: "datetime2"); 783 | 784 | migrationBuilder.AlterColumn( 785 | name: "Algorithm", 786 | table: "Keys", 787 | type: "TEXT", 788 | maxLength: 100, 789 | nullable: false, 790 | oldClrType: typeof(string), 791 | oldType: "nvarchar(100)", 792 | oldMaxLength: 100); 793 | 794 | migrationBuilder.AlterColumn( 795 | name: "Id", 796 | table: "Keys", 797 | type: "TEXT", 798 | nullable: false, 799 | oldClrType: typeof(string), 800 | oldType: "nvarchar(450)"); 801 | 802 | migrationBuilder.AlterColumn( 803 | name: "SubjectId", 804 | table: "DeviceCodes", 805 | type: "TEXT", 806 | maxLength: 200, 807 | nullable: true, 808 | oldClrType: typeof(string), 809 | oldType: "nvarchar(200)", 810 | oldMaxLength: 200, 811 | oldNullable: true); 812 | 813 | migrationBuilder.AlterColumn( 814 | name: "SessionId", 815 | table: "DeviceCodes", 816 | type: "TEXT", 817 | maxLength: 100, 818 | nullable: true, 819 | oldClrType: typeof(string), 820 | oldType: "nvarchar(100)", 821 | oldMaxLength: 100, 822 | oldNullable: true); 823 | 824 | migrationBuilder.AlterColumn( 825 | name: "Expiration", 826 | table: "DeviceCodes", 827 | type: "TEXT", 828 | nullable: false, 829 | oldClrType: typeof(DateTime), 830 | oldType: "datetime2"); 831 | 832 | migrationBuilder.AlterColumn( 833 | name: "DeviceCode", 834 | table: "DeviceCodes", 835 | type: "TEXT", 836 | maxLength: 200, 837 | nullable: false, 838 | oldClrType: typeof(string), 839 | oldType: "nvarchar(200)", 840 | oldMaxLength: 200); 841 | 842 | migrationBuilder.AlterColumn( 843 | name: "Description", 844 | table: "DeviceCodes", 845 | type: "TEXT", 846 | maxLength: 200, 847 | nullable: true, 848 | oldClrType: typeof(string), 849 | oldType: "nvarchar(200)", 850 | oldMaxLength: 200, 851 | oldNullable: true); 852 | 853 | migrationBuilder.AlterColumn( 854 | name: "Data", 855 | table: "DeviceCodes", 856 | type: "TEXT", 857 | maxLength: 50000, 858 | nullable: false, 859 | oldClrType: typeof(string), 860 | oldType: "nvarchar(max)", 861 | oldMaxLength: 50000); 862 | 863 | migrationBuilder.AlterColumn( 864 | name: "CreationTime", 865 | table: "DeviceCodes", 866 | type: "TEXT", 867 | nullable: false, 868 | oldClrType: typeof(DateTime), 869 | oldType: "datetime2"); 870 | 871 | migrationBuilder.AlterColumn( 872 | name: "ClientId", 873 | table: "DeviceCodes", 874 | type: "TEXT", 875 | maxLength: 200, 876 | nullable: false, 877 | oldClrType: typeof(string), 878 | oldType: "nvarchar(200)", 879 | oldMaxLength: 200); 880 | 881 | migrationBuilder.AlterColumn( 882 | name: "UserCode", 883 | table: "DeviceCodes", 884 | type: "TEXT", 885 | maxLength: 200, 886 | nullable: false, 887 | oldClrType: typeof(string), 888 | oldType: "nvarchar(200)", 889 | oldMaxLength: 200); 890 | 891 | migrationBuilder.AlterColumn( 892 | name: "Value", 893 | table: "AspNetUserTokens", 894 | type: "TEXT", 895 | nullable: true, 896 | oldClrType: typeof(string), 897 | oldType: "nvarchar(max)", 898 | oldNullable: true); 899 | 900 | migrationBuilder.AlterColumn( 901 | name: "Name", 902 | table: "AspNetUserTokens", 903 | type: "TEXT", 904 | maxLength: 128, 905 | nullable: false, 906 | oldClrType: typeof(string), 907 | oldType: "nvarchar(128)", 908 | oldMaxLength: 128); 909 | 910 | migrationBuilder.AlterColumn( 911 | name: "LoginProvider", 912 | table: "AspNetUserTokens", 913 | type: "TEXT", 914 | maxLength: 128, 915 | nullable: false, 916 | oldClrType: typeof(string), 917 | oldType: "nvarchar(128)", 918 | oldMaxLength: 128); 919 | 920 | migrationBuilder.AlterColumn( 921 | name: "UserId", 922 | table: "AspNetUserTokens", 923 | type: "TEXT", 924 | nullable: false, 925 | oldClrType: typeof(string), 926 | oldType: "nvarchar(450)"); 927 | 928 | migrationBuilder.AlterColumn( 929 | name: "UserName", 930 | table: "AspNetUsers", 931 | type: "TEXT", 932 | maxLength: 256, 933 | nullable: true, 934 | oldClrType: typeof(string), 935 | oldType: "nvarchar(256)", 936 | oldMaxLength: 256, 937 | oldNullable: true); 938 | 939 | migrationBuilder.AlterColumn( 940 | name: "TwoFactorEnabled", 941 | table: "AspNetUsers", 942 | type: "INTEGER", 943 | nullable: false, 944 | oldClrType: typeof(bool), 945 | oldType: "bit"); 946 | 947 | migrationBuilder.AlterColumn( 948 | name: "SecurityStamp", 949 | table: "AspNetUsers", 950 | type: "TEXT", 951 | nullable: true, 952 | oldClrType: typeof(string), 953 | oldType: "nvarchar(max)", 954 | oldNullable: true); 955 | 956 | migrationBuilder.AlterColumn( 957 | name: "PhoneNumberConfirmed", 958 | table: "AspNetUsers", 959 | type: "INTEGER", 960 | nullable: false, 961 | oldClrType: typeof(bool), 962 | oldType: "bit"); 963 | 964 | migrationBuilder.AlterColumn( 965 | name: "PhoneNumber", 966 | table: "AspNetUsers", 967 | type: "TEXT", 968 | nullable: true, 969 | oldClrType: typeof(string), 970 | oldType: "nvarchar(max)", 971 | oldNullable: true); 972 | 973 | migrationBuilder.AlterColumn( 974 | name: "PasswordHash", 975 | table: "AspNetUsers", 976 | type: "TEXT", 977 | nullable: true, 978 | oldClrType: typeof(string), 979 | oldType: "nvarchar(max)", 980 | oldNullable: true); 981 | 982 | migrationBuilder.AlterColumn( 983 | name: "NormalizedUserName", 984 | table: "AspNetUsers", 985 | type: "TEXT", 986 | maxLength: 256, 987 | nullable: true, 988 | oldClrType: typeof(string), 989 | oldType: "nvarchar(256)", 990 | oldMaxLength: 256, 991 | oldNullable: true); 992 | 993 | migrationBuilder.AlterColumn( 994 | name: "NormalizedEmail", 995 | table: "AspNetUsers", 996 | type: "TEXT", 997 | maxLength: 256, 998 | nullable: true, 999 | oldClrType: typeof(string), 1000 | oldType: "nvarchar(256)", 1001 | oldMaxLength: 256, 1002 | oldNullable: true); 1003 | 1004 | migrationBuilder.AlterColumn( 1005 | name: "LockoutEnd", 1006 | table: "AspNetUsers", 1007 | type: "TEXT", 1008 | nullable: true, 1009 | oldClrType: typeof(DateTimeOffset), 1010 | oldType: "datetimeoffset", 1011 | oldNullable: true); 1012 | 1013 | migrationBuilder.AlterColumn( 1014 | name: "LockoutEnabled", 1015 | table: "AspNetUsers", 1016 | type: "INTEGER", 1017 | nullable: false, 1018 | oldClrType: typeof(bool), 1019 | oldType: "bit"); 1020 | 1021 | migrationBuilder.AlterColumn( 1022 | name: "EmailConfirmed", 1023 | table: "AspNetUsers", 1024 | type: "INTEGER", 1025 | nullable: false, 1026 | oldClrType: typeof(bool), 1027 | oldType: "bit"); 1028 | 1029 | migrationBuilder.AlterColumn( 1030 | name: "Email", 1031 | table: "AspNetUsers", 1032 | type: "TEXT", 1033 | maxLength: 256, 1034 | nullable: true, 1035 | oldClrType: typeof(string), 1036 | oldType: "nvarchar(256)", 1037 | oldMaxLength: 256, 1038 | oldNullable: true); 1039 | 1040 | migrationBuilder.AlterColumn( 1041 | name: "ConcurrencyStamp", 1042 | table: "AspNetUsers", 1043 | type: "TEXT", 1044 | nullable: true, 1045 | oldClrType: typeof(string), 1046 | oldType: "nvarchar(max)", 1047 | oldNullable: true); 1048 | 1049 | migrationBuilder.AlterColumn( 1050 | name: "AccessFailedCount", 1051 | table: "AspNetUsers", 1052 | type: "INTEGER", 1053 | nullable: false, 1054 | oldClrType: typeof(int), 1055 | oldType: "int"); 1056 | 1057 | migrationBuilder.AlterColumn( 1058 | name: "Id", 1059 | table: "AspNetUsers", 1060 | type: "TEXT", 1061 | nullable: false, 1062 | oldClrType: typeof(string), 1063 | oldType: "nvarchar(450)"); 1064 | 1065 | migrationBuilder.AlterColumn( 1066 | name: "RoleId", 1067 | table: "AspNetUserRoles", 1068 | type: "TEXT", 1069 | nullable: false, 1070 | oldClrType: typeof(string), 1071 | oldType: "nvarchar(450)"); 1072 | 1073 | migrationBuilder.AlterColumn( 1074 | name: "UserId", 1075 | table: "AspNetUserRoles", 1076 | type: "TEXT", 1077 | nullable: false, 1078 | oldClrType: typeof(string), 1079 | oldType: "nvarchar(450)"); 1080 | 1081 | migrationBuilder.AlterColumn( 1082 | name: "UserId", 1083 | table: "AspNetUserLogins", 1084 | type: "TEXT", 1085 | nullable: false, 1086 | oldClrType: typeof(string), 1087 | oldType: "nvarchar(450)"); 1088 | 1089 | migrationBuilder.AlterColumn( 1090 | name: "ProviderDisplayName", 1091 | table: "AspNetUserLogins", 1092 | type: "TEXT", 1093 | nullable: true, 1094 | oldClrType: typeof(string), 1095 | oldType: "nvarchar(max)", 1096 | oldNullable: true); 1097 | 1098 | migrationBuilder.AlterColumn( 1099 | name: "ProviderKey", 1100 | table: "AspNetUserLogins", 1101 | type: "TEXT", 1102 | maxLength: 128, 1103 | nullable: false, 1104 | oldClrType: typeof(string), 1105 | oldType: "nvarchar(128)", 1106 | oldMaxLength: 128); 1107 | 1108 | migrationBuilder.AlterColumn( 1109 | name: "LoginProvider", 1110 | table: "AspNetUserLogins", 1111 | type: "TEXT", 1112 | maxLength: 128, 1113 | nullable: false, 1114 | oldClrType: typeof(string), 1115 | oldType: "nvarchar(128)", 1116 | oldMaxLength: 128); 1117 | 1118 | migrationBuilder.AlterColumn( 1119 | name: "UserId", 1120 | table: "AspNetUserClaims", 1121 | type: "TEXT", 1122 | nullable: false, 1123 | oldClrType: typeof(string), 1124 | oldType: "nvarchar(450)"); 1125 | 1126 | migrationBuilder.AlterColumn( 1127 | name: "ClaimValue", 1128 | table: "AspNetUserClaims", 1129 | type: "TEXT", 1130 | nullable: true, 1131 | oldClrType: typeof(string), 1132 | oldType: "nvarchar(max)", 1133 | oldNullable: true); 1134 | 1135 | migrationBuilder.AlterColumn( 1136 | name: "ClaimType", 1137 | table: "AspNetUserClaims", 1138 | type: "TEXT", 1139 | nullable: true, 1140 | oldClrType: typeof(string), 1141 | oldType: "nvarchar(max)", 1142 | oldNullable: true); 1143 | 1144 | migrationBuilder.AlterColumn( 1145 | name: "Id", 1146 | table: "AspNetUserClaims", 1147 | type: "INTEGER", 1148 | nullable: false, 1149 | oldClrType: typeof(int), 1150 | oldType: "int") 1151 | .OldAnnotation("SqlServer:Identity", "1, 1"); 1152 | 1153 | migrationBuilder.AlterColumn( 1154 | name: "NormalizedName", 1155 | table: "AspNetRoles", 1156 | type: "TEXT", 1157 | maxLength: 256, 1158 | nullable: true, 1159 | oldClrType: typeof(string), 1160 | oldType: "nvarchar(256)", 1161 | oldMaxLength: 256, 1162 | oldNullable: true); 1163 | 1164 | migrationBuilder.AlterColumn( 1165 | name: "Name", 1166 | table: "AspNetRoles", 1167 | type: "TEXT", 1168 | maxLength: 256, 1169 | nullable: true, 1170 | oldClrType: typeof(string), 1171 | oldType: "nvarchar(256)", 1172 | oldMaxLength: 256, 1173 | oldNullable: true); 1174 | 1175 | migrationBuilder.AlterColumn( 1176 | name: "ConcurrencyStamp", 1177 | table: "AspNetRoles", 1178 | type: "TEXT", 1179 | nullable: true, 1180 | oldClrType: typeof(string), 1181 | oldType: "nvarchar(max)", 1182 | oldNullable: true); 1183 | 1184 | migrationBuilder.AlterColumn( 1185 | name: "Id", 1186 | table: "AspNetRoles", 1187 | type: "TEXT", 1188 | nullable: false, 1189 | oldClrType: typeof(string), 1190 | oldType: "nvarchar(450)"); 1191 | 1192 | migrationBuilder.AlterColumn( 1193 | name: "RoleId", 1194 | table: "AspNetRoleClaims", 1195 | type: "TEXT", 1196 | nullable: false, 1197 | oldClrType: typeof(string), 1198 | oldType: "nvarchar(450)"); 1199 | 1200 | migrationBuilder.AlterColumn( 1201 | name: "ClaimValue", 1202 | table: "AspNetRoleClaims", 1203 | type: "TEXT", 1204 | nullable: true, 1205 | oldClrType: typeof(string), 1206 | oldType: "nvarchar(max)", 1207 | oldNullable: true); 1208 | 1209 | migrationBuilder.AlterColumn( 1210 | name: "ClaimType", 1211 | table: "AspNetRoleClaims", 1212 | type: "TEXT", 1213 | nullable: true, 1214 | oldClrType: typeof(string), 1215 | oldType: "nvarchar(max)", 1216 | oldNullable: true); 1217 | 1218 | migrationBuilder.AlterColumn( 1219 | name: "Id", 1220 | table: "AspNetRoleClaims", 1221 | type: "INTEGER", 1222 | nullable: false, 1223 | oldClrType: typeof(int), 1224 | oldType: "int") 1225 | .OldAnnotation("SqlServer:Identity", "1, 1"); 1226 | 1227 | migrationBuilder.CreateIndex( 1228 | name: "UserNameIndex", 1229 | table: "AspNetUsers", 1230 | column: "NormalizedUserName", 1231 | unique: true); 1232 | 1233 | migrationBuilder.CreateIndex( 1234 | name: "RoleNameIndex", 1235 | table: "AspNetRoles", 1236 | column: "NormalizedName", 1237 | unique: true); 1238 | } 1239 | } 1240 | } 1241 | -------------------------------------------------------------------------------- /Data/Migrations/ApplicationDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using ASPWebApp.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | #nullable disable 10 | 11 | namespace ASPWebApp.Data.Migrations 12 | { 13 | [DbContext(typeof(ApplicationDbContext))] 14 | partial class ApplicationDbContextModelSnapshot : ModelSnapshot 15 | { 16 | protected override void BuildModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "6.0.1") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 22 | 23 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); 24 | 25 | modelBuilder.Entity("ASPWebApp.Models.ApplicationUser", b => 26 | { 27 | b.Property("Id") 28 | .HasColumnType("nvarchar(450)"); 29 | 30 | b.Property("AccessFailedCount") 31 | .HasColumnType("int"); 32 | 33 | b.Property("ConcurrencyStamp") 34 | .IsConcurrencyToken() 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("Email") 38 | .HasMaxLength(256) 39 | .HasColumnType("nvarchar(256)"); 40 | 41 | b.Property("EmailConfirmed") 42 | .HasColumnType("bit"); 43 | 44 | b.Property("LockoutEnabled") 45 | .HasColumnType("bit"); 46 | 47 | b.Property("LockoutEnd") 48 | .HasColumnType("datetimeoffset"); 49 | 50 | b.Property("NormalizedEmail") 51 | .HasMaxLength(256) 52 | .HasColumnType("nvarchar(256)"); 53 | 54 | b.Property("NormalizedUserName") 55 | .HasMaxLength(256) 56 | .HasColumnType("nvarchar(256)"); 57 | 58 | b.Property("PasswordHash") 59 | .HasColumnType("nvarchar(max)"); 60 | 61 | b.Property("PhoneNumber") 62 | .HasColumnType("nvarchar(max)"); 63 | 64 | b.Property("PhoneNumberConfirmed") 65 | .HasColumnType("bit"); 66 | 67 | b.Property("SecurityStamp") 68 | .HasColumnType("nvarchar(max)"); 69 | 70 | b.Property("TwoFactorEnabled") 71 | .HasColumnType("bit"); 72 | 73 | b.Property("UserName") 74 | .HasMaxLength(256) 75 | .HasColumnType("nvarchar(256)"); 76 | 77 | b.HasKey("Id"); 78 | 79 | b.HasIndex("NormalizedEmail") 80 | .HasDatabaseName("EmailIndex"); 81 | 82 | b.HasIndex("NormalizedUserName") 83 | .IsUnique() 84 | .HasDatabaseName("UserNameIndex") 85 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 86 | 87 | b.ToTable("AspNetUsers", (string)null); 88 | }); 89 | 90 | modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", b => 91 | { 92 | b.Property("UserCode") 93 | .HasMaxLength(200) 94 | .HasColumnType("nvarchar(200)"); 95 | 96 | b.Property("ClientId") 97 | .IsRequired() 98 | .HasMaxLength(200) 99 | .HasColumnType("nvarchar(200)"); 100 | 101 | b.Property("CreationTime") 102 | .HasColumnType("datetime2"); 103 | 104 | b.Property("Data") 105 | .IsRequired() 106 | .HasMaxLength(50000) 107 | .HasColumnType("nvarchar(max)"); 108 | 109 | b.Property("Description") 110 | .HasMaxLength(200) 111 | .HasColumnType("nvarchar(200)"); 112 | 113 | b.Property("DeviceCode") 114 | .IsRequired() 115 | .HasMaxLength(200) 116 | .HasColumnType("nvarchar(200)"); 117 | 118 | b.Property("Expiration") 119 | .IsRequired() 120 | .HasColumnType("datetime2"); 121 | 122 | b.Property("SessionId") 123 | .HasMaxLength(100) 124 | .HasColumnType("nvarchar(100)"); 125 | 126 | b.Property("SubjectId") 127 | .HasMaxLength(200) 128 | .HasColumnType("nvarchar(200)"); 129 | 130 | b.HasKey("UserCode"); 131 | 132 | b.HasIndex("DeviceCode") 133 | .IsUnique(); 134 | 135 | b.HasIndex("Expiration"); 136 | 137 | b.ToTable("DeviceCodes", (string)null); 138 | }); 139 | 140 | modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.Key", b => 141 | { 142 | b.Property("Id") 143 | .HasColumnType("nvarchar(450)"); 144 | 145 | b.Property("Algorithm") 146 | .IsRequired() 147 | .HasMaxLength(100) 148 | .HasColumnType("nvarchar(100)"); 149 | 150 | b.Property("Created") 151 | .HasColumnType("datetime2"); 152 | 153 | b.Property("Data") 154 | .IsRequired() 155 | .HasColumnType("nvarchar(max)"); 156 | 157 | b.Property("DataProtected") 158 | .HasColumnType("bit"); 159 | 160 | b.Property("IsX509Certificate") 161 | .HasColumnType("bit"); 162 | 163 | b.Property("Use") 164 | .HasColumnType("nvarchar(450)"); 165 | 166 | b.Property("Version") 167 | .HasColumnType("int"); 168 | 169 | b.HasKey("Id"); 170 | 171 | b.HasIndex("Use"); 172 | 173 | b.ToTable("Keys"); 174 | }); 175 | 176 | modelBuilder.Entity("Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", b => 177 | { 178 | b.Property("Key") 179 | .HasMaxLength(200) 180 | .HasColumnType("nvarchar(200)"); 181 | 182 | b.Property("ClientId") 183 | .IsRequired() 184 | .HasMaxLength(200) 185 | .HasColumnType("nvarchar(200)"); 186 | 187 | b.Property("ConsumedTime") 188 | .HasColumnType("datetime2"); 189 | 190 | b.Property("CreationTime") 191 | .HasColumnType("datetime2"); 192 | 193 | b.Property("Data") 194 | .IsRequired() 195 | .HasMaxLength(50000) 196 | .HasColumnType("nvarchar(max)"); 197 | 198 | b.Property("Description") 199 | .HasMaxLength(200) 200 | .HasColumnType("nvarchar(200)"); 201 | 202 | b.Property("Expiration") 203 | .HasColumnType("datetime2"); 204 | 205 | b.Property("SessionId") 206 | .HasMaxLength(100) 207 | .HasColumnType("nvarchar(100)"); 208 | 209 | b.Property("SubjectId") 210 | .HasMaxLength(200) 211 | .HasColumnType("nvarchar(200)"); 212 | 213 | b.Property("Type") 214 | .IsRequired() 215 | .HasMaxLength(50) 216 | .HasColumnType("nvarchar(50)"); 217 | 218 | b.HasKey("Key"); 219 | 220 | b.HasIndex("ConsumedTime"); 221 | 222 | b.HasIndex("Expiration"); 223 | 224 | b.HasIndex("SubjectId", "ClientId", "Type"); 225 | 226 | b.HasIndex("SubjectId", "SessionId", "Type"); 227 | 228 | b.ToTable("PersistedGrants", (string)null); 229 | }); 230 | 231 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 232 | { 233 | b.Property("Id") 234 | .HasColumnType("nvarchar(450)"); 235 | 236 | b.Property("ConcurrencyStamp") 237 | .IsConcurrencyToken() 238 | .HasColumnType("nvarchar(max)"); 239 | 240 | b.Property("Name") 241 | .HasMaxLength(256) 242 | .HasColumnType("nvarchar(256)"); 243 | 244 | b.Property("NormalizedName") 245 | .HasMaxLength(256) 246 | .HasColumnType("nvarchar(256)"); 247 | 248 | b.HasKey("Id"); 249 | 250 | b.HasIndex("NormalizedName") 251 | .IsUnique() 252 | .HasDatabaseName("RoleNameIndex") 253 | .HasFilter("[NormalizedName] IS NOT NULL"); 254 | 255 | b.ToTable("AspNetRoles", (string)null); 256 | }); 257 | 258 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 259 | { 260 | b.Property("Id") 261 | .ValueGeneratedOnAdd() 262 | .HasColumnType("int"); 263 | 264 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 265 | 266 | b.Property("ClaimType") 267 | .HasColumnType("nvarchar(max)"); 268 | 269 | b.Property("ClaimValue") 270 | .HasColumnType("nvarchar(max)"); 271 | 272 | b.Property("RoleId") 273 | .IsRequired() 274 | .HasColumnType("nvarchar(450)"); 275 | 276 | b.HasKey("Id"); 277 | 278 | b.HasIndex("RoleId"); 279 | 280 | b.ToTable("AspNetRoleClaims", (string)null); 281 | }); 282 | 283 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 284 | { 285 | b.Property("Id") 286 | .ValueGeneratedOnAdd() 287 | .HasColumnType("int"); 288 | 289 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); 290 | 291 | b.Property("ClaimType") 292 | .HasColumnType("nvarchar(max)"); 293 | 294 | b.Property("ClaimValue") 295 | .HasColumnType("nvarchar(max)"); 296 | 297 | b.Property("UserId") 298 | .IsRequired() 299 | .HasColumnType("nvarchar(450)"); 300 | 301 | b.HasKey("Id"); 302 | 303 | b.HasIndex("UserId"); 304 | 305 | b.ToTable("AspNetUserClaims", (string)null); 306 | }); 307 | 308 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 309 | { 310 | b.Property("LoginProvider") 311 | .HasMaxLength(128) 312 | .HasColumnType("nvarchar(128)"); 313 | 314 | b.Property("ProviderKey") 315 | .HasMaxLength(128) 316 | .HasColumnType("nvarchar(128)"); 317 | 318 | b.Property("ProviderDisplayName") 319 | .HasColumnType("nvarchar(max)"); 320 | 321 | b.Property("UserId") 322 | .IsRequired() 323 | .HasColumnType("nvarchar(450)"); 324 | 325 | b.HasKey("LoginProvider", "ProviderKey"); 326 | 327 | b.HasIndex("UserId"); 328 | 329 | b.ToTable("AspNetUserLogins", (string)null); 330 | }); 331 | 332 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 333 | { 334 | b.Property("UserId") 335 | .HasColumnType("nvarchar(450)"); 336 | 337 | b.Property("RoleId") 338 | .HasColumnType("nvarchar(450)"); 339 | 340 | b.HasKey("UserId", "RoleId"); 341 | 342 | b.HasIndex("RoleId"); 343 | 344 | b.ToTable("AspNetUserRoles", (string)null); 345 | }); 346 | 347 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 348 | { 349 | b.Property("UserId") 350 | .HasColumnType("nvarchar(450)"); 351 | 352 | b.Property("LoginProvider") 353 | .HasMaxLength(128) 354 | .HasColumnType("nvarchar(128)"); 355 | 356 | b.Property("Name") 357 | .HasMaxLength(128) 358 | .HasColumnType("nvarchar(128)"); 359 | 360 | b.Property("Value") 361 | .HasColumnType("nvarchar(max)"); 362 | 363 | b.HasKey("UserId", "LoginProvider", "Name"); 364 | 365 | b.ToTable("AspNetUserTokens", (string)null); 366 | }); 367 | 368 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 369 | { 370 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 371 | .WithMany() 372 | .HasForeignKey("RoleId") 373 | .OnDelete(DeleteBehavior.Cascade) 374 | .IsRequired(); 375 | }); 376 | 377 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 378 | { 379 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 380 | .WithMany() 381 | .HasForeignKey("UserId") 382 | .OnDelete(DeleteBehavior.Cascade) 383 | .IsRequired(); 384 | }); 385 | 386 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 387 | { 388 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 389 | .WithMany() 390 | .HasForeignKey("UserId") 391 | .OnDelete(DeleteBehavior.Cascade) 392 | .IsRequired(); 393 | }); 394 | 395 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 396 | { 397 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 398 | .WithMany() 399 | .HasForeignKey("RoleId") 400 | .OnDelete(DeleteBehavior.Cascade) 401 | .IsRequired(); 402 | 403 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 404 | .WithMany() 405 | .HasForeignKey("UserId") 406 | .OnDelete(DeleteBehavior.Cascade) 407 | .IsRequired(); 408 | }); 409 | 410 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 411 | { 412 | b.HasOne("ASPWebApp.Models.ApplicationUser", null) 413 | .WithMany() 414 | .HasForeignKey("UserId") 415 | .OnDelete(DeleteBehavior.Cascade) 416 | .IsRequired(); 417 | }); 418 | #pragma warning restore 612, 618 419 | } 420 | } 421 | } 422 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base 2 | WORKDIR /app 3 | EXPOSE 80 4 | EXPOSE 443 5 | 6 | FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build 7 | 8 | # Install Node.js 9 | RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \ 10 | && apt-get install -y \ 11 | nodejs \ 12 | && rm -rf /var/lib/apt/lists/* 13 | 14 | WORKDIR /src 15 | COPY ["ASPWebApp.csproj", "./"] 16 | RUN dotnet restore "ASPWebApp.csproj" 17 | COPY . . 18 | WORKDIR "/src/" 19 | RUN dotnet build "ASPWebApp.csproj" -c Release -o /app/build 20 | 21 | FROM build AS publish 22 | RUN dotnet publish "ASPWebApp.csproj" -c Release -o /app/publish 23 | 24 | FROM base AS final 25 | WORKDIR /app 26 | COPY --from=publish /app/publish . 27 | ENTRYPOINT ["dotnet", "ASPWebApp.dll"] 28 | -------------------------------------------------------------------------------- /Models/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace ASPWebApp.Models; 4 | 5 | public class ApplicationUser : IdentityUser 6 | { 7 | } -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using ASPWebApp.Data; 2 | using ASPWebApp.Models; 3 | using Microsoft.AspNetCore.Authentication; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | var builder = WebApplication.CreateBuilder(args); 7 | 8 | // Add services to the container. 9 | var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); 10 | builder.Services.AddDbContext(options => 11 | options.UseSqlServer(connectionString)); 12 | builder.Services.AddDatabaseDeveloperPageExceptionFilter(); 13 | 14 | builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) 15 | .AddEntityFrameworkStores(); 16 | 17 | builder.Services.AddIdentityServer() 18 | .AddApiAuthorization(); 19 | 20 | builder.Services.AddAuthentication() 21 | .AddIdentityServerJwt(); 22 | 23 | builder.Services.AddControllersWithViews(); 24 | builder.Services.AddRazorPages(); 25 | 26 | var app = builder.Build(); 27 | 28 | // Configure the HTTP request pipeline. 29 | if (app.Environment.IsDevelopment()) 30 | { 31 | app.UseMigrationsEndPoint(); 32 | } 33 | else 34 | { 35 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 36 | app.UseHsts(); 37 | } 38 | 39 | app.UseHttpsRedirection(); 40 | app.UseStaticFiles(); 41 | app.UseRouting(); 42 | 43 | app.UseAuthentication(); 44 | app.UseIdentityServer(); 45 | app.UseAuthorization(); 46 | 47 | app.MapControllerRoute( 48 | "default", 49 | "{controller}/{action=Index}/{id?}"); 50 | app.MapRazorPages(); 51 | 52 | app.MapFallbackToFile("index.html"); 53 | ; 54 | 55 | app.Run(); -------------------------------------------------------------------------------- /Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:53118", 7 | "sslPort": 44379 8 | } 9 | }, 10 | "profiles": { 11 | "ASPWebApp": { 12 | "commandName": "Project", 13 | "launchBrowser": true, 14 | "applicationUrl": "https://localhost:7242;http://localhost:5242", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development", 17 | "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" 18 | } 19 | }, 20 | "IIS Express": { 21 | "commandName": "IISExpress", 22 | "launchBrowser": true, 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development", 25 | "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | namespace ASPWebApp; 2 | 3 | public class WeatherForecast 4 | { 5 | public DateTime Date { get; set; } 6 | 7 | public int TemperatureC { get; set; } 8 | 9 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 10 | 11 | public string? Summary { get; set; } 12 | } -------------------------------------------------------------------------------- /app.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/ASPWebAppWithDocker/1e5f4526b3424be67a198ea9f3a4f63549a13c30/app.db -------------------------------------------------------------------------------- /app.db-shm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/ASPWebAppWithDocker/1e5f4526b3424be67a198ea9f3a4f63549a13c30/app.db-shm -------------------------------------------------------------------------------- /app.db-wal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/ASPWebAppWithDocker/1e5f4526b3424be67a198ea9f3a4f63549a13c30/app.db-wal -------------------------------------------------------------------------------- /appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.AspNetCore.SpaProxy": "Information", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "IdentityServer": { 11 | "Key": { 12 | "Type": "Development" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Data Source=localhost;Integrated Security=True;Initial Catalog=ASPWebDocker;MultipleActiveResultSets=true" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "IdentityServer": { 13 | "Clients": { 14 | "ASPWebApp": { 15 | "Profile": "IdentityServerSPA" 16 | } 17 | } 18 | }, 19 | "AllowedHosts": "*" 20 | } 21 | -------------------------------------------------------------------------------- /wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/ASPWebAppWithDocker/1e5f4526b3424be67a198ea9f3a4f63549a13c30/wwwroot/favicon.ico --------------------------------------------------------------------------------