From 9a5b467ab0678fbcda9e7df9b04bb209a17edd55 Mon Sep 17 00:00:00 2001 From: Balint Morasz Date: Fri, 27 Oct 2023 12:14:12 +0200 Subject: [PATCH] epic: first try at adding a backend --- .dockerignore | 25 + .github/workflows/ci.yml | 9 +- .gitignore | 5 +- .idea/.idea.Kemkas/.idea/.gitignore | 13 + .idea/.idea.Kemkas/.idea/.name | 1 + .idea/.idea.Kemkas/.idea/encodings.xml | 4 + .idea/.idea.Kemkas/.idea/indexLayout.xml | 8 + .../.idea.Kemkas/.idea/jsLibraryMappings.xml | 6 + .idea/.idea.Kemkas/.idea/vcs.xml | 6 + .../.idea/jsLibraryMappings.xml | 6 + .idea/{kem-web-fe.iml => kemkas.iml} | 0 Kemkas.Web/.gitignore | 235 +++++++++ .../OidcConfigurationController.cs | 26 + .../Controllers/WeatherForecastController.cs | 35 ++ Kemkas.Web/Data/ApplicationDbContext.cs | 15 + ...000000000_CreateIdentitySchema.Designer.cs | 444 ++++++++++++++++++ .../00000000000000_CreateIdentitySchema.cs | 304 ++++++++++++ .../ApplicationDbContextModelSnapshot.cs | 442 +++++++++++++++++ Kemkas.Web/Dockerfile | 27 ++ Kemkas.Web/Kemkas.Web.csproj | 66 +++ Kemkas.Web/Models/ApplicationUser.cs | 7 + Kemkas.Web/Models/WeatherForecast.cs | 12 + Kemkas.Web/Pages/Error.cshtml | 26 + Kemkas.Web/Pages/Error.cshtml.cs | 25 + Kemkas.Web/Pages/Shared/_LoginPartial.cshtml | 36 ++ Kemkas.Web/Pages/_ViewImports.cshtml | 3 + Kemkas.Web/Program.cs | 58 +++ Kemkas.Web/Properties/launchSettings.json | 29 ++ Kemkas.Web/appsettings.Development.json | 15 + Kemkas.Web/appsettings.json | 20 + .../frontend}/.dockerignore | 0 Kemkas.Web/frontend/.env | 1 + Kemkas.Web/frontend/.env.development | 3 + {frontend => Kemkas.Web/frontend}/Dockerfile | 0 {frontend => Kemkas.Web/frontend}/README.md | 0 Kemkas.Web/frontend/aspnetcore-https.js | 33 ++ Kemkas.Web/frontend/aspnetcore-react.js | 55 +++ .../frontend}/compile-less.sh | 0 .../frontend}/package.json | 39 +- .../frontend}/public/Merienda-Bold.ttf | Bin .../frontend}/public/Merienda-Regular.ttf | Bin .../frontend}/public/favicon.ico | Bin .../frontend}/public/index.html | 0 .../public/km_karakterlap_hysteria_1.2.pdf | Bin .../frontend}/public/logo-original.png | Bin .../frontend}/public/logo192.png | Bin .../frontend}/public/logo512.png | Bin .../frontend}/public/manifest.json | 0 .../frontend}/public/ogl.html | 0 .../frontend}/public/robots.txt | 0 {frontend => Kemkas.Web/frontend}/src/App.css | 0 .../frontend}/src/App.test.tsx | 0 {frontend => Kemkas.Web/frontend}/src/App.tsx | 0 .../components/BasicNewLevel.tsx | 0 .../first-edition/components/FajSelector.tsx | 0 .../first-edition/components/Felszereles.tsx | 0 .../components/HarcosFegyverSpecializacio.tsx | 0 .../src/first-edition/components/Helpers.tsx | 0 .../components/JellemSelector.tsx | 0 .../components/KalozKritikus.tsx | 0 .../components/KarakterKepzettsegek.tsx | 0 .../components/KepzettsegSelector.tsx | 0 .../src/first-edition/components/LevelUps.tsx | 0 .../components/MasodlagosErtekek.tsx | 0 .../components/OsztalySelector.tsx | 0 .../components/TulajdonsagInput.tsx | 0 .../components/TulajdonsagNoveles.tsx | 0 .../components/Tulajdonsagok.tsx | 0 .../domain-models/allowed-fegyver.ts | 0 .../domain-models/allowed-pancel-types.ts | 0 .../src/first-edition/domain-models/faj.ts | 0 .../first-edition/domain-models/fegyver.json | 0 .../domain-models/felszereles.json | 0 .../domain-models/felszereles.ts | 0 .../src/first-edition/domain-models/jellem.ts | 0 .../first-edition/domain-models/karakter.ts | 0 .../domain-models/kepzettsegek.ts | 0 .../src/first-edition/domain-models/kockak.ts | 0 .../src/first-edition/domain-models/level.ts | 0 .../domain-models/masodlagos_ertekek.ts | 0 .../memorizalt_varazslat_tabla.json | 0 .../domain-models/memorizalt_varazslatok.ts | 0 .../src/first-edition/domain-models/mentok.ts | 0 .../first-edition/domain-models/osztaly.ts | 0 .../first-edition/domain-models/pajzs.json | 0 .../first-edition/domain-models/pancel.json | 0 .../domain-models/tamadas_bonus_tabla.json | 0 .../domain-models/tamadas_bonusz.test.ts | 0 .../domain-models/tamadas_bonusz.ts | 0 .../domain-models/tulajdonsag.ts | 0 .../src/first-edition/pages/.gitignore | 0 .../first-edition/pages/CreateCharacter.less | 0 .../first-edition/pages/CreateCharacter.tsx | 0 .../src/first-edition/pdf/character.pdf.ts | 0 .../src/first-edition/pdf/fegyverek.pdf.ts | 0 .../first-edition/pdf/karakter_pdf_view.ts | 0 .../src/first-edition/pdf/magic.pdf.ts | 0 .../pdf/masodlagos_ertekek.pdf.ts | 0 .../src/first-edition/pdf/mentok.pdf.ts | 0 .../src/first-edition/pdf/osztaly_skills.ts | 0 .../first-edition/pdf/osztaly_specials.pdf.ts | 0 .../first-edition/pdf/tulajdonsagok.pdf.ts | 0 .../frontend}/src/index.css | 0 .../frontend}/src/index.tsx | 0 .../frontend}/src/react-app-env.d.ts | 0 .../frontend}/src/reportWebVitals.ts | 0 Kemkas.Web/frontend/src/setupProxy.js | 36 ++ Kemkas.Web/frontend/src/setupTests.ts | 31 ++ {frontend => Kemkas.Web/frontend}/src/util.ts | 0 .../frontend}/tsconfig.json | 0 {frontend => Kemkas.Web/frontend}/yarn.lock | 73 ++- Kemkas.sln | 16 + Kemkas.sln.DotSettings | 2 + frontend/src/setupTests.ts | 5 - 114 files changed, 2167 insertions(+), 35 deletions(-) create mode 100644 .dockerignore create mode 100644 .idea/.idea.Kemkas/.idea/.gitignore create mode 100644 .idea/.idea.Kemkas/.idea/.name create mode 100644 .idea/.idea.Kemkas/.idea/encodings.xml create mode 100644 .idea/.idea.Kemkas/.idea/indexLayout.xml create mode 100644 .idea/.idea.Kemkas/.idea/jsLibraryMappings.xml create mode 100644 .idea/.idea.Kemkas/.idea/vcs.xml create mode 100644 .idea/.idea.kemkas.dir/.idea/jsLibraryMappings.xml rename .idea/{kem-web-fe.iml => kemkas.iml} (100%) create mode 100644 Kemkas.Web/.gitignore create mode 100644 Kemkas.Web/Controllers/OidcConfigurationController.cs create mode 100644 Kemkas.Web/Controllers/WeatherForecastController.cs create mode 100644 Kemkas.Web/Data/ApplicationDbContext.cs create mode 100644 Kemkas.Web/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs create mode 100644 Kemkas.Web/Data/Migrations/00000000000000_CreateIdentitySchema.cs create mode 100644 Kemkas.Web/Data/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 Kemkas.Web/Dockerfile create mode 100644 Kemkas.Web/Kemkas.Web.csproj create mode 100644 Kemkas.Web/Models/ApplicationUser.cs create mode 100644 Kemkas.Web/Models/WeatherForecast.cs create mode 100644 Kemkas.Web/Pages/Error.cshtml create mode 100644 Kemkas.Web/Pages/Error.cshtml.cs create mode 100644 Kemkas.Web/Pages/Shared/_LoginPartial.cshtml create mode 100644 Kemkas.Web/Pages/_ViewImports.cshtml create mode 100644 Kemkas.Web/Program.cs create mode 100644 Kemkas.Web/Properties/launchSettings.json create mode 100644 Kemkas.Web/appsettings.Development.json create mode 100644 Kemkas.Web/appsettings.json rename {frontend => Kemkas.Web/frontend}/.dockerignore (100%) create mode 100644 Kemkas.Web/frontend/.env create mode 100644 Kemkas.Web/frontend/.env.development rename {frontend => Kemkas.Web/frontend}/Dockerfile (100%) rename {frontend => Kemkas.Web/frontend}/README.md (100%) create mode 100644 Kemkas.Web/frontend/aspnetcore-https.js create mode 100644 Kemkas.Web/frontend/aspnetcore-react.js rename {frontend => Kemkas.Web/frontend}/compile-less.sh (100%) rename {frontend => Kemkas.Web/frontend}/package.json (59%) rename {frontend => Kemkas.Web/frontend}/public/Merienda-Bold.ttf (100%) rename {frontend => Kemkas.Web/frontend}/public/Merienda-Regular.ttf (100%) rename {frontend => Kemkas.Web/frontend}/public/favicon.ico (100%) rename {frontend => Kemkas.Web/frontend}/public/index.html (100%) rename {frontend => Kemkas.Web/frontend}/public/km_karakterlap_hysteria_1.2.pdf (100%) rename {frontend => Kemkas.Web/frontend}/public/logo-original.png (100%) rename {frontend => Kemkas.Web/frontend}/public/logo192.png (100%) rename {frontend => Kemkas.Web/frontend}/public/logo512.png (100%) rename {frontend => Kemkas.Web/frontend}/public/manifest.json (100%) rename {frontend => Kemkas.Web/frontend}/public/ogl.html (100%) rename {frontend => Kemkas.Web/frontend}/public/robots.txt (100%) rename {frontend => Kemkas.Web/frontend}/src/App.css (100%) rename {frontend => Kemkas.Web/frontend}/src/App.test.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/App.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/BasicNewLevel.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/FajSelector.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/Felszereles.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/HarcosFegyverSpecializacio.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/Helpers.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/JellemSelector.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/KalozKritikus.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/KarakterKepzettsegek.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/KepzettsegSelector.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/LevelUps.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/MasodlagosErtekek.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/OsztalySelector.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/TulajdonsagInput.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/TulajdonsagNoveles.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/components/Tulajdonsagok.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/allowed-fegyver.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/allowed-pancel-types.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/faj.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/fegyver.json (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/felszereles.json (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/felszereles.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/jellem.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/karakter.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/kepzettsegek.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/kockak.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/level.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/masodlagos_ertekek.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/memorizalt_varazslat_tabla.json (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/memorizalt_varazslatok.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/mentok.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/osztaly.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/pajzs.json (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/pancel.json (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/tamadas_bonus_tabla.json (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/tamadas_bonusz.test.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/tamadas_bonusz.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/domain-models/tulajdonsag.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pages/.gitignore (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pages/CreateCharacter.less (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pages/CreateCharacter.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pdf/character.pdf.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pdf/fegyverek.pdf.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pdf/karakter_pdf_view.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pdf/magic.pdf.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pdf/masodlagos_ertekek.pdf.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pdf/mentok.pdf.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pdf/osztaly_skills.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pdf/osztaly_specials.pdf.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/first-edition/pdf/tulajdonsagok.pdf.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/index.css (100%) rename {frontend => Kemkas.Web/frontend}/src/index.tsx (100%) rename {frontend => Kemkas.Web/frontend}/src/react-app-env.d.ts (100%) rename {frontend => Kemkas.Web/frontend}/src/reportWebVitals.ts (100%) create mode 100644 Kemkas.Web/frontend/src/setupProxy.js create mode 100644 Kemkas.Web/frontend/src/setupTests.ts rename {frontend => Kemkas.Web/frontend}/src/util.ts (100%) rename {frontend => Kemkas.Web/frontend}/tsconfig.json (100%) rename {frontend => Kemkas.Web/frontend}/yarn.lock (99%) create mode 100644 Kemkas.sln create mode 100644 Kemkas.sln.DotSettings delete mode 100644 frontend/src/setupTests.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cd967fc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54db7f6..00dcd56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,17 +22,17 @@ jobs: with: key: npm-${{ hashFiles('./frontend/yarn.lock') }} path: | - ./frontend/node_modules + ./Kemkas.Web/frontend/node_modules restore-keys: | npm-${{ hashFiles('./frontend/yarn.lock') }} npm- - name: Yarn Install run: | - cd ./frontend + cd ./Kemkas.Web/frontend yarn install --frozen-lockfiles - name: Yarn Test run: | - cd ./frontend + cd ./Kemkas.Web/frontend ./compile-less.sh yarn test yarn build @@ -51,7 +51,8 @@ jobs: run: doctl registry login --expiry-seconds 1200 - uses: docker/build-push-action@v5 with: - context: frontend/ + context: . + file: Kemkas.Web/Dockerfile cache-from: type=gha cache-to: type=gha,mode=max push: false diff --git a/.gitignore b/.gitignore index d80e700..476d627 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,7 @@ yarn-error.log* # local temp files /tmp /temp -/local \ No newline at end of file +/local + +obj/ +bin/ \ No newline at end of file diff --git a/.idea/.idea.Kemkas/.idea/.gitignore b/.idea/.idea.Kemkas/.idea/.gitignore new file mode 100644 index 0000000..e562b88 --- /dev/null +++ b/.idea/.idea.Kemkas/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/projectSettingsUpdater.xml +/modules.xml +/contentModel.xml +/.idea.Kemkas.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.Kemkas/.idea/.name b/.idea/.idea.Kemkas/.idea/.name new file mode 100644 index 0000000..a3fd214 --- /dev/null +++ b/.idea/.idea.Kemkas/.idea/.name @@ -0,0 +1 @@ +Kemkas \ No newline at end of file diff --git a/.idea/.idea.Kemkas/.idea/encodings.xml b/.idea/.idea.Kemkas/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.Kemkas/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.Kemkas/.idea/indexLayout.xml b/.idea/.idea.Kemkas/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.Kemkas/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Kemkas/.idea/jsLibraryMappings.xml b/.idea/.idea.Kemkas/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..d23208f --- /dev/null +++ b/.idea/.idea.Kemkas/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/.idea.Kemkas/.idea/vcs.xml b/.idea/.idea.Kemkas/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.Kemkas/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/.idea.kemkas.dir/.idea/jsLibraryMappings.xml b/.idea/.idea.kemkas.dir/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..d23208f --- /dev/null +++ b/.idea/.idea.kemkas.dir/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/kem-web-fe.iml b/.idea/kemkas.iml similarity index 100% rename from .idea/kem-web-fe.iml rename to .idea/kemkas.iml diff --git a/Kemkas.Web/.gitignore b/Kemkas.Web/.gitignore new file mode 100644 index 0000000..990dc5b --- /dev/null +++ b/Kemkas.Web/.gitignore @@ -0,0 +1,235 @@ +## 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 diff --git a/Kemkas.Web/Controllers/OidcConfigurationController.cs b/Kemkas.Web/Controllers/OidcConfigurationController.cs new file mode 100644 index 0000000..9fc5fe7 --- /dev/null +++ b/Kemkas.Web/Controllers/OidcConfigurationController.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.ApiAuthorization.IdentityServer; +using Microsoft.AspNetCore.Mvc; + +namespace Kemkas.Web.Controllers; + +public class OidcConfigurationController : Controller +{ + private readonly ILogger _logger; + + public OidcConfigurationController( + IClientRequestParametersProvider clientRequestParametersProvider, + ILogger logger) + { + ClientRequestParametersProvider = clientRequestParametersProvider; + _logger = logger; + } + + public IClientRequestParametersProvider ClientRequestParametersProvider { get; } + + [HttpGet("_configuration/{clientId}")] + public IActionResult GetClientRequestParameters([FromRoute] string clientId) + { + var parameters = ClientRequestParametersProvider.GetClientParameters(HttpContext, clientId); + return Ok(parameters); + } +} diff --git a/Kemkas.Web/Controllers/WeatherForecastController.cs b/Kemkas.Web/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..1c9d2d3 --- /dev/null +++ b/Kemkas.Web/Controllers/WeatherForecastController.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Kemkas.Web.Controllers; + +// [Authorize] +[ApiController] +[Route("[controller]")] +public class WeatherForecastController : ControllerBase +{ + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select( + index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } +} diff --git a/Kemkas.Web/Data/ApplicationDbContext.cs b/Kemkas.Web/Data/ApplicationDbContext.cs new file mode 100644 index 0000000..1f0833b --- /dev/null +++ b/Kemkas.Web/Data/ApplicationDbContext.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.ApiAuthorization.IdentityServer; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; +using Duende.IdentityServer.EntityFramework.Options; +using Kemkas.Web.Models; + +namespace Kemkas.Web.Data; + +public class ApplicationDbContext : ApiAuthorizationDbContext +{ + public ApplicationDbContext(DbContextOptions options, IOptions operationalStoreOptions) + : base(options, operationalStoreOptions) + { + } +} diff --git a/Kemkas.Web/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs b/Kemkas.Web/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs new file mode 100644 index 0000000..cc245af --- /dev/null +++ b/Kemkas.Web/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs @@ -0,0 +1,444 @@ +// + +using System; +using Kemkas.Web.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Kemkas.Web.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("00000000000000_CreateIdentitySchema")] + partial class CreateIdentitySchema + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "5.0.0-rc.1.20417.2"); + + modelBuilder.Entity( + "Kemkas.Web.Models.ApplicationUser", + b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity( + "Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", + b => + { + b.Property("UserCode") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(51740) + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("DeviceCode") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Expiration") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.HasKey("UserCode"); + + b.HasIndex("DeviceCode") + .IsUnique(); + + b.HasIndex("Expiration"); + + b.ToTable("DeviceCodes"); + }); + + modelBuilder.Entity( + "Duende.IdentityServer.EntityFramework.Entities.Key", + b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Algorithm") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(51740) + .HasColumnType("TEXT"); + + b.Property("DataProtected") + .HasColumnType("INTEGER"); + + b.Property("IsX509Certificate") + .HasColumnType("INTEGER"); + + b.Property("Use") + .HasMaxLength(450) + .HasColumnType("TEXT"); + + b.Property("Version") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Use"); + + b.ToTable("Keys"); + }); + + modelBuilder.Entity( + "Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", + b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ConsumedTime") + .HasColumnType("TEXT"); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(51740) + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Expiration") + .HasColumnType("TEXT"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Key"); + + b.HasIndex("ConsumedTime"); + + b.HasIndex("Expiration"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.HasIndex("SubjectId", "SessionId", "Type"); + + b.ToTable("PersistedGrants"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityRole", + b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityRoleClaim", + b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserClaim", + b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserLogin", + b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserRole", + b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserToken", + b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityRoleClaim", + b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserClaim", + b => + { + b.HasOne("Kemkas.Web.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserLogin", + b => + { + b.HasOne("Kemkas.Web.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserRole", + b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Kemkas.Web.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserToken", + b => + { + b.HasOne("Kemkas.Web.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Kemkas.Web/Data/Migrations/00000000000000_CreateIdentitySchema.cs b/Kemkas.Web/Data/Migrations/00000000000000_CreateIdentitySchema.cs new file mode 100644 index 0000000..0d75083 --- /dev/null +++ b/Kemkas.Web/Data/Migrations/00000000000000_CreateIdentitySchema.cs @@ -0,0 +1,304 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Kemkas.Web.Data.Migrations +{ + public partial class CreateIdentitySchema : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => { table.PrimaryKey("PK_AspNetRoles", x => x.Id); }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + UserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + Email = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "TEXT", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "INTEGER", nullable: false), + PasswordHash = table.Column(type: "TEXT", nullable: true), + SecurityStamp = table.Column(type: "TEXT", nullable: true), + ConcurrencyStamp = table.Column(type: "TEXT", nullable: true), + PhoneNumber = table.Column(type: "TEXT", nullable: true), + PhoneNumberConfirmed = table.Column(type: "INTEGER", nullable: false), + TwoFactorEnabled = table.Column(type: "INTEGER", nullable: false), + LockoutEnd = table.Column(type: "TEXT", nullable: true), + LockoutEnabled = table.Column(type: "INTEGER", nullable: false), + AccessFailedCount = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => { table.PrimaryKey("PK_AspNetUsers", x => x.Id); }); + + migrationBuilder.CreateTable( + name: "DeviceCodes", + columns: table => new + { + UserCode = table.Column(type: "TEXT", maxLength: 200, nullable: false), + DeviceCode = table.Column(type: "TEXT", maxLength: 200, nullable: false), + SubjectId = table.Column(type: "TEXT", maxLength: 200, nullable: true), + SessionId = table.Column(type: "TEXT", maxLength: 100, nullable: true), + ClientId = table.Column(type: "TEXT", maxLength: 200, nullable: false), + Description = table.Column(type: "TEXT", maxLength: 200, nullable: true), + CreationTime = table.Column(type: "TEXT", nullable: false), + Expiration = table.Column(type: "TEXT", nullable: false), + Data = table.Column(type: "TEXT", maxLength: 51740, nullable: false) + }, + constraints: table => { table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); }); + + migrationBuilder.CreateTable( + name: "Keys", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Version = table.Column(type: "INTEGER", nullable: false), + Created = table.Column(type: "TEXT", nullable: false), + Use = table.Column(type: "TEXT", maxLength: 450, nullable: true), + Algorithm = table.Column(type: "TEXT", maxLength: 100, nullable: false), + IsX509Certificate = table.Column(type: "INTEGER", nullable: false), + DataProtected = table.Column(type: "INTEGER", nullable: false), + Data = table.Column(type: "TEXT", maxLength: 51740, nullable: false) + }, + constraints: table => { table.PrimaryKey("PK_Keys", x => x.Id); }); + + migrationBuilder.CreateTable( + name: "PersistedGrants", + columns: table => new + { + Key = table.Column(type: "TEXT", maxLength: 200, nullable: false), + Type = table.Column(type: "TEXT", maxLength: 50, nullable: false), + SubjectId = table.Column(type: "TEXT", maxLength: 200, nullable: true), + SessionId = table.Column(type: "TEXT", maxLength: 100, nullable: true), + ClientId = table.Column(type: "TEXT", maxLength: 200, nullable: false), + Description = table.Column(type: "TEXT", maxLength: 200, nullable: true), + CreationTime = table.Column(type: "TEXT", nullable: false), + Expiration = table.Column(type: "TEXT", nullable: true), + ConsumedTime = table.Column(type: "TEXT", nullable: true), + Data = table.Column(type: "TEXT", maxLength: 51740, nullable: false) + }, + constraints: table => { table.PrimaryKey("PK_PersistedGrants", x => x.Key); }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RoleId = table.Column(type: "TEXT", nullable: false), + ClaimType = table.Column(type: "TEXT", nullable: true), + ClaimValue = table.Column(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(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(type: "TEXT", nullable: false), + ClaimType = table.Column(type: "TEXT", nullable: true), + ClaimValue = table.Column(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(type: "TEXT", maxLength: 128, nullable: false), + ProviderKey = table.Column(type: "TEXT", maxLength: 128, nullable: false), + ProviderDisplayName = table.Column(type: "TEXT", nullable: true), + UserId = table.Column(type: "TEXT", 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(type: "TEXT", nullable: false), + RoleId = table.Column(type: "TEXT", 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(type: "TEXT", nullable: false), + LoginProvider = table.Column(type: "TEXT", maxLength: 128, nullable: false), + Name = table.Column(type: "TEXT", maxLength: 128, nullable: false), + Value = table.Column(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); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_DeviceCode", + table: "DeviceCodes", + column: "DeviceCode", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_Expiration", + table: "DeviceCodes", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_Keys_Use", + table: "Keys", + column: "Use"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_ConsumedTime", + table: "PersistedGrants", + column: "ConsumedTime"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_Expiration", + table: "PersistedGrants", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_SubjectId_ClientId_Type", + table: "PersistedGrants", + columns: new[] { "SubjectId", "ClientId", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_SubjectId_SessionId_Type", + table: "PersistedGrants", + columns: new[] { "SubjectId", "SessionId", "Type" }); + } + + 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: "DeviceCodes"); + + migrationBuilder.DropTable( + name: "Keys"); + + migrationBuilder.DropTable( + name: "PersistedGrants"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/Kemkas.Web/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/Kemkas.Web/Data/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..377cdd3 --- /dev/null +++ b/Kemkas.Web/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,442 @@ +// + +using System; +using Kemkas.Web.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Kemkas.Web.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "5.0.0-rc.1.20417.2"); + + modelBuilder.Entity( + "Kemkas.Web.Models.ApplicationUser", + b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity( + "Duende.IdentityServer.EntityFramework.Entities.DeviceFlowCodes", + b => + { + b.Property("UserCode") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(51740) + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("DeviceCode") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Expiration") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.HasKey("UserCode"); + + b.HasIndex("DeviceCode") + .IsUnique(); + + b.HasIndex("Expiration"); + + b.ToTable("DeviceCodes"); + }); + + modelBuilder.Entity( + "Duende.IdentityServer.EntityFramework.Entities.Key", + b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Algorithm") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(51740) + .HasColumnType("TEXT"); + + b.Property("DataProtected") + .HasColumnType("INTEGER"); + + b.Property("IsX509Certificate") + .HasColumnType("INTEGER"); + + b.Property("Use") + .HasMaxLength(450) + .HasColumnType("TEXT"); + + b.Property("Version") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Use"); + + b.ToTable("Keys"); + }); + + modelBuilder.Entity( + "Duende.IdentityServer.EntityFramework.Entities.PersistedGrant", + b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ConsumedTime") + .HasColumnType("TEXT"); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(51740) + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Expiration") + .HasColumnType("TEXT"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Key"); + + b.HasIndex("ConsumedTime"); + + b.HasIndex("Expiration"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.HasIndex("SubjectId", "SessionId", "Type"); + + b.ToTable("PersistedGrants"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityRole", + b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityRoleClaim", + b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserClaim", + b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserLogin", + b => + { + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserRole", + b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserToken", + b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityRoleClaim", + b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserClaim", + b => + { + b.HasOne("Kemkas.Web.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserLogin", + b => + { + b.HasOne("Kemkas.Web.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserRole", + b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Kemkas.Web.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity( + "Microsoft.AspNetCore.Identity.IdentityUserToken", + b => + { + b.HasOne("Kemkas.Web.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Kemkas.Web/Dockerfile b/Kemkas.Web/Dockerfile new file mode 100644 index 0000000..70f4dcd --- /dev/null +++ b/Kemkas.Web/Dockerfile @@ -0,0 +1,27 @@ +FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build + +# Install Node.js +RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \ + && apt-get install -y nodejs \ + && npm install --global yarn \ + && rm -rf /var/lib/apt/lists/* + +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"] diff --git a/Kemkas.Web/Kemkas.Web.csproj b/Kemkas.Web/Kemkas.Web.csproj new file mode 100644 index 0000000..b5c2330 --- /dev/null +++ b/Kemkas.Web/Kemkas.Web.csproj @@ -0,0 +1,66 @@ + + + + net7.0 + enable + true + Latest + false + frontend\ + $(DefaultItemExcludes);$(SpaRoot)node_modules\** + https://localhost:44478 + yarn start + enable + Linux + + + + + + + + + + + + + + + + + + + + + .dockerignore + + + + + + + + + + + + + + + + + + + + + + + + + wwwroot\%(RecursiveDir)%(FileName)%(Extension) + PreserveNewest + true + + + + diff --git a/Kemkas.Web/Models/ApplicationUser.cs b/Kemkas.Web/Models/ApplicationUser.cs new file mode 100644 index 0000000..22197c0 --- /dev/null +++ b/Kemkas.Web/Models/ApplicationUser.cs @@ -0,0 +1,7 @@ +using Microsoft.AspNetCore.Identity; + +namespace Kemkas.Web.Models; + +public class ApplicationUser : IdentityUser +{ +} diff --git a/Kemkas.Web/Models/WeatherForecast.cs b/Kemkas.Web/Models/WeatherForecast.cs new file mode 100644 index 0000000..e28e0b2 --- /dev/null +++ b/Kemkas.Web/Models/WeatherForecast.cs @@ -0,0 +1,12 @@ +namespace Kemkas.Web; + +public class WeatherForecast +{ + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } +} diff --git a/Kemkas.Web/Pages/Error.cshtml b/Kemkas.Web/Pages/Error.cshtml new file mode 100644 index 0000000..6f92b95 --- /dev/null +++ b/Kemkas.Web/Pages/Error.cshtml @@ -0,0 +1,26 @@ +@page +@model ErrorModel +@{ + ViewData["Title"] = "Error"; +} + +

Error.

+

An error occurred while processing your request.

+ +@if (Model.ShowRequestId) +{ +

+ Request ID: @Model.RequestId +

+} + +

Development Mode

+

+ Swapping to the Development environment displays detailed information about the error that occurred. +

+

+ The Development environment shouldn't be enabled for deployed applications. + It can result in displaying sensitive information from exceptions to end users. + For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development + and restarting the app. +

diff --git a/Kemkas.Web/Pages/Error.cshtml.cs b/Kemkas.Web/Pages/Error.cshtml.cs new file mode 100644 index 0000000..59a5744 --- /dev/null +++ b/Kemkas.Web/Pages/Error.cshtml.cs @@ -0,0 +1,25 @@ +using System.Diagnostics; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace Kemkas.Web.Pages; + +[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] +public class ErrorModel : PageModel +{ + private readonly ILogger _logger; + + public ErrorModel(ILogger logger) + { + _logger = logger; + } + + public string? RequestId { get; set; } + + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + + public void OnGet() + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; + } +} diff --git a/Kemkas.Web/Pages/Shared/_LoginPartial.cshtml b/Kemkas.Web/Pages/Shared/_LoginPartial.cshtml new file mode 100644 index 0000000..2eb2b83 --- /dev/null +++ b/Kemkas.Web/Pages/Shared/_LoginPartial.cshtml @@ -0,0 +1,36 @@ +@using Microsoft.AspNetCore.Identity +@using Kemkas.Web.Models; +@inject SignInManager SignInManager +@inject UserManager UserManager + +@{ + string? returnUrl = null; + var query = ViewContext.HttpContext.Request.Query; + if (query.ContainsKey("returnUrl")) + { + returnUrl = query["returnUrl"]; + } +} + + diff --git a/Kemkas.Web/Pages/_ViewImports.cshtml b/Kemkas.Web/Pages/_ViewImports.cshtml new file mode 100644 index 0000000..d7e60bd --- /dev/null +++ b/Kemkas.Web/Pages/_ViewImports.cshtml @@ -0,0 +1,3 @@ +@using Kemkas.Web +@namespace Kemkas.Web.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/Kemkas.Web/Program.cs b/Kemkas.Web/Program.cs new file mode 100644 index 0000000..ddefefa --- /dev/null +++ b/Kemkas.Web/Program.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.UI; +using Microsoft.EntityFrameworkCore; +using Kemkas.Web.Data; +using Kemkas.Web.Models; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? + throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); +builder.Services.AddDbContext( + options => + options.UseSqlite(connectionString)); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); + +builder.Services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) + .AddEntityFrameworkStores(); + +builder.Services.AddIdentityServer() + .AddApiAuthorization(); + +// builder.Services.AddAuthentication() +// .AddIdentityServerJwt(); + +builder.Services.AddControllersWithViews(); +builder.Services.AddRazorPages(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseMigrationsEndPoint(); +} +else +{ + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); +} + +// app.UseHttpsRedirection(); // reverse proxy should take care of that +app.UseStaticFiles(); +app.UseRouting(); + +// app.UseAuthentication(); +// app.UseIdentityServer(); +// app.UseAuthorization(); + +app.MapControllerRoute( + name: "default", + pattern: "{controller}/{action=Index}/{id?}"); +app.MapRazorPages(); + +app.MapFallbackToFile("index.html"); + +app.Run(); diff --git a/Kemkas.Web/Properties/launchSettings.json b/Kemkas.Web/Properties/launchSettings.json new file mode 100644 index 0000000..b302da6 --- /dev/null +++ b/Kemkas.Web/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:40870", + "sslPort": 44348 + } + }, + "profiles": { + "Kemkas.Web": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:7251;http://localhost:5174", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" + } + } + } +} diff --git a/Kemkas.Web/appsettings.Development.json b/Kemkas.Web/appsettings.Development.json new file mode 100644 index 0000000..20847b8 --- /dev/null +++ b/Kemkas.Web/appsettings.Development.json @@ -0,0 +1,15 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.AspNetCore.SpaProxy": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "IdentityServer": { + "Key": { + "Type": "Development" + } + } +} diff --git a/Kemkas.Web/appsettings.json b/Kemkas.Web/appsettings.json new file mode 100644 index 0000000..11dca72 --- /dev/null +++ b/Kemkas.Web/appsettings.json @@ -0,0 +1,20 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "DataSource=app.db;Cache=Shared" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "IdentityServer": { + "Clients": { + "Kemkas.Web": { + "Profile": "IdentityServerSPA" + } + } + }, +"AllowedHosts": "*" +} diff --git a/frontend/.dockerignore b/Kemkas.Web/frontend/.dockerignore similarity index 100% rename from frontend/.dockerignore rename to Kemkas.Web/frontend/.dockerignore diff --git a/Kemkas.Web/frontend/.env b/Kemkas.Web/frontend/.env new file mode 100644 index 0000000..6ce384e --- /dev/null +++ b/Kemkas.Web/frontend/.env @@ -0,0 +1 @@ +BROWSER=none diff --git a/Kemkas.Web/frontend/.env.development b/Kemkas.Web/frontend/.env.development new file mode 100644 index 0000000..60ad7c8 --- /dev/null +++ b/Kemkas.Web/frontend/.env.development @@ -0,0 +1,3 @@ +PORT=44478 +HTTPS=true + diff --git a/frontend/Dockerfile b/Kemkas.Web/frontend/Dockerfile similarity index 100% rename from frontend/Dockerfile rename to Kemkas.Web/frontend/Dockerfile diff --git a/frontend/README.md b/Kemkas.Web/frontend/README.md similarity index 100% rename from frontend/README.md rename to Kemkas.Web/frontend/README.md diff --git a/Kemkas.Web/frontend/aspnetcore-https.js b/Kemkas.Web/frontend/aspnetcore-https.js new file mode 100644 index 0000000..2bde928 --- /dev/null +++ b/Kemkas.Web/frontend/aspnetcore-https.js @@ -0,0 +1,33 @@ +// This script sets up HTTPS for the application using the ASP.NET Core HTTPS certificate +const fs = require('fs'); +const spawn = require('child_process').spawn; +const path = require('path'); + +const baseFolder = + process.env.APPDATA !== undefined && process.env.APPDATA !== '' + ? `${process.env.APPDATA}/ASP.NET/https` + : `${process.env.HOME}/.aspnet/https`; + +const certificateArg = process.argv.map(arg => arg.match(/--name=(?.+)/i)).filter(Boolean)[0]; +const certificateName = certificateArg ? certificateArg.groups.value : process.env.npm_package_name; + +if (!certificateName) { + console.error('Invalid certificate name. Run this script in the context of an npm/yarn script or pass --name=<> explicitly.') + process.exit(-1); +} + +const certFilePath = path.join(baseFolder, `${certificateName}.pem`); +const keyFilePath = path.join(baseFolder, `${certificateName}.key`); + +if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) { + spawn('dotnet', [ + 'dev-certs', + 'https', + '--export-path', + certFilePath, + '--format', + 'Pem', + '--no-password', + ], { stdio: 'inherit', }) + .on('exit', (code) => process.exit(code)); +} diff --git a/Kemkas.Web/frontend/aspnetcore-react.js b/Kemkas.Web/frontend/aspnetcore-react.js new file mode 100644 index 0000000..3b28895 --- /dev/null +++ b/Kemkas.Web/frontend/aspnetcore-react.js @@ -0,0 +1,55 @@ +// This script configures the .env.development.local file with additional environment variables to configure HTTPS using the ASP.NET Core +// development certificate in the webpack development proxy. + +const fs = require('fs'); +const path = require('path'); + +const baseFolder = + process.env.APPDATA !== undefined && process.env.APPDATA !== '' + ? `${process.env.APPDATA}/ASP.NET/https` + : `${process.env.HOME}/.aspnet/https`; + +const certificateArg = process.argv.map(arg => arg.match(/--name=(?.+)/i)).filter(Boolean)[0]; +const certificateName = certificateArg ? certificateArg.groups.value : process.env.npm_package_name; + +if (!certificateName) { + console.error('Invalid certificate name. Run this script in the context of an npm/yarn script or pass --name=<> explicitly.') + process.exit(-1); +} + +const certFilePath = path.join(baseFolder, `${certificateName}.pem`); +const keyFilePath = path.join(baseFolder, `${certificateName}.key`); + +if (!fs.existsSync('.env.development.local')) { + fs.writeFileSync( + '.env.development.local', +`SSL_CRT_FILE=${certFilePath} +SSL_KEY_FILE=${keyFilePath}` + ); +} else { + let lines = fs.readFileSync('.env.development.local') + .toString() + .split('\n'); + + let hasCert, hasCertKey = false; + for (const line of lines) { + if (/SSL_CRT_FILE=.*/i.test(line)) { + hasCert = true; + } + if (/SSL_KEY_FILE=.*/i.test(line)) { + hasCertKey = true; + } + } + if (!hasCert) { + fs.appendFileSync( + '.env.development.local', + `\nSSL_CRT_FILE=${certFilePath}` + ); + } + if (!hasCertKey) { + fs.appendFileSync( + '.env.development.local', + `\nSSL_KEY_FILE=${keyFilePath}` + ); + } +} diff --git a/frontend/compile-less.sh b/Kemkas.Web/frontend/compile-less.sh similarity index 100% rename from frontend/compile-less.sh rename to Kemkas.Web/frontend/compile-less.sh diff --git a/frontend/package.json b/Kemkas.Web/frontend/package.json similarity index 59% rename from frontend/package.json rename to Kemkas.Web/frontend/package.json index 237efbc..b2010ed 100644 --- a/frontend/package.json +++ b/Kemkas.Web/frontend/package.json @@ -1,5 +1,5 @@ { - "name": "kem-web-fe", + "name": "kemkas", "version": "0.1.0", "private": true, "dependencies": { @@ -15,18 +15,43 @@ "bootstrap": "^5.3.2", "downloadjs": "^1.4.7", "pdf-lib": "^1.17.1", + "http-proxy-middleware": "^2.0.6", + "jquery": "^3.6.0", + "merge": "^2.1.1", + "oidc-client": "^1.11.5", "react": "^18.2.0", "react-bootstrap": "^2.9.1", "react-dom": "^18.2.0", "react-router-dom": "^6.17.0", "react-scripts": "5.0.1", + "rimraf": "^3.0.2", "typescript": "^5.2.2", - "web-vitals": "^3.5.0" + "web-vitals": "^3.5.0", + "workbox-background-sync": "^6.5.4", + "workbox-broadcast-update": "^6.5.4", + "workbox-cacheable-response": "^6.5.4", + "workbox-core": "^6.5.4", + "workbox-expiration": "^6.5.4", + "workbox-google-analytics": "^6.5.4", + "workbox-navigation-preload": "^6.5.4", + "workbox-precaching": "^6.5.4", + "workbox-range-requests": "^6.5.4", + "workbox-routing": "^6.5.4", + "workbox-strategies": "^6.5.4", + "workbox-streams": "^6.5.4" + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@types/downloadjs": "^1.4.4", + "cross-env": "^7.0.3", + "less": "^4.2.0", + "less-loader": "^11.1.3" }, "scripts": { - "start": "react-scripts start", + "prestart": "node aspnetcore-https && node aspnetcore-react", + "start": "rimraf ./build && react-scripts start", "build": "react-scripts build", - "test": "react-scripts test", + "test": "cross-env CI=true react-scripts test --env=jsdom", "eject": "react-scripts eject" }, "eslintConfig": { @@ -46,11 +71,5 @@ "last 1 firefox version", "last 1 safari version" ] - }, - "devDependencies": { - "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@types/downloadjs": "^1.4.4", - "less": "^4.2.0", - "less-loader": "^11.1.3" } } diff --git a/frontend/public/Merienda-Bold.ttf b/Kemkas.Web/frontend/public/Merienda-Bold.ttf similarity index 100% rename from frontend/public/Merienda-Bold.ttf rename to Kemkas.Web/frontend/public/Merienda-Bold.ttf diff --git a/frontend/public/Merienda-Regular.ttf b/Kemkas.Web/frontend/public/Merienda-Regular.ttf similarity index 100% rename from frontend/public/Merienda-Regular.ttf rename to Kemkas.Web/frontend/public/Merienda-Regular.ttf diff --git a/frontend/public/favicon.ico b/Kemkas.Web/frontend/public/favicon.ico similarity index 100% rename from frontend/public/favicon.ico rename to Kemkas.Web/frontend/public/favicon.ico diff --git a/frontend/public/index.html b/Kemkas.Web/frontend/public/index.html similarity index 100% rename from frontend/public/index.html rename to Kemkas.Web/frontend/public/index.html diff --git a/frontend/public/km_karakterlap_hysteria_1.2.pdf b/Kemkas.Web/frontend/public/km_karakterlap_hysteria_1.2.pdf similarity index 100% rename from frontend/public/km_karakterlap_hysteria_1.2.pdf rename to Kemkas.Web/frontend/public/km_karakterlap_hysteria_1.2.pdf diff --git a/frontend/public/logo-original.png b/Kemkas.Web/frontend/public/logo-original.png similarity index 100% rename from frontend/public/logo-original.png rename to Kemkas.Web/frontend/public/logo-original.png diff --git a/frontend/public/logo192.png b/Kemkas.Web/frontend/public/logo192.png similarity index 100% rename from frontend/public/logo192.png rename to Kemkas.Web/frontend/public/logo192.png diff --git a/frontend/public/logo512.png b/Kemkas.Web/frontend/public/logo512.png similarity index 100% rename from frontend/public/logo512.png rename to Kemkas.Web/frontend/public/logo512.png diff --git a/frontend/public/manifest.json b/Kemkas.Web/frontend/public/manifest.json similarity index 100% rename from frontend/public/manifest.json rename to Kemkas.Web/frontend/public/manifest.json diff --git a/frontend/public/ogl.html b/Kemkas.Web/frontend/public/ogl.html similarity index 100% rename from frontend/public/ogl.html rename to Kemkas.Web/frontend/public/ogl.html diff --git a/frontend/public/robots.txt b/Kemkas.Web/frontend/public/robots.txt similarity index 100% rename from frontend/public/robots.txt rename to Kemkas.Web/frontend/public/robots.txt diff --git a/frontend/src/App.css b/Kemkas.Web/frontend/src/App.css similarity index 100% rename from frontend/src/App.css rename to Kemkas.Web/frontend/src/App.css diff --git a/frontend/src/App.test.tsx b/Kemkas.Web/frontend/src/App.test.tsx similarity index 100% rename from frontend/src/App.test.tsx rename to Kemkas.Web/frontend/src/App.test.tsx diff --git a/frontend/src/App.tsx b/Kemkas.Web/frontend/src/App.tsx similarity index 100% rename from frontend/src/App.tsx rename to Kemkas.Web/frontend/src/App.tsx diff --git a/frontend/src/first-edition/components/BasicNewLevel.tsx b/Kemkas.Web/frontend/src/first-edition/components/BasicNewLevel.tsx similarity index 100% rename from frontend/src/first-edition/components/BasicNewLevel.tsx rename to Kemkas.Web/frontend/src/first-edition/components/BasicNewLevel.tsx diff --git a/frontend/src/first-edition/components/FajSelector.tsx b/Kemkas.Web/frontend/src/first-edition/components/FajSelector.tsx similarity index 100% rename from frontend/src/first-edition/components/FajSelector.tsx rename to Kemkas.Web/frontend/src/first-edition/components/FajSelector.tsx diff --git a/frontend/src/first-edition/components/Felszereles.tsx b/Kemkas.Web/frontend/src/first-edition/components/Felszereles.tsx similarity index 100% rename from frontend/src/first-edition/components/Felszereles.tsx rename to Kemkas.Web/frontend/src/first-edition/components/Felszereles.tsx diff --git a/frontend/src/first-edition/components/HarcosFegyverSpecializacio.tsx b/Kemkas.Web/frontend/src/first-edition/components/HarcosFegyverSpecializacio.tsx similarity index 100% rename from frontend/src/first-edition/components/HarcosFegyverSpecializacio.tsx rename to Kemkas.Web/frontend/src/first-edition/components/HarcosFegyverSpecializacio.tsx diff --git a/frontend/src/first-edition/components/Helpers.tsx b/Kemkas.Web/frontend/src/first-edition/components/Helpers.tsx similarity index 100% rename from frontend/src/first-edition/components/Helpers.tsx rename to Kemkas.Web/frontend/src/first-edition/components/Helpers.tsx diff --git a/frontend/src/first-edition/components/JellemSelector.tsx b/Kemkas.Web/frontend/src/first-edition/components/JellemSelector.tsx similarity index 100% rename from frontend/src/first-edition/components/JellemSelector.tsx rename to Kemkas.Web/frontend/src/first-edition/components/JellemSelector.tsx diff --git a/frontend/src/first-edition/components/KalozKritikus.tsx b/Kemkas.Web/frontend/src/first-edition/components/KalozKritikus.tsx similarity index 100% rename from frontend/src/first-edition/components/KalozKritikus.tsx rename to Kemkas.Web/frontend/src/first-edition/components/KalozKritikus.tsx diff --git a/frontend/src/first-edition/components/KarakterKepzettsegek.tsx b/Kemkas.Web/frontend/src/first-edition/components/KarakterKepzettsegek.tsx similarity index 100% rename from frontend/src/first-edition/components/KarakterKepzettsegek.tsx rename to Kemkas.Web/frontend/src/first-edition/components/KarakterKepzettsegek.tsx diff --git a/frontend/src/first-edition/components/KepzettsegSelector.tsx b/Kemkas.Web/frontend/src/first-edition/components/KepzettsegSelector.tsx similarity index 100% rename from frontend/src/first-edition/components/KepzettsegSelector.tsx rename to Kemkas.Web/frontend/src/first-edition/components/KepzettsegSelector.tsx diff --git a/frontend/src/first-edition/components/LevelUps.tsx b/Kemkas.Web/frontend/src/first-edition/components/LevelUps.tsx similarity index 100% rename from frontend/src/first-edition/components/LevelUps.tsx rename to Kemkas.Web/frontend/src/first-edition/components/LevelUps.tsx diff --git a/frontend/src/first-edition/components/MasodlagosErtekek.tsx b/Kemkas.Web/frontend/src/first-edition/components/MasodlagosErtekek.tsx similarity index 100% rename from frontend/src/first-edition/components/MasodlagosErtekek.tsx rename to Kemkas.Web/frontend/src/first-edition/components/MasodlagosErtekek.tsx diff --git a/frontend/src/first-edition/components/OsztalySelector.tsx b/Kemkas.Web/frontend/src/first-edition/components/OsztalySelector.tsx similarity index 100% rename from frontend/src/first-edition/components/OsztalySelector.tsx rename to Kemkas.Web/frontend/src/first-edition/components/OsztalySelector.tsx diff --git a/frontend/src/first-edition/components/TulajdonsagInput.tsx b/Kemkas.Web/frontend/src/first-edition/components/TulajdonsagInput.tsx similarity index 100% rename from frontend/src/first-edition/components/TulajdonsagInput.tsx rename to Kemkas.Web/frontend/src/first-edition/components/TulajdonsagInput.tsx diff --git a/frontend/src/first-edition/components/TulajdonsagNoveles.tsx b/Kemkas.Web/frontend/src/first-edition/components/TulajdonsagNoveles.tsx similarity index 100% rename from frontend/src/first-edition/components/TulajdonsagNoveles.tsx rename to Kemkas.Web/frontend/src/first-edition/components/TulajdonsagNoveles.tsx diff --git a/frontend/src/first-edition/components/Tulajdonsagok.tsx b/Kemkas.Web/frontend/src/first-edition/components/Tulajdonsagok.tsx similarity index 100% rename from frontend/src/first-edition/components/Tulajdonsagok.tsx rename to Kemkas.Web/frontend/src/first-edition/components/Tulajdonsagok.tsx diff --git a/frontend/src/first-edition/domain-models/allowed-fegyver.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/allowed-fegyver.ts similarity index 100% rename from frontend/src/first-edition/domain-models/allowed-fegyver.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/allowed-fegyver.ts diff --git a/frontend/src/first-edition/domain-models/allowed-pancel-types.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/allowed-pancel-types.ts similarity index 100% rename from frontend/src/first-edition/domain-models/allowed-pancel-types.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/allowed-pancel-types.ts diff --git a/frontend/src/first-edition/domain-models/faj.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/faj.ts similarity index 100% rename from frontend/src/first-edition/domain-models/faj.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/faj.ts diff --git a/frontend/src/first-edition/domain-models/fegyver.json b/Kemkas.Web/frontend/src/first-edition/domain-models/fegyver.json similarity index 100% rename from frontend/src/first-edition/domain-models/fegyver.json rename to Kemkas.Web/frontend/src/first-edition/domain-models/fegyver.json diff --git a/frontend/src/first-edition/domain-models/felszereles.json b/Kemkas.Web/frontend/src/first-edition/domain-models/felszereles.json similarity index 100% rename from frontend/src/first-edition/domain-models/felszereles.json rename to Kemkas.Web/frontend/src/first-edition/domain-models/felszereles.json diff --git a/frontend/src/first-edition/domain-models/felszereles.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/felszereles.ts similarity index 100% rename from frontend/src/first-edition/domain-models/felszereles.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/felszereles.ts diff --git a/frontend/src/first-edition/domain-models/jellem.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/jellem.ts similarity index 100% rename from frontend/src/first-edition/domain-models/jellem.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/jellem.ts diff --git a/frontend/src/first-edition/domain-models/karakter.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/karakter.ts similarity index 100% rename from frontend/src/first-edition/domain-models/karakter.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/karakter.ts diff --git a/frontend/src/first-edition/domain-models/kepzettsegek.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/kepzettsegek.ts similarity index 100% rename from frontend/src/first-edition/domain-models/kepzettsegek.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/kepzettsegek.ts diff --git a/frontend/src/first-edition/domain-models/kockak.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/kockak.ts similarity index 100% rename from frontend/src/first-edition/domain-models/kockak.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/kockak.ts diff --git a/frontend/src/first-edition/domain-models/level.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/level.ts similarity index 100% rename from frontend/src/first-edition/domain-models/level.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/level.ts diff --git a/frontend/src/first-edition/domain-models/masodlagos_ertekek.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/masodlagos_ertekek.ts similarity index 100% rename from frontend/src/first-edition/domain-models/masodlagos_ertekek.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/masodlagos_ertekek.ts diff --git a/frontend/src/first-edition/domain-models/memorizalt_varazslat_tabla.json b/Kemkas.Web/frontend/src/first-edition/domain-models/memorizalt_varazslat_tabla.json similarity index 100% rename from frontend/src/first-edition/domain-models/memorizalt_varazslat_tabla.json rename to Kemkas.Web/frontend/src/first-edition/domain-models/memorizalt_varazslat_tabla.json diff --git a/frontend/src/first-edition/domain-models/memorizalt_varazslatok.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/memorizalt_varazslatok.ts similarity index 100% rename from frontend/src/first-edition/domain-models/memorizalt_varazslatok.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/memorizalt_varazslatok.ts diff --git a/frontend/src/first-edition/domain-models/mentok.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/mentok.ts similarity index 100% rename from frontend/src/first-edition/domain-models/mentok.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/mentok.ts diff --git a/frontend/src/first-edition/domain-models/osztaly.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/osztaly.ts similarity index 100% rename from frontend/src/first-edition/domain-models/osztaly.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/osztaly.ts diff --git a/frontend/src/first-edition/domain-models/pajzs.json b/Kemkas.Web/frontend/src/first-edition/domain-models/pajzs.json similarity index 100% rename from frontend/src/first-edition/domain-models/pajzs.json rename to Kemkas.Web/frontend/src/first-edition/domain-models/pajzs.json diff --git a/frontend/src/first-edition/domain-models/pancel.json b/Kemkas.Web/frontend/src/first-edition/domain-models/pancel.json similarity index 100% rename from frontend/src/first-edition/domain-models/pancel.json rename to Kemkas.Web/frontend/src/first-edition/domain-models/pancel.json diff --git a/frontend/src/first-edition/domain-models/tamadas_bonus_tabla.json b/Kemkas.Web/frontend/src/first-edition/domain-models/tamadas_bonus_tabla.json similarity index 100% rename from frontend/src/first-edition/domain-models/tamadas_bonus_tabla.json rename to Kemkas.Web/frontend/src/first-edition/domain-models/tamadas_bonus_tabla.json diff --git a/frontend/src/first-edition/domain-models/tamadas_bonusz.test.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/tamadas_bonusz.test.ts similarity index 100% rename from frontend/src/first-edition/domain-models/tamadas_bonusz.test.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/tamadas_bonusz.test.ts diff --git a/frontend/src/first-edition/domain-models/tamadas_bonusz.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/tamadas_bonusz.ts similarity index 100% rename from frontend/src/first-edition/domain-models/tamadas_bonusz.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/tamadas_bonusz.ts diff --git a/frontend/src/first-edition/domain-models/tulajdonsag.ts b/Kemkas.Web/frontend/src/first-edition/domain-models/tulajdonsag.ts similarity index 100% rename from frontend/src/first-edition/domain-models/tulajdonsag.ts rename to Kemkas.Web/frontend/src/first-edition/domain-models/tulajdonsag.ts diff --git a/frontend/src/first-edition/pages/.gitignore b/Kemkas.Web/frontend/src/first-edition/pages/.gitignore similarity index 100% rename from frontend/src/first-edition/pages/.gitignore rename to Kemkas.Web/frontend/src/first-edition/pages/.gitignore diff --git a/frontend/src/first-edition/pages/CreateCharacter.less b/Kemkas.Web/frontend/src/first-edition/pages/CreateCharacter.less similarity index 100% rename from frontend/src/first-edition/pages/CreateCharacter.less rename to Kemkas.Web/frontend/src/first-edition/pages/CreateCharacter.less diff --git a/frontend/src/first-edition/pages/CreateCharacter.tsx b/Kemkas.Web/frontend/src/first-edition/pages/CreateCharacter.tsx similarity index 100% rename from frontend/src/first-edition/pages/CreateCharacter.tsx rename to Kemkas.Web/frontend/src/first-edition/pages/CreateCharacter.tsx diff --git a/frontend/src/first-edition/pdf/character.pdf.ts b/Kemkas.Web/frontend/src/first-edition/pdf/character.pdf.ts similarity index 100% rename from frontend/src/first-edition/pdf/character.pdf.ts rename to Kemkas.Web/frontend/src/first-edition/pdf/character.pdf.ts diff --git a/frontend/src/first-edition/pdf/fegyverek.pdf.ts b/Kemkas.Web/frontend/src/first-edition/pdf/fegyverek.pdf.ts similarity index 100% rename from frontend/src/first-edition/pdf/fegyverek.pdf.ts rename to Kemkas.Web/frontend/src/first-edition/pdf/fegyverek.pdf.ts diff --git a/frontend/src/first-edition/pdf/karakter_pdf_view.ts b/Kemkas.Web/frontend/src/first-edition/pdf/karakter_pdf_view.ts similarity index 100% rename from frontend/src/first-edition/pdf/karakter_pdf_view.ts rename to Kemkas.Web/frontend/src/first-edition/pdf/karakter_pdf_view.ts diff --git a/frontend/src/first-edition/pdf/magic.pdf.ts b/Kemkas.Web/frontend/src/first-edition/pdf/magic.pdf.ts similarity index 100% rename from frontend/src/first-edition/pdf/magic.pdf.ts rename to Kemkas.Web/frontend/src/first-edition/pdf/magic.pdf.ts diff --git a/frontend/src/first-edition/pdf/masodlagos_ertekek.pdf.ts b/Kemkas.Web/frontend/src/first-edition/pdf/masodlagos_ertekek.pdf.ts similarity index 100% rename from frontend/src/first-edition/pdf/masodlagos_ertekek.pdf.ts rename to Kemkas.Web/frontend/src/first-edition/pdf/masodlagos_ertekek.pdf.ts diff --git a/frontend/src/first-edition/pdf/mentok.pdf.ts b/Kemkas.Web/frontend/src/first-edition/pdf/mentok.pdf.ts similarity index 100% rename from frontend/src/first-edition/pdf/mentok.pdf.ts rename to Kemkas.Web/frontend/src/first-edition/pdf/mentok.pdf.ts diff --git a/frontend/src/first-edition/pdf/osztaly_skills.ts b/Kemkas.Web/frontend/src/first-edition/pdf/osztaly_skills.ts similarity index 100% rename from frontend/src/first-edition/pdf/osztaly_skills.ts rename to Kemkas.Web/frontend/src/first-edition/pdf/osztaly_skills.ts diff --git a/frontend/src/first-edition/pdf/osztaly_specials.pdf.ts b/Kemkas.Web/frontend/src/first-edition/pdf/osztaly_specials.pdf.ts similarity index 100% rename from frontend/src/first-edition/pdf/osztaly_specials.pdf.ts rename to Kemkas.Web/frontend/src/first-edition/pdf/osztaly_specials.pdf.ts diff --git a/frontend/src/first-edition/pdf/tulajdonsagok.pdf.ts b/Kemkas.Web/frontend/src/first-edition/pdf/tulajdonsagok.pdf.ts similarity index 100% rename from frontend/src/first-edition/pdf/tulajdonsagok.pdf.ts rename to Kemkas.Web/frontend/src/first-edition/pdf/tulajdonsagok.pdf.ts diff --git a/frontend/src/index.css b/Kemkas.Web/frontend/src/index.css similarity index 100% rename from frontend/src/index.css rename to Kemkas.Web/frontend/src/index.css diff --git a/frontend/src/index.tsx b/Kemkas.Web/frontend/src/index.tsx similarity index 100% rename from frontend/src/index.tsx rename to Kemkas.Web/frontend/src/index.tsx diff --git a/frontend/src/react-app-env.d.ts b/Kemkas.Web/frontend/src/react-app-env.d.ts similarity index 100% rename from frontend/src/react-app-env.d.ts rename to Kemkas.Web/frontend/src/react-app-env.d.ts diff --git a/frontend/src/reportWebVitals.ts b/Kemkas.Web/frontend/src/reportWebVitals.ts similarity index 100% rename from frontend/src/reportWebVitals.ts rename to Kemkas.Web/frontend/src/reportWebVitals.ts diff --git a/Kemkas.Web/frontend/src/setupProxy.js b/Kemkas.Web/frontend/src/setupProxy.js new file mode 100644 index 0000000..f352d2d --- /dev/null +++ b/Kemkas.Web/frontend/src/setupProxy.js @@ -0,0 +1,36 @@ +const { createProxyMiddleware } = require('http-proxy-middleware'); +const { env } = require('process'); + +const target = env.ASPNETCORE_HTTPS_PORT ? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}` : + env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:40870'; + +const context = [ + "/weatherforecast", + "/_configuration", + "/.well-known", + "/Identity", + "/connect", + "/ApplyDatabaseMigrations", + "/_framework" +]; + +const onError = (err, req, resp, target) => { + console.error(`${err.message}`); +} + +module.exports = function (app) { + const appProxy = createProxyMiddleware(context, { + target: target, + // Handle errors to prevent the proxy middleware from crashing when + // the ASP NET Core webserver is unavailable + onError: onError, + secure: false, + // Uncomment this line to add support for proxying websockets + //ws: true, + headers: { + Connection: 'Keep-Alive' + } + }); + + app.use(appProxy); +}; diff --git a/Kemkas.Web/frontend/src/setupTests.ts b/Kemkas.Web/frontend/src/setupTests.ts new file mode 100644 index 0000000..5030fa8 --- /dev/null +++ b/Kemkas.Web/frontend/src/setupTests.ts @@ -0,0 +1,31 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom'; + +const localStorageMock = { + getItem: jest.fn(), + setItem: jest.fn(), + removeItem: jest.fn(), + clear: jest.fn(), + length: 0, + key: jest.fn() +}; +global.localStorage = localStorageMock; + +// Mock the request issued by the react app to get the client configuration parameters. +window.fetch = () => { + return Promise.resolve( + { + ok: true, + json: () => Promise.resolve({ + "authority": "https://localhost:7251", + "client_id": "Kemkas.Web", + "redirect_uri": "https://localhost:7251/authentication/login-callback", + "post_logout_redirect_uri": "https://localhost:7251/authentication/logout-callback", + "response_type": "id_token token", + "scope": "Kemkas.WebAPI openid profile" + }) + }); +}; diff --git a/frontend/src/util.ts b/Kemkas.Web/frontend/src/util.ts similarity index 100% rename from frontend/src/util.ts rename to Kemkas.Web/frontend/src/util.ts diff --git a/frontend/tsconfig.json b/Kemkas.Web/frontend/tsconfig.json similarity index 100% rename from frontend/tsconfig.json rename to Kemkas.Web/frontend/tsconfig.json diff --git a/frontend/yarn.lock b/Kemkas.Web/frontend/yarn.lock similarity index 99% rename from frontend/yarn.lock rename to Kemkas.Web/frontend/yarn.lock index fbdcc1f..21b212b 100644 --- a/frontend/yarn.lock +++ b/Kemkas.Web/frontend/yarn.lock @@ -2747,7 +2747,7 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@^7.1.1: +acorn@^7.1.1, acorn@^7.4.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -3184,6 +3184,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" @@ -3644,6 +3649,11 @@ core-js@^3.19.2: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.31.1.tgz#f2b0eea9be9da0def2c5fece71064a7e5d687653" integrity sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ== +core-js@^3.8.3: + version "3.33.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.33.1.tgz#ef3766cfa382482d0a2c2bc5cb52c6d88805da52" + integrity sha512-qVSq3s+d4+GsqN0teRCJtM6tdEEXyWxjzbhVrCHmBS5ZTM0FS2MOS0D13dUXAWDUN6a+lHI/N1hF9Ytz6iLl9Q== + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -3671,7 +3681,14 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -3680,6 +3697,11 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +crypto-js@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" @@ -5313,7 +5335,7 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-proxy-middleware@^2.0.3: +http-proxy-middleware@^2.0.3, http-proxy-middleware@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== @@ -6303,6 +6325,11 @@ jiti@^1.18.2: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.1.tgz#fa99e4b76a23053e0e7cde098efe1704a14c16f1" integrity sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg== +jquery@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -6677,6 +6704,11 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +merge@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/merge/-/merge-2.1.1.tgz#59ef4bf7e0b3e879186436e8481c06a6c162ca98" + integrity sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -6979,6 +7011,17 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== +oidc-client@^1.11.5: + version "1.11.5" + resolved "https://registry.yarnpkg.com/oidc-client/-/oidc-client-1.11.5.tgz#020aa193d68a3e1f87a24fcbf50073b738de92bb" + integrity sha512-LcKrKC8Av0m/KD/4EFmo9Sg8fSQ+WFJWBrmtWd+tZkNn3WT/sQG3REmPANE9tzzhbjW6VkTNy4xhAXCfPApAOg== + dependencies: + acorn "^7.4.1" + base64-js "^1.5.1" + core-js "^3.8.3" + crypto-js "^4.0.0" + serialize-javascript "^4.0.0" + on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -9672,7 +9715,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -workbox-background-sync@6.6.1: +workbox-background-sync@6.6.1, workbox-background-sync@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.6.1.tgz#08d603a33717ce663e718c30cc336f74909aff2f" integrity sha512-trJd3ovpWCvzu4sW0E8rV3FUyIcC0W8G+AZ+VcqzzA890AsWZlUGOTSxIMmIHVusUw/FDq1HFWfy/kC/WTRqSg== @@ -9680,7 +9723,7 @@ workbox-background-sync@6.6.1: idb "^7.0.1" workbox-core "6.6.1" -workbox-broadcast-update@6.6.1: +workbox-broadcast-update@6.6.1, workbox-broadcast-update@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.6.1.tgz#0fad9454cf8e4ace0c293e5617c64c75d8a8c61e" integrity sha512-fBhffRdaANdeQ1V8s692R9l/gzvjjRtydBOvR6WCSB0BNE2BacA29Z4r9/RHd9KaXCPl6JTdI9q0bR25YKP8TQ== @@ -9730,19 +9773,19 @@ workbox-build@6.6.1: workbox-sw "6.6.1" workbox-window "6.6.1" -workbox-cacheable-response@6.6.1: +workbox-cacheable-response@6.6.1, workbox-cacheable-response@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.6.1.tgz#284c2b86be3f4fd191970ace8c8e99797bcf58e9" integrity sha512-85LY4veT2CnTCDxaVG7ft3NKaFbH6i4urZXgLiU4AiwvKqS2ChL6/eILiGRYXfZ6gAwDnh5RkuDbr/GMS4KSag== dependencies: workbox-core "6.6.1" -workbox-core@6.6.1: +workbox-core@6.6.1, workbox-core@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.6.1.tgz#7184776d4134c5ed2f086878c882728fc9084265" integrity sha512-ZrGBXjjaJLqzVothoE12qTbVnOAjFrHDXpZe7coCb6q65qI/59rDLwuFMO4PcZ7jcbxY+0+NhUVztzR/CbjEFw== -workbox-expiration@6.6.1: +workbox-expiration@6.6.1, workbox-expiration@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.6.1.tgz#a841fa36676104426dbfb9da1ef6a630b4f93739" integrity sha512-qFiNeeINndiOxaCrd2DeL1Xh1RFug3JonzjxUHc5WkvkD2u5abY3gZL1xSUNt3vZKsFFGGORItSjVTVnWAZO4A== @@ -9750,7 +9793,7 @@ workbox-expiration@6.6.1: idb "^7.0.1" workbox-core "6.6.1" -workbox-google-analytics@6.6.1: +workbox-google-analytics@6.6.1, workbox-google-analytics@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.6.1.tgz#a07a6655ab33d89d1b0b0a935ffa5dea88618c5d" integrity sha512-1TjSvbFSLmkpqLcBsF7FuGqqeDsf+uAXO/pjiINQKg3b1GN0nBngnxLcXDYo1n/XxK4N7RaRrpRlkwjY/3ocuA== @@ -9760,14 +9803,14 @@ workbox-google-analytics@6.6.1: workbox-routing "6.6.1" workbox-strategies "6.6.1" -workbox-navigation-preload@6.6.1: +workbox-navigation-preload@6.6.1, workbox-navigation-preload@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.6.1.tgz#61a34fe125558dd88cf09237f11bd966504ea059" integrity sha512-DQCZowCecO+wRoIxJI2V6bXWK6/53ff+hEXLGlQL4Rp9ZaPDLrgV/32nxwWIP7QpWDkVEtllTAK5h6cnhxNxDA== dependencies: workbox-core "6.6.1" -workbox-precaching@6.6.1: +workbox-precaching@6.6.1, workbox-precaching@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.6.1.tgz#dedeeba10a2d163d990bf99f1c2066ac0d1a19e2" integrity sha512-K4znSJ7IKxCnCYEdhNkMr7X1kNh8cz+mFgx9v5jFdz1MfI84pq8C2zG+oAoeE5kFrUf7YkT5x4uLWBNg0DVZ5A== @@ -9776,7 +9819,7 @@ workbox-precaching@6.6.1: workbox-routing "6.6.1" workbox-strategies "6.6.1" -workbox-range-requests@6.6.1: +workbox-range-requests@6.6.1, workbox-range-requests@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.6.1.tgz#ddaf7e73af11d362fbb2f136a9063a4c7f507a39" integrity sha512-4BDzk28govqzg2ZpX0IFkthdRmCKgAKreontYRC5YsAPB2jDtPNxqx3WtTXgHw1NZalXpcH/E4LqUa9+2xbv1g== @@ -9795,21 +9838,21 @@ workbox-recipes@6.6.1: workbox-routing "6.6.1" workbox-strategies "6.6.1" -workbox-routing@6.6.1: +workbox-routing@6.6.1, workbox-routing@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.6.1.tgz#cba9a1c7e0d1ea11e24b6f8c518840efdc94f581" integrity sha512-j4ohlQvfpVdoR8vDYxTY9rA9VvxTHogkIDwGdJ+rb2VRZQ5vt1CWwUUZBeD/WGFAni12jD1HlMXvJ8JS7aBWTg== dependencies: workbox-core "6.6.1" -workbox-strategies@6.6.1: +workbox-strategies@6.6.1, workbox-strategies@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.6.1.tgz#38d0f0fbdddba97bd92e0c6418d0b1a2ccd5b8bf" integrity sha512-WQLXkRnsk4L81fVPkkgon1rZNxnpdO5LsO+ws7tYBC6QQQFJVI6v98klrJEjFtZwzw/mB/HT5yVp7CcX0O+mrw== dependencies: workbox-core "6.6.1" -workbox-streams@6.6.1: +workbox-streams@6.6.1, workbox-streams@^6.5.4: version "6.6.1" resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.6.1.tgz#b2f7ba7b315c27a6e3a96a476593f99c5d227d26" integrity sha512-maKG65FUq9e4BLotSKWSTzeF0sgctQdYyTMq529piEN24Dlu9b6WhrAfRpHdCncRS89Zi2QVpW5V33NX8PgH3Q== diff --git a/Kemkas.sln b/Kemkas.sln new file mode 100644 index 0000000..4925aa5 --- /dev/null +++ b/Kemkas.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kemkas.Web", "Kemkas.Web\Kemkas.Web.csproj", "{ABAEE4DC-1A07-40AE-A2B6-4D3755A6C1E8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ABAEE4DC-1A07-40AE-A2B6-4D3755A6C1E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABAEE4DC-1A07-40AE-A2B6-4D3755A6C1E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABAEE4DC-1A07-40AE-A2B6-4D3755A6C1E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABAEE4DC-1A07-40AE-A2B6-4D3755A6C1E8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Kemkas.sln.DotSettings b/Kemkas.sln.DotSettings new file mode 100644 index 0000000..518cbb5 --- /dev/null +++ b/Kemkas.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/frontend/src/setupTests.ts b/frontend/src/setupTests.ts deleted file mode 100644 index 8f2609b..0000000 --- a/frontend/src/setupTests.ts +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom';