mirror of
https://github.com/morbalint/kemkas.git
synced 2026-07-17 19:03:46 +00:00
ci: split repo: make this repo frontend only again
This commit is contained in:
+9
-147
@@ -18,54 +18,22 @@ jobs:
|
|||||||
- name: Cache NPM packages
|
- name: Cache NPM packages
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
key: npm-${{ hashFiles('./Kemkas.Web/frontend/yarn.lock') }}
|
key: npm-${{ hashFiles('./frontend/yarn.lock') }}
|
||||||
path: |
|
path: |
|
||||||
./Kemkas.Web/frontend/node_modules
|
./frontend/node_modules
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
npm-${{ hashFiles('./Kemkas.Web/frontend/yarn.lock') }}
|
npm-${{ hashFiles('./frontend/yarn.lock') }}
|
||||||
npm-
|
npm-
|
||||||
- name: Yarn Install
|
- name: Yarn Install
|
||||||
run: |
|
run: |
|
||||||
cd ./Kemkas.Web/frontend
|
cd ./frontend
|
||||||
yarn install --frozen-lockfiles
|
yarn install --frozen-lockfiles
|
||||||
- name: Yarn Test
|
- name: Yarn Test
|
||||||
run: |
|
run: |
|
||||||
cd ./Kemkas.Web/frontend
|
cd ./frontend
|
||||||
./compile-less.sh
|
./compile-less.sh
|
||||||
yarn build
|
yarn build
|
||||||
|
|
||||||
docker-build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Install doctl
|
|
||||||
uses: digitalocean/action-doctl@v2
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.DO_ACCESS_TOKEN }}
|
|
||||||
- name: Log in to DigitalOcean Container Registry with short-lived credentials
|
|
||||||
run: doctl registry login --expiry-seconds 1200
|
|
||||||
- name: Log in to GitHub Container Registry
|
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
|
||||||
- uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Kemkas.Web/Dockerfile
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
push: false
|
|
||||||
load: true
|
|
||||||
tags: kemkas/kemkas:edge
|
|
||||||
- name: Tag container image
|
|
||||||
run: |
|
|
||||||
docker tag kemkas/kemkas:edge registry.digitalocean.com/kemkas/kemkas:${GITHUB_SHA::8}
|
|
||||||
docker tag kemkas/kemkas:edge ghcr.io/${{ github.repository_owner }}/kemkas:${GITHUB_SHA::8}
|
|
||||||
- name: Push image to Container Registry
|
|
||||||
run: |
|
|
||||||
docker push registry.digitalocean.com/kemkas/kemkas:${GITHUB_SHA::8}
|
|
||||||
docker push ghcr.io/${{ github.repository_owner }}/kemkas:${GITHUB_SHA::8}
|
|
||||||
|
|
||||||
docker-fe-build:
|
docker-fe-build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
@@ -82,8 +50,8 @@ jobs:
|
|||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||||
- uses: docker/build-push-action@v5
|
- uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: ./Kemkas.Web/frontend/
|
context: ./frontend/
|
||||||
file: ./Kemkas.Web/frontend/Dockerfile
|
file: ./frontend/Dockerfile
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
push: false
|
push: false
|
||||||
@@ -92,114 +60,8 @@ jobs:
|
|||||||
- name: Tag container image
|
- name: Tag container image
|
||||||
run: |
|
run: |
|
||||||
docker tag kemkas/kemkas-fe:edge registry.digitalocean.com/kemkas/kemkas-fe:${GITHUB_SHA::8}
|
docker tag kemkas/kemkas-fe:edge registry.digitalocean.com/kemkas/kemkas-fe:${GITHUB_SHA::8}
|
||||||
docker tag kemkas/kemkas-fe:edge ghcr.io/${{ github.repository_owner }}/kemkas-fe:${GITHUB_SHA::8}
|
docker tag kemkas/kemkas-fe:edge ghcr.io/${{ github.repository_owner }}/kemkas-frontend:${GITHUB_SHA::8}
|
||||||
- name: Push image to Container Registry
|
- name: Push image to Container Registry
|
||||||
run: |
|
run: |
|
||||||
docker push registry.digitalocean.com/kemkas/kemkas-fe:${GITHUB_SHA::8}
|
docker push registry.digitalocean.com/kemkas/kemkas-fe:${GITHUB_SHA::8}
|
||||||
docker push ghcr.io/${{ github.repository_owner }}/kemkas-fe:${GITHUB_SHA::8}
|
docker push ghcr.io/${{ github.repository_owner }}/kemkas-frontend:${GITHUB_SHA::8}
|
||||||
|
|
||||||
docker-be-build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Install doctl
|
|
||||||
uses: digitalocean/action-doctl@v2
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.DO_ACCESS_TOKEN }}
|
|
||||||
- name: Log in to DigitalOcean Container Registry with short-lived credentials
|
|
||||||
run: doctl registry login --expiry-seconds 1200
|
|
||||||
- name: Log in to GitHub Container Registry
|
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
|
||||||
- uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Kemkas.Web/Backend.Dockerfile
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
push: false
|
|
||||||
load: true
|
|
||||||
tags: kemkas/kemkas-be:edge
|
|
||||||
- name: Tag container image
|
|
||||||
run: |
|
|
||||||
docker tag kemkas/kemkas-be:edge registry.digitalocean.com/kemkas/kemkas-be:${GITHUB_SHA::8}
|
|
||||||
docker tag kemkas/kemkas-be:edge ghcr.io/${{ github.repository_owner }}/kemkas-be:${GITHUB_SHA::8}
|
|
||||||
- name: Push image to Container Registry
|
|
||||||
run: |
|
|
||||||
docker push registry.digitalocean.com/kemkas/kemkas-be:${GITHUB_SHA::8}
|
|
||||||
docker push ghcr.io/${{ github.repository_owner }}/kemkas-be:${GITHUB_SHA::8}
|
|
||||||
|
|
||||||
docker-composit-build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
needs:
|
|
||||||
- docker-be-build
|
|
||||||
- docker-fe-build
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Log in to GitHub Container Registry
|
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
|
||||||
- run: |
|
|
||||||
echo "GITHUB_SHA_SHORT=$(echo ${GITHUB_SHA::8})" >> $GITHUB_ENV
|
|
||||||
- uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Kemkas.Web/Composite.Dockerfile
|
|
||||||
build-args: |
|
|
||||||
FE_TAG=${{ env.GITHUB_SHA_SHORT }}
|
|
||||||
BE_TAG=${{ env.GITHUB_SHA_SHORT }}
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
push: false
|
|
||||||
load: true
|
|
||||||
tags: ghcr.io/${{ github.repository_owner }}/kemkas/kemkas-composite:${{ env.GITHUB_SHA_SHORT }}
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- ci-fe
|
|
||||||
- docker-build
|
|
||||||
if: ${{ github.event_name == 'push' || ( github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged ) }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Install doctl
|
|
||||||
uses: digitalocean/action-doctl@v2
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.DO_ACCESS_TOKEN }}
|
|
||||||
- name: Log in to DigitalOcean Container Registry with short-lived credentials
|
|
||||||
run: doctl registry login --expiry-seconds 1200
|
|
||||||
- name: Log in to GitHub Container Registry
|
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
|
||||||
- name: Tag container image with latest tag
|
|
||||||
run: |
|
|
||||||
docker pull ghcr.io/${{ github.repository_owner }}/kemkas:${GITHUB_SHA::8}
|
|
||||||
docker pull registry.digitalocean.com/kemkas/kemkas:${GITHUB_SHA::8}
|
|
||||||
docker tag registry.digitalocean.com/kemkas/kemkas:${GITHUB_SHA::8} registry.digitalocean.com/kemkas/kemkas:latest
|
|
||||||
docker tag ghcr.io/${{ github.repository_owner }}/kemkas:${GITHUB_SHA::8} ghcr.io/${{ github.repository_owner }}/kemkas:latest
|
|
||||||
- name: Push image to Container Registry
|
|
||||||
run: |
|
|
||||||
docker push registry.digitalocean.com/kemkas/kemkas:latest
|
|
||||||
docker push ghcr.io/${{ github.repository_owner }}/kemkas:latest
|
|
||||||
- name: Get container image ID of the images just pushed
|
|
||||||
run: |
|
|
||||||
docker images ghcr.io/${{ github.repository_owner }}/kemkas:${GITHUB_SHA::8} --format "{{.ID}}"
|
|
||||||
export DOCKER_IMAGE_ID=$(docker images ghcr.io/${{ github.repository_owner }}/kemkas:${GITHUB_SHA::8} --format "{{.ID}}")
|
|
||||||
export DOCKER_IMAGE_ID=GHCR-$DOCKER_IMAGE_ID
|
|
||||||
echo "DOCKER_IMAGE_ID=$DOCKER_IMAGE_ID" >> $GITHUB_ENV
|
|
||||||
- uses: mukunku/tag-exists-action@v1.6.0
|
|
||||||
with:
|
|
||||||
tag: ${{ env.DOCKER_IMAGE_ID }}
|
|
||||||
- name: Tag commit with docker image ID
|
|
||||||
if: steps.check-tag.outputs.exists == 'false'
|
|
||||||
uses: actions/github-script@v5
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
github.rest.git.createRef({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
ref: "refs/tags/${{ env.DOCKER_IMAGE_ID }}",
|
|
||||||
sha: context.sha
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 1,
|
|
||||||
"isRoot": true,
|
|
||||||
"tools": {
|
|
||||||
"dotnet-aspnet-codegenerator": {
|
|
||||||
"version": "8.0.0",
|
|
||||||
"commands": [
|
|
||||||
"dotnet-aspnet-codegenerator"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"dotnet-ef": {
|
|
||||||
"version": "8.0.0",
|
|
||||||
"commands": [
|
|
||||||
"dotnet-ef"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
|
||||||
## files generated by popular Visual Studio add-ons.
|
|
||||||
|
|
||||||
# User-specific files
|
|
||||||
*.suo
|
|
||||||
*.user
|
|
||||||
*.userosscache
|
|
||||||
*.sln.docstates
|
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
|
||||||
*.userprefs
|
|
||||||
|
|
||||||
# Build results
|
|
||||||
[Dd]ebug/
|
|
||||||
[Dd]ebugPublic/
|
|
||||||
[Rr]elease/
|
|
||||||
[Rr]eleases/
|
|
||||||
x64/
|
|
||||||
x86/
|
|
||||||
build/
|
|
||||||
bld/
|
|
||||||
bin/
|
|
||||||
Bin/
|
|
||||||
obj/
|
|
||||||
Obj/
|
|
||||||
|
|
||||||
# Visual Studio 2015 cache/options directory
|
|
||||||
.vs/
|
|
||||||
/wwwroot/dist/
|
|
||||||
|
|
||||||
# MSTest test Results
|
|
||||||
[Tt]est[Rr]esult*/
|
|
||||||
[Bb]uild[Ll]og.*
|
|
||||||
|
|
||||||
# NUNIT
|
|
||||||
*.VisualState.xml
|
|
||||||
TestResult.xml
|
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
|
||||||
[Dd]ebugPS/
|
|
||||||
[Rr]eleasePS/
|
|
||||||
dlldata.c
|
|
||||||
|
|
||||||
*_i.c
|
|
||||||
*_p.c
|
|
||||||
*_i.h
|
|
||||||
*.ilk
|
|
||||||
*.meta
|
|
||||||
*.obj
|
|
||||||
*.pch
|
|
||||||
*.pdb
|
|
||||||
*.pgc
|
|
||||||
*.pgd
|
|
||||||
*.rsp
|
|
||||||
*.sbr
|
|
||||||
*.tlb
|
|
||||||
*.tli
|
|
||||||
*.tlh
|
|
||||||
*.tmp
|
|
||||||
*.tmp_proj
|
|
||||||
*.log
|
|
||||||
*.vspscc
|
|
||||||
*.vssscc
|
|
||||||
.builds
|
|
||||||
*.pidb
|
|
||||||
*.svclog
|
|
||||||
*.scc
|
|
||||||
|
|
||||||
# Chutzpah Test files
|
|
||||||
_Chutzpah*
|
|
||||||
|
|
||||||
# Visual C++ cache files
|
|
||||||
ipch/
|
|
||||||
*.aps
|
|
||||||
*.ncb
|
|
||||||
*.opendb
|
|
||||||
*.opensdf
|
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
|
||||||
|
|
||||||
# Visual Studio profiler
|
|
||||||
*.psess
|
|
||||||
*.vsp
|
|
||||||
*.vspx
|
|
||||||
*.sap
|
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
|
||||||
$tf/
|
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
|
||||||
*.gpState
|
|
||||||
|
|
||||||
# ReSharper is a .NET coding add-in
|
|
||||||
_ReSharper*/
|
|
||||||
*.[Rr]e[Ss]harper
|
|
||||||
*.DotSettings.user
|
|
||||||
|
|
||||||
# JustCode is a .NET coding add-in
|
|
||||||
.JustCode
|
|
||||||
|
|
||||||
# TeamCity is a build add-in
|
|
||||||
_TeamCity*
|
|
||||||
|
|
||||||
# DotCover is a Code Coverage Tool
|
|
||||||
*.dotCover
|
|
||||||
|
|
||||||
# NCrunch
|
|
||||||
_NCrunch_*
|
|
||||||
.*crunch*.local.xml
|
|
||||||
nCrunchTemp_*
|
|
||||||
|
|
||||||
# MightyMoose
|
|
||||||
*.mm.*
|
|
||||||
AutoTest.Net/
|
|
||||||
|
|
||||||
# Web workbench (sass)
|
|
||||||
.sass-cache/
|
|
||||||
|
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
|
||||||
DocProject/buildhelp/
|
|
||||||
DocProject/Help/*.HxT
|
|
||||||
DocProject/Help/*.HxC
|
|
||||||
DocProject/Help/*.hhc
|
|
||||||
DocProject/Help/*.hhk
|
|
||||||
DocProject/Help/*.hhp
|
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
|
||||||
|
|
||||||
# Click-Once directory
|
|
||||||
publish/
|
|
||||||
|
|
||||||
# Publish Web Output
|
|
||||||
*.[Pp]ublish.xml
|
|
||||||
*.azurePubxml
|
|
||||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
|
||||||
|
|
||||||
# NuGet Packages
|
|
||||||
*.nupkg
|
|
||||||
# The packages folder can be ignored because of Package Restore
|
|
||||||
**/packages/*
|
|
||||||
# except build/, which is used as an MSBuild target.
|
|
||||||
!**/packages/build/
|
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
|
||||||
#!**/packages/repositories.config
|
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
|
||||||
csx/
|
|
||||||
*.build.csdef
|
|
||||||
|
|
||||||
# Microsoft Azure Emulator
|
|
||||||
ecf/
|
|
||||||
rcf/
|
|
||||||
|
|
||||||
# Microsoft Azure ApplicationInsights config file
|
|
||||||
ApplicationInsights.config
|
|
||||||
|
|
||||||
# Windows Store app package directory
|
|
||||||
AppPackages/
|
|
||||||
BundleArtifacts/
|
|
||||||
|
|
||||||
# Visual Studio cache files
|
|
||||||
# files ending in .cache can be ignored
|
|
||||||
*.[Cc]ache
|
|
||||||
# but keep track of directories ending in .cache
|
|
||||||
!*.[Cc]ache/
|
|
||||||
|
|
||||||
# Others
|
|
||||||
ClientBin/
|
|
||||||
~$*
|
|
||||||
*~
|
|
||||||
*.dbmdl
|
|
||||||
*.dbproj.schemaview
|
|
||||||
*.pfx
|
|
||||||
*.publishsettings
|
|
||||||
orleans.codegen.cs
|
|
||||||
|
|
||||||
/node_modules
|
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
|
||||||
# because we have git ;-)
|
|
||||||
_UpgradeReport_Files/
|
|
||||||
Backup*/
|
|
||||||
UpgradeLog*.XML
|
|
||||||
UpgradeLog*.htm
|
|
||||||
|
|
||||||
# SQL Server files
|
|
||||||
*.mdf
|
|
||||||
*.ldf
|
|
||||||
|
|
||||||
# Business Intelligence projects
|
|
||||||
*.rdl.data
|
|
||||||
*.bim.layout
|
|
||||||
*.bim_*.settings
|
|
||||||
|
|
||||||
# Microsoft Fakes
|
|
||||||
FakesAssemblies/
|
|
||||||
|
|
||||||
# GhostDoc plugin setting file
|
|
||||||
*.GhostDoc.xml
|
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
|
||||||
.ntvs_analysis.dat
|
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
|
||||||
*.plg
|
|
||||||
|
|
||||||
# Visual Studio 6 workspace options file
|
|
||||||
*.opt
|
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/ModelManifest.xml
|
|
||||||
**/*.Server/GeneratedArtifacts
|
|
||||||
**/*.Server/ModelManifest.xml
|
|
||||||
_Pvt_Extensions
|
|
||||||
|
|
||||||
# Paket dependency manager
|
|
||||||
.paket/paket.exe
|
|
||||||
|
|
||||||
# FAKE - F# Make
|
|
||||||
.fake/
|
|
||||||
|
|
||||||
# temp sqlite db
|
|
||||||
/app.db
|
|
||||||
|
|
||||||
# local env vars
|
|
||||||
.env
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
GET https://localhost:7251/WeatherForecast
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# Simple character
|
|
||||||
|
|
||||||
POST https://localhost:7251/Character
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "Névtelen Kalandozó",
|
|
||||||
"faj": "f_ember",
|
|
||||||
"kor": 20,
|
|
||||||
"jellem": "S",
|
|
||||||
"tulajdonsagok": {
|
|
||||||
"t_ero": 10,
|
|
||||||
"t_ugy": 10,
|
|
||||||
"t_egs": 10,
|
|
||||||
"t_int": 10,
|
|
||||||
"t_bol": 10,
|
|
||||||
"t_kar": 10
|
|
||||||
},
|
|
||||||
"osztaly": "o_kaloz",
|
|
||||||
"kepzettsegek": ["k_allatidomitas", "k_eloadas", "k_ertekbecsles", "k_gyogyitas"],
|
|
||||||
"Tolvajkepzettsegek": [],
|
|
||||||
"szint": 1,
|
|
||||||
"hpRolls": [],
|
|
||||||
"tulajdonsagNovelesek": [],
|
|
||||||
"harcosSpecializaciok": [],
|
|
||||||
"kalozKritikus": [],
|
|
||||||
"felszereles": {
|
|
||||||
"fegyverIDk": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
### Get simple character
|
|
||||||
|
|
||||||
GET https://localhost:7251/Character/f43aecb5-c247-4d3f-a31b-c886cfeae54b
|
|
||||||
Accept: application/json
|
|
||||||
|
|
||||||
### Complex character
|
|
||||||
|
|
||||||
POST https://localhost:7251/Character
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "Névtelen Kalandozó",
|
|
||||||
"faj": "f_ember",
|
|
||||||
"kor": 20,
|
|
||||||
"jellem": "S",
|
|
||||||
"tulajdonsagok": {
|
|
||||||
"t_ero": 12,
|
|
||||||
"t_ugy": 15,
|
|
||||||
"t_egs": 14,
|
|
||||||
"t_int": 11,
|
|
||||||
"t_bol": 8,
|
|
||||||
"t_kar": 11
|
|
||||||
},
|
|
||||||
"osztaly": "o_harcos",
|
|
||||||
"kepzettsegek": [
|
|
||||||
"k_allatidomitas",
|
|
||||||
"k_eloadas",
|
|
||||||
"k_ertekbecsles",
|
|
||||||
"k_gyogyitas"
|
|
||||||
],
|
|
||||||
"szint": 5,
|
|
||||||
"hpRolls": [
|
|
||||||
9,
|
|
||||||
7,
|
|
||||||
9,
|
|
||||||
4
|
|
||||||
],
|
|
||||||
"tulajdonsagNovelesek": [
|
|
||||||
"t_egs"
|
|
||||||
],
|
|
||||||
"harcosSpecializaciok": ["szablya", "csatabard", "fejsze"],
|
|
||||||
"kalozKritikus": [],
|
|
||||||
"felszereles": {
|
|
||||||
"fegyverIDk": ["szablya"],
|
|
||||||
"pancelID": "kivert_bor",
|
|
||||||
"pajzsID": "nagy_fa"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
### Get complex character
|
|
||||||
|
|
||||||
GET https://localhost:7251/Character/a448f4d6-7a61-46a5-9453-c58093c58bd1
|
|
||||||
Accept: application/json
|
|
||||||
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
@page
|
|
||||||
@model AccessDeniedModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Access denied";
|
|
||||||
}
|
|
||||||
|
|
||||||
<header>
|
|
||||||
<h1 class="text-danger">@ViewData["Title"]</h1>
|
|
||||||
<p class="text-danger">You do not have access to this resource.</p>
|
|
||||||
</header>
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class AccessDeniedModel : PageModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public void OnGet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ConfirmEmailModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Confirm email";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<partial name="_StatusMessage" model="Model.StatusMessage" />
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
public class ConfirmEmailModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
|
|
||||||
public ConfirmEmailModel(UserManager<ApplicationUser> userManager)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
public async Task<IActionResult> OnGetAsync(string userId, string code)
|
|
||||||
{
|
|
||||||
if (userId == null || code == null)
|
|
||||||
{
|
|
||||||
return RedirectToPage("/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await _userManager.FindByIdAsync(userId);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{userId}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code));
|
|
||||||
var result = await _userManager.ConfirmEmailAsync(user, code);
|
|
||||||
StatusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email.";
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ConfirmEmailChangeModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Confirm email change";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<partial name="_StatusMessage" model="Model.StatusMessage" />
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
public class ConfirmEmailChangeModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
|
|
||||||
public ConfirmEmailChangeModel(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync(string userId, string email, string code)
|
|
||||||
{
|
|
||||||
if (userId == null || email == null || code == null)
|
|
||||||
{
|
|
||||||
return RedirectToPage("/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await _userManager.FindByIdAsync(userId);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{userId}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code));
|
|
||||||
var result = await _userManager.ChangeEmailAsync(user, email, code);
|
|
||||||
if (!result.Succeeded)
|
|
||||||
{
|
|
||||||
StatusMessage = "Error changing email.";
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
// In our UI email and user name are one and the same, so when we update the email
|
|
||||||
// we need to update the user name.
|
|
||||||
var setUserNameResult = await _userManager.SetUserNameAsync(user, email);
|
|
||||||
if (!setUserNameResult.Succeeded)
|
|
||||||
{
|
|
||||||
StatusMessage = "Error changing user name.";
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
await _signInManager.RefreshSignInAsync(user);
|
|
||||||
StatusMessage = "Thank you for confirming your email change.";
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ExternalLoginModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Register";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<h2 id="external-login-title">Associate your @Model.ProviderDisplayName account.</h2>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<p id="external-login-description" class="text-info">
|
|
||||||
You've successfully authenticated with <strong>@Model.ProviderDisplayName</strong>.
|
|
||||||
Please enter an email address for this site below and click the Register button to finish
|
|
||||||
logging in.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<form asp-page-handler="Confirmation" asp-route-returnUrl="@Model.ReturnUrl" method="post">
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Email" class="form-control" autocomplete="email" placeholder="Please enter your email."/>
|
|
||||||
<label asp-for="Input.Email" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.Email" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Register</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,246 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
[AllowAnonymous]
|
|
||||||
public class ExternalLoginModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly IUserStore<ApplicationUser> _userStore;
|
|
||||||
private readonly IUserEmailStore<ApplicationUser> _emailStore;
|
|
||||||
private readonly IEmailSender _emailSender;
|
|
||||||
private readonly ILogger<ExternalLoginModel> _logger;
|
|
||||||
|
|
||||||
public ExternalLoginModel(
|
|
||||||
SignInManager<ApplicationUser> signInManager,
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
IUserStore<ApplicationUser> userStore,
|
|
||||||
ILogger<ExternalLoginModel> logger,
|
|
||||||
IEmailSender emailSender)
|
|
||||||
{
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_userManager = userManager;
|
|
||||||
_userStore = userStore;
|
|
||||||
_emailStore = GetEmailStore();
|
|
||||||
_logger = logger;
|
|
||||||
_emailSender = emailSender;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string ProviderDisplayName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string ReturnUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string ErrorMessage { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[EmailAddress]
|
|
||||||
public string Email { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IActionResult OnGet() => RedirectToPage("./Login");
|
|
||||||
|
|
||||||
public IActionResult OnPost(string provider, string returnUrl = null)
|
|
||||||
{
|
|
||||||
// Request a redirect to the external login provider.
|
|
||||||
var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl });
|
|
||||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
|
|
||||||
return new ChallengeResult(provider, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
|
|
||||||
{
|
|
||||||
returnUrl = returnUrl ?? Url.Content("~/");
|
|
||||||
if (remoteError != null)
|
|
||||||
{
|
|
||||||
ErrorMessage = $"Error from external provider: {remoteError}";
|
|
||||||
return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
|
|
||||||
}
|
|
||||||
var info = await _signInManager.GetExternalLoginInfoAsync();
|
|
||||||
if (info == null)
|
|
||||||
{
|
|
||||||
ErrorMessage = "Error loading external login information.";
|
|
||||||
return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign in the user with this external login provider if the user already has a login.
|
|
||||||
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
|
|
||||||
return LocalRedirect(returnUrl);
|
|
||||||
}
|
|
||||||
if (result.IsLockedOut)
|
|
||||||
{
|
|
||||||
return RedirectToPage("./Lockout");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the user does not have an account, and no email claim, then ask the user to create an account.
|
|
||||||
ReturnUrl = returnUrl;
|
|
||||||
ProviderDisplayName = info.ProviderDisplayName;
|
|
||||||
if (!info.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
|
|
||||||
{
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
// User doesn't have account but external provider has email claim. => Register with claimed email.
|
|
||||||
Input = new InputModel
|
|
||||||
{
|
|
||||||
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
|
|
||||||
};
|
|
||||||
var user = CreateUser();
|
|
||||||
await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
|
|
||||||
await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
|
|
||||||
var registrationResult = await _userManager.CreateAsync(user);
|
|
||||||
if (registrationResult.Succeeded)
|
|
||||||
{
|
|
||||||
registrationResult = await _userManager.AddLoginAsync(user, info);
|
|
||||||
if (registrationResult.Succeeded)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
|
|
||||||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
|
||||||
await _userManager.ConfirmEmailAsync(user, code);
|
|
||||||
await _signInManager.SignInAsync(user, isPersistent: false, info.LoginProvider);
|
|
||||||
return LocalRedirect(returnUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var error in registrationResult.Errors)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, error.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostConfirmationAsync(string returnUrl = null)
|
|
||||||
{
|
|
||||||
returnUrl = returnUrl ?? Url.Content("~/");
|
|
||||||
// Get the information about the user from the external login provider
|
|
||||||
var info = await _signInManager.GetExternalLoginInfoAsync();
|
|
||||||
if (info == null)
|
|
||||||
{
|
|
||||||
ErrorMessage = "Error loading external login information during confirmation.";
|
|
||||||
return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ModelState.IsValid)
|
|
||||||
{
|
|
||||||
var user = CreateUser();
|
|
||||||
|
|
||||||
await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
|
|
||||||
await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
|
|
||||||
|
|
||||||
var result = await _userManager.CreateAsync(user);
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
result = await _userManager.AddLoginAsync(user, info);
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
|
|
||||||
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
|
||||||
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
|
||||||
var callbackUrl = Url.Page(
|
|
||||||
"/Account/ConfirmEmail",
|
|
||||||
pageHandler: null,
|
|
||||||
values: new { area = "Identity", userId = userId, code = code },
|
|
||||||
protocol: Request.Scheme);
|
|
||||||
|
|
||||||
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
|
|
||||||
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
|
||||||
|
|
||||||
// If account confirmation is required, we need to show the link if we don't have a real email sender
|
|
||||||
if (_userManager.Options.SignIn.RequireConfirmedAccount)
|
|
||||||
{
|
|
||||||
return RedirectToPage("./RegisterConfirmation", new { Email = Input.Email });
|
|
||||||
}
|
|
||||||
|
|
||||||
await _signInManager.SignInAsync(user, isPersistent: false, info.LoginProvider);
|
|
||||||
return LocalRedirect(returnUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var error in result.Errors)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, error.Description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProviderDisplayName = info.ProviderDisplayName;
|
|
||||||
ReturnUrl = returnUrl;
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ApplicationUser CreateUser()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Activator.CreateInstance<ApplicationUser>();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " +
|
|
||||||
$"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor, or alternatively " +
|
|
||||||
$"override the external login page in /Areas/Identity/Pages/Account/ExternalLogin.cshtml");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IUserEmailStore<ApplicationUser> GetEmailStore()
|
|
||||||
{
|
|
||||||
if (!_userManager.SupportsUserEmail)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("The default UI requires a user store with email support.");
|
|
||||||
}
|
|
||||||
return (IUserEmailStore<ApplicationUser>)_userStore;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ForgotPasswordModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Forgot your password?";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<h2>Enter your email.</h2>
|
|
||||||
<hr />
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<form method="post">
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="name@example.com" />
|
|
||||||
<label asp-for="Input.Email" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.Email" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Reset Password</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
public class ForgotPasswordModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly IEmailSender _emailSender;
|
|
||||||
|
|
||||||
public ForgotPasswordModel(UserManager<ApplicationUser> userManager, IEmailSender emailSender)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_emailSender = emailSender;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[EmailAddress]
|
|
||||||
public string Email { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
if (ModelState.IsValid)
|
|
||||||
{
|
|
||||||
var user = await _userManager.FindByEmailAsync(Input.Email);
|
|
||||||
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
|
|
||||||
{
|
|
||||||
// Don't reveal that the user does not exist or is not confirmed
|
|
||||||
return RedirectToPage("./ForgotPasswordConfirmation");
|
|
||||||
}
|
|
||||||
|
|
||||||
// For more information on how to enable account confirmation and password reset please
|
|
||||||
// visit https://go.microsoft.com/fwlink/?LinkID=532713
|
|
||||||
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
|
|
||||||
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
|
||||||
var callbackUrl = Url.Page(
|
|
||||||
"/Account/ResetPassword",
|
|
||||||
pageHandler: null,
|
|
||||||
values: new { area = "Identity", code },
|
|
||||||
protocol: Request.Scheme);
|
|
||||||
|
|
||||||
await _emailSender.SendEmailAsync(
|
|
||||||
Input.Email,
|
|
||||||
"Reset Password",
|
|
||||||
$"Please reset your password by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
|
||||||
|
|
||||||
return RedirectToPage("./ForgotPasswordConfirmation");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ForgotPasswordConfirmation
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Forgot password confirmation";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<p>
|
|
||||||
Please check your email to reset your password.
|
|
||||||
</p>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[AllowAnonymous]
|
|
||||||
public class ForgotPasswordConfirmation : PageModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public void OnGet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
@page
|
|
||||||
@model LockoutModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Locked out";
|
|
||||||
}
|
|
||||||
|
|
||||||
<header>
|
|
||||||
<h1 class="text-danger">@ViewData["Title"]</h1>
|
|
||||||
<p class="text-danger">This account has been locked out, please try again later.</p>
|
|
||||||
</header>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[AllowAnonymous]
|
|
||||||
public class LockoutModel : PageModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public void OnGet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
@page
|
|
||||||
@model LoginModel
|
|
||||||
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Log in";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<section>
|
|
||||||
<form id="account" method="post">
|
|
||||||
<h2>Use a local account to log in.</h2>
|
|
||||||
<hr />
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="name@example.com" />
|
|
||||||
<label asp-for="Input.Email" class="form-label">Email</label>
|
|
||||||
<span asp-validation-for="Input.Email" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Password" class="form-control" autocomplete="current-password" aria-required="true" placeholder="password" />
|
|
||||||
<label asp-for="Input.Password" class="form-label">Password</label>
|
|
||||||
<span asp-validation-for="Input.Password" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox mb-3">
|
|
||||||
<label asp-for="Input.RememberMe" class="form-label">
|
|
||||||
<input class="form-check-input" asp-for="Input.RememberMe" />
|
|
||||||
@Html.DisplayNameFor(m => m.Input.RememberMe)
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button id="login-submit" type="submit" class="w-100 btn btn-lg btn-primary">Log in</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
<a id="forgot-password" asp-page="./ForgotPassword">Forgot your password?</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a id="resend-confirmation" asp-page="./ResendEmailConfirmation">Resend email confirmation</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6 col-md-offset-2">
|
|
||||||
<section>
|
|
||||||
<h3>Use another service to log in.</h3>
|
|
||||||
<hr />
|
|
||||||
@{
|
|
||||||
if ((Model.ExternalLogins?.Count ?? 0) == 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
There are no external authentication services configured. See this <a href="https://go.microsoft.com/fwlink/?LinkID=532715">article
|
|
||||||
about setting up this ASP.NET application to support logging in via external services</a>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
<button type="submit" class="btn" name="provider" value="Discord" title="Log in using your Discord account"><img height="24px" alt="Discord" src="/img/discord-logo-blue.svg" /></button>
|
|
||||||
@foreach (var provider in Model.ExternalLogins!.Where(el => el.Name != "Discord"))
|
|
||||||
{
|
|
||||||
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
|
|
||||||
}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Authentication;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
public class LoginModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly ILogger<LoginModel> _logger;
|
|
||||||
private readonly IWebHostEnvironment _environment;
|
|
||||||
|
|
||||||
public LoginModel(SignInManager<ApplicationUser> signInManager, ILogger<LoginModel> logger, IWebHostEnvironment environment)
|
|
||||||
{
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_logger = logger;
|
|
||||||
_environment = environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public IList<AuthenticationScheme> ExternalLogins { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string ReturnUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string ErrorMessage { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[EmailAddress]
|
|
||||||
public string Email { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
public string Password { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Display(Name = "Remember me?")]
|
|
||||||
public bool RememberMe { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task OnGetAsync(string returnUrl = null)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(ErrorMessage))
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, ErrorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
returnUrl ??= Url.Content("~/");
|
|
||||||
|
|
||||||
// Clear the existing external cookie to ensure a clean login process
|
|
||||||
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
|
|
||||||
|
|
||||||
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
|
|
||||||
|
|
||||||
// Disable not yet approved external login providers in production
|
|
||||||
if (!_environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
ExternalLogins = ExternalLogins.Where(el => el.Name == "Discord").ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnUrl = returnUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
|
|
||||||
{
|
|
||||||
returnUrl ??= Url.Content("~/");
|
|
||||||
|
|
||||||
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
|
|
||||||
|
|
||||||
// Disable not yet approved external login providers in production
|
|
||||||
if (!_environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
ExternalLogins = ExternalLogins.Where(el => el.Name == "Discord").ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ModelState.IsValid)
|
|
||||||
{
|
|
||||||
// This doesn't count login failures towards account lockout
|
|
||||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
|
||||||
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("User logged in.");
|
|
||||||
return LocalRedirect(returnUrl);
|
|
||||||
}
|
|
||||||
if (result.RequiresTwoFactor)
|
|
||||||
{
|
|
||||||
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
|
|
||||||
}
|
|
||||||
if (result.IsLockedOut)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("User account locked out.");
|
|
||||||
return RedirectToPage("./Lockout");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we got this far, something failed, redisplay form
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
@page
|
|
||||||
@model LoginWith2faModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Two-factor authentication";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<hr />
|
|
||||||
<p>Your login is protected with an authenticator app. Enter your authenticator code below.</p>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<form method="post" asp-route-returnUrl="@Model.ReturnUrl">
|
|
||||||
<input asp-for="RememberMe" type="hidden" />
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.TwoFactorCode" class="form-control" autocomplete="off" />
|
|
||||||
<label asp-for="Input.TwoFactorCode" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.TwoFactorCode" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox mb-3">
|
|
||||||
<label asp-for="Input.RememberMachine" class="form-label">
|
|
||||||
<input asp-for="Input.RememberMachine" />
|
|
||||||
@Html.DisplayNameFor(m => m.Input.RememberMachine)
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Log in</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
Don't have access to your authenticator device? You can
|
|
||||||
<a id="recovery-code-login" asp-page="./LoginWithRecoveryCode" asp-route-returnUrl="@Model.ReturnUrl">log in with a recovery code</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
public class LoginWith2faModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly ILogger<LoginWith2faModel> _logger;
|
|
||||||
|
|
||||||
public LoginWith2faModel(
|
|
||||||
SignInManager<ApplicationUser> signInManager,
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
ILogger<LoginWith2faModel> logger)
|
|
||||||
{
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_userManager = userManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public bool RememberMe { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string ReturnUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
|
|
||||||
[DataType(DataType.Text)]
|
|
||||||
[Display(Name = "Authenticator code")]
|
|
||||||
public string TwoFactorCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Display(Name = "Remember this machine")]
|
|
||||||
public bool RememberMachine { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync(bool rememberMe, string returnUrl = null)
|
|
||||||
{
|
|
||||||
// Ensure the user has gone through the username & password screen first
|
|
||||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
|
||||||
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Unable to load two-factor authentication user.");
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnUrl = returnUrl;
|
|
||||||
RememberMe = rememberMe;
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync(bool rememberMe, string returnUrl = null)
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
returnUrl = returnUrl ?? Url.Content("~/");
|
|
||||||
|
|
||||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Unable to load two-factor authentication user.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var authenticatorCode = Input.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);
|
|
||||||
|
|
||||||
var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, Input.RememberMachine);
|
|
||||||
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id);
|
|
||||||
return LocalRedirect(returnUrl);
|
|
||||||
}
|
|
||||||
else if (result.IsLockedOut)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id);
|
|
||||||
return RedirectToPage("./Lockout");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id);
|
|
||||||
ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
@page
|
|
||||||
@model LoginWithRecoveryCodeModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Recovery code verification";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<hr />
|
|
||||||
<p>
|
|
||||||
You have requested to log in with a recovery code. This login will not be remembered until you provide
|
|
||||||
an authenticator app code at log in or disable 2FA and log in again.
|
|
||||||
</p>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<form method="post">
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.RecoveryCode" class="form-control" autocomplete="off" placeholder="RecoveryCode" />
|
|
||||||
<label asp-for="Input.RecoveryCode" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.RecoveryCode" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Log in</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
public class LoginWithRecoveryCodeModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly ILogger<LoginWithRecoveryCodeModel> _logger;
|
|
||||||
|
|
||||||
public LoginWithRecoveryCodeModel(
|
|
||||||
SignInManager<ApplicationUser> signInManager,
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
ILogger<LoginWithRecoveryCodeModel> logger)
|
|
||||||
{
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_userManager = userManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string ReturnUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
[Required]
|
|
||||||
[DataType(DataType.Text)]
|
|
||||||
[Display(Name = "Recovery Code")]
|
|
||||||
public string RecoveryCode { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync(string returnUrl = null)
|
|
||||||
{
|
|
||||||
// Ensure the user has gone through the username & password screen first
|
|
||||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Unable to load two-factor authentication user.");
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnUrl = returnUrl;
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Unable to load two-factor authentication user.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var recoveryCode = Input.RecoveryCode.Replace(" ", string.Empty);
|
|
||||||
|
|
||||||
var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode);
|
|
||||||
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
_logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", user.Id);
|
|
||||||
return LocalRedirect(returnUrl ?? Url.Content("~/"));
|
|
||||||
}
|
|
||||||
if (result.IsLockedOut)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("User account locked out.");
|
|
||||||
return RedirectToPage("./Lockout");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", user.Id);
|
|
||||||
ModelState.AddModelError(string.Empty, "Invalid recovery code entered.");
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
@page
|
|
||||||
@model LogoutModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Log out";
|
|
||||||
}
|
|
||||||
|
|
||||||
<header>
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
@{
|
|
||||||
if (User.Identity?.IsAuthenticated ?? false)
|
|
||||||
{
|
|
||||||
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/", new { area = "" })" method="post">
|
|
||||||
<button type="submit" class="nav-link btn btn-link text-dark">Click here to Logout</button>
|
|
||||||
</form>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<p>You have successfully logged out of the application.</p>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</header>
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
[IgnoreAntiforgeryToken(Order = 1001)]
|
|
||||||
public class LogoutModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly ILogger<LogoutModel> _logger;
|
|
||||||
|
|
||||||
public LogoutModel(SignInManager<ApplicationUser> signInManager, ILogger<LogoutModel> logger)
|
|
||||||
{
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPost(string returnUrl = null)
|
|
||||||
{
|
|
||||||
await _signInManager.SignOutAsync();
|
|
||||||
_logger.LogInformation("User logged out.");
|
|
||||||
if (returnUrl != null)
|
|
||||||
{
|
|
||||||
return LocalRedirect(returnUrl);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This needs to be a redirect so that the browser performs a new
|
|
||||||
// request and the identity for the user gets updated.
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ChangePasswordModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Change password";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.ChangePassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<form id="change-password-form" method="post">
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.OldPassword" class="form-control" autocomplete="current-password" aria-required="true" placeholder="Please enter your old password." />
|
|
||||||
<label asp-for="Input.OldPassword" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.OldPassword" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.NewPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="Please enter your new password." />
|
|
||||||
<label asp-for="Input.NewPassword" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.NewPassword" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="Please confirm your new password."/>
|
|
||||||
<label asp-for="Input.ConfirmPassword" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Update password</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class ChangePasswordModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly ILogger<ChangePasswordModel> _logger;
|
|
||||||
|
|
||||||
public ChangePasswordModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
SignInManager<ApplicationUser> signInManager,
|
|
||||||
ILogger<ChangePasswordModel> logger)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
[Display(Name = "Current password")]
|
|
||||||
public string OldPassword { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
[Display(Name = "New password")]
|
|
||||||
public string NewPassword { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
[Display(Name = "Confirm new password")]
|
|
||||||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
|
|
||||||
public string ConfirmPassword { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasPassword = await _userManager.HasPasswordAsync(user);
|
|
||||||
if (!hasPassword)
|
|
||||||
{
|
|
||||||
return RedirectToPage("./SetPassword");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var changePasswordResult = await _userManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword);
|
|
||||||
if (!changePasswordResult.Succeeded)
|
|
||||||
{
|
|
||||||
foreach (var error in changePasswordResult.Errors)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, error.Description);
|
|
||||||
}
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
await _signInManager.RefreshSignInAsync(user);
|
|
||||||
_logger.LogInformation("User changed their password successfully.");
|
|
||||||
StatusMessage = "Your password has been changed.";
|
|
||||||
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
@page
|
|
||||||
@model DeletePersonalDataModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Delete Personal Data";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.PersonalData;
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
|
|
||||||
<div class="alert alert-warning" role="alert">
|
|
||||||
<p>
|
|
||||||
<strong>Deleting this data will permanently remove your account, and this cannot be recovered.</strong>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<form id="delete-user" method="post">
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
@if (Model.RequirePassword)
|
|
||||||
{
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Password" class="form-control" autocomplete="current-password" aria-required="true" placeholder="Please enter your password." />
|
|
||||||
<label asp-for="Input.Password" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.Password" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<button class="w-100 btn btn-lg btn-danger" type="submit">Delete data and close my account</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class DeletePersonalDataModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly ILogger<DeletePersonalDataModel> _logger;
|
|
||||||
|
|
||||||
public DeletePersonalDataModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
SignInManager<ApplicationUser> signInManager,
|
|
||||||
ILogger<DeletePersonalDataModel> logger)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
public string Password { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public bool RequirePassword { get; set; }
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGet()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
RequirePassword = await _userManager.HasPasswordAsync(user);
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
RequirePassword = await _userManager.HasPasswordAsync(user);
|
|
||||||
if (RequirePassword)
|
|
||||||
{
|
|
||||||
if (!await _userManager.CheckPasswordAsync(user, Input.Password))
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, "Incorrect password.");
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await _userManager.DeleteAsync(user);
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
if (!result.Succeeded)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Unexpected error occurred deleting user.");
|
|
||||||
}
|
|
||||||
|
|
||||||
await _signInManager.SignOutAsync();
|
|
||||||
|
|
||||||
_logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId);
|
|
||||||
|
|
||||||
return Redirect("~/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
@page
|
|
||||||
@model Disable2faModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Disable two-factor authentication (2FA)";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
|
|
||||||
}
|
|
||||||
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
|
|
||||||
<div class="alert alert-warning" role="alert">
|
|
||||||
<p>
|
|
||||||
<strong>This action only disables 2FA.</strong>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Disabling 2FA does not change the keys used in authenticator apps. If you wish to change the key
|
|
||||||
used in an authenticator app you should <a asp-page="./ResetAuthenticator">reset your authenticator keys.</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<form method="post">
|
|
||||||
<button class="btn btn-danger" type="submit">Disable 2FA</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class Disable2faModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly ILogger<Disable2faModel> _logger;
|
|
||||||
|
|
||||||
public Disable2faModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
ILogger<Disable2faModel> logger)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGet()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!await _userManager.GetTwoFactorEnabledAsync(user))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Cannot disable 2FA for user as it's not currently enabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var disable2faResult = await _userManager.SetTwoFactorEnabledAsync(user, false);
|
|
||||||
if (!disable2faResult.Succeeded)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Unexpected error occurred disabling 2FA.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", _userManager.GetUserId(User));
|
|
||||||
StatusMessage = "2fa has been disabled. You can reenable 2fa when you setup an authenticator app";
|
|
||||||
return RedirectToPage("./TwoFactorAuthentication");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
@page
|
|
||||||
@model DownloadPersonalDataModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Download Your Data";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.PersonalData;
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class DownloadPersonalDataModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly ILogger<DownloadPersonalDataModel> _logger;
|
|
||||||
|
|
||||||
public DownloadPersonalDataModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
ILogger<DownloadPersonalDataModel> logger)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IActionResult OnGet()
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("User with ID '{UserId}' asked for their personal data.", _userManager.GetUserId(User));
|
|
||||||
|
|
||||||
// Only include personal data for download
|
|
||||||
var personalData = new Dictionary<string, string>();
|
|
||||||
var personalDataProps = typeof(ApplicationUser).GetProperties().Where(
|
|
||||||
prop => Attribute.IsDefined(prop, typeof(PersonalDataAttribute)));
|
|
||||||
foreach (var p in personalDataProps)
|
|
||||||
{
|
|
||||||
personalData.Add(p.Name, p.GetValue(user)?.ToString() ?? "null");
|
|
||||||
}
|
|
||||||
|
|
||||||
var logins = await _userManager.GetLoginsAsync(user);
|
|
||||||
foreach (var l in logins)
|
|
||||||
{
|
|
||||||
personalData.Add($"{l.LoginProvider} external login provider key", l.ProviderKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
personalData.Add($"Authenticator Key", await _userManager.GetAuthenticatorKeyAsync(user));
|
|
||||||
|
|
||||||
Response.Headers.TryAdd("Content-Disposition", "attachment; filename=PersonalData.json");
|
|
||||||
return new FileContentResult(JsonSerializer.SerializeToUtf8Bytes(personalData), "application/json");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
@page
|
|
||||||
@model EmailModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Manage Email";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.Email;
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<form id="email-form" method="post">
|
|
||||||
<div asp-validation-summary="All" class="text-danger" role="alert"></div>
|
|
||||||
@if (Model.IsEmailConfirmed)
|
|
||||||
{
|
|
||||||
<div class="form-floating mb-3 input-group">
|
|
||||||
<input asp-for="Email" class="form-control" placeholder="Please enter your email." disabled />
|
|
||||||
<div class="input-group-append">
|
|
||||||
<span class="h-100 input-group-text text-success font-weight-bold">✓</span>
|
|
||||||
</div>
|
|
||||||
<label asp-for="Email" class="form-label"></label>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Email" class="form-control" placeholder="Please enter your email." disabled />
|
|
||||||
<label asp-for="Email" class="form-label"></label>
|
|
||||||
<button id="email-verification" type="submit" asp-page-handler="SendVerificationEmail" class="btn btn-link">Send verification email</button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.NewEmail" class="form-control" autocomplete="email" aria-required="true" placeholder="Please enter new email." />
|
|
||||||
<label asp-for="Input.NewEmail" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.NewEmail" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button id="change-email-button" type="submit" asp-page-handler="ChangeEmail" class="w-100 btn btn-lg btn-primary">Change email</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class EmailModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly IEmailSender _emailSender;
|
|
||||||
|
|
||||||
public EmailModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
SignInManager<ApplicationUser> signInManager,
|
|
||||||
IEmailSender emailSender)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_emailSender = emailSender;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string Email { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsEmailConfirmed { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[EmailAddress]
|
|
||||||
[Display(Name = "New email")]
|
|
||||||
public string NewEmail { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadAsync(ApplicationUser user)
|
|
||||||
{
|
|
||||||
var email = await _userManager.GetEmailAsync(user);
|
|
||||||
Email = email;
|
|
||||||
|
|
||||||
Input = new InputModel
|
|
||||||
{
|
|
||||||
NewEmail = email,
|
|
||||||
};
|
|
||||||
|
|
||||||
IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
await LoadAsync(user);
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostChangeEmailAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
await LoadAsync(user);
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
var email = await _userManager.GetEmailAsync(user);
|
|
||||||
if (Input.NewEmail != email)
|
|
||||||
{
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
var code = await _userManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail);
|
|
||||||
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
|
||||||
var callbackUrl = Url.Page(
|
|
||||||
"/Account/ConfirmEmailChange",
|
|
||||||
pageHandler: null,
|
|
||||||
values: new { area = "Identity", userId = userId, email = Input.NewEmail, code = code },
|
|
||||||
protocol: Request.Scheme);
|
|
||||||
await _emailSender.SendEmailAsync(
|
|
||||||
Input.NewEmail,
|
|
||||||
"Confirm your email",
|
|
||||||
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
|
||||||
|
|
||||||
StatusMessage = "Confirmation link to change email sent. Please check your email.";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusMessage = "Your email is unchanged.";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostSendVerificationEmailAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
await LoadAsync(user);
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
var email = await _userManager.GetEmailAsync(user);
|
|
||||||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
|
||||||
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
|
||||||
var callbackUrl = Url.Page(
|
|
||||||
"/Account/ConfirmEmail",
|
|
||||||
pageHandler: null,
|
|
||||||
values: new { area = "Identity", userId = userId, code = code },
|
|
||||||
protocol: Request.Scheme);
|
|
||||||
await _emailSender.SendEmailAsync(
|
|
||||||
email,
|
|
||||||
"Confirm your email",
|
|
||||||
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
|
||||||
|
|
||||||
StatusMessage = "Verification email sent. Please check your email.";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
@page
|
|
||||||
@model EnableAuthenticatorModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Configure authenticator app";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
|
|
||||||
}
|
|
||||||
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
<div>
|
|
||||||
<p>To use an authenticator app go through the following steps:</p>
|
|
||||||
<ol class="list">
|
|
||||||
<li>
|
|
||||||
<p>
|
|
||||||
Download a two-factor authenticator app like Microsoft Authenticator for
|
|
||||||
<a href="https://go.microsoft.com/fwlink/?Linkid=825072">Android</a> and
|
|
||||||
<a href="https://go.microsoft.com/fwlink/?Linkid=825073">iOS</a> or
|
|
||||||
Google Authenticator for
|
|
||||||
<a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en">Android</a> and
|
|
||||||
<a href="https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8">iOS</a>.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>Scan the QR Code or enter this key <kbd>@Model.SharedKey</kbd> into your two factor authenticator app. Spaces and casing do not matter.</p>
|
|
||||||
@* <div class="alert alert-info">Learn how to <a href="https://go.microsoft.com/fwlink/?Linkid=852423">enable QR code generation</a>.</div> *@
|
|
||||||
<div id="qrCode"></div>
|
|
||||||
<div id="qrCodeData" data-url="@Model.AuthenticatorUri"></div>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p>
|
|
||||||
Once you have scanned the QR code or input the key above, your two factor authentication app will provide you
|
|
||||||
with a unique code. Enter the code in the confirmation box below.
|
|
||||||
</p>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<form id="send-code" method="post">
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Code" class="form-control" autocomplete="off" placeholder="Please enter the code."/>
|
|
||||||
<label asp-for="Input.Code" class="control-label form-label">Verification Code</label>
|
|
||||||
<span asp-validation-for="Input.Code" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Verify</button>
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
|
|
||||||
<script type="text/javascript" src="~/lib/qrcode/qrcode.min.js"></script>
|
|
||||||
<script type="text/javascript" src="~/js/qr.js"></script>
|
|
||||||
}
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class EnableAuthenticatorModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly ILogger<EnableAuthenticatorModel> _logger;
|
|
||||||
private readonly UrlEncoder _urlEncoder;
|
|
||||||
|
|
||||||
private const string AuthenticatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6";
|
|
||||||
|
|
||||||
public EnableAuthenticatorModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
ILogger<EnableAuthenticatorModel> logger,
|
|
||||||
UrlEncoder urlEncoder)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_logger = logger;
|
|
||||||
_urlEncoder = urlEncoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string SharedKey { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string AuthenticatorUri { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string[] RecoveryCodes { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
|
|
||||||
[DataType(DataType.Text)]
|
|
||||||
[Display(Name = "Verification Code")]
|
|
||||||
public string Code { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
await LoadSharedKeyAndQrCodeUriAsync(user);
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
await LoadSharedKeyAndQrCodeUriAsync(user);
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip spaces and hyphens
|
|
||||||
var verificationCode = Input.Code.Replace(" ", string.Empty).Replace("-", string.Empty);
|
|
||||||
|
|
||||||
var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync(
|
|
||||||
user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode);
|
|
||||||
|
|
||||||
if (!is2faTokenValid)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError("Input.Code", "Verification code is invalid.");
|
|
||||||
await LoadSharedKeyAndQrCodeUriAsync(user);
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
await _userManager.SetTwoFactorEnabledAsync(user, true);
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
_logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", userId);
|
|
||||||
|
|
||||||
StatusMessage = "Your authenticator app has been verified.";
|
|
||||||
|
|
||||||
if (await _userManager.CountRecoveryCodesAsync(user) == 0)
|
|
||||||
{
|
|
||||||
var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
|
|
||||||
RecoveryCodes = recoveryCodes.ToArray();
|
|
||||||
return RedirectToPage("./ShowRecoveryCodes");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return RedirectToPage("./TwoFactorAuthentication");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadSharedKeyAndQrCodeUriAsync(ApplicationUser user)
|
|
||||||
{
|
|
||||||
// Load the authenticator key & QR code URI to display on the form
|
|
||||||
var unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
|
|
||||||
if (string.IsNullOrEmpty(unformattedKey))
|
|
||||||
{
|
|
||||||
await _userManager.ResetAuthenticatorKeyAsync(user);
|
|
||||||
unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedKey = FormatKey(unformattedKey);
|
|
||||||
|
|
||||||
var email = await _userManager.GetEmailAsync(user);
|
|
||||||
AuthenticatorUri = GenerateQrCodeUri(email, unformattedKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string FormatKey(string unformattedKey)
|
|
||||||
{
|
|
||||||
var result = new StringBuilder();
|
|
||||||
int currentPosition = 0;
|
|
||||||
while (currentPosition + 4 < unformattedKey.Length)
|
|
||||||
{
|
|
||||||
result.Append(unformattedKey.AsSpan(currentPosition, 4)).Append(' ');
|
|
||||||
currentPosition += 4;
|
|
||||||
}
|
|
||||||
if (currentPosition < unformattedKey.Length)
|
|
||||||
{
|
|
||||||
result.Append(unformattedKey.AsSpan(currentPosition));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.ToString().ToLowerInvariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GenerateQrCodeUri(string email, string unformattedKey)
|
|
||||||
{
|
|
||||||
return string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
AuthenticatorUriFormat,
|
|
||||||
_urlEncoder.Encode("Kemkas"),
|
|
||||||
_urlEncoder.Encode(email),
|
|
||||||
unformattedKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ExternalLoginsModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Manage your external logins";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.ExternalLogins;
|
|
||||||
}
|
|
||||||
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
@if (Model.CurrentLogins?.Count > 0)
|
|
||||||
{
|
|
||||||
<h3>Registered Logins</h3>
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
@foreach (var login in Model.CurrentLogins)
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td id="@($"login-provider-{login.LoginProvider}")">@login.ProviderDisplayName</td>
|
|
||||||
<td>
|
|
||||||
@if (Model.ShowRemoveButton)
|
|
||||||
{
|
|
||||||
<form id="@($"remove-login-{login.LoginProvider}")" asp-page-handler="RemoveLogin" method="post">
|
|
||||||
<div>
|
|
||||||
<input asp-for="@login.LoginProvider" name="LoginProvider" type="hidden" />
|
|
||||||
<input asp-for="@login.ProviderKey" name="ProviderKey" type="hidden" />
|
|
||||||
<button type="submit" class="btn btn-primary" title="Remove this @login.ProviderDisplayName login from your account">Remove</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@:
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
}
|
|
||||||
@if (Model.OtherLogins?.Count > 0)
|
|
||||||
{
|
|
||||||
<h4>Add another service to log in.</h4>
|
|
||||||
<hr />
|
|
||||||
<form id="link-login-form" asp-page-handler="LinkLogin" method="post" class="form-horizontal">
|
|
||||||
<div id="socialLoginList">
|
|
||||||
<p>
|
|
||||||
@foreach (var provider in Model.OtherLogins)
|
|
||||||
{
|
|
||||||
<button id="@($"link-login-button-{provider.Name}")" type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
|
|
||||||
}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
}
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Authentication;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class ExternalLoginsModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly IUserStore<ApplicationUser> _userStore;
|
|
||||||
|
|
||||||
public ExternalLoginsModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
SignInManager<ApplicationUser> signInManager,
|
|
||||||
IUserStore<ApplicationUser> userStore)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_userStore = userStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public IList<UserLoginInfo> CurrentLogins { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public IList<AuthenticationScheme> OtherLogins { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public bool ShowRemoveButton { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentLogins = await _userManager.GetLoginsAsync(user);
|
|
||||||
OtherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
|
|
||||||
.Where(auth => CurrentLogins.All(ul => auth.Name != ul.LoginProvider))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
string passwordHash = null;
|
|
||||||
if (_userStore is IUserPasswordStore<ApplicationUser> userPasswordStore)
|
|
||||||
{
|
|
||||||
passwordHash = await userPasswordStore.GetPasswordHashAsync(user, HttpContext.RequestAborted);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShowRemoveButton = passwordHash != null || CurrentLogins.Count > 1;
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostRemoveLoginAsync(string loginProvider, string providerKey)
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await _userManager.RemoveLoginAsync(user, loginProvider, providerKey);
|
|
||||||
if (!result.Succeeded)
|
|
||||||
{
|
|
||||||
StatusMessage = "The external login was not removed.";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
await _signInManager.RefreshSignInAsync(user);
|
|
||||||
StatusMessage = "The external login was removed.";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostLinkLoginAsync(string provider)
|
|
||||||
{
|
|
||||||
// Clear the existing external cookie to ensure a clean login process
|
|
||||||
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
|
|
||||||
|
|
||||||
// Request a redirect to the external login provider to link a login for the current user
|
|
||||||
var redirectUrl = Url.Page("./ExternalLogins", pageHandler: "LinkLoginCallback");
|
|
||||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
|
|
||||||
return new ChallengeResult(provider, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetLinkLoginCallbackAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
var info = await _signInManager.GetExternalLoginInfoAsync(userId);
|
|
||||||
if (info == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Unexpected error occurred loading external login info.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await _userManager.AddLoginAsync(user, info);
|
|
||||||
if (!result.Succeeded)
|
|
||||||
{
|
|
||||||
StatusMessage = "The external login was not added. External logins can only be associated with one account.";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the existing external cookie to ensure a clean login process
|
|
||||||
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
|
|
||||||
|
|
||||||
StatusMessage = "The external login was added.";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
@page
|
|
||||||
@model GenerateRecoveryCodesModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Generate two-factor authentication (2FA) recovery codes";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
|
|
||||||
}
|
|
||||||
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
<div class="alert alert-warning" role="alert">
|
|
||||||
<p>
|
|
||||||
<span class="glyphicon glyphicon-warning-sign"></span>
|
|
||||||
<strong>Put these codes in a safe place.</strong>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If you lose your device and don't have the recovery codes you will lose access to your account.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Generating new recovery codes does not change the keys used in authenticator apps. If you wish to change the key
|
|
||||||
used in an authenticator app you should <a asp-page="./ResetAuthenticator">reset your authenticator keys.</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<form method="post">
|
|
||||||
<button class="btn btn-danger" type="submit">Generate Recovery Codes</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class GenerateRecoveryCodesModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly ILogger<GenerateRecoveryCodesModel> _logger;
|
|
||||||
|
|
||||||
public GenerateRecoveryCodesModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
ILogger<GenerateRecoveryCodesModel> logger)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string[] RecoveryCodes { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user);
|
|
||||||
if (!isTwoFactorEnabled)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Cannot generate recovery codes for user because they do not have 2FA enabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user);
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
if (!isTwoFactorEnabled)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Cannot generate recovery codes for user as they do not have 2FA enabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);
|
|
||||||
RecoveryCodes = recoveryCodes.ToArray();
|
|
||||||
|
|
||||||
_logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", userId);
|
|
||||||
StatusMessage = "You have generated new recovery codes.";
|
|
||||||
return RedirectToPage("./ShowRecoveryCodes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
@page
|
|
||||||
@model IndexModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Profile";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.Index;
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<form id="profile-form" method="post">
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Username" class="form-control" placeholder="Please choose your username." disabled />
|
|
||||||
<label asp-for="Username" class="form-label"></label>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.PhoneNumber" class="form-control" placeholder="Please enter your phone number."/>
|
|
||||||
<label asp-for="Input.PhoneNumber" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button id="update-profile-button" type="submit" class="w-100 btn btn-lg btn-primary">Save</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class IndexModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
|
|
||||||
public IndexModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
SignInManager<ApplicationUser> signInManager)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string Username { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Phone]
|
|
||||||
[Display(Name = "Phone number")]
|
|
||||||
public string PhoneNumber { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadAsync(ApplicationUser user)
|
|
||||||
{
|
|
||||||
var userName = await _userManager.GetUserNameAsync(user);
|
|
||||||
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
|
|
||||||
|
|
||||||
Username = userName;
|
|
||||||
|
|
||||||
Input = new InputModel
|
|
||||||
{
|
|
||||||
PhoneNumber = phoneNumber
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
await LoadAsync(user);
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
await LoadAsync(user);
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
|
|
||||||
if (Input.PhoneNumber != phoneNumber)
|
|
||||||
{
|
|
||||||
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
|
|
||||||
if (!setPhoneResult.Succeeded)
|
|
||||||
{
|
|
||||||
StatusMessage = "Unexpected error when trying to set phone number.";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await _signInManager.RefreshSignInAsync(user);
|
|
||||||
StatusMessage = "Your profile has been updated";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static class ManageNavPages
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string Index => "Index";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string Email => "Email";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string ChangePassword => "ChangePassword";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string DownloadPersonalData => "DownloadPersonalData";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string DeletePersonalData => "DeletePersonalData";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string ExternalLogins => "ExternalLogins";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string PersonalData => "PersonalData";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string TwoFactorAuthentication => "TwoFactorAuthentication";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string EmailNavClass(ViewContext viewContext) => PageNavClass(viewContext, Email);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string DownloadPersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DownloadPersonalData);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string DeletePersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DeletePersonalData);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string ExternalLoginsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ExternalLogins);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string PersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, PersonalData);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public static string PageNavClass(ViewContext viewContext, string page)
|
|
||||||
{
|
|
||||||
var activePage = viewContext.ViewData["ActivePage"] as string
|
|
||||||
?? System.IO.Path.GetFileNameWithoutExtension(viewContext.ActionDescriptor.DisplayName);
|
|
||||||
return string.Equals(activePage, page, StringComparison.OrdinalIgnoreCase) ? "active" : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
@page
|
|
||||||
@model PersonalDataModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Personal Data";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.PersonalData;
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<p>Your account contains personal data that you have given us. This page allows you to download or delete that data.</p>
|
|
||||||
<p>
|
|
||||||
<strong>Deleting this data will permanently remove your account, and this cannot be recovered.</strong>
|
|
||||||
</p>
|
|
||||||
<form id="download-data" asp-page="DownloadPersonalData" method="post">
|
|
||||||
<button class="btn btn-primary" type="submit">Download</button>
|
|
||||||
</form>
|
|
||||||
<p>
|
|
||||||
<a id="delete" asp-page="DeletePersonalData" class="btn btn-danger">Delete</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class PersonalDataModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly ILogger<PersonalDataModel> _logger;
|
|
||||||
|
|
||||||
public PersonalDataModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
ILogger<PersonalDataModel> logger)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGet()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ResetAuthenticatorModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Reset authenticator key";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
|
|
||||||
}
|
|
||||||
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
<div class="alert alert-warning" role="alert">
|
|
||||||
<p>
|
|
||||||
<span class="glyphicon glyphicon-warning-sign"></span>
|
|
||||||
<strong>If you reset your authenticator key your authenticator app will not work until you reconfigure it.</strong>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
This process disables 2FA until you verify your authenticator app.
|
|
||||||
If you do not complete your authenticator app configuration you may lose access to your account.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<form id="reset-authenticator-form" method="post">
|
|
||||||
<button id="reset-authenticator-button" class="btn btn-danger" type="submit">Reset authenticator key</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class ResetAuthenticatorModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly ILogger<ResetAuthenticatorModel> _logger;
|
|
||||||
|
|
||||||
public ResetAuthenticatorModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
SignInManager<ApplicationUser> signInManager,
|
|
||||||
ILogger<ResetAuthenticatorModel> logger)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGet()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
await _userManager.SetTwoFactorEnabledAsync(user, false);
|
|
||||||
await _userManager.ResetAuthenticatorKeyAsync(user);
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
_logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", user.Id);
|
|
||||||
|
|
||||||
await _signInManager.RefreshSignInAsync(user);
|
|
||||||
StatusMessage = "Your authenticator app key has been reset, you will need to configure your authenticator app using the new key.";
|
|
||||||
|
|
||||||
return RedirectToPage("./EnableAuthenticator");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
@page
|
|
||||||
@model SetPasswordModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Set password";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.ChangePassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>Set your password</h3>
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<p class="text-info">
|
|
||||||
You do not have a local username/password for this site. Add a local
|
|
||||||
account so you can log in without an external login.
|
|
||||||
</p>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<form id="set-password-form" method="post">
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.NewPassword" class="form-control" autocomplete="new-password" placeholder="Please enter your new password."/>
|
|
||||||
<label asp-for="Input.NewPassword" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.NewPassword" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-password" placeholder="Please confirm your new password."/>
|
|
||||||
<label asp-for="Input.ConfirmPassword" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Set password</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class SetPasswordModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
|
|
||||||
public SetPasswordModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
SignInManager<ApplicationUser> signInManager)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
[Display(Name = "New password")]
|
|
||||||
public string NewPassword { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
[Display(Name = "Confirm new password")]
|
|
||||||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
|
|
||||||
public string ConfirmPassword { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasPassword = await _userManager.HasPasswordAsync(user);
|
|
||||||
|
|
||||||
if (hasPassword)
|
|
||||||
{
|
|
||||||
return RedirectToPage("./ChangePassword");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var addPasswordResult = await _userManager.AddPasswordAsync(user, Input.NewPassword);
|
|
||||||
if (!addPasswordResult.Succeeded)
|
|
||||||
{
|
|
||||||
foreach (var error in addPasswordResult.Errors)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, error.Description);
|
|
||||||
}
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
await _signInManager.RefreshSignInAsync(user);
|
|
||||||
StatusMessage = "Your password has been set.";
|
|
||||||
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ShowRecoveryCodesModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Recovery codes";
|
|
||||||
ViewData["ActivePage"] = "TwoFactorAuthentication";
|
|
||||||
}
|
|
||||||
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
<div class="alert alert-warning" role="alert">
|
|
||||||
<p>
|
|
||||||
<strong>Put these codes in a safe place.</strong>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If you lose your device and don't have the recovery codes you will lose access to your account.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
|
||||||
@for (var row = 0; row < Model.RecoveryCodes.Length; row += 2)
|
|
||||||
{
|
|
||||||
<code class="recovery-code">@Model.RecoveryCodes[row]</code><text> </text><code class="recovery-code">@Model.RecoveryCodes[row + 1]</code><br />
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class ShowRecoveryCodesModel : PageModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string[] RecoveryCodes { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public IActionResult OnGet()
|
|
||||||
{
|
|
||||||
if (RecoveryCodes == null || RecoveryCodes.Length == 0)
|
|
||||||
{
|
|
||||||
return RedirectToPage("./TwoFactorAuthentication");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
@page
|
|
||||||
@using Microsoft.AspNetCore.Http.Features
|
|
||||||
@model TwoFactorAuthenticationModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Two-factor authentication (2FA)";
|
|
||||||
ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication;
|
|
||||||
}
|
|
||||||
|
|
||||||
<partial name="_StatusMessage" for="StatusMessage" />
|
|
||||||
<h3>@ViewData["Title"]</h3>
|
|
||||||
@{
|
|
||||||
var consentFeature = HttpContext.Features.Get<ITrackingConsentFeature>();
|
|
||||||
@if (consentFeature?.CanTrack ?? true)
|
|
||||||
{
|
|
||||||
@if (Model.Is2faEnabled)
|
|
||||||
{
|
|
||||||
if (Model.RecoveryCodesLeft == 0)
|
|
||||||
{
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<strong>You have no recovery codes left.</strong>
|
|
||||||
<p>You must <a asp-page="./GenerateRecoveryCodes">generate a new set of recovery codes</a> before you can log in with a recovery code.</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else if (Model.RecoveryCodesLeft == 1)
|
|
||||||
{
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<strong>You have 1 recovery code left.</strong>
|
|
||||||
<p>You can <a asp-page="./GenerateRecoveryCodes">generate a new set of recovery codes</a>.</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else if (Model.RecoveryCodesLeft <= 3)
|
|
||||||
{
|
|
||||||
<div class="alert alert-warning">
|
|
||||||
<strong>You have @Model.RecoveryCodesLeft recovery codes left.</strong>
|
|
||||||
<p>You should <a asp-page="./GenerateRecoveryCodes">generate a new set of recovery codes</a>.</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Model.IsMachineRemembered)
|
|
||||||
{
|
|
||||||
<form method="post" style="display: inline-block">
|
|
||||||
<button type="submit" class="btn btn-primary">Forget this browser</button>
|
|
||||||
</form>
|
|
||||||
}
|
|
||||||
<a asp-page="./Disable2fa" class="btn btn-primary">Disable 2FA</a>
|
|
||||||
<a asp-page="./GenerateRecoveryCodes" class="btn btn-primary">Reset recovery codes</a>
|
|
||||||
}
|
|
||||||
|
|
||||||
<h4>Authenticator app</h4>
|
|
||||||
@if (!Model.HasAuthenticator)
|
|
||||||
{
|
|
||||||
<a id="enable-authenticator" asp-page="./EnableAuthenticator" class="btn btn-primary">Add authenticator app</a>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<a id="enable-authenticator" asp-page="./EnableAuthenticator" class="btn btn-primary">Set up authenticator app</a>
|
|
||||||
<a id="reset-authenticator" asp-page="./ResetAuthenticator" class="btn btn-primary">Reset authenticator app</a>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<strong>Privacy and cookie policy have not been accepted.</strong>
|
|
||||||
<p>You must accept the policy before you can enable two factor authentication.</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
{
|
|
||||||
public class TwoFactorAuthenticationModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly ILogger<TwoFactorAuthenticationModel> _logger;
|
|
||||||
|
|
||||||
public TwoFactorAuthenticationModel(
|
|
||||||
UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, ILogger<TwoFactorAuthenticationModel> logger)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public bool HasAuthenticator { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public int RecoveryCodesLeft { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public bool Is2faEnabled { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsMachineRemembered { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[TempData]
|
|
||||||
public string StatusMessage { get; set; }
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
HasAuthenticator = await _userManager.GetAuthenticatorKeyAsync(user) != null;
|
|
||||||
Is2faEnabled = await _userManager.GetTwoFactorEnabledAsync(user);
|
|
||||||
IsMachineRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user);
|
|
||||||
RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user);
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
var user = await _userManager.GetUserAsync(User);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
await _signInManager.ForgetTwoFactorClientAsync();
|
|
||||||
StatusMessage = "The current browser has been forgotten. When you login again from this browser you will be prompted for your 2fa code.";
|
|
||||||
return RedirectToPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
@{
|
|
||||||
if (ViewData.TryGetValue("ParentLayout", out var parentLayout) && parentLayout != null)
|
|
||||||
{
|
|
||||||
Layout = parentLayout.ToString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Layout = "/Areas/Identity/Pages/_Layout.cshtml";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>Manage your account</h1>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h2>Change your account settings</h2>
|
|
||||||
<hr />
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3">
|
|
||||||
<partial name="_ManageNav" />
|
|
||||||
</div>
|
|
||||||
<div class="col-md-9">
|
|
||||||
@RenderBody()
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
@RenderSection("Scripts", required: false)
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
@inject SignInManager<ApplicationUser> SignInManager
|
|
||||||
@{
|
|
||||||
var hasExternalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).Any();
|
|
||||||
}
|
|
||||||
<ul class="nav nav-pills flex-column">
|
|
||||||
<li class="nav-item"><a class="nav-link @ManageNavPages.IndexNavClass(ViewContext)" id="profile" asp-page="./Index">Profile</a></li>
|
|
||||||
<li class="nav-item"><a class="nav-link @ManageNavPages.EmailNavClass(ViewContext)" id="email" asp-page="./Email">Email</a></li>
|
|
||||||
<li class="nav-item"><a class="nav-link @ManageNavPages.ChangePasswordNavClass(ViewContext)" id="change-password" asp-page="./ChangePassword">Password</a></li>
|
|
||||||
@if (hasExternalLogins)
|
|
||||||
{
|
|
||||||
<li id="external-logins" class="nav-item"><a id="external-login" class="nav-link @ManageNavPages.ExternalLoginsNavClass(ViewContext)" asp-page="./ExternalLogins">External logins</a></li>
|
|
||||||
}
|
|
||||||
<li class="nav-item"><a class="nav-link @ManageNavPages.TwoFactorAuthenticationNavClass(ViewContext)" id="two-factor" asp-page="./TwoFactorAuthentication">Two-factor authentication</a></li>
|
|
||||||
<li class="nav-item"><a class="nav-link @ManageNavPages.PersonalDataNavClass(ViewContext)" id="personal-data" asp-page="./PersonalData">Personal data</a></li>
|
|
||||||
</ul>
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
@model string
|
|
||||||
|
|
||||||
@if (!String.IsNullOrEmpty(Model))
|
|
||||||
{
|
|
||||||
var statusMessageClass = Model.StartsWith("Error") ? "danger" : "success";
|
|
||||||
<div class="alert alert-@statusMessageClass alert-dismissible" role="alert">
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
||||||
@Model
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
@using Kemkas.Web.Areas.Identity.Pages.Account.Manage
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
@page
|
|
||||||
@model RegisterModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Register";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<form id="registerForm" asp-route-returnUrl="@Model.ReturnUrl" method="post">
|
|
||||||
<h2>Create a new account.</h2>
|
|
||||||
<hr />
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="name@example.com" />
|
|
||||||
<label asp-for="Input.Email">Email</label>
|
|
||||||
<span asp-validation-for="Input.Email" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Password" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
|
|
||||||
<label asp-for="Input.Password">Password</label>
|
|
||||||
<span asp-validation-for="Input.Password" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
|
|
||||||
<label asp-for="Input.ConfirmPassword">Confirm Password</label>
|
|
||||||
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button id="registerSubmit" type="submit" class="w-100 btn btn-lg btn-primary">Register</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6 col-md-offset-2">
|
|
||||||
<section>
|
|
||||||
<h3>Use another service to register.</h3>
|
|
||||||
<hr />
|
|
||||||
@{
|
|
||||||
if ((Model.ExternalLogins?.Count ?? 0) == 0)
|
|
||||||
{
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
There are no external authentication services configured. See this <a href="https://go.microsoft.com/fwlink/?LinkID=532715">article
|
|
||||||
about setting up this ASP.NET application to support logging in via external services</a>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
<button type="submit" class="btn" name="provider" value="Discord" title="Log in using your Discord account"><img height="24px" alt="Discord" src="/img/discord-logo-blue.svg" /></button>
|
|
||||||
@foreach (var provider in Model.ExternalLogins!.Where(el => el.Name != "Discord"))
|
|
||||||
{
|
|
||||||
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
|
|
||||||
}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authentication;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
public class RegisterModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly IUserStore<ApplicationUser> _userStore;
|
|
||||||
private readonly IUserEmailStore<ApplicationUser> _emailStore;
|
|
||||||
private readonly ILogger<RegisterModel> _logger;
|
|
||||||
private readonly IEmailSender _emailSender;
|
|
||||||
private readonly IWebHostEnvironment _environment;
|
|
||||||
|
|
||||||
public RegisterModel(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
IUserStore<ApplicationUser> userStore,
|
|
||||||
SignInManager<ApplicationUser> signInManager,
|
|
||||||
ILogger<RegisterModel> logger,
|
|
||||||
IEmailSender emailSender,
|
|
||||||
IWebHostEnvironment environment)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_userStore = userStore;
|
|
||||||
_emailStore = GetEmailStore();
|
|
||||||
_signInManager = signInManager;
|
|
||||||
_logger = logger;
|
|
||||||
_emailSender = emailSender;
|
|
||||||
_environment = environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string ReturnUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public IList<AuthenticationScheme> ExternalLogins { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[EmailAddress]
|
|
||||||
[Display(Name = "Email")]
|
|
||||||
public string Email { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
[Display(Name = "Password")]
|
|
||||||
public string Password { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
[Display(Name = "Confirm password")]
|
|
||||||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
|
|
||||||
public string ConfirmPassword { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async Task OnGetAsync(string returnUrl = null)
|
|
||||||
{
|
|
||||||
ReturnUrl = returnUrl;
|
|
||||||
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
|
|
||||||
// Disable not yet approved external login providers in production
|
|
||||||
if (!_environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
ExternalLogins = ExternalLogins.Where(el => el.Name == "Discord").ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
|
|
||||||
{
|
|
||||||
returnUrl ??= Url.Content("~/");
|
|
||||||
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
|
|
||||||
// Disable not yet approved external login providers in production
|
|
||||||
if (!_environment.IsDevelopment())
|
|
||||||
{
|
|
||||||
ExternalLogins = ExternalLogins.Where(el => el.Name == "Discord").ToList();
|
|
||||||
}
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
var user = CreateUser();
|
|
||||||
|
|
||||||
await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
|
|
||||||
await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
|
|
||||||
var result = await _userManager.CreateAsync(user, Input.Password);
|
|
||||||
|
|
||||||
if (!result.Succeeded)
|
|
||||||
{
|
|
||||||
foreach (var error in result.Errors)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, error.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("User created a new account with password.");
|
|
||||||
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
|
||||||
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
|
||||||
var callbackUrl = Url.Page(
|
|
||||||
"/Account/ConfirmEmail",
|
|
||||||
pageHandler: null,
|
|
||||||
values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
|
|
||||||
protocol: Request.Scheme);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
|
|
||||||
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await _userManager.DeleteAsync(user); // Delete user to free up the email address for a second registration.
|
|
||||||
ModelState.AddModelError("Input.Email", "Failed to send account confirmation email!");
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_userManager.Options.SignIn.RequireConfirmedAccount)
|
|
||||||
{
|
|
||||||
return RedirectToPage("RegisterConfirmation",
|
|
||||||
new { email = Input.Email, returnUrl = returnUrl });
|
|
||||||
}
|
|
||||||
|
|
||||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
|
||||||
return LocalRedirect(returnUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ApplicationUser CreateUser()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Activator.CreateInstance<ApplicationUser>();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " +
|
|
||||||
$"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor, or alternatively " +
|
|
||||||
$"override the register page in /Areas/Identity/Pages/Account/Register.cshtml");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IUserEmailStore<ApplicationUser> GetEmailStore()
|
|
||||||
{
|
|
||||||
if (!_userManager.SupportsUserEmail)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("The default UI requires a user store with email support.");
|
|
||||||
}
|
|
||||||
return (IUserEmailStore<ApplicationUser>)_userStore;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
@page
|
|
||||||
@model RegisterConfirmationModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Register confirmation";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<p>
|
|
||||||
Please check your email to confirm your account.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
[AllowAnonymous]
|
|
||||||
public class RegisterConfirmationModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly IEmailSender _sender;
|
|
||||||
|
|
||||||
public RegisterConfirmationModel(UserManager<ApplicationUser> userManager, IEmailSender sender)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_sender = sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string Email { get; set; }
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
|
|
||||||
{
|
|
||||||
if (email == null)
|
|
||||||
{
|
|
||||||
return RedirectToPage("/Index");
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await _userManager.FindByEmailAsync(email);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound($"Unable to load user with email '{email}'.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Email = email;
|
|
||||||
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ResendEmailConfirmationModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Resend email confirmation";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<h2>Enter your email.</h2>
|
|
||||||
<hr />
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<form method="post">
|
|
||||||
<div asp-validation-summary="All" class="text-danger" role="alert"></div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Email" class="form-control" aria-required="true" placeholder="name@example.com" />
|
|
||||||
<label asp-for="Input.Email" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.Email" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Resend</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
[AllowAnonymous]
|
|
||||||
public class ResendEmailConfirmationModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
private readonly IEmailSender _emailSender;
|
|
||||||
|
|
||||||
public ResendEmailConfirmationModel(UserManager<ApplicationUser> userManager, IEmailSender emailSender)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
_emailSender = emailSender;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[EmailAddress]
|
|
||||||
public string Email { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnGet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await _userManager.FindByEmailAsync(Input.Email);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, "Verification email sent. Please check your email.");
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
var userId = await _userManager.GetUserIdAsync(user);
|
|
||||||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
|
||||||
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
|
|
||||||
var callbackUrl = Url.Page(
|
|
||||||
"/Account/ConfirmEmail",
|
|
||||||
pageHandler: null,
|
|
||||||
values: new { userId = userId, code = code },
|
|
||||||
protocol: Request.Scheme);
|
|
||||||
await _emailSender.SendEmailAsync(
|
|
||||||
Input.Email,
|
|
||||||
"Confirm your email",
|
|
||||||
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
|
||||||
|
|
||||||
ModelState.AddModelError(string.Empty, "Verification email sent. Please check your email.");
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ResetPasswordModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Reset password";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<h2>Reset your password.</h2>
|
|
||||||
<hr />
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<form method="post">
|
|
||||||
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
|
|
||||||
<input asp-for="Input.Code" type="hidden" />
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="name@example.com" />
|
|
||||||
<label asp-for="Input.Email" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.Email" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.Password" class="form-control" autocomplete="new-password" aria-required="true" placeholder="Please enter your password." />
|
|
||||||
<label asp-for="Input.Password" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.Password" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="Please confirm your password." />
|
|
||||||
<label asp-for="Input.ConfirmPassword" class="form-label"></label>
|
|
||||||
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="w-100 btn btn-lg btn-primary">Reset</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<partial name="_ValidationScriptsPartial" />
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
public class ResetPasswordModel : PageModel
|
|
||||||
{
|
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
|
||||||
|
|
||||||
public ResetPasswordModel(UserManager<ApplicationUser> userManager)
|
|
||||||
{
|
|
||||||
_userManager = userManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[BindProperty]
|
|
||||||
public InputModel Input { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public class InputModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[EmailAddress]
|
|
||||||
public string Email { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
public string Password { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[DataType(DataType.Password)]
|
|
||||||
[Display(Name = "Confirm password")]
|
|
||||||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
|
|
||||||
public string ConfirmPassword { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public string Code { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IActionResult OnGet(string code = null)
|
|
||||||
{
|
|
||||||
if (code == null)
|
|
||||||
{
|
|
||||||
return BadRequest("A code must be supplied for password reset.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Input = new InputModel
|
|
||||||
{
|
|
||||||
Code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code))
|
|
||||||
};
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IActionResult> OnPostAsync()
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = await _userManager.FindByEmailAsync(Input.Email);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
// Don't reveal that the user does not exist
|
|
||||||
return RedirectToPage("./ResetPasswordConfirmation");
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await _userManager.ResetPasswordAsync(user, Input.Code, Input.Password);
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
return RedirectToPage("./ResetPasswordConfirmation");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var error in result.Errors)
|
|
||||||
{
|
|
||||||
ModelState.AddModelError(string.Empty, error.Description);
|
|
||||||
}
|
|
||||||
return Page();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ResetPasswordConfirmationModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Reset password confirmation";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<p>
|
|
||||||
Your password has been reset. Please <a asp-page="./Login">click here to log in</a>.
|
|
||||||
</p>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[AllowAnonymous]
|
|
||||||
public class ResetPasswordConfirmationModel : PageModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public void OnGet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
@model string
|
|
||||||
|
|
||||||
@if (!String.IsNullOrEmpty(Model))
|
|
||||||
{
|
|
||||||
var statusMessageClass = Model.StartsWith("Error") ? "danger" : "success";
|
|
||||||
<div class="alert alert-@statusMessageClass alert-dismissible" role="alert">
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
||||||
@Model
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
@using Kemkas.Web.Areas.Identity.Pages.Account
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
@page
|
|
||||||
@model ErrorModel
|
|
||||||
@{
|
|
||||||
ViewData["Title"] = "Error";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h1 class="text-danger">Error.</h1>
|
|
||||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
|
||||||
|
|
||||||
@if (Model.ShowRequestId)
|
|
||||||
{
|
|
||||||
<p>
|
|
||||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
|
|
||||||
<h3>Development Mode</h3>
|
|
||||||
<p>
|
|
||||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
|
|
||||||
</p>
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System.Diagnostics;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Areas.Identity.Pages
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
[AllowAnonymous]
|
|
||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
||||||
public class ErrorModel : PageModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public string RequestId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
|
||||||
/// directly from your code. This API may change or be removed in future releases.
|
|
||||||
/// </summary>
|
|
||||||
public void OnGet()
|
|
||||||
{
|
|
||||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
@using Microsoft.AspNetCore.Identity
|
|
||||||
@using Kemkas.Web.Areas.Identity
|
|
||||||
@using Kemkas.Web.Areas.Identity.Pages
|
|
||||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
|
||||||
@using Kemkas.Web.Db.Models
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
|
|
||||||
@{
|
|
||||||
Layout = "/Pages/Shared/_Layout.cshtml";
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
|
||||||
WORKDIR /app
|
|
||||||
EXPOSE 80
|
|
||||||
EXPOSE 443
|
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
|
||||||
WORKDIR /src
|
|
||||||
COPY ["Kemkas.Web/Kemkas.Web.csproj", "Kemkas.Web/"]
|
|
||||||
RUN dotnet restore "Kemkas.Web/Kemkas.Web.csproj"
|
|
||||||
COPY . .
|
|
||||||
WORKDIR "/src/Kemkas.Web"
|
|
||||||
RUN dotnet build "Kemkas.Web.csproj" -c Release -o /app/build
|
|
||||||
|
|
||||||
FROM build AS publish
|
|
||||||
RUN dotnet publish "Kemkas.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
|
||||||
|
|
||||||
FROM base AS final
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=publish /app/publish .
|
|
||||||
ENTRYPOINT ["dotnet", "Kemkas.Web.dll"]
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
|
||||||
WORKDIR /app
|
|
||||||
EXPOSE 80
|
|
||||||
EXPOSE 443
|
|
||||||
|
|
||||||
ARG FE_TAG=latest
|
|
||||||
ARG BE_TAG=latest
|
|
||||||
|
|
||||||
FROM ghcr.io/morbalint/kemkas-fe:$FE_TAG as frontend
|
|
||||||
FROM ghcr.io/morbalint/kemkas-be:$BE_TAG as backend
|
|
||||||
|
|
||||||
FROM base AS final
|
|
||||||
COPY --from=backend /app .
|
|
||||||
COPY --from=frontend /usr/share/nginx/html ./wwwroot
|
|
||||||
ENTRYPOINT ["dotnet", "Kemkas.Web.dll"]
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace Kemkas.Web.Config;
|
|
||||||
|
|
||||||
public class ExternalAuthOptions
|
|
||||||
{
|
|
||||||
public string? ClientId { get; set; }
|
|
||||||
|
|
||||||
public string? ClientSecret { get; set; }
|
|
||||||
|
|
||||||
public bool IsValid() => ClientId != null && ClientSecret != null;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace Kemkas.Web.Config;
|
|
||||||
|
|
||||||
public class MailgunOptions
|
|
||||||
{
|
|
||||||
public const string Section = "Email";
|
|
||||||
|
|
||||||
public string ApiKey { get; set; }
|
|
||||||
|
|
||||||
public string DomainName { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
using OpenTelemetry.Metrics;
|
|
||||||
using OpenTelemetry.Resources;
|
|
||||||
using OpenTelemetry.Trace;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Config;
|
|
||||||
|
|
||||||
public static class WebApplicationBuilderExtensions
|
|
||||||
{
|
|
||||||
public static void AddAuth(this WebApplicationBuilder builder)
|
|
||||||
{
|
|
||||||
var externalAuthConfigSection = builder.Configuration.GetSection("Authentication");
|
|
||||||
var authenticationBuilder = builder.Services.AddAuthentication();
|
|
||||||
|
|
||||||
var googleAuthOptions = new ExternalAuthOptions();
|
|
||||||
externalAuthConfigSection.GetSection("Google").Bind(googleAuthOptions);
|
|
||||||
if (googleAuthOptions.IsValid())
|
|
||||||
{
|
|
||||||
authenticationBuilder.AddGoogle(options =>
|
|
||||||
{
|
|
||||||
options.ClientId = googleAuthOptions.ClientId!;
|
|
||||||
options.ClientSecret = googleAuthOptions.ClientSecret!;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var facebookAuthOptions = new ExternalAuthOptions();
|
|
||||||
externalAuthConfigSection.GetSection("Facebook").Bind(facebookAuthOptions);
|
|
||||||
if (facebookAuthOptions.IsValid())
|
|
||||||
{
|
|
||||||
authenticationBuilder.AddFacebook(options =>
|
|
||||||
{
|
|
||||||
options.ClientId = facebookAuthOptions.ClientId!;
|
|
||||||
options.ClientSecret = facebookAuthOptions.ClientSecret!;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var discordAuthOptions = new ExternalAuthOptions();
|
|
||||||
externalAuthConfigSection.GetSection("Discord").Bind(discordAuthOptions);
|
|
||||||
if (discordAuthOptions.IsValid())
|
|
||||||
{
|
|
||||||
authenticationBuilder.AddDiscord(options =>
|
|
||||||
{
|
|
||||||
options.ClientId = discordAuthOptions.ClientId!;
|
|
||||||
options.ClientSecret = discordAuthOptions.ClientSecret!;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddOpenTelemetry(this WebApplicationBuilder builder)
|
|
||||||
{
|
|
||||||
var otlResourceBuilder = ResourceBuilder.CreateDefault().AddService("kemkas-api");
|
|
||||||
var openTelemetryEndpoint = builder.Configuration.GetSection("monitoring")["url"];
|
|
||||||
var consoleEnabled = builder.Configuration.GetSection("monitoring")["console"] == "true";
|
|
||||||
|
|
||||||
builder.Services.AddOpenTelemetry().WithTracing(tracerProviderBuilder =>
|
|
||||||
{
|
|
||||||
tracerProviderBuilder
|
|
||||||
.SetResourceBuilder(otlResourceBuilder)
|
|
||||||
.AddAspNetCoreInstrumentation();
|
|
||||||
if (openTelemetryEndpoint != null)
|
|
||||||
{
|
|
||||||
tracerProviderBuilder.AddOtlpExporter(opt => opt.Endpoint = new Uri(openTelemetryEndpoint));
|
|
||||||
}
|
|
||||||
else if (consoleEnabled)
|
|
||||||
{
|
|
||||||
tracerProviderBuilder.AddConsoleExporter();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.WithMetrics(meterProviderBuilder =>
|
|
||||||
{
|
|
||||||
meterProviderBuilder
|
|
||||||
.SetResourceBuilder(otlResourceBuilder)
|
|
||||||
.AddAspNetCoreInstrumentation();
|
|
||||||
if (openTelemetryEndpoint != null)
|
|
||||||
{
|
|
||||||
meterProviderBuilder.AddOtlpExporter(opt => opt.Endpoint = new Uri(openTelemetryEndpoint));
|
|
||||||
}
|
|
||||||
else if (consoleEnabled)
|
|
||||||
{
|
|
||||||
meterProviderBuilder.AddConsoleExporter();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Kemkas.Web.Services.FirstEdition.Character;
|
|
||||||
using Kemkas.Web.Services.Shared;
|
|
||||||
using Kemkas.Web.ViewModels;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Controllers;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// First edition character endpoints
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="validationService"></param>
|
|
||||||
/// <param name="dtoToDbModelService"></param>
|
|
||||||
/// <param name="dbModelToDto1EService"></param>
|
|
||||||
/// <param name="persistenceService"></param>
|
|
||||||
[ApiController]
|
|
||||||
[Route("[controller]")]
|
|
||||||
public class Character1EController(
|
|
||||||
ICharacterValidationService validationService,
|
|
||||||
ICharacter1EDtoToDbModelService dtoToDbModelService,
|
|
||||||
ICharacterDbModelToDto1EService dbModelToDto1EService,
|
|
||||||
ICharacterPersistenceService persistenceService)
|
|
||||||
: ControllerBase
|
|
||||||
{
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<ActionResult<Guid>> StoreNewCharacter([FromBody] Character1eDto dto, [FromQuery]bool isPublic = true)
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return BadRequest(ModelState);
|
|
||||||
}
|
|
||||||
var errors = validationService.Validate(dto);
|
|
||||||
if (errors != null)
|
|
||||||
{
|
|
||||||
return BadRequest(errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
V1Karakter model;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
model = dtoToDbModelService.Convert(dto);
|
|
||||||
}
|
|
||||||
catch (ValidationException ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
var id = await persistenceService.StoreNewCharacter1E(model, isPublic);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("{id:guid}")]
|
|
||||||
public async Task<ActionResult<Character1eDto>> GetCharacterById([FromRoute] Guid id)
|
|
||||||
{
|
|
||||||
var entity = await persistenceService.GetCharacter1EById(id);
|
|
||||||
if (entity is null)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbModelToDto1EService.Convert(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id:guid}")]
|
|
||||||
public async Task<ActionResult<Guid>> UpdateCharacter([FromRoute] Guid id, [FromBody] Character1eDto dto, [FromQuery]bool isPublic = true)
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return BadRequest(ModelState);
|
|
||||||
}
|
|
||||||
var errors = validationService.Validate(dto);
|
|
||||||
if (errors != null)
|
|
||||||
{
|
|
||||||
return BadRequest(errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
var original = await persistenceService.GetCharacter1EById(id, tracking: true);
|
|
||||||
if (original is null)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
dtoToDbModelService.Update(original, dto);
|
|
||||||
|
|
||||||
await persistenceService.UpdateCharacter1E(original, isPublic);
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Kemkas.Web.Services.SecondEdition.Character;
|
|
||||||
using Kemkas.Web.Services.Shared;
|
|
||||||
using Kemkas.Web.ViewModels;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Controllers;
|
|
||||||
|
|
||||||
[ApiController]
|
|
||||||
[Route("[controller]")]
|
|
||||||
public class Character2EController(
|
|
||||||
ICharacter2EDtoToDbModelService dtoToDbModelService,
|
|
||||||
ICharacterPersistenceService persistenceService,
|
|
||||||
ICharacterDbModelToDto2EService dbModelToDtoService
|
|
||||||
) : ControllerBase
|
|
||||||
{
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<ActionResult<Guid>> StoreNewCharacter([FromBody] Character2eDto dto, [FromQuery]bool isPublic = true)
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return BadRequest(ModelState);
|
|
||||||
}
|
|
||||||
// var errors = validationService.Validate(dto);
|
|
||||||
// if (errors != null)
|
|
||||||
// {
|
|
||||||
// return BadRequest(errors);
|
|
||||||
// }
|
|
||||||
|
|
||||||
V2Karakter model;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
model = dtoToDbModelService.Convert(dto);
|
|
||||||
}
|
|
||||||
catch (ValidationException ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
var id = await persistenceService.StoreNewCharacter2E(model, isPublic);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("{id:guid}")]
|
|
||||||
public async Task<ActionResult<Character2eDto>> GetCharacterById([FromRoute] Guid id)
|
|
||||||
{
|
|
||||||
var entity = await persistenceService.GetCharacter2EById(id);
|
|
||||||
if (entity is null)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbModelToDtoService.Convert(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id:guid}")]
|
|
||||||
public async Task<ActionResult<Guid>> UpdateCharacter([FromRoute] Guid id, [FromBody] Character2eDto dto, [FromQuery]bool isPublic = true)
|
|
||||||
{
|
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return BadRequest(ModelState);
|
|
||||||
}
|
|
||||||
// var errors = validationService.Validate(dto);
|
|
||||||
// if (errors != null)
|
|
||||||
// {
|
|
||||||
// return BadRequest(errors);
|
|
||||||
// }
|
|
||||||
|
|
||||||
var original = await persistenceService.GetCharacter2EById(id, tracking: true);
|
|
||||||
if (original is null)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dtoToDbModelService.Update(original, dto);
|
|
||||||
}
|
|
||||||
catch (ValidationException ex)
|
|
||||||
{
|
|
||||||
return BadRequest(ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
await persistenceService.UpdateCharacter2E(original, isPublic);
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
using Kemkas.Web.Services.FirstEdition.Character;
|
|
||||||
using Kemkas.Web.Services.Shared;
|
|
||||||
using Kemkas.Web.ViewModels;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Controllers;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shared first and second edition character endpoints
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="persistenceService"></param>
|
|
||||||
[ApiController]
|
|
||||||
[Route("[controller]")]
|
|
||||||
public class CharacterController(ICharacterPersistenceService persistenceService) : ControllerBase
|
|
||||||
{
|
|
||||||
[HttpGet]
|
|
||||||
[Authorize]
|
|
||||||
public async Task<List<CharacterListItemDto>> GetAllCharacters()
|
|
||||||
{
|
|
||||||
return await persistenceService.GetAllCharactersOfUser();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Controllers;
|
|
||||||
|
|
||||||
[Route("[controller]")]
|
|
||||||
[ApiController]
|
|
||||||
public class UserController : ControllerBase
|
|
||||||
{
|
|
||||||
// GET
|
|
||||||
[HttpGet("me")]
|
|
||||||
public async Task<string?> Me([FromServices] UserManager<ApplicationUser> userManager)
|
|
||||||
{
|
|
||||||
var user = await userManager.GetUserAsync(User);
|
|
||||||
return user?.UserName ?? user?.Email;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using Kemkas.Web.Db.Models;
|
|
||||||
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db;
|
|
||||||
|
|
||||||
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>, IDataProtectionKeyContext
|
|
||||||
{
|
|
||||||
public ApplicationDbContext(DbContextOptions options) : base(options)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
|
|
||||||
|
|
||||||
// 1st edition character
|
|
||||||
|
|
||||||
public DbSet<V1Karakter> Karakterek { get; set; }
|
|
||||||
|
|
||||||
public DbSet<V1KarakterKepzettseg> KarakterKepzettsegek { get; set; }
|
|
||||||
|
|
||||||
public DbSet<V1Szintlepes> Szintlepesek { get; set; }
|
|
||||||
|
|
||||||
public DbSet<V1Felszereles> Felszerelesek { get; set; }
|
|
||||||
|
|
||||||
// 2nd edition character
|
|
||||||
|
|
||||||
public DbSet<V2Karakter> Karakterek2E { get; set; }
|
|
||||||
|
|
||||||
public DbSet<V2KarakterKepzettseg> KarakterKepzettsegek2E { get; set; }
|
|
||||||
|
|
||||||
public DbSet<V2Szintlepes> Szintlepesek2E { get; set; }
|
|
||||||
|
|
||||||
public DbSet<V2Felszereles> Felszerelesek2E { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
public enum Faj1E
|
|
||||||
{
|
|
||||||
Ember = 0,
|
|
||||||
Amazon = 1,
|
|
||||||
Birodalmi = 2,
|
|
||||||
Etuniai = 3,
|
|
||||||
Eszaki = 4,
|
|
||||||
Osember = 5,
|
|
||||||
Elf = 6,
|
|
||||||
Felelf = 7,
|
|
||||||
Felork = 8,
|
|
||||||
Felszerzet = 9,
|
|
||||||
Gnom = 10,
|
|
||||||
Torpe = 11,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Faj2E
|
|
||||||
{
|
|
||||||
Ember = 0,
|
|
||||||
Amazon = 1,
|
|
||||||
Birodalmi = 2,
|
|
||||||
Nomad = 3,
|
|
||||||
Eszaki = 4,
|
|
||||||
Osember = 5,
|
|
||||||
Elf = 6,
|
|
||||||
Felelf = 7,
|
|
||||||
Felork = 8,
|
|
||||||
Felszerzet = 9,
|
|
||||||
Gnom = 10,
|
|
||||||
Torpe = 11,
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
public static class FajExtensions
|
|
||||||
{
|
|
||||||
public static Faj1E Convert1E(string faj)
|
|
||||||
{
|
|
||||||
return faj switch
|
|
||||||
{
|
|
||||||
"f_ember" => Faj1E.Ember,
|
|
||||||
"f_amazon" => Faj1E.Amazon,
|
|
||||||
"f_birodalmi" => Faj1E.Birodalmi,
|
|
||||||
"f_etuniai" => Faj1E.Etuniai,
|
|
||||||
"f_eszaki" => Faj1E.Eszaki,
|
|
||||||
"f_osember" => Faj1E.Osember,
|
|
||||||
"f_elf" => Faj1E.Elf,
|
|
||||||
"f_felelf" => Faj1E.Felelf,
|
|
||||||
"f_felork" => Faj1E.Felork,
|
|
||||||
"f_felszerzet" => Faj1E.Felszerzet,
|
|
||||||
"f_gnom" => Faj1E.Gnom,
|
|
||||||
"f_torpe" => Faj1E.Torpe,
|
|
||||||
_ => throw new Exception("invalid faj: " + faj)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Faj2E Convert2E(string faj)
|
|
||||||
{
|
|
||||||
return faj switch
|
|
||||||
{
|
|
||||||
"f_2e_ember" => Faj2E.Ember,
|
|
||||||
"f_2e_amazon" => Faj2E.Amazon,
|
|
||||||
"f_2e_birodalmi" => Faj2E.Birodalmi,
|
|
||||||
"f_2e_nomad" => Faj2E.Nomad,
|
|
||||||
"f_2e_eszaki" => Faj2E.Eszaki,
|
|
||||||
"f_2e_osember" => Faj2E.Osember,
|
|
||||||
"f_2e_elf" => Faj2E.Elf,
|
|
||||||
"f_2e_felelf" => Faj2E.Felelf,
|
|
||||||
"f_2e_felork" => Faj2E.Felork,
|
|
||||||
"f_2e_felszerzet" => Faj2E.Felszerzet,
|
|
||||||
"f_2e_gnom" => Faj2E.Gnom,
|
|
||||||
"f_2e_torpe" => Faj2E.Torpe,
|
|
||||||
_ => throw new Exception("invalid faj: " + faj)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Convert(this Faj1E faj)
|
|
||||||
{
|
|
||||||
return faj switch
|
|
||||||
{
|
|
||||||
Faj1E.Ember => "f_ember",
|
|
||||||
Faj1E.Amazon => "f_amazon",
|
|
||||||
Faj1E.Birodalmi => "f_birodalmi",
|
|
||||||
Faj1E.Etuniai => "f_etuniai",
|
|
||||||
Faj1E.Eszaki => "f_eszaki",
|
|
||||||
Faj1E.Osember => "f_osember",
|
|
||||||
Faj1E.Elf => "f_elf",
|
|
||||||
Faj1E.Felelf => "f_felelf",
|
|
||||||
Faj1E.Felork => "f_felork",
|
|
||||||
Faj1E.Felszerzet => "f_felszerzet",
|
|
||||||
Faj1E.Gnom => "f_gnom",
|
|
||||||
Faj1E.Torpe => "f_torpe",
|
|
||||||
_ => throw new Exception("invalid faj: " + faj)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Convert(this Faj2E faj)
|
|
||||||
{
|
|
||||||
return faj switch
|
|
||||||
{
|
|
||||||
Faj2E.Ember => "f_2e_ember",
|
|
||||||
Faj2E.Amazon => "f_2e_amazon",
|
|
||||||
Faj2E.Birodalmi => "f_2e_birodalmi",
|
|
||||||
Faj2E.Nomad => "f_2e_nomad",
|
|
||||||
Faj2E.Eszaki => "f_2e_eszaki",
|
|
||||||
Faj2E.Osember => "f_2e_osember",
|
|
||||||
Faj2E.Elf => "f_2e_elf",
|
|
||||||
Faj2E.Felelf => "f_2e_felelf",
|
|
||||||
Faj2E.Felork => "f_2e_felork",
|
|
||||||
Faj2E.Felszerzet => "f_2e_felszerzet",
|
|
||||||
Faj2E.Gnom => "f_2e_gnom",
|
|
||||||
Faj2E.Torpe => "f_2e_torpe",
|
|
||||||
_ => throw new Exception("invalid faj: " + faj)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum Jellem : byte
|
|
||||||
{
|
|
||||||
Semleges = 0,
|
|
||||||
Torvenyes = 1,
|
|
||||||
Kaotikus = 2,
|
|
||||||
Jo = 4,
|
|
||||||
TorvenyesJo = Torvenyes | Jo, // 5
|
|
||||||
KaotikusJo = Kaotikus | Jo, // 6
|
|
||||||
Gonosz = 8,
|
|
||||||
TorvenyesGonosz = Torvenyes | Gonosz, // 9
|
|
||||||
KaotikusGonosz = Kaotikus | Gonosz, // 10
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
public static class JellemExtensions
|
|
||||||
{
|
|
||||||
public static Jellem Convert(string jellem)
|
|
||||||
{
|
|
||||||
return jellem switch
|
|
||||||
{
|
|
||||||
"TJ" => Jellem.TorvenyesJo,
|
|
||||||
"SJ" => Jellem.Jo,
|
|
||||||
"KJ" => Jellem.KaotikusJo,
|
|
||||||
"TS" => Jellem.Torvenyes,
|
|
||||||
"S" => Jellem.Semleges,
|
|
||||||
"KS" => Jellem.Kaotikus,
|
|
||||||
"TG" => Jellem.TorvenyesGonosz,
|
|
||||||
"SG" => Jellem.Gonosz,
|
|
||||||
"KG" => Jellem.KaotikusGonosz,
|
|
||||||
_ => throw new ValidationException("invalid jellem: " + jellem)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Convert(this Jellem jellem)
|
|
||||||
{
|
|
||||||
return jellem switch
|
|
||||||
{
|
|
||||||
Jellem.TorvenyesJo => "TJ",
|
|
||||||
Jellem.Jo => "SJ",
|
|
||||||
Jellem.KaotikusJo => "KJ",
|
|
||||||
Jellem.Torvenyes => "TS",
|
|
||||||
Jellem.Semleges => "S",
|
|
||||||
Jellem.Kaotikus => "KS",
|
|
||||||
Jellem.TorvenyesGonosz => "TG",
|
|
||||||
Jellem.Gonosz => "SG",
|
|
||||||
Jellem.KaotikusGonosz => "KG",
|
|
||||||
_ => throw new ValidationException("invalid jellem: " + (byte)jellem)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
public enum Kepzettseg1E
|
|
||||||
{
|
|
||||||
Alkimia = 1,
|
|
||||||
Alcazas = 2,
|
|
||||||
Allatidomitas = 3,
|
|
||||||
Csapdak = 4,
|
|
||||||
Csillagjoslas = 5,
|
|
||||||
Egyensulyozas = 6,
|
|
||||||
Eloadas = 7,
|
|
||||||
Ertekbecsles = 8,
|
|
||||||
Gyogyitas = 9,
|
|
||||||
Hajozas = 10,
|
|
||||||
Hallgatozas = 11,
|
|
||||||
Hamisitas = 12,
|
|
||||||
JelekOlvasasa = 13,
|
|
||||||
Koncentracio = 14,
|
|
||||||
Lovaglas = 15,
|
|
||||||
Maszas = 16,
|
|
||||||
Megfigyeles = 17,
|
|
||||||
Meregkeveres = 18,
|
|
||||||
Mesterseg = 19,
|
|
||||||
Nyomkereses = 20,
|
|
||||||
Osonas = 21,
|
|
||||||
Rejtozes = 22,
|
|
||||||
Szabadulomuveszet = 23,
|
|
||||||
Tudas = 24,
|
|
||||||
Ugras = 25,
|
|
||||||
Uszas = 26,
|
|
||||||
Varazslatismeret = 27,
|
|
||||||
Zarnyitas = 28,
|
|
||||||
Zsebmetszes = 29,
|
|
||||||
}
|
|
||||||
|
|
||||||
// offset by 200 to make it more different from 1e karakter kepzettsegek
|
|
||||||
// I don't plan to mix them, but let's make it obvious which one is which.
|
|
||||||
// But it could be useful in one-time character conversions in the future.
|
|
||||||
public enum Kepzettseg2E
|
|
||||||
{
|
|
||||||
Alkimia = 201,
|
|
||||||
Alcazas = 202,
|
|
||||||
Allatidomitas = 203,
|
|
||||||
Csapdak = 204,
|
|
||||||
Csillagjoslas = 205,
|
|
||||||
Egyensulyozas = 206,
|
|
||||||
Eloadas = 207,
|
|
||||||
Ertekbecsles = 208,
|
|
||||||
Gyogyitas = 209,
|
|
||||||
Hajozas = 210,
|
|
||||||
Hallgatozas = 211,
|
|
||||||
Hamisitas = 212,
|
|
||||||
JelekOlvasasa = 213,
|
|
||||||
Herbalizmus = 601,
|
|
||||||
Historia = 602,
|
|
||||||
Lovaglas = 215,
|
|
||||||
Maszas = 216,
|
|
||||||
Megfigyeles = 217,
|
|
||||||
Meregkeveres = 218,
|
|
||||||
Mesterseg = 219,
|
|
||||||
Nyomkereses = 220,
|
|
||||||
Okkultizmus = 666, // inside joke
|
|
||||||
Osonas = 221,
|
|
||||||
Szabadulomuveszet = 223,
|
|
||||||
Ugras = 225,
|
|
||||||
Uszas = 226,
|
|
||||||
Vadonjaras = 603,
|
|
||||||
Zarnyitas = 228,
|
|
||||||
Zsebmetszes = 229,
|
|
||||||
}
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
public static class KepzettsegExtensions
|
|
||||||
{
|
|
||||||
public static Kepzettseg1E Convert1E(string kepzettseg)
|
|
||||||
{
|
|
||||||
return kepzettseg switch
|
|
||||||
{
|
|
||||||
"k_alkimia" => Kepzettseg1E.Alkimia,
|
|
||||||
"k_alcazas" => Kepzettseg1E.Alcazas,
|
|
||||||
"k_allatidomitas" => Kepzettseg1E.Allatidomitas,
|
|
||||||
"k_csapdak" => Kepzettseg1E.Csapdak,
|
|
||||||
"k_csillagjoslas" => Kepzettseg1E.Csillagjoslas,
|
|
||||||
"k_egyensulyozas" => Kepzettseg1E.Egyensulyozas,
|
|
||||||
"k_eloadas" => Kepzettseg1E.Eloadas,
|
|
||||||
"k_ertekbecsles" => Kepzettseg1E.Ertekbecsles,
|
|
||||||
"k_gyogyitas" => Kepzettseg1E.Gyogyitas,
|
|
||||||
"k_hajozas" => Kepzettseg1E.Hajozas,
|
|
||||||
"k_hallgatozas" => Kepzettseg1E.Hallgatozas,
|
|
||||||
"k_hamisitas" => Kepzettseg1E.Hamisitas,
|
|
||||||
"k_jelek_olvasasa" => Kepzettseg1E.JelekOlvasasa,
|
|
||||||
"k_koncentracio" => Kepzettseg1E.Koncentracio,
|
|
||||||
"k_lovaglas" => Kepzettseg1E.Lovaglas,
|
|
||||||
"k_maszas" => Kepzettseg1E.Maszas,
|
|
||||||
"k_megfigyeles" => Kepzettseg1E.Megfigyeles,
|
|
||||||
"k_meregkeveres" => Kepzettseg1E.Meregkeveres,
|
|
||||||
"k_mesterseg" => Kepzettseg1E.Mesterseg,
|
|
||||||
"k_nyomkereses" => Kepzettseg1E.Nyomkereses,
|
|
||||||
"k_osonas" => Kepzettseg1E.Osonas,
|
|
||||||
"k_rejtozes" => Kepzettseg1E.Rejtozes,
|
|
||||||
"k_szabadulomuveszet" => Kepzettseg1E.Szabadulomuveszet,
|
|
||||||
"k_tudas" => Kepzettseg1E.Tudas,
|
|
||||||
"k_ugras" => Kepzettseg1E.Ugras,
|
|
||||||
"k_uszas" => Kepzettseg1E.Uszas,
|
|
||||||
"k_varazslatismeret" => Kepzettseg1E.Varazslatismeret,
|
|
||||||
"k_zarnyitas" => Kepzettseg1E.Zarnyitas,
|
|
||||||
"k_zsebmetszes" => Kepzettseg1E.Zsebmetszes,
|
|
||||||
_ => throw new ValidationException("invalid kepzettseg: " + kepzettseg),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Kepzettseg2E Convert2E(string kepzettseg)
|
|
||||||
{
|
|
||||||
return kepzettseg switch
|
|
||||||
{
|
|
||||||
"k_alkimia" => Kepzettseg2E.Alkimia,
|
|
||||||
"k_alcazas" => Kepzettseg2E.Alcazas,
|
|
||||||
"k_allatidomitas" => Kepzettseg2E.Allatidomitas,
|
|
||||||
"k_csapdak" => Kepzettseg2E.Csapdak,
|
|
||||||
"k_csillagjoslas" => Kepzettseg2E.Csillagjoslas,
|
|
||||||
"k_egyensulyozas" => Kepzettseg2E.Egyensulyozas,
|
|
||||||
"k_eloadas" => Kepzettseg2E.Eloadas,
|
|
||||||
"k_ertekbecsles" => Kepzettseg2E.Ertekbecsles,
|
|
||||||
"k_gyogyitas" => Kepzettseg2E.Gyogyitas,
|
|
||||||
"k_hajozas" => Kepzettseg2E.Hajozas,
|
|
||||||
"k_hallgatozas" => Kepzettseg2E.Hallgatozas,
|
|
||||||
"k_hamisitas" => Kepzettseg2E.Hamisitas,
|
|
||||||
"k_herbalizmus" => Kepzettseg2E.Herbalizmus,
|
|
||||||
"k_historia" => Kepzettseg2E.Historia,
|
|
||||||
"k_jelek_olvasasa" => Kepzettseg2E.JelekOlvasasa,
|
|
||||||
"k_lovaglas" => Kepzettseg2E.Lovaglas,
|
|
||||||
"k_maszas" => Kepzettseg2E.Maszas,
|
|
||||||
"k_megfigyeles" => Kepzettseg2E.Megfigyeles,
|
|
||||||
"k_meregkeveres" => Kepzettseg2E.Meregkeveres,
|
|
||||||
"k_mesterseg" => Kepzettseg2E.Mesterseg,
|
|
||||||
"k_nyomkereses" => Kepzettseg2E.Nyomkereses,
|
|
||||||
"k_okkultizmus" => Kepzettseg2E.Okkultizmus,
|
|
||||||
"k_osonas" => Kepzettseg2E.Osonas,
|
|
||||||
"k_szabadulomuveszet" => Kepzettseg2E.Szabadulomuveszet,
|
|
||||||
"k_ugras" => Kepzettseg2E.Ugras,
|
|
||||||
"k_uszas" => Kepzettseg2E.Uszas,
|
|
||||||
"k_vadonjaras" => Kepzettseg2E.Vadonjaras,
|
|
||||||
"k_zarnyitas" => Kepzettseg2E.Zarnyitas,
|
|
||||||
"k_zsebmetszes" => Kepzettseg2E.Zsebmetszes,
|
|
||||||
_ => throw new ValidationException("invalid kepzettseg: " + kepzettseg),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Convert(this Kepzettseg1E kepzettseg)
|
|
||||||
{
|
|
||||||
return kepzettseg switch
|
|
||||||
{
|
|
||||||
Kepzettseg1E.Alkimia => "k_alkimia",
|
|
||||||
Kepzettseg1E.Alcazas => "k_alcazas",
|
|
||||||
Kepzettseg1E.Allatidomitas => "k_allatidomitas",
|
|
||||||
Kepzettseg1E.Csapdak => "k_csapdak",
|
|
||||||
Kepzettseg1E.Csillagjoslas => "k_csillagjoslas",
|
|
||||||
Kepzettseg1E.Egyensulyozas => "k_egyensulyozas",
|
|
||||||
Kepzettseg1E.Eloadas => "k_eloadas",
|
|
||||||
Kepzettseg1E.Ertekbecsles => "k_ertekbecsles",
|
|
||||||
Kepzettseg1E.Gyogyitas => "k_gyogyitas",
|
|
||||||
Kepzettseg1E.Hajozas => "k_hajozas",
|
|
||||||
Kepzettseg1E.Hallgatozas => "k_hallgatozas",
|
|
||||||
Kepzettseg1E.Hamisitas => "k_hamisitas",
|
|
||||||
Kepzettseg1E.JelekOlvasasa => "k_jelek_olvasasa",
|
|
||||||
Kepzettseg1E.Koncentracio => "k_koncentracio",
|
|
||||||
Kepzettseg1E.Lovaglas => "k_lovaglas",
|
|
||||||
Kepzettseg1E.Maszas => "k_maszas",
|
|
||||||
Kepzettseg1E.Megfigyeles => "k_megfigyeles",
|
|
||||||
Kepzettseg1E.Meregkeveres => "k_meregkeveres",
|
|
||||||
Kepzettseg1E.Mesterseg => "k_mesterseg",
|
|
||||||
Kepzettseg1E.Nyomkereses => "k_nyomkereses",
|
|
||||||
Kepzettseg1E.Osonas => "k_osonas",
|
|
||||||
Kepzettseg1E.Rejtozes => "k_rejtozes",
|
|
||||||
Kepzettseg1E.Szabadulomuveszet => "k_szabadulomuveszet",
|
|
||||||
Kepzettseg1E.Tudas => "k_tudas",
|
|
||||||
Kepzettseg1E.Ugras => "k_ugras",
|
|
||||||
Kepzettseg1E.Uszas => "k_uszas",
|
|
||||||
Kepzettseg1E.Varazslatismeret => "k_varazslatismeret",
|
|
||||||
Kepzettseg1E.Zarnyitas => "k_zarnyitas",
|
|
||||||
Kepzettseg1E.Zsebmetszes => "k_zsebmetszes",
|
|
||||||
_ => throw new ValidationException("invalid kepzettseg: " + kepzettseg),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Convert(this Kepzettseg2E kepzettseg)
|
|
||||||
{
|
|
||||||
return kepzettseg switch
|
|
||||||
{
|
|
||||||
Kepzettseg2E.Alkimia => "k_alkimia",
|
|
||||||
Kepzettseg2E.Alcazas => "k_alcazas",
|
|
||||||
Kepzettseg2E.Allatidomitas => "k_allatidomitas",
|
|
||||||
Kepzettseg2E.Csapdak => "k_csapdak",
|
|
||||||
Kepzettseg2E.Csillagjoslas => "k_csillagjoslas",
|
|
||||||
Kepzettseg2E.Egyensulyozas => "k_egyensulyozas",
|
|
||||||
Kepzettseg2E.Eloadas => "k_eloadas",
|
|
||||||
Kepzettseg2E.Ertekbecsles => "k_ertekbecsles",
|
|
||||||
Kepzettseg2E.Gyogyitas => "k_gyogyitas",
|
|
||||||
Kepzettseg2E.Hajozas => "k_hajozas",
|
|
||||||
Kepzettseg2E.Hallgatozas => "k_hallgatozas",
|
|
||||||
Kepzettseg2E.Hamisitas => "k_hamisitas",
|
|
||||||
Kepzettseg2E.Herbalizmus => "k_herbalizmus",
|
|
||||||
Kepzettseg2E.Historia => "k_historia",
|
|
||||||
Kepzettseg2E.JelekOlvasasa => "k_jelek_olvasasa",
|
|
||||||
Kepzettseg2E.Lovaglas => "k_lovaglas",
|
|
||||||
Kepzettseg2E.Maszas => "k_maszas",
|
|
||||||
Kepzettseg2E.Megfigyeles => "k_megfigyeles",
|
|
||||||
Kepzettseg2E.Meregkeveres => "k_meregkeveres",
|
|
||||||
Kepzettseg2E.Mesterseg => "k_mesterseg",
|
|
||||||
Kepzettseg2E.Nyomkereses => "k_nyomkereses",
|
|
||||||
Kepzettseg2E.Okkultizmus => "k_okkultizmus",
|
|
||||||
Kepzettseg2E.Osonas => "k_osonas",
|
|
||||||
Kepzettseg2E.Szabadulomuveszet => "k_szabadulomuveszet",
|
|
||||||
Kepzettseg2E.Ugras => "k_ugras",
|
|
||||||
Kepzettseg2E.Uszas => "k_uszas",
|
|
||||||
Kepzettseg2E.Vadonjaras => "k_vadonjaras",
|
|
||||||
Kepzettseg2E.Zarnyitas => "k_zarnyitas",
|
|
||||||
Kepzettseg2E.Zsebmetszes => "k_zsebmetszes",
|
|
||||||
_ => throw new ValidationException("invalid kepzettseg: " + kepzettseg),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
public enum Osztaly1E
|
|
||||||
{
|
|
||||||
Error = 0, // for unset enum value mapping
|
|
||||||
Harcos = 1,
|
|
||||||
Ijasz = 2,
|
|
||||||
Amazon = 3,
|
|
||||||
Kaloz = 4,
|
|
||||||
Barbar = 5,
|
|
||||||
Pap = 6,
|
|
||||||
Tolvaj = 7,
|
|
||||||
Varazslo = 8,
|
|
||||||
Illuzionista = 9,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Osztaly2E
|
|
||||||
{
|
|
||||||
Error = 0, // for unset enum value mapping
|
|
||||||
Harcos = 1,
|
|
||||||
Ijasz = 2,
|
|
||||||
Amazon = 3,
|
|
||||||
Tengeresz = 4,
|
|
||||||
Barbar = 5,
|
|
||||||
Pap = 6,
|
|
||||||
Tolvaj = 7,
|
|
||||||
Varazslo = 8,
|
|
||||||
Illuzionista = 9,
|
|
||||||
Dalnok = 10,
|
|
||||||
Druida = 11,
|
|
||||||
Vandor = 12,
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
public static class OsztalyExtensions
|
|
||||||
{
|
|
||||||
public static Osztaly1E Convert1E(string osztaly)
|
|
||||||
{
|
|
||||||
return osztaly switch
|
|
||||||
{
|
|
||||||
"o_harcos" => Osztaly1E.Harcos,
|
|
||||||
"o_ijasz" => Osztaly1E.Ijasz,
|
|
||||||
"o_amazon" => Osztaly1E.Amazon,
|
|
||||||
"o_kaloz" => Osztaly1E.Kaloz,
|
|
||||||
"o_barbar" => Osztaly1E.Barbar,
|
|
||||||
"o_pap" => Osztaly1E.Pap,
|
|
||||||
"o_tolvaj" => Osztaly1E.Tolvaj,
|
|
||||||
"o_varazslo" => Osztaly1E.Varazslo,
|
|
||||||
"o_illuzionista" => Osztaly1E.Illuzionista,
|
|
||||||
_ => throw new ValidationException("unknown osztaly: " + osztaly)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Osztaly2E Convert2E(string osztaly)
|
|
||||||
{
|
|
||||||
return osztaly switch
|
|
||||||
{
|
|
||||||
"o_2e_harcos" => Osztaly2E.Harcos,
|
|
||||||
"o_2e_ijasz" => Osztaly2E.Ijasz,
|
|
||||||
"o_2e_amazon" => Osztaly2E.Amazon,
|
|
||||||
"o_2e_tengeresz" => Osztaly2E.Tengeresz,
|
|
||||||
"o_2e_barbar" => Osztaly2E.Barbar,
|
|
||||||
"o_2e_pap" => Osztaly2E.Pap,
|
|
||||||
"o_2e_tolvaj" => Osztaly2E.Tolvaj,
|
|
||||||
"o_2e_varazslo" => Osztaly2E.Varazslo,
|
|
||||||
"o_2e_illuzionista" => Osztaly2E.Illuzionista,
|
|
||||||
"o_2e_dalnok" => Osztaly2E.Dalnok,
|
|
||||||
"o_2e_druida" => Osztaly2E.Druida,
|
|
||||||
"o_2e_vandor" => Osztaly2E.Vandor,
|
|
||||||
_ => throw new ValidationException("unknown osztaly: " + osztaly)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Convert(this Osztaly1E osztaly)
|
|
||||||
{
|
|
||||||
return osztaly switch
|
|
||||||
{
|
|
||||||
Osztaly1E.Harcos => "o_harcos",
|
|
||||||
Osztaly1E.Ijasz => "o_ijasz",
|
|
||||||
Osztaly1E.Amazon => "o_amazon",
|
|
||||||
Osztaly1E.Kaloz => "o_kaloz",
|
|
||||||
Osztaly1E.Barbar => "o_barbar",
|
|
||||||
Osztaly1E.Pap => "o_pap",
|
|
||||||
Osztaly1E.Tolvaj => "o_tolvaj",
|
|
||||||
Osztaly1E.Varazslo => "o_varazslo",
|
|
||||||
Osztaly1E.Illuzionista => "o_illuzionista",
|
|
||||||
_ => throw new ValidationException("invalid osztaly!")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Convert(this Osztaly2E osztaly)
|
|
||||||
{
|
|
||||||
return osztaly switch
|
|
||||||
{
|
|
||||||
Osztaly2E.Harcos => "o_2e_harcos",
|
|
||||||
Osztaly2E.Ijasz => "o_2e_ijasz",
|
|
||||||
Osztaly2E.Amazon => "o_2e_amazon",
|
|
||||||
Osztaly2E.Tengeresz => "o_2e_tengeresz",
|
|
||||||
Osztaly2E.Barbar => "o_2e_barbar",
|
|
||||||
Osztaly2E.Pap => "o_2e_pap",
|
|
||||||
Osztaly2E.Tolvaj => "o_2e_tolvaj",
|
|
||||||
Osztaly2E.Varazslo => "o_2e_varazslo",
|
|
||||||
Osztaly2E.Illuzionista => "o_2e_illuzionista",
|
|
||||||
Osztaly2E.Dalnok => "o_2e_dalnok",
|
|
||||||
Osztaly2E.Druida => "o_2e_druida",
|
|
||||||
Osztaly2E.Vandor => "o_2e_vandor",
|
|
||||||
_ => throw new ValidationException("invalid osztaly!")
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum Tulajdonsag : byte
|
|
||||||
{
|
|
||||||
Ero = 1,
|
|
||||||
Ugyesseg = 2,
|
|
||||||
Egeszseg = 4,
|
|
||||||
Intelligencia = 8,
|
|
||||||
Bolcsesseg = 16,
|
|
||||||
Karizma = 32,
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db.Enums;
|
|
||||||
|
|
||||||
public static class TulajdonsagExtensions
|
|
||||||
{
|
|
||||||
public static Tulajdonsag Convert(string tulajdonsag)
|
|
||||||
{
|
|
||||||
return tulajdonsag switch
|
|
||||||
{
|
|
||||||
"t_ero" => Tulajdonsag.Ero,
|
|
||||||
"t_ugy" => Tulajdonsag.Ugyesseg,
|
|
||||||
"t_egs" => Tulajdonsag.Egeszseg,
|
|
||||||
"t_int" => Tulajdonsag.Intelligencia,
|
|
||||||
"t_bol" => Tulajdonsag.Bolcsesseg,
|
|
||||||
"t_kar" => Tulajdonsag.Karizma,
|
|
||||||
_ => throw new ValidationException("invalid tulajdonsag: " + tulajdonsag),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Convert(this Tulajdonsag tulajdonsag)
|
|
||||||
{
|
|
||||||
return tulajdonsag switch
|
|
||||||
{
|
|
||||||
Tulajdonsag.Ero => "t_ero",
|
|
||||||
Tulajdonsag.Ugyesseg => "t_ugy",
|
|
||||||
Tulajdonsag.Egeszseg => "t_egs",
|
|
||||||
Tulajdonsag.Intelligencia => "t_int",
|
|
||||||
Tulajdonsag.Bolcsesseg => "t_bol",
|
|
||||||
Tulajdonsag.Karizma => "t_kar",
|
|
||||||
_ => throw new ValidationException("invalid tulajdonsag: " + tulajdonsag),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,284 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Kemkas.Web.Db;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(ApplicationDbContext))]
|
|
||||||
[Migration("20231215102054_Initial")]
|
|
||||||
partial class Initial
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "8.0.0")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.ApplicationRole", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ConcurrencyStamp")
|
|
||||||
.IsConcurrencyToken()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedName")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("RoleNameIndex");
|
|
||||||
|
|
||||||
b.ToTable("AspNetRoles", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.ApplicationUser", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<int>("AccessFailedCount")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("ConcurrencyStamp")
|
|
||||||
.IsConcurrencyToken()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("EmailConfirmed")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<bool>("LockoutEnabled")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedEmail")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedUserName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<bool>("PhoneNumberConfirmed")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("SecurityStamp")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<bool>("TwoFactorEnabled")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedEmail")
|
|
||||||
.HasDatabaseName("EmailIndex");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedUserName")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("UserNameIndex");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUsers", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ClaimType")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimValue")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("RoleId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("RoleId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetRoleClaims", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ClaimType")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimValue")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserClaims", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("LoginProvider")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("ProviderKey")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("ProviderDisplayName")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("LoginProvider", "ProviderKey");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserLogins", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<int>("RoleId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("UserId", "RoleId");
|
|
||||||
|
|
||||||
b.HasIndex("RoleId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserRoles", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("LoginProvider")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Value")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.HasKey("UserId", "LoginProvider", "Name");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserTokens", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationRole", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("RoleId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationRole", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("RoleId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class Initial : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "AspNetRoles",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
Name = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
|
||||||
NormalizedName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
|
||||||
ConcurrencyStamp = table.Column<string>(type: "text", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "AspNetUsers",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
UserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
|
||||||
NormalizedUserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
|
||||||
Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
|
||||||
NormalizedEmail = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
|
||||||
EmailConfirmed = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
PasswordHash = table.Column<string>(type: "text", nullable: true),
|
|
||||||
SecurityStamp = table.Column<string>(type: "text", nullable: true),
|
|
||||||
ConcurrencyStamp = table.Column<string>(type: "text", nullable: true),
|
|
||||||
PhoneNumber = table.Column<string>(type: "text", nullable: true),
|
|
||||||
PhoneNumberConfirmed = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
TwoFactorEnabled = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
LockoutEnd = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
|
||||||
LockoutEnabled = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
AccessFailedCount = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "AspNetRoleClaims",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
RoleId = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
ClaimType = table.Column<string>(type: "text", nullable: true),
|
|
||||||
ClaimValue = table.Column<string>(type: "text", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
|
|
||||||
column: x => x.RoleId,
|
|
||||||
principalTable: "AspNetRoles",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "AspNetUserClaims",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
UserId = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
ClaimType = table.Column<string>(type: "text", nullable: true),
|
|
||||||
ClaimValue = table.Column<string>(type: "text", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
|
|
||||||
column: x => x.UserId,
|
|
||||||
principalTable: "AspNetUsers",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "AspNetUserLogins",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
LoginProvider = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
|
|
||||||
ProviderKey = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
|
|
||||||
ProviderDisplayName = table.Column<string>(type: "text", nullable: true),
|
|
||||||
UserId = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
|
|
||||||
column: x => x.UserId,
|
|
||||||
principalTable: "AspNetUsers",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "AspNetUserRoles",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
UserId = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
RoleId = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
|
|
||||||
column: x => x.RoleId,
|
|
||||||
principalTable: "AspNetRoles",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
|
|
||||||
column: x => x.UserId,
|
|
||||||
principalTable: "AspNetUsers",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "AspNetUserTokens",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
UserId = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
LoginProvider = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
|
|
||||||
Name = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
|
|
||||||
Value = table.Column<string>(type: "text", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
|
|
||||||
column: x => x.UserId,
|
|
||||||
principalTable: "AspNetUsers",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_AspNetRoleClaims_RoleId",
|
|
||||||
table: "AspNetRoleClaims",
|
|
||||||
column: "RoleId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "RoleNameIndex",
|
|
||||||
table: "AspNetRoles",
|
|
||||||
column: "NormalizedName",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_AspNetUserClaims_UserId",
|
|
||||||
table: "AspNetUserClaims",
|
|
||||||
column: "UserId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_AspNetUserLogins_UserId",
|
|
||||||
table: "AspNetUserLogins",
|
|
||||||
column: "UserId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_AspNetUserRoles_RoleId",
|
|
||||||
table: "AspNetUserRoles",
|
|
||||||
column: "RoleId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "EmailIndex",
|
|
||||||
table: "AspNetUsers",
|
|
||||||
column: "NormalizedEmail");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "UserNameIndex",
|
|
||||||
table: "AspNetUsers",
|
|
||||||
column: "NormalizedUserName",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "AspNetRoleClaims");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "AspNetUserClaims");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "AspNetUserLogins");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "AspNetUserRoles");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "AspNetUserTokens");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "AspNetRoles");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "AspNetUsers");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,476 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Kemkas.Web.Db;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(ApplicationDbContext))]
|
|
||||||
[Migration("20231216232129_AddV1Character")]
|
|
||||||
partial class AddV1Character
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "8.0.0")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.ApplicationRole", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ConcurrencyStamp")
|
|
||||||
.IsConcurrencyToken()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedName")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("RoleNameIndex");
|
|
||||||
|
|
||||||
b.ToTable("AspNetRoles", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.ApplicationUser", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<int>("AccessFailedCount")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("ConcurrencyStamp")
|
|
||||||
.IsConcurrencyToken()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("EmailConfirmed")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<bool>("LockoutEnabled")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedEmail")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedUserName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<bool>("PhoneNumberConfirmed")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("SecurityStamp")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<bool>("TwoFactorEnabled")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedEmail")
|
|
||||||
.HasDatabaseName("EmailIndex");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedUserName")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("UserNameIndex");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUsers", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Felszereles", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<bool>("IsFegyver")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<Guid>("KarakterId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("KarakterId");
|
|
||||||
|
|
||||||
b.ToTable("Felszerelesek");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Karakter", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<byte>("Bolcsesseg")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte>("Egeszseg")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte>("Ero")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<int>("Faj")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<byte>("Intelligencia")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<bool>("IsPublic")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("Isten")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<byte>("Jellem")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte>("Karizma")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<double?>("Kor")
|
|
||||||
.HasColumnType("double precision");
|
|
||||||
|
|
||||||
b.Property<string>("Nem")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Nev")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("Osztaly")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<int?>("OwnerUserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("Pajzs")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Pancel")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<byte>("Szint")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte>("Ugyesseg")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("OwnerUserId");
|
|
||||||
|
|
||||||
b.ToTable("Karakterek");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1KarakterKepzettseg", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<bool>("IsTolvajKepzettseg")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<Guid>("KarakterId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<int>("Kepzettseg")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("KarakterId");
|
|
||||||
|
|
||||||
b.ToTable("KarakterKepzettsegek");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Szintlepes", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<string>("FegyverSpecializacio")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<byte>("HpRoll")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<Guid>("KarakterId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<byte>("KarakterSzint")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte?>("TulajdonsagNoveles")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("KarakterId");
|
|
||||||
|
|
||||||
b.ToTable("Szintlepesek");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ClaimType")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimValue")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("RoleId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("RoleId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetRoleClaims", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ClaimType")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimValue")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserClaims", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("LoginProvider")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("ProviderKey")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("ProviderDisplayName")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("LoginProvider", "ProviderKey");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserLogins", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<int>("RoleId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("UserId", "RoleId");
|
|
||||||
|
|
||||||
b.HasIndex("RoleId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserRoles", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("LoginProvider")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Value")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.HasKey("UserId", "LoginProvider", "Name");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserTokens", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Felszereles", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.V1Karakter", "Karakter")
|
|
||||||
.WithMany("Felszereles")
|
|
||||||
.HasForeignKey("KarakterId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Karakter");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Karakter", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", "OwnerUser")
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("OwnerUserId");
|
|
||||||
|
|
||||||
b.Navigation("OwnerUser");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1KarakterKepzettseg", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.V1Karakter", "Karakter")
|
|
||||||
.WithMany("KarakterKepzettsegek")
|
|
||||||
.HasForeignKey("KarakterId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Karakter");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Szintlepes", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.V1Karakter", "Karakter")
|
|
||||||
.WithMany("Szintlepesek")
|
|
||||||
.HasForeignKey("KarakterId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Karakter");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationRole", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("RoleId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationRole", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("RoleId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Karakter", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Felszereles");
|
|
||||||
|
|
||||||
b.Navigation("KarakterKepzettsegek");
|
|
||||||
|
|
||||||
b.Navigation("Szintlepesek");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddV1Character : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Karakterek",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
IsPublic = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
OwnerUserId = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
Nev = table.Column<string>(type: "text", nullable: false),
|
|
||||||
Nem = table.Column<string>(type: "text", nullable: true),
|
|
||||||
Kor = table.Column<double>(type: "double precision", nullable: true),
|
|
||||||
Jellem = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
Isten = table.Column<string>(type: "text", nullable: true),
|
|
||||||
Faj = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
Osztaly = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
Ero = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
Ugyesseg = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
Egeszseg = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
Intelligencia = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
Bolcsesseg = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
Karizma = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
Szint = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
Pancel = table.Column<string>(type: "text", nullable: true),
|
|
||||||
Pajzs = table.Column<string>(type: "text", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Karakterek", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Karakterek_AspNetUsers_OwnerUserId",
|
|
||||||
column: x => x.OwnerUserId,
|
|
||||||
principalTable: "AspNetUsers",
|
|
||||||
principalColumn: "Id");
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Felszerelesek",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
KarakterId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
Name = table.Column<string>(type: "text", nullable: false),
|
|
||||||
IsFegyver = table.Column<bool>(type: "boolean", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Felszerelesek", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Felszerelesek_Karakterek_KarakterId",
|
|
||||||
column: x => x.KarakterId,
|
|
||||||
principalTable: "Karakterek",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "KarakterKepzettsegek",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
KarakterId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
Kepzettseg = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
IsTolvajKepzettseg = table.Column<bool>(type: "boolean", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_KarakterKepzettsegek", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_KarakterKepzettsegek_Karakterek_KarakterId",
|
|
||||||
column: x => x.KarakterId,
|
|
||||||
principalTable: "Karakterek",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Szintlepesek",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
KarakterId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
KarakterSzint = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
HpRoll = table.Column<byte>(type: "smallint", nullable: false),
|
|
||||||
TulajdonsagNoveles = table.Column<byte>(type: "smallint", nullable: true),
|
|
||||||
FegyverSpecializacio = table.Column<string>(type: "text", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Szintlepesek", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Szintlepesek_Karakterek_KarakterId",
|
|
||||||
column: x => x.KarakterId,
|
|
||||||
principalTable: "Karakterek",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Felszerelesek_KarakterId",
|
|
||||||
table: "Felszerelesek",
|
|
||||||
column: "KarakterId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Karakterek_OwnerUserId",
|
|
||||||
table: "Karakterek",
|
|
||||||
column: "OwnerUserId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_KarakterKepzettsegek_KarakterId",
|
|
||||||
table: "KarakterKepzettsegek",
|
|
||||||
column: "KarakterId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Szintlepesek_KarakterId",
|
|
||||||
table: "Szintlepesek",
|
|
||||||
column: "KarakterId");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Felszerelesek");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "KarakterKepzettsegek");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Szintlepesek");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Karakterek");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,495 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Kemkas.Web.Db;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Kemkas.Web.Db.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(ApplicationDbContext))]
|
|
||||||
[Migration("20231219150639_AddDataProtectionKeys")]
|
|
||||||
partial class AddDataProtectionKeys
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasAnnotation("ProductVersion", "8.0.0")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.ApplicationRole", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ConcurrencyStamp")
|
|
||||||
.IsConcurrencyToken()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedName")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("RoleNameIndex");
|
|
||||||
|
|
||||||
b.ToTable("AspNetRoles", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.ApplicationUser", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<int>("AccessFailedCount")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("ConcurrencyStamp")
|
|
||||||
.IsConcurrencyToken()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("EmailConfirmed")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<bool>("LockoutEnabled")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedEmail")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<string>("NormalizedUserName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("PhoneNumber")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<bool>("PhoneNumberConfirmed")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("SecurityStamp")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<bool>("TwoFactorEnabled")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("character varying(256)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedEmail")
|
|
||||||
.HasDatabaseName("EmailIndex");
|
|
||||||
|
|
||||||
b.HasIndex("NormalizedUserName")
|
|
||||||
.IsUnique()
|
|
||||||
.HasDatabaseName("UserNameIndex");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUsers", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Felszereles", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<bool>("IsFegyver")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<Guid>("KarakterId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("KarakterId");
|
|
||||||
|
|
||||||
b.ToTable("Felszerelesek");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Karakter", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<byte>("Bolcsesseg")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte>("Egeszseg")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte>("Ero")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<int>("Faj")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<byte>("Intelligencia")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<bool>("IsPublic")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<string>("Isten")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<byte>("Jellem")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte>("Karizma")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<double?>("Kor")
|
|
||||||
.HasColumnType("double precision");
|
|
||||||
|
|
||||||
b.Property<string>("Nem")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Nev")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("Osztaly")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<int?>("OwnerUserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("Pajzs")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Pancel")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<byte>("Szint")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte>("Ugyesseg")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("OwnerUserId");
|
|
||||||
|
|
||||||
b.ToTable("Karakterek");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1KarakterKepzettseg", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<bool>("IsTolvajKepzettseg")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<Guid>("KarakterId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<int>("Kepzettseg")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("KarakterId");
|
|
||||||
|
|
||||||
b.ToTable("KarakterKepzettsegek");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Szintlepes", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<string>("FegyverSpecializacio")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<byte>("HpRoll")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<Guid>("KarakterId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<byte>("KarakterSzint")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.Property<byte?>("TulajdonsagNoveles")
|
|
||||||
.HasColumnType("smallint");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("KarakterId");
|
|
||||||
|
|
||||||
b.ToTable("Szintlepesek");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("FriendlyName")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Xml")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("DataProtectionKeys");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ClaimType")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimValue")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("RoleId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("RoleId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetRoleClaims", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<string>("ClaimType")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("ClaimValue")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserClaims", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("LoginProvider")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("ProviderKey")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("ProviderDisplayName")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("LoginProvider", "ProviderKey");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserLogins", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<int>("RoleId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("UserId", "RoleId");
|
|
||||||
|
|
||||||
b.HasIndex("RoleId");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserRoles", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("UserId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<string>("LoginProvider")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasMaxLength(128)
|
|
||||||
.HasColumnType("character varying(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Value")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.HasKey("UserId", "LoginProvider", "Name");
|
|
||||||
|
|
||||||
b.ToTable("AspNetUserTokens", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Felszereles", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.V1Karakter", "Karakter")
|
|
||||||
.WithMany("Felszereles")
|
|
||||||
.HasForeignKey("KarakterId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Karakter");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Karakter", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", "OwnerUser")
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("OwnerUserId");
|
|
||||||
|
|
||||||
b.Navigation("OwnerUser");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1KarakterKepzettseg", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.V1Karakter", "Karakter")
|
|
||||||
.WithMany("KarakterKepzettsegek")
|
|
||||||
.HasForeignKey("KarakterId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Karakter");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Szintlepes", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.V1Karakter", "Karakter")
|
|
||||||
.WithMany("Szintlepesek")
|
|
||||||
.HasForeignKey("KarakterId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Karakter");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationRole", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("RoleId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationRole", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("RoleId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Kemkas.Web.Db.Models.ApplicationUser", null)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("UserId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kemkas.Web.Db.Models.V1Karakter", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Felszereles");
|
|
||||||
|
|
||||||
b.Navigation("KarakterKepzettsegek");
|
|
||||||
|
|
||||||
b.Navigation("Szintlepesek");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user