├── .gitignore ├── AdditionalControllersForDemos ├── AccountController.cs └── ExternalController.cs ├── Finished sample ├── BethanysPieShopHRM.Api │ ├── BethanysPieShopHRM.Api.csproj │ ├── Controllers │ │ ├── CountryController.cs │ │ ├── EmployeeController.cs │ │ └── JobCategoryController.cs │ ├── Migrations │ │ ├── 20191013091026_Initial.Designer.cs │ │ ├── 20191013091026_Initial.cs │ │ ├── 20191014195303_EmployeeLatLongAdded.Designer.cs │ │ ├── 20191014195303_EmployeeLatLongAdded.cs │ │ └── AppDbContextModelSnapshot.cs │ ├── Models │ │ ├── AppDbContext.cs │ │ ├── CountryRepository.cs │ │ ├── EmployeeRepository.cs │ │ ├── ICountryRepository.cs │ │ ├── IEmployeeRepository.cs │ │ ├── IJobCategoryRepository.cs │ │ └── JobCategoryRepository.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── appsettings.Development.json │ └── appsettings.json ├── BethanysPieShopHRM.ComponentsLibrary │ ├── BethanysPieShopHRM.ComponentsLibrary.csproj │ ├── Map │ │ ├── Map.razor │ │ ├── Marker.cs │ │ └── Point.cs │ └── wwwroot │ │ ├── deliveryMap.js │ │ └── leaflet │ │ ├── images │ │ ├── layers-2x.png │ │ ├── layers.png │ │ ├── marker-icon-2x.png │ │ ├── marker-icon.png │ │ └── marker-shadow.png │ │ ├── leaflet.css │ │ └── leaflet.js ├── BethanysPieShopHRM.Server │ ├── App.razor │ ├── BethanysPieShopHRM.Server.csproj │ ├── Components │ │ ├── AddEmployeeDialog.razor │ │ └── AddEmployeeDialogBase.cs │ ├── Pages │ │ ├── EmployeeDetail.razor │ │ ├── EmployeeDetailBase.cs │ │ ├── EmployeeEdit.razor │ │ ├── EmployeeEditBase.cs │ │ ├── EmployeeOverview.razor │ │ ├── EmployeeOverviewBase.cs │ │ ├── Error.razor │ │ ├── Index.razor │ │ ├── Login.cshtml │ │ ├── Login.cshtml.cs │ │ ├── LoginIDP.cshtml │ │ ├── LoginIDP.cshtml.cs │ │ ├── Logout.cshtml │ │ ├── Logout.cshtml.cs │ │ ├── LogoutIDP.cshtml │ │ ├── LogoutIDP.cshtml.cs │ │ ├── _Host.cshtml │ │ └── _ViewImports.cshtml │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Services │ │ ├── CountryDataService.cs │ │ ├── EmployeeDataService.cs │ │ ├── ICountryDataService.cs │ │ ├── IEmployeeDataService.cs │ │ ├── IJobCategoryDataService.cs │ │ ├── JobCategoryDataService.cs │ │ └── MockEmployeeDataService.cs │ ├── Shared │ │ ├── MainLayout.razor │ │ └── NavMenu.razor │ ├── Startup.cs │ ├── _Imports.razor │ ├── appsettings.Development.json │ ├── appsettings.json │ └── wwwroot │ │ ├── css │ │ ├── bootstrap │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── open-iconic │ │ │ ├── FONT-LICENSE │ │ │ ├── ICON-LICENSE │ │ │ ├── README.md │ │ │ └── font │ │ │ │ ├── css │ │ │ │ └── open-iconic-bootstrap.min.css │ │ │ │ └── fonts │ │ │ │ ├── open-iconic.eot │ │ │ │ ├── open-iconic.otf │ │ │ │ ├── open-iconic.svg │ │ │ │ ├── open-iconic.ttf │ │ │ │ └── open-iconic.woff │ │ └── site.css │ │ ├── favicon.ico │ │ └── images │ │ ├── bethanylogo.png │ │ ├── pattern.png │ │ └── profilePicture.jpg ├── BethanysPieShopHRM.Shared │ ├── BethanysPieShopHRM.Shared.csproj │ ├── Country.cs │ ├── Employee.cs │ ├── Gender.cs │ ├── JobCategory.cs │ ├── MaritalStatus.cs │ └── Policies │ │ └── Policies.cs ├── BethanysPieShopHRM.sln └── Marvin.IDP │ ├── Areas │ └── Identity │ │ ├── Data │ │ ├── ApplicationUser.cs │ │ └── UserDbContext.cs │ │ ├── IdentityHostingStartup.cs │ │ └── Pages │ │ ├── Account │ │ ├── ConfirmEmail.cshtml │ │ ├── ConfirmEmail.cshtml.cs │ │ ├── Register.cshtml │ │ ├── Register.cshtml.cs │ │ ├── RegisterConfirmation.cshtml │ │ ├── RegisterConfirmation.cshtml.cs │ │ ├── _StatusMessage.cshtml │ │ └── _ViewImports.cshtml │ │ ├── _ValidationScriptsPartial.cshtml │ │ ├── _ViewImports.cshtml │ │ └── _ViewStart.cshtml │ ├── Config.cs │ ├── DummyEmailSender.cs │ ├── Marvin.IDP.csproj │ ├── Migrations │ ├── 20191122130510_CreateIdentitySchema.Designer.cs │ ├── 20191122130510_CreateIdentitySchema.cs │ └── UserDbContextModelSnapshot.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Quickstart │ ├── Account │ │ ├── AccountController.cs │ │ ├── AccountOptions.cs │ │ ├── ExternalController.cs │ │ ├── ExternalProvider.cs │ │ ├── LoggedOutViewModel.cs │ │ ├── LoginInputModel.cs │ │ ├── LoginViewModel.cs │ │ ├── LogoutInputModel.cs │ │ ├── LogoutViewModel.cs │ │ └── RedirectViewModel.cs │ ├── Consent │ │ ├── ConsentController.cs │ │ ├── ConsentInputModel.cs │ │ ├── ConsentOptions.cs │ │ ├── ConsentViewModel.cs │ │ ├── ProcessConsentResult.cs │ │ └── ScopeViewModel.cs │ ├── Device │ │ ├── DeviceAuthorizationInputModel.cs │ │ ├── DeviceAuthorizationViewModel.cs │ │ └── DeviceController.cs │ ├── Diagnostics │ │ ├── DiagnosticsController.cs │ │ └── DiagnosticsViewModel.cs │ ├── Extensions.cs │ ├── Grants │ │ ├── GrantsController.cs │ │ └── GrantsViewModel.cs │ ├── Home │ │ ├── ErrorViewModel.cs │ │ └── HomeController.cs │ ├── SecurityHeadersAttribute.cs │ └── TestUsers.cs │ ├── ScaffoldingReadme.txt │ ├── Startup.cs │ ├── Views │ ├── Account │ │ ├── AccessDenied.cshtml │ │ ├── LoggedOut.cshtml │ │ ├── Login.cshtml │ │ └── Logout.cshtml │ ├── Consent │ │ └── Index.cshtml │ ├── Device │ │ ├── Success.cshtml │ │ ├── UserCodeCapture.cshtml │ │ └── UserCodeConfirmation.cshtml │ ├── Diagnostics │ │ └── Index.cshtml │ ├── Grants │ │ └── Index.cshtml │ ├── Home │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── Redirect.cshtml │ │ ├── _CookieConsentPartial.cshtml │ │ ├── _Layout.cshtml │ │ ├── _LoginPartial.cshtml │ │ ├── _ScopeListItem.cshtml │ │ └── _ValidationSummary.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml │ ├── appsettings.json │ ├── tempkey.rsa │ ├── updateUI.ps1 │ └── wwwroot │ ├── css │ ├── site.css │ ├── site.less │ └── site.min.css │ ├── favicon.ico │ ├── icon.jpg │ ├── icon.png │ ├── js │ ├── signin-redirect.js │ └── signout-redirect.js │ └── lib │ ├── bootstrap │ ├── css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── js │ │ ├── bootstrap.js │ │ └── bootstrap.min.js │ └── jquery │ ├── jquery.js │ ├── jquery.min.js │ └── jquery.min.map ├── LICENSE ├── README.md └── Starter files ├── BethanysPieShopHRM.Api ├── BethanysPieShopHRM.Api.csproj ├── Controllers │ ├── CountryController.cs │ ├── EmployeeController.cs │ └── JobCategoryController.cs ├── Migrations │ ├── 20191013091026_Initial.Designer.cs │ ├── 20191013091026_Initial.cs │ ├── 20191014195303_EmployeeLatLongAdded.Designer.cs │ ├── 20191014195303_EmployeeLatLongAdded.cs │ └── AppDbContextModelSnapshot.cs ├── Models │ ├── AppDbContext.cs │ ├── CountryRepository.cs │ ├── EmployeeRepository.cs │ ├── ICountryRepository.cs │ ├── IEmployeeRepository.cs │ ├── IJobCategoryRepository.cs │ └── JobCategoryRepository.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── appsettings.Development.json └── appsettings.json ├── BethanysPieShopHRM.ComponentsLibrary ├── BethanysPieShopHRM.ComponentsLibrary.csproj ├── Map │ ├── Map.razor │ ├── Marker.cs │ └── Point.cs └── wwwroot │ ├── deliveryMap.js │ └── leaflet │ ├── images │ ├── layers-2x.png │ ├── layers.png │ ├── marker-icon-2x.png │ ├── marker-icon.png │ └── marker-shadow.png │ ├── leaflet.css │ └── leaflet.js ├── BethanysPieShopHRM.Server ├── App.razor ├── BethanysPieShopHRM.Server.csproj ├── Components │ ├── AddEmployeeDialog.razor │ └── AddEmployeeDialogBase.cs ├── Pages │ ├── EmployeeDetail.razor │ ├── EmployeeDetailBase.cs │ ├── EmployeeEdit.razor │ ├── EmployeeEditBase.cs │ ├── EmployeeOverview.razor │ ├── EmployeeOverviewBase.cs │ ├── Error.razor │ ├── Index.razor │ └── _Host.cshtml ├── Program.cs ├── Properties │ └── launchSettings.json ├── Services │ ├── CountryDataService.cs │ ├── EmployeeDataService.cs │ ├── ICountryDataService.cs │ ├── IEmployeeDataService.cs │ ├── IJobCategoryDataService.cs │ ├── JobCategoryDataService.cs │ └── MockEmployeeDataService.cs ├── Shared │ ├── MainLayout.razor │ └── NavMenu.razor ├── Startup.cs ├── _Imports.razor ├── appsettings.Development.json ├── appsettings.json └── wwwroot │ ├── css │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── open-iconic │ │ ├── FONT-LICENSE │ │ ├── ICON-LICENSE │ │ ├── README.md │ │ └── font │ │ │ ├── css │ │ │ └── open-iconic-bootstrap.min.css │ │ │ └── fonts │ │ │ ├── open-iconic.eot │ │ │ ├── open-iconic.otf │ │ │ ├── open-iconic.svg │ │ │ ├── open-iconic.ttf │ │ │ └── open-iconic.woff │ └── site.css │ ├── favicon.ico │ └── images │ ├── bethanylogo.png │ ├── pattern.png │ └── profilePicture.jpg ├── BethanysPieShopHRM.Shared ├── BethanysPieShopHRM.Shared.csproj ├── Country.cs ├── Employee.cs ├── Gender.cs ├── JobCategory.cs └── MaritalStatus.cs └── BethanysPieShopHRM.sln /Finished sample/BethanysPieShopHRM.Api/BethanysPieShopHRM.Api.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | all 17 | runtime; build; native; contentfiles; analyzers; buildtransitive 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Controllers/CountryController.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 5 | 6 | namespace BethanysPieShopHRM.Api.Controllers 7 | { 8 | [Route("api/[controller]")] 9 | [ApiController] 10 | public class CountryController : Controller 11 | { 12 | private readonly ICountryRepository _countryRepository; 13 | 14 | public CountryController(ICountryRepository countryRepository) 15 | { 16 | _countryRepository = countryRepository; 17 | } 18 | 19 | // GET: api/ 20 | [HttpGet] 21 | public IActionResult GetCountries() 22 | { 23 | return Ok(_countryRepository.GetAllCountries()); 24 | } 25 | 26 | // GET api//5 27 | [HttpGet("{id}")] 28 | public IActionResult GetCountryById(int id) 29 | { 30 | return Ok(_countryRepository.GetCountryById(id)); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Controllers/EmployeeController.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using BethanysPieShopHRM.Shared; 3 | using Microsoft.AspNetCore.Authorization; 4 | using Microsoft.AspNetCore.Mvc; 5 | 6 | namespace BethanysPieShopHRM.Api.Controllers 7 | { 8 | [Route("api/[controller]")] 9 | [ApiController] 10 | public class EmployeeController : Controller 11 | { 12 | private readonly IEmployeeRepository _employeeRepository; 13 | 14 | public EmployeeController(IEmployeeRepository employeeRepository) 15 | { 16 | _employeeRepository = employeeRepository; 17 | } 18 | 19 | [HttpGet] 20 | [Authorize(Policy = BethanysPieShopHRM.Shared.Policies.CanManageEmployees)] 21 | public IActionResult GetAllEmployees() 22 | { 23 | return Ok(_employeeRepository.GetAllEmployees()); 24 | } 25 | 26 | [HttpGet("{id}")] 27 | public IActionResult GetEmployeeById(int id) 28 | { 29 | return Ok(_employeeRepository.GetEmployeeById(id)); 30 | } 31 | 32 | [HttpPost] 33 | public IActionResult CreateEmployee([FromBody] Employee employee) 34 | { 35 | if (employee == null) 36 | return BadRequest(); 37 | 38 | if (employee.FirstName == string.Empty || employee.LastName == string.Empty) 39 | { 40 | ModelState.AddModelError("Name/FirstName", "The name or first name shouldn't be empty"); 41 | } 42 | 43 | if (!ModelState.IsValid) 44 | return BadRequest(ModelState); 45 | 46 | var createdEmployee = _employeeRepository.AddEmployee(employee); 47 | 48 | return Created("employee", createdEmployee); 49 | } 50 | 51 | [HttpPut] 52 | public IActionResult UpdateEmployee([FromBody] Employee employee) 53 | { 54 | if (employee == null) 55 | return BadRequest(); 56 | 57 | if (employee.FirstName == string.Empty || employee.LastName == string.Empty) 58 | { 59 | ModelState.AddModelError("Name/FirstName", "The name or first name shouldn't be empty"); 60 | } 61 | 62 | if (!ModelState.IsValid) 63 | return BadRequest(ModelState); 64 | 65 | var employeeToUpdate = _employeeRepository.GetEmployeeById(employee.EmployeeId); 66 | 67 | if (employeeToUpdate == null) 68 | return NotFound(); 69 | 70 | _employeeRepository.UpdateEmployee(employee); 71 | 72 | return NoContent(); //success 73 | } 74 | 75 | [HttpDelete("{id}")] 76 | public IActionResult DeleteEmployee(int id) 77 | { 78 | if (id == 0) 79 | return BadRequest(); 80 | 81 | var employeeToDelete = _employeeRepository.GetEmployeeById(id); 82 | if (employeeToDelete == null) 83 | return NotFound(); 84 | 85 | _employeeRepository.DeleteEmployee(id); 86 | 87 | return NoContent();//success 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Controllers/JobCategoryController.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 5 | 6 | namespace BethanysPieShopHRM.Api.Controllers 7 | { 8 | [Route("api/[controller]")] 9 | [ApiController] 10 | public class JobCategoryController : Controller 11 | { 12 | private readonly IJobCategoryRepository _jobCategoryRepository; 13 | 14 | public JobCategoryController(IJobCategoryRepository jobCategoryRepository) 15 | { 16 | _jobCategoryRepository = jobCategoryRepository; 17 | } 18 | 19 | 20 | // GET: api/ 21 | [HttpGet] 22 | public IActionResult GetJobCategories() 23 | { 24 | return Ok(_jobCategoryRepository.GetAllJobCategories()); 25 | } 26 | 27 | // GET api//5 28 | [HttpGet("{id}")] 29 | public IActionResult GetJobCategoryById(int id) 30 | { 31 | return Ok(_jobCategoryRepository.GetJobCategoryById(id)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Models/CountryRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Api.Models 6 | { 7 | public class CountryRepository : ICountryRepository 8 | { 9 | private readonly AppDbContext _appDbContext; 10 | 11 | public CountryRepository(AppDbContext appDbContext) 12 | { 13 | _appDbContext = appDbContext; 14 | } 15 | 16 | public IEnumerable GetAllCountries() 17 | { 18 | return _appDbContext.Countries; 19 | } 20 | 21 | public Country GetCountryById(int countryId) 22 | { 23 | return _appDbContext.Countries.FirstOrDefault(c => c.CountryId == countryId); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Models/EmployeeRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Api.Models 6 | { 7 | public class EmployeeRepository : IEmployeeRepository 8 | { 9 | private readonly AppDbContext _appDbContext; 10 | 11 | public EmployeeRepository(AppDbContext appDbContext) 12 | { 13 | _appDbContext = appDbContext; 14 | } 15 | 16 | public IEnumerable GetAllEmployees() 17 | { 18 | return _appDbContext.Employees; 19 | } 20 | 21 | public Employee GetEmployeeById(int employeeId) 22 | { 23 | return _appDbContext.Employees.FirstOrDefault(c => c.EmployeeId == employeeId); 24 | } 25 | 26 | public Employee AddEmployee(Employee employee) 27 | { 28 | var addedEntity = _appDbContext.Employees.Add(employee); 29 | _appDbContext.SaveChanges(); 30 | return addedEntity.Entity; 31 | } 32 | 33 | public Employee UpdateEmployee(Employee employee) 34 | { 35 | var foundEmployee = _appDbContext.Employees.FirstOrDefault(e => e.EmployeeId == employee.EmployeeId); 36 | 37 | if (foundEmployee != null) 38 | { 39 | foundEmployee.CountryId = employee.CountryId; 40 | foundEmployee.MaritalStatus = employee.MaritalStatus; 41 | foundEmployee.BirthDate = employee.BirthDate; 42 | foundEmployee.City = employee.City; 43 | foundEmployee.Email = employee.Email; 44 | foundEmployee.FirstName = employee.FirstName; 45 | foundEmployee.LastName = employee.LastName; 46 | foundEmployee.Gender = employee.Gender; 47 | foundEmployee.PhoneNumber = employee.PhoneNumber; 48 | foundEmployee.Smoker = employee.Smoker; 49 | foundEmployee.Street = employee.Street; 50 | foundEmployee.Zip = employee.Zip; 51 | foundEmployee.JobCategoryId = employee.JobCategoryId; 52 | foundEmployee.Comment = employee.Comment; 53 | foundEmployee.ExitDate = employee.ExitDate; 54 | foundEmployee.JoinedDate = employee.JoinedDate; 55 | 56 | _appDbContext.SaveChanges(); 57 | 58 | return foundEmployee; 59 | } 60 | 61 | return null; 62 | } 63 | 64 | public void DeleteEmployee(int employeeId) 65 | { 66 | var foundEmployee = _appDbContext.Employees.FirstOrDefault(e => e.EmployeeId == employeeId); 67 | if (foundEmployee == null) return; 68 | 69 | _appDbContext.Employees.Remove(foundEmployee); 70 | _appDbContext.SaveChanges(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Models/ICountryRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Api.Models 8 | { 9 | public interface ICountryRepository 10 | { 11 | IEnumerable GetAllCountries(); 12 | Country GetCountryById(int countryId); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Models/IEmployeeRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Api.Models 8 | { 9 | public interface IEmployeeRepository 10 | { 11 | IEnumerable GetAllEmployees(); 12 | Employee GetEmployeeById(int employeeId); 13 | Employee AddEmployee(Employee employee); 14 | Employee UpdateEmployee(Employee employee); 15 | void DeleteEmployee(int employeeId); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Models/IJobCategoryRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using BethanysPieShopHRM.Shared; 3 | 4 | namespace BethanysPieShopHRM.Api.Models 5 | { 6 | public interface IJobCategoryRepository 7 | { 8 | IEnumerable GetAllJobCategories(); 9 | JobCategory GetJobCategoryById(int jobCategoryId); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Models/JobCategoryRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Api.Models 8 | { 9 | public class JobCategoryRepository: IJobCategoryRepository 10 | { 11 | private readonly AppDbContext _appDbContext; 12 | 13 | public JobCategoryRepository(AppDbContext appDbContext) 14 | { 15 | _appDbContext = appDbContext; 16 | } 17 | 18 | public IEnumerable GetAllJobCategories() 19 | { 20 | return _appDbContext.JobCategories; 21 | } 22 | 23 | public JobCategory GetJobCategoryById(int jobCategoryId) 24 | { 25 | return _appDbContext.JobCategories.FirstOrDefault(c => c.JobCategoryId == jobCategoryId); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Program.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Hosting; 5 | 6 | namespace BethanysPieShopHRM.Api 7 | { 8 | public class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | var host = CreateHostBuilder(args).Build(); 13 | 14 | using (var scope = host.Services.CreateScope()) 15 | { 16 | using var context = scope.ServiceProvider.GetService(); 17 | context.Database.EnsureCreated(); 18 | } 19 | 20 | host.Run(); 21 | } 22 | 23 | public static IHostBuilder CreateHostBuilder(string[] args) => 24 | Host.CreateDefaultBuilder(args) 25 | .ConfigureWebHostDefaults(webBuilder => 26 | { 27 | webBuilder.UseStartup(); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:62408", 7 | "sslPort": 44340 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "Project", 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | }, 17 | "applicationUrl": "https://localhost:44340/" 18 | }, 19 | "BethanysPieShopHRM.Api": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "launchUrl": "weatherforecast", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | }, 26 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/Startup.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using IdentityServer4.AccessTokenValidation; 3 | using Microsoft.AspNetCore.Authorization; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.AspNetCore.Mvc.Authorization; 7 | using Microsoft.EntityFrameworkCore; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Hosting; 11 | 12 | namespace BethanysPieShopHRM.Api 13 | { 14 | public class Startup 15 | { 16 | public Startup(IConfiguration configuration) 17 | { 18 | Configuration = configuration; 19 | } 20 | 21 | public IConfiguration Configuration { get; } 22 | 23 | // This method gets called by the runtime. Use this method to add services to the container. 24 | public void ConfigureServices(IServiceCollection services) 25 | { 26 | services.AddAuthorization(authorizationOptions => 27 | { 28 | authorizationOptions.AddPolicy( 29 | BethanysPieShopHRM.Shared.Policies.CanManageEmployees, 30 | BethanysPieShopHRM.Shared.Policies.CanManageEmployeesPolicy()); 31 | }); 32 | 33 | //services.AddDbContext(options => options.UseInMemoryDatabase(databaseName: "BethanysPieShopHRM")); 34 | 35 | services.AddDbContext(options => 36 | options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 37 | 38 | services.AddScoped(); 39 | services.AddScoped(); 40 | services.AddScoped(); 41 | 42 | services.AddCors(options => 43 | { 44 | options.AddPolicy("Open", builder => builder.AllowAnyOrigin().AllowAnyHeader()); 45 | }); 46 | 47 | var requireAuthenticatedUserPolicy = new AuthorizationPolicyBuilder() 48 | .RequireAuthenticatedUser() 49 | .Build(); 50 | 51 | services.AddControllers(configure => 52 | { 53 | configure.Filters.Add(new AuthorizeFilter(requireAuthenticatedUserPolicy)); 54 | }); 55 | //.AddJsonOptions(options => options.JsonSerializerOptions.ca); 56 | 57 | services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) 58 | .AddIdentityServerAuthentication(options => 59 | { 60 | options.Authority = "https://localhost:44333/"; 61 | options.ApiName = "bethanyspieshophrapi"; 62 | }); 63 | 64 | } 65 | 66 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 67 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 68 | { 69 | if (env.IsDevelopment()) 70 | { 71 | app.UseDeveloperExceptionPage(); 72 | } 73 | 74 | app.UseHttpsRedirection(); 75 | 76 | app.UseRouting(); 77 | 78 | app.UseAuthentication(); 79 | 80 | app.UseAuthorization(); 81 | 82 | // app.UseCors("Open"); 83 | 84 | app.UseEndpoints(endpoints => 85 | { 86 | endpoints.MapControllers(); 87 | }); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Api/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=BethanysPieShopHRM3;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | 5 | }, 6 | "Logging": { 7 | "LogLevel": { 8 | "Default": "Information", 9 | "Microsoft": "Warning", 10 | "Microsoft.Hosting.Lifetime": "Information" 11 | } 12 | }, 13 | "AllowedHosts": "*" 14 | } 15 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.ComponentsLibrary/BethanysPieShopHRM.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 3.0 6 | BethanysPieShopHRM.ComponentsLibrary 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using System 2 | @using System.Collections.Generic 3 | @using System.Threading.Tasks 4 | @using Microsoft.AspNetCore.Components 5 | @using Microsoft.JSInterop 6 | @using BethanysPieShopHRM.ComponentsLibrary.Map 7 | @inject IJSRuntime JSRuntime 8 | 9 |
10 | 11 | @code { 12 | 13 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 14 | 15 | [Parameter] 16 | public double Zoom { get; set; } 17 | 18 | [Parameter] 19 | public List Markers { get; set; } 20 | 21 | protected override async Task OnAfterRenderAsync(bool firstRender) 22 | { 23 | await JSRuntime.InvokeVoidAsync( 24 | "deliveryMap.showOrUpdate", 25 | elementId, 26 | Markers); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.ComponentsLibrary.Map 2 | { 3 | public class Marker 4 | { 5 | public string Description { get; set; } 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.ComponentsLibrary.Map 2 | { 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |

Sorry, you're not authorized to view this page.

7 |

You may want to try logging in (as someone with the necessary authorization).

8 |
9 |
10 |
11 | 12 | 13 |

Sorry, there's nothing at this address.

14 |
15 |
16 |
17 |
-------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/BethanysPieShopHRM.Server.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | all 12 | runtime; build; native; contentfiles; analyzers; buildtransitive 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Components/AddEmployeeDialog.razor: -------------------------------------------------------------------------------- 1 |  2 | @inherits AddEmployeeDialogBase 3 | 4 | @if (ShowDialog) 5 | { 6 | 47 | } -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Components/AddEmployeeDialogBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.Server.Services; 4 | using BethanysPieShopHRM.Shared; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace BethanysPieShopHRM.Server.Components 8 | { 9 | public class AddEmployeeDialogBase : ComponentBase 10 | { 11 | public bool ShowDialog { get; set; } 12 | 13 | public Employee Employee { get; set; } = new Employee { CountryId = 1, JobCategoryId = 1, BirthDate = DateTime.Now, JoinedDate = DateTime.Now }; 14 | 15 | [Parameter] 16 | public EventCallback CloseEventCallback { get; set; } 17 | 18 | [Inject] 19 | public IEmployeeDataService EmployeeDataService { get; set; } 20 | 21 | 22 | 23 | public void Show() 24 | { 25 | ResetDialog(); 26 | ShowDialog = true; 27 | StateHasChanged(); 28 | } 29 | 30 | private void ResetDialog() 31 | { 32 | Employee = new Employee { CountryId = 1, JobCategoryId = 1, BirthDate = DateTime.Now, JoinedDate = DateTime.Now }; 33 | } 34 | 35 | public void Close() 36 | { 37 | ShowDialog = false; 38 | StateHasChanged(); 39 | } 40 | 41 | protected async Task HandleValidSubmit() 42 | { 43 | await EmployeeDataService.AddEmployee(Employee); 44 | ShowDialog = false; 45 | 46 | await CloseEventCallback.InvokeAsync(true); 47 | StateHasChanged(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/EmployeeDetailBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.ComponentsLibrary.Map; 4 | using BethanysPieShopHRM.Server.Services; 5 | using BethanysPieShopHRM.Shared; 6 | using Microsoft.AspNetCore.Components; 7 | 8 | namespace BethanysPieShopHRM.Server.Pages 9 | { 10 | public class EmployeeDetailBase : ComponentBase 11 | { 12 | [Inject] 13 | public IEmployeeDataService EmployeeDataService { get; set; } 14 | 15 | [Inject] 16 | public IJobCategoryDataService JobCategoryDataService{ get; set; } 17 | 18 | [Parameter] 19 | public string EmployeeId { get; set; } 20 | 21 | public List MapMarkers { get; set; } = new List(); 22 | 23 | protected string JobCategory = string.Empty; 24 | 25 | public Employee Employee { get; set; } = new Employee(); 26 | 27 | protected override async Task OnInitializedAsync() 28 | { 29 | Employee = await EmployeeDataService.GetEmployeeDetails(int.Parse(EmployeeId)); 30 | 31 | MapMarkers = new List 32 | { 33 | new Marker{Description = $"{Employee.FirstName} {Employee.LastName}", ShowPopup = false, X = Employee.Longitude, Y = Employee.Latitude} 34 | }; 35 | JobCategory = (await JobCategoryDataService.GetJobCategoryById(Employee.JobCategoryId)).JobCategoryName; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/EmployeeOverview.razor: -------------------------------------------------------------------------------- 1 | @page "/employeeoverview" 2 | @inherits EmployeeOverviewBase 3 | @*@attribute [Authorize(Policy = BethanysPieShopHRM.Shared.Policies.CanManageEmployees)]*@ 4 | 5 |

All employees

6 | 7 | @if (Employees == null) 8 | { 9 |

Loading...

10 | } 11 | else 12 | { 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | @foreach (var employee in Employees) 25 | { 26 | 27 | 28 | 29 | 30 | 31 | 39 | 40 | } 41 | 42 |
Employee IDFirst nameLast name
@employee.EmployeeId@employee.FirstName@employee.LastName 32 | 33 | 34 | 35 | 36 | 37 | 38 |
43 | } 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/EmployeeOverviewBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Net.Http; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Server.Components; 6 | using BethanysPieShopHRM.Server.Services; 7 | using BethanysPieShopHRM.Shared; 8 | using Microsoft.AspNetCore.Components; 9 | using Microsoft.AspNetCore.Components.Authorization; 10 | 11 | namespace BethanysPieShopHRM.Server.Pages 12 | { 13 | public class EmployeeOverviewBase: ComponentBase 14 | { 15 | [CascadingParameter] 16 | Task authenticationStateTask { get; set; } 17 | 18 | [Inject] 19 | public IEmployeeDataService EmployeeDataService { get; set; } 20 | 21 | public List Employees { get; set; } 22 | 23 | protected AddEmployeeDialog AddEmployeeDialog { get; set; } 24 | 25 | protected override async Task OnInitializedAsync() 26 | { 27 | Employees = (await EmployeeDataService.GetAllEmployees()).ToList(); 28 | } 29 | 30 | public async void AddEmployeeDialog_OnDialogClose() 31 | { 32 | Employees = (await EmployeeDataService.GetAllEmployees()).ToList(); 33 | StateHasChanged(); 34 | } 35 | 36 | protected async Task QuickAddEmployee() 37 | { 38 | var authenticationState = await authenticationStateTask; 39 | if (authenticationState.User.Identity.Name == "Kevin") 40 | { 41 | AddEmployeeDialog.Show(); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/Error.razor: -------------------------------------------------------------------------------- 1 | @page "/error" 2 | 3 |

Error.

4 |

An error occurred while processing your request.

5 | 6 |

Development Mode

7 |

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

10 |

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

-------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 |

Welcome to Bethany's Pie Shop HRM!

4 |
5 |

Using this application, you can manage our wonderful staff working for us all over the world, bringing people the best pies ever!

6 | 7 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/Login.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model BethanysPieShopHRM.Server.Pages.LoginModel 3 | @{ 4 | ViewData["Title"] = "Login"; 5 | } 6 |

Login

7 |
8 |
9 |
10 |
11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 |
22 |
23 |
24 | 25 |
26 |
27 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/Login.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System.Threading.Tasks; 7 | using Microsoft.AspNetCore.Authentication; 8 | using Microsoft.AspNetCore.Authentication.Cookies; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.AspNetCore.Mvc.RazorPages; 11 | 12 | namespace BethanysPieShopHRM.Server.Pages 13 | { 14 | public class LoginModel : PageModel 15 | { 16 | [BindProperty] 17 | public string Email { get; set; } 18 | 19 | [BindProperty] 20 | [DataType(DataType.Password)] 21 | public string Password { get; set; } 22 | 23 | 24 | public async Task OnPostAsync() 25 | { 26 | if (!(Email == "kevin.dockx@gmail.com" && Password == "password")) 27 | { 28 | return Page(); 29 | } 30 | 31 | var claims = new List 32 | { 33 | new Claim(ClaimTypes.Name, "Kevin"), 34 | new Claim(ClaimTypes.Email, Email), 35 | }; 36 | 37 | var claimsIdentity = new ClaimsIdentity( 38 | claims, 39 | CookieAuthenticationDefaults.AuthenticationScheme); 40 | 41 | await HttpContext.SignInAsync( 42 | CookieAuthenticationDefaults.AuthenticationScheme, 43 | new ClaimsPrincipal(claimsIdentity)); 44 | 45 | return LocalRedirect(Url.Content("~/")); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/LoginIDP.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model BethanysPieShopHRM.Server.Pages.LoginIDPModel 3 | @{ 4 | ViewData["Title"] = "LoginIDP"; 5 | } 6 | 7 |

LoginIDP

8 | 9 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/LoginIDP.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authentication; 6 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.AspNetCore.Mvc.RazorPages; 9 | 10 | namespace BethanysPieShopHRM.Server.Pages 11 | { 12 | public class LoginIDPModel : PageModel 13 | { 14 | public async Task OnGetAsync() 15 | { 16 | if (!HttpContext.User.Identity.IsAuthenticated) 17 | { 18 | await HttpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme); 19 | } 20 | else 21 | { 22 | // redirect to the root 23 | Response.Redirect(Url.Content("~/").ToString()); 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/Logout.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model BethanysPieShopHRM.Server.Pages.LogoutModel 3 | @{ 4 | ViewData["Title"] = "Logout"; 5 | } 6 | 7 |

Logout

8 | 9 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/Logout.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authentication; 6 | using Microsoft.AspNetCore.Authentication.Cookies; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.AspNetCore.Mvc.RazorPages; 9 | 10 | namespace BethanysPieShopHRM.Server.Pages 11 | { 12 | public class LogoutModel : PageModel 13 | { 14 | public async Task OnGetAsync() 15 | { 16 | await HttpContext 17 | .SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); 18 | 19 | return LocalRedirect(Url.Content("~/")); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/LogoutIDP.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model BethanysPieShopHRM.Server.Pages.LogoutIDPModel 3 | @{ 4 | ViewData["Title"] = "LogoutIDP"; 5 | } 6 | 7 |

LogoutIDP

8 | 9 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/LogoutIDP.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authentication; 6 | using Microsoft.AspNetCore.Authentication.Cookies; 7 | using Microsoft.AspNetCore.Authentication.OpenIdConnect; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.AspNetCore.Mvc.RazorPages; 10 | 11 | namespace BethanysPieShopHRM.Server.Pages 12 | { 13 | public class LogoutIDPModel : PageModel 14 | { 15 | public async Task OnGetAsync() 16 | { 17 | await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); 18 | await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace BethanysPieShopHRM.Server.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Bethany's Pie Shop HR 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | @(await Html.RenderComponentAsync(RenderMode.ServerPrerendered)) 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | BethanysPieShopHRM.Server 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace BethanysPieShopHRM.Server 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "https://localhost:44329/", 7 | "sslPort": 44329 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "launchUrl": "https://localhost:44329/", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "BethanysPieShopHRM.Server": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Services/CountryDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Server.Services 8 | { 9 | public class CountryDataService : ICountryDataService 10 | { 11 | private readonly HttpClient _httpClient; 12 | 13 | public CountryDataService(HttpClient httpClient) 14 | { 15 | _httpClient = httpClient; 16 | } 17 | 18 | public async Task> GetAllCountries() 19 | { 20 | return await JsonSerializer.DeserializeAsync> 21 | (await _httpClient.GetStreamAsync($"api/country"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 22 | } 23 | 24 | public async Task GetCountryById(int countryId) 25 | { 26 | return await JsonSerializer.DeserializeAsync 27 | (await _httpClient.GetStreamAsync($"api/country{countryId}"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Services/EmployeeDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text; 4 | using System.Text.Json; 5 | using System.Threading.Tasks; 6 | using BethanysPieShopHRM.Shared; 7 | using Microsoft.AspNetCore.Authentication; 8 | using Microsoft.AspNetCore.Http; 9 | 10 | namespace BethanysPieShopHRM.Server.Services 11 | { 12 | public class EmployeeDataService : IEmployeeDataService 13 | { 14 | private readonly HttpClient _httpClient; 15 | private readonly IHttpContextAccessor _httpContextAccessor; 16 | 17 | public EmployeeDataService(HttpClient httpClient, 18 | IHttpContextAccessor httpContextAccessor) 19 | { 20 | _httpClient = httpClient ?? 21 | throw new System.ArgumentNullException(nameof(httpClient)); 22 | _httpContextAccessor = httpContextAccessor ?? 23 | throw new System.ArgumentNullException(nameof(httpContextAccessor)); 24 | } 25 | 26 | 27 | public async Task> GetAllEmployees() 28 | { 29 | var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token"); 30 | if (accessToken != null) 31 | { 32 | _httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken); 33 | } 34 | return await JsonSerializer.DeserializeAsync> 35 | (await _httpClient.GetStreamAsync($"api/employee"), new JsonSerializerOptions() 36 | { PropertyNameCaseInsensitive = true }); 37 | } 38 | 39 | public async Task GetEmployeeDetails(int employeeId) 40 | { 41 | return await JsonSerializer.DeserializeAsync 42 | (await _httpClient.GetStreamAsync($"api/employee/{employeeId}"), 43 | new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 44 | } 45 | 46 | public async Task AddEmployee(Employee employee) 47 | { 48 | var employeeJson = 49 | new StringContent(JsonSerializer.Serialize(employee), Encoding.UTF8, "application/json"); 50 | 51 | var response = await _httpClient.PostAsync("api/employee", employeeJson); 52 | 53 | if (response.IsSuccessStatusCode) 54 | { 55 | return await JsonSerializer.DeserializeAsync(await response.Content.ReadAsStreamAsync()); 56 | } 57 | 58 | return null; 59 | } 60 | 61 | public async Task UpdateEmployee(Employee employee) 62 | { 63 | var employeeJson = 64 | new StringContent(JsonSerializer.Serialize(employee), Encoding.UTF8, "application/json"); 65 | 66 | await _httpClient.PutAsync("api/employee", employeeJson); 67 | } 68 | 69 | public async Task DeleteEmployee(int employeeId) 70 | { 71 | await _httpClient.DeleteAsync($"api/employee/{employeeId}"); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Services/ICountryDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Server.Services 6 | { 7 | public interface ICountryDataService 8 | { 9 | Task> GetAllCountries(); 10 | Task GetCountryById(int countryId); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Services/IEmployeeDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Server.Services 6 | { 7 | public interface IEmployeeDataService 8 | { 9 | Task> GetAllEmployees(); 10 | Task GetEmployeeDetails(int employeeId); 11 | Task AddEmployee(Employee employee); 12 | Task UpdateEmployee(Employee employee); 13 | Task DeleteEmployee(int employeeId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Services/IJobCategoryDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Server.Services 6 | { 7 | public interface IJobCategoryDataService 8 | { 9 | Task> GetAllJobCategories(); 10 | Task GetJobCategoryById(int jobCategoryId); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Services/JobCategoryDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Server.Services 8 | { 9 | public class JobCategoryDataService : IJobCategoryDataService 10 | { 11 | private readonly HttpClient _httpClient; 12 | 13 | public JobCategoryDataService(HttpClient httpClient) 14 | { 15 | _httpClient = httpClient; 16 | } 17 | 18 | public async Task> GetAllJobCategories() 19 | { 20 | return await JsonSerializer.DeserializeAsync> 21 | (await _httpClient.GetStreamAsync($"api/jobcategory"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 22 | } 23 | 24 | public async Task GetJobCategoryById(int jobCategoryId) 25 | { 26 | return await JsonSerializer.DeserializeAsync 27 | (await _httpClient.GetStreamAsync($"api/jobcategory/{jobCategoryId}"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 5 | 6 | 7 |
8 | 9 | 16 | 17 |
18 | 19 | @Body 20 |
21 |
22 | 23 |
24 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  2 | 53 | 54 | @code { 55 | bool collapseNavMenu = true; 56 | 57 | string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 58 | 59 | void ToggleNavMenu() 60 | { 61 | collapseNavMenu = !collapseNavMenu; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using BethanysPieShopHRM.Server 9 | @using BethanysPieShopHRM.Server.Shared 10 | 11 | @using BethanysPieShopHRM.Server.Components 12 | 13 | @using BethanysPieShopHRM.ComponentsLibrary 14 | @using BethanysPieShopHRM.ComponentsLibrary.Map -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.Server/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/wwwroot/images/bethanylogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.Server/wwwroot/images/bethanylogo.png -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/wwwroot/images/pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.Server/wwwroot/images/pattern.png -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Server/wwwroot/images/profilePicture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/BethanysPieShopHRM.Server/wwwroot/images/profilePicture.jpg -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Shared/BethanysPieShopHRM.Shared.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Shared/Country.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.Shared 2 | { 3 | public class Country 4 | { 5 | public int CountryId { get; set; } 6 | public string Name { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Shared/Employee.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace BethanysPieShopHRM.Shared 5 | { 6 | public class Employee 7 | { 8 | public int EmployeeId { get; set; } 9 | [Required] 10 | [StringLength(50, ErrorMessage = "First name is too long.")] 11 | public string FirstName { get; set; } 12 | 13 | [Required] 14 | [StringLength(50, ErrorMessage = "Last name is too long.")] 15 | public string LastName { get; set; } 16 | 17 | public DateTime BirthDate { get; set; } 18 | 19 | [Required] 20 | [EmailAddress] 21 | public string Email { get; set; } 22 | public string Street { get; set; } 23 | public string Zip { get; set; } 24 | public string City { get; set; } 25 | public int CountryId { get; set; } 26 | public Country Country { get; set; } 27 | public string PhoneNumber { get; set; } 28 | public bool Smoker { get; set; } 29 | public MaritalStatus MaritalStatus { get; set; } 30 | public Gender Gender { get; set; } 31 | [StringLength(1000, ErrorMessage = "Comment length can't exceed 1000 characters.")] 32 | public string Comment { get; set; } 33 | public DateTime? JoinedDate { get; set; } 34 | public DateTime? ExitDate { get; set; } 35 | 36 | public int JobCategoryId { get; set; } 37 | public JobCategory JobCategory { get; set; } 38 | 39 | public double Latitude { get; set; } 40 | public double Longitude { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Shared/Gender.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.Shared 2 | { 3 | public enum Gender 4 | { 5 | Male, 6 | Female, 7 | Other 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Shared/JobCategory.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.Shared 2 | { 3 | public class JobCategory 4 | { 5 | public int JobCategoryId { get; set; } 6 | public string JobCategoryName { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Shared/MaritalStatus.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.Shared 2 | { 3 | public enum MaritalStatus 4 | { 5 | Married, 6 | Single, 7 | Other 8 | } 9 | } -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.Shared/Policies/Policies.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace BethanysPieShopHRM.Shared 7 | { 8 | public static class Policies 9 | { 10 | public const string CanManageEmployees = "CanManageEmployees"; 11 | 12 | public static AuthorizationPolicy CanManageEmployeesPolicy() 13 | { 14 | return new AuthorizationPolicyBuilder() 15 | .RequireAuthenticatedUser() 16 | .RequireClaim("country", "BE") 17 | .Build(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Finished sample/BethanysPieShopHRM.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29403.142 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BethanysPieShopHRM.Server", "BethanysPieShopHRM.Server\BethanysPieShopHRM.Server.csproj", "{F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BethanysPieShopHRM.Api", "BethanysPieShopHRM.Api\BethanysPieShopHRM.Api.csproj", "{FA4C51A3-7BF1-4577-8575-B43AED0F9A81}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BethanysPieShopHRM.Shared", "BethanysPieShopHRM.Shared\BethanysPieShopHRM.Shared.csproj", "{369581F2-82E5-45E8-BF3C-9E1CC83DD769}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BethanysPieShopHRM.ComponentsLibrary", "BethanysPieShopHRM.ComponentsLibrary\BethanysPieShopHRM.ComponentsLibrary.csproj", "{BD196906-CA10-437E-BBCC-A8BC2A954F13}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marvin.IDP", "Marvin.IDP\Marvin.IDP.csproj", "{8E86CC50-06AD-4E89-90A2-8B3B3F76D685}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {FA4C51A3-7BF1-4577-8575-B43AED0F9A81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {FA4C51A3-7BF1-4577-8575-B43AED0F9A81}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {FA4C51A3-7BF1-4577-8575-B43AED0F9A81}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {FA4C51A3-7BF1-4577-8575-B43AED0F9A81}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {369581F2-82E5-45E8-BF3C-9E1CC83DD769}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {369581F2-82E5-45E8-BF3C-9E1CC83DD769}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {369581F2-82E5-45E8-BF3C-9E1CC83DD769}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {369581F2-82E5-45E8-BF3C-9E1CC83DD769}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {BD196906-CA10-437E-BBCC-A8BC2A954F13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {BD196906-CA10-437E-BBCC-A8BC2A954F13}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {BD196906-CA10-437E-BBCC-A8BC2A954F13}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {BD196906-CA10-437E-BBCC-A8BC2A954F13}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {8E86CC50-06AD-4E89-90A2-8B3B3F76D685}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {8E86CC50-06AD-4E89-90A2-8B3B3F76D685}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {8E86CC50-06AD-4E89-90A2-8B3B3F76D685}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {8E86CC50-06AD-4E89-90A2-8B3B3F76D685}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {8FAD6A7F-346C-4B06-9840-20E884BDEB91} 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Data/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Identity; 6 | 7 | namespace Marvin.IDP.Areas.Identity.Data 8 | { 9 | // Add profile data for application users by adding properties to the ApplicationUser class 10 | public class ApplicationUser : IdentityUser 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Data/UserDbContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Marvin.IDP.Areas.Identity.Data; 6 | using Microsoft.AspNetCore.Identity; 7 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 8 | using Microsoft.EntityFrameworkCore; 9 | 10 | namespace Marvin.IDP.Contexts 11 | { 12 | public class UserDbContext : IdentityDbContext 13 | { 14 | public UserDbContext(DbContextOptions options) 15 | : base(options) 16 | { 17 | } 18 | 19 | protected override void OnModelCreating(ModelBuilder builder) 20 | { 21 | base.OnModelCreating(builder); 22 | // Customize the ASP.NET Identity model and override the defaults if needed. 23 | // For example, you can rename the ASP.NET Identity table names and more. 24 | // Add your customizations after calling base.OnModelCreating(builder); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/IdentityHostingStartup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Marvin.IDP.Areas.Identity.Data; 3 | using Marvin.IDP.Contexts; 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.AspNetCore.Identity; 6 | using Microsoft.AspNetCore.Identity.UI; 7 | using Microsoft.AspNetCore.Identity.UI.Services; 8 | using Microsoft.EntityFrameworkCore; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | [assembly: HostingStartup(typeof(Marvin.IDP.Areas.Identity.IdentityHostingStartup))] 13 | namespace Marvin.IDP.Areas.Identity 14 | { 15 | public class IdentityHostingStartup : IHostingStartup 16 | { 17 | public void Configure(IWebHostBuilder builder) 18 | { 19 | builder.ConfigureServices((context, services) => { 20 | services.AddDbContext(options => 21 | options.UseSqlServer( 22 | context.Configuration.GetConnectionString("UserDbContextConnection"))); 23 | 24 | //services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) 25 | // .AddEntityFrameworkStores(); 26 | 27 | services.AddIdentity(options => 28 | options.SignIn.RequireConfirmedAccount = true) 29 | .AddEntityFrameworkStores() 30 | .AddDefaultTokenProviders(); 31 | 32 | services.AddTransient(); 33 | }); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/Account/ConfirmEmail.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ConfirmEmailModel 3 | @{ 4 | ViewData["Title"] = "Confirm email"; 5 | } 6 | 7 |

@ViewData["Title"]

8 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Marvin.IDP.Areas.Identity.Data; 8 | using Microsoft.AspNetCore.Identity; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.AspNetCore.Mvc.RazorPages; 11 | using Microsoft.AspNetCore.WebUtilities; 12 | 13 | namespace Marvin.IDP.Areas.Identity.Pages.Account 14 | { 15 | [AllowAnonymous] 16 | public class ConfirmEmailModel : PageModel 17 | { 18 | private readonly UserManager _userManager; 19 | 20 | public ConfirmEmailModel(UserManager userManager) 21 | { 22 | _userManager = userManager; 23 | } 24 | 25 | [TempData] 26 | public string StatusMessage { get; set; } 27 | 28 | public async Task OnGetAsync(string userId, string code) 29 | { 30 | if (userId == null || code == null) 31 | { 32 | return RedirectToPage("/Index"); 33 | } 34 | 35 | var user = await _userManager.FindByIdAsync(userId); 36 | if (user == null) 37 | { 38 | return NotFound($"Unable to load user with ID '{userId}'."); 39 | } 40 | 41 | code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); 42 | var result = await _userManager.ConfirmEmailAsync(user, code); 43 | StatusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email."; 44 | return Page(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/Account/Register.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model RegisterModel 3 | @{ 4 | ViewData["Title"] = "Register"; 5 | } 6 | 7 |

@ViewData["Title"]

8 | 9 |
10 |
11 |
12 |

Create a new account.

13 |
14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 | 31 |
32 |
33 |
34 |
35 |

Use another service to register.

36 |
37 | @{ 38 | if ((Model.ExternalLogins?.Count ?? 0) == 0) 39 | { 40 |
41 |

42 | There are no external authentication services configured. See this article 43 | for details on setting up this ASP.NET application to support logging in via external services. 44 |

45 |
46 | } 47 | else 48 | { 49 |
50 |
51 |

52 | @foreach (var provider in Model.ExternalLogins) 53 | { 54 | 55 | } 56 |

57 |
58 |
59 | } 60 | } 61 |
62 |
63 |
64 | 65 | @section Scripts { 66 | 67 | } 68 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model RegisterConfirmationModel 3 | @{ 4 | ViewData["Title"] = "Register confirmation"; 5 | } 6 | 7 |

@ViewData["Title"]

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

12 | This app does not currently have a real email sender registered, see these docs for how to configure a real email sender. 13 | Normally this would be emailed: Click here to confirm your account 14 |

15 | } 16 | else 17 | { 18 |

19 | Please check your email to confirm your account. 20 |

21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using System.Text; 3 | using System.Threading.Tasks; 4 | using Marvin.IDP.Areas.Identity.Data; 5 | using Microsoft.AspNetCore.Identity.UI.Services; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | using Microsoft.AspNetCore.WebUtilities; 9 | using Microsoft.AspNetCore.Identity; 10 | 11 | namespace Marvin.IDP.Areas.Identity.Pages.Account 12 | { 13 | [AllowAnonymous] 14 | public class RegisterConfirmationModel : PageModel 15 | { 16 | private readonly UserManager _userManager; 17 | private readonly IEmailSender _sender; 18 | 19 | public RegisterConfirmationModel(UserManager userManager, IEmailSender sender) 20 | { 21 | _userManager = userManager; 22 | _sender = sender; 23 | } 24 | 25 | public string Email { get; set; } 26 | 27 | public bool DisplayConfirmAccountLink { get; set; } 28 | 29 | public string EmailConfirmationUrl { get; set; } 30 | 31 | public async Task OnGetAsync(string email) 32 | { 33 | if (email == null) 34 | { 35 | return RedirectToPage("/Index"); 36 | } 37 | 38 | var user = await _userManager.FindByEmailAsync(email); 39 | if (user == null) 40 | { 41 | return NotFound($"Unable to load user with email '{email}'."); 42 | } 43 | 44 | Email = email; 45 | // Once you add a real email sender, you should remove this code that lets you confirm the account 46 | DisplayConfirmAccountLink = true; 47 | if (DisplayConfirmAccountLink) 48 | { 49 | var userId = await _userManager.GetUserIdAsync(user); 50 | var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); 51 | code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); 52 | EmailConfirmationUrl = Url.Page( 53 | "/Account/ConfirmEmail", 54 | pageHandler: null, 55 | values: new { area = "Identity", userId = userId, code = code }, 56 | protocol: Request.Scheme); 57 | } 58 | 59 | return Page(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/Account/_StatusMessage.cshtml: -------------------------------------------------------------------------------- 1 | @model string 2 | 3 | @if (!String.IsNullOrEmpty(Model)) 4 | { 5 | var statusMessageClass = Model.StartsWith("Error") ? "danger" : "success"; 6 | 10 | } 11 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/Account/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Marvin.IDP.Areas.Identity.Pages.Account -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @using Marvin.IDP.Areas.Identity 3 | @using Marvin.IDP.Areas.Identity.Pages 4 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 5 | @using Marvin.IDP.Areas.Identity.Data 6 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Areas/Identity/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 |  2 | @{ 3 | Layout = "/Views/Shared/_Layout.cshtml"; 4 | } 5 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Config.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityModel; 6 | using IdentityServer4.Models; 7 | using System.Collections.Generic; 8 | 9 | namespace Marvin.IDP 10 | { 11 | public static class Config 12 | { 13 | public static IEnumerable Ids => 14 | new IdentityResource[] 15 | { 16 | new IdentityResources.OpenId(), 17 | new IdentityResources.Profile(), 18 | new IdentityResources.Email(), 19 | new IdentityResource("country", new [] { "country" }) 20 | }; 21 | 22 | 23 | public static IEnumerable Apis => 24 | new ApiResource[] 25 | { 26 | new ApiResource("bethanyspieshophrapi", 27 | "Bethany's Pie Shop HR API", 28 | new [] { "country" }) 29 | }; 30 | 31 | 32 | public static IEnumerable Clients => 33 | new Client[] 34 | { 35 | new Client 36 | { 37 | ClientId = "bethanyspieshophr", 38 | ClientName = "Bethany's Pie Shop HR", 39 | AllowedGrantTypes = GrantTypes.Hybrid, 40 | ClientSecrets = { new Secret("108B7B4F-BEFC-4DD2-82E1-7F025F0F75D0".Sha256()) }, 41 | RedirectUris = { "https://localhost:44329/signin-oidc" }, 42 | PostLogoutRedirectUris = { "https://localhost:44329/signout-callback-oidc" }, 43 | AllowOfflineAccess = true, 44 | RequireConsent = false, 45 | AllowedScopes = { "openid", "profile", "email", "bethanyspieshophrapi", "country" } 46 | } 47 | }; 48 | } 49 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/DummyEmailSender.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.UI.Services; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Marvin.IDP 8 | { 9 | public class DummyEmailSender : IEmailSender 10 | { 11 | public Task SendEmailAsync(string email, string subject, string htmlMessage) 12 | { 13 | return Task.CompletedTask; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Marvin.IDP.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | all 21 | runtime; build; native; contentfiles; analyzers; buildtransitive 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": true, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "https://localhost:44333", 7 | "sslPort": 44365 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "environmentVariables": { 14 | "ASPNETCORE_ENVIRONMENT": "Development" 15 | }, 16 | "applicationUrl": "https://localhost:44333" 17 | }, 18 | "SelfHost": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Account/AccountOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System; 6 | 7 | namespace IdentityServer4.Quickstart.UI 8 | { 9 | public class AccountOptions 10 | { 11 | public static bool AllowLocalLogin = true; 12 | public static bool AllowRememberLogin = true; 13 | public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30); 14 | 15 | public static bool ShowLogoutPrompt = true; 16 | public static bool AutomaticRedirectAfterSignOut = false; 17 | 18 | // specify the Windows authentication scheme being used 19 | public static readonly string WindowsAuthenticationSchemeName = Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme; 20 | // if user uses windows auth, should we load the groups from windows 21 | public static bool IncludeWindowsGroups = false; 22 | 23 | public static string InvalidCredentialsErrorMessage = "Invalid username or password"; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Account/ExternalProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI 6 | { 7 | public class ExternalProvider 8 | { 9 | public string DisplayName { get; set; } 10 | public string AuthenticationScheme { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Account/LoggedOutViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI 6 | { 7 | public class LoggedOutViewModel 8 | { 9 | public string PostLogoutRedirectUri { get; set; } 10 | public string ClientName { get; set; } 11 | public string SignOutIframeUrl { get; set; } 12 | 13 | public bool AutomaticRedirectAfterSignOut { get; set; } 14 | 15 | public string LogoutId { get; set; } 16 | public bool TriggerExternalSignout => ExternalAuthenticationScheme != null; 17 | public string ExternalAuthenticationScheme { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Account/LoginInputModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace IdentityServer4.Quickstart.UI 8 | { 9 | public class LoginInputModel 10 | { 11 | [Required] 12 | public string Username { get; set; } 13 | [Required] 14 | public string Password { get; set; } 15 | public bool RememberLogin { get; set; } 16 | public string ReturnUrl { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Account/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace IdentityServer4.Quickstart.UI 10 | { 11 | public class LoginViewModel : LoginInputModel 12 | { 13 | public bool AllowRememberLogin { get; set; } = true; 14 | public bool EnableLocalLogin { get; set; } = true; 15 | 16 | public IEnumerable ExternalProviders { get; set; } = Enumerable.Empty(); 17 | public IEnumerable VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName)); 18 | 19 | public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1; 20 | public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null; 21 | } 22 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Account/LogoutInputModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI 6 | { 7 | public class LogoutInputModel 8 | { 9 | public string LogoutId { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Account/LogoutViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI 6 | { 7 | public class LogoutViewModel : LogoutInputModel 8 | { 9 | public bool ShowLogoutPrompt { get; set; } = true; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Account/RedirectViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | 6 | namespace IdentityServer4.Quickstart.UI 7 | { 8 | public class RedirectViewModel 9 | { 10 | public string RedirectUrl { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Consent/ConsentInputModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.Collections.Generic; 6 | 7 | namespace IdentityServer4.Quickstart.UI 8 | { 9 | public class ConsentInputModel 10 | { 11 | public string Button { get; set; } 12 | public IEnumerable ScopesConsented { get; set; } 13 | public bool RememberConsent { get; set; } 14 | public string ReturnUrl { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Consent/ConsentOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI 6 | { 7 | public class ConsentOptions 8 | { 9 | public static bool EnableOfflineAccess = true; 10 | public static string OfflineAccessDisplayName = "Offline Access"; 11 | public static string OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; 12 | 13 | public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission"; 14 | public static readonly string InvalidSelectionErrorMessage = "Invalid selection"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Consent/ConsentViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.Collections.Generic; 6 | 7 | namespace IdentityServer4.Quickstart.UI 8 | { 9 | public class ConsentViewModel : ConsentInputModel 10 | { 11 | public string ClientName { get; set; } 12 | public string ClientUrl { get; set; } 13 | public string ClientLogoUrl { get; set; } 14 | public bool AllowRememberConsent { get; set; } 15 | 16 | public IEnumerable IdentityScopes { get; set; } 17 | public IEnumerable ResourceScopes { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Consent/ProcessConsentResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI 6 | { 7 | public class ProcessConsentResult 8 | { 9 | public bool IsRedirect => RedirectUri != null; 10 | public string RedirectUri { get; set; } 11 | public string ClientId { get; set; } 12 | 13 | public bool ShowView => ViewModel != null; 14 | public ConsentViewModel ViewModel { get; set; } 15 | 16 | public bool HasValidationError => ValidationError != null; 17 | public string ValidationError { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Consent/ScopeViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI 6 | { 7 | public class ScopeViewModel 8 | { 9 | public string Name { get; set; } 10 | public string DisplayName { get; set; } 11 | public string Description { get; set; } 12 | public bool Emphasize { get; set; } 13 | public bool Required { get; set; } 14 | public bool Checked { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Device/DeviceAuthorizationInputModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI.Device 6 | { 7 | public class DeviceAuthorizationInputModel : ConsentInputModel 8 | { 9 | public string UserCode { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Device/DeviceAuthorizationViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer4.Quickstart.UI.Device 6 | { 7 | public class DeviceAuthorizationViewModel : ConsentViewModel 8 | { 9 | public string UserCode { get; set; } 10 | public bool ConfirmUserCode { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Diagnostics/DiagnosticsController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Microsoft.AspNetCore.Authentication; 8 | using Microsoft.AspNetCore.Authorization; 9 | using Microsoft.AspNetCore.Mvc; 10 | 11 | namespace IdentityServer4.Quickstart.UI 12 | { 13 | [SecurityHeaders] 14 | [Authorize] 15 | public class DiagnosticsController : Controller 16 | { 17 | public async Task Index() 18 | { 19 | var localAddresses = new string[] { "127.0.0.1", "::1", HttpContext.Connection.LocalIpAddress.ToString() }; 20 | if (!localAddresses.Contains(HttpContext.Connection.RemoteIpAddress.ToString())) 21 | { 22 | return NotFound(); 23 | } 24 | 25 | var model = new DiagnosticsViewModel(await HttpContext.AuthenticateAsync()); 26 | return View(model); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Diagnostics/DiagnosticsViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityModel; 6 | using Microsoft.AspNetCore.Authentication; 7 | using Newtonsoft.Json; 8 | using System.Collections.Generic; 9 | using System.Text; 10 | 11 | namespace IdentityServer4.Quickstart.UI 12 | { 13 | public class DiagnosticsViewModel 14 | { 15 | public DiagnosticsViewModel(AuthenticateResult result) 16 | { 17 | AuthenticateResult = result; 18 | 19 | if (result.Properties.Items.ContainsKey("client_list")) 20 | { 21 | var encoded = result.Properties.Items["client_list"]; 22 | var bytes = Base64Url.Decode(encoded); 23 | var value = Encoding.UTF8.GetString(bytes); 24 | 25 | Clients = JsonConvert.DeserializeObject(value); 26 | } 27 | } 28 | 29 | public AuthenticateResult AuthenticateResult { get; } 30 | public IEnumerable Clients { get; } = new List(); 31 | } 32 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using IdentityServer4.Stores; 3 | 4 | namespace IdentityServer4.Quickstart.UI 5 | { 6 | public static class Extensions 7 | { 8 | /// 9 | /// Determines whether the client is configured to use PKCE. 10 | /// 11 | /// The store. 12 | /// The client identifier. 13 | /// 14 | public static async Task IsPkceClientAsync(this IClientStore store, string client_id) 15 | { 16 | if (!string.IsNullOrWhiteSpace(client_id)) 17 | { 18 | var client = await store.FindEnabledClientByIdAsync(client_id); 19 | return client?.RequirePkce == true; 20 | } 21 | 22 | return false; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Grants/GrantsViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace IdentityServer4.Quickstart.UI 9 | { 10 | public class GrantsViewModel 11 | { 12 | public IEnumerable Grants { get; set; } 13 | } 14 | 15 | public class GrantViewModel 16 | { 17 | public string ClientId { get; set; } 18 | public string ClientName { get; set; } 19 | public string ClientUrl { get; set; } 20 | public string ClientLogoUrl { get; set; } 21 | public DateTime Created { get; set; } 22 | public DateTime? Expires { get; set; } 23 | public IEnumerable IdentityGrantNames { get; set; } 24 | public IEnumerable ApiGrantNames { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Home/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityServer4.Models; 6 | 7 | namespace IdentityServer4.Quickstart.UI 8 | { 9 | public class ErrorViewModel 10 | { 11 | public ErrorViewModel() 12 | { 13 | } 14 | 15 | public ErrorViewModel(string error) 16 | { 17 | Error = new ErrorMessage { Error = error }; 18 | } 19 | 20 | public ErrorMessage Error { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/Home/HomeController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityServer4.Services; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.Extensions.Logging; 11 | using System.Threading.Tasks; 12 | 13 | namespace IdentityServer4.Quickstart.UI 14 | { 15 | [SecurityHeaders] 16 | [AllowAnonymous] 17 | public class HomeController : Controller 18 | { 19 | private readonly IIdentityServerInteractionService _interaction; 20 | private readonly IWebHostEnvironment _environment; 21 | private readonly ILogger _logger; 22 | 23 | public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment, ILogger logger) 24 | { 25 | _interaction = interaction; 26 | _environment = environment; 27 | _logger = logger; 28 | } 29 | 30 | public IActionResult Index() 31 | { 32 | if (_environment.IsDevelopment()) 33 | { 34 | // only show in development 35 | return View(); 36 | } 37 | 38 | _logger.LogInformation("Homepage is disabled in production. Returning 404."); 39 | return NotFound(); 40 | } 41 | 42 | /// 43 | /// Shows the error page 44 | /// 45 | public async Task Error(string errorId) 46 | { 47 | var vm = new ErrorViewModel(); 48 | 49 | // retrieve error details from identityserver 50 | var message = await _interaction.GetErrorContextAsync(errorId); 51 | if (message != null) 52 | { 53 | vm.Error = message; 54 | 55 | if (!_environment.IsDevelopment()) 56 | { 57 | // only show in development 58 | message.ErrorDescription = null; 59 | } 60 | } 61 | 62 | return View("Error", vm); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/SecurityHeadersAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.Filters; 7 | 8 | namespace IdentityServer4.Quickstart.UI 9 | { 10 | public class SecurityHeadersAttribute : ActionFilterAttribute 11 | { 12 | public override void OnResultExecuting(ResultExecutingContext context) 13 | { 14 | var result = context.Result; 15 | if (result is ViewResult) 16 | { 17 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options 18 | if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) 19 | { 20 | context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); 21 | } 22 | 23 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options 24 | if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) 25 | { 26 | context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); 27 | } 28 | 29 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 30 | var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';"; 31 | // also consider adding upgrade-insecure-requests once you have HTTPS in place for production 32 | //csp += "upgrade-insecure-requests;"; 33 | // also an example if you need client images to be displayed from twitter 34 | // csp += "img-src 'self' https://pbs.twimg.com;"; 35 | 36 | // once for standards compliant browsers 37 | if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) 38 | { 39 | context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); 40 | } 41 | // and once again for IE 42 | if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) 43 | { 44 | context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); 45 | } 46 | 47 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy 48 | var referrer_policy = "no-referrer"; 49 | if (!context.HttpContext.Response.Headers.ContainsKey("Referrer-Policy")) 50 | { 51 | context.HttpContext.Response.Headers.Add("Referrer-Policy", referrer_policy); 52 | } 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Quickstart/TestUsers.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityModel; 6 | using IdentityServer4.Test; 7 | using System.Collections.Generic; 8 | using System.Security.Claims; 9 | 10 | namespace Marvin.IDP 11 | { 12 | public class TestUsers 13 | { 14 | public static List Users = new List 15 | { 16 | new TestUser{SubjectId = "06c71238-0137-4df6-bb6a-e50e62a4a7c5", 17 | Username = "Jack", Password = "password", 18 | Claims = 19 | { 20 | new Claim(JwtClaimTypes.Name, "Jack Torrance"), 21 | new Claim(JwtClaimTypes.GivenName, "Jack"), 22 | new Claim(JwtClaimTypes.FamilyName, "Torrance"), 23 | new Claim(JwtClaimTypes.Email, "jack.torrance@email.com"), 24 | new Claim("country", "BE") 25 | } 26 | }, 27 | new TestUser{SubjectId = "37d0f2fa-1069-489f-9d65-48c9ba44639b", 28 | Username = "Wendy", Password = "password", 29 | Claims = 30 | { 31 | new Claim(JwtClaimTypes.Name, "Wendy Torrance"), 32 | new Claim(JwtClaimTypes.GivenName, "Wendy"), 33 | new Claim(JwtClaimTypes.FamilyName, "Torrance"), 34 | new Claim(JwtClaimTypes.Email, "wendy.torrance@email.com"), 35 | new Claim("country", "NL") 36 | } 37 | } 38 | }; 39 | } 40 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/ScaffoldingReadme.txt: -------------------------------------------------------------------------------- 1 | Support for ASP.NET Core Identity was added to your project 2 | - The code for adding Identity to your project was generated under Areas/Identity. 3 | 4 | Configuration of the Identity related services can be found in the Areas/Identity/IdentityHostingStartup.cs file. 5 | 6 | 7 | The generated UI requires support for static files. To add static files to your app: 8 | 1. Call app.UseStaticFiles() from your Configure method 9 | 10 | To use ASP.NET Core Identity you also need to enable authentication. To authentication to your app: 11 | 1. Call app.UseAuthentication() from your Configure method (after static files) 12 | 13 | The generated UI requires MVC. To add MVC to your app: 14 | 1. Call services.AddMvc() from your ConfigureServices method 15 | 2. Call app.UseRouting() at the top your Configure method, and UseEndpoints() after authentication: 16 | app.UseEndpoints(endpoints => 17 | { 18 | endpoints.MapControllers(); 19 | endpoints.MapRazorPages(); 20 | }); 21 | 22 | Apps that use ASP.NET Core Identity should also use HTTPS. To enable HTTPS see https://go.microsoft.com/fwlink/?linkid=848054. 23 | 24 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityServer4; 6 | using IdentityServer4.Quickstart.UI; 7 | using Marvin.IDP.Areas.Identity.Data; 8 | using Microsoft.AspNetCore.Builder; 9 | using Microsoft.AspNetCore.Hosting; 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | using Microsoft.Extensions.Hosting; 13 | 14 | namespace Marvin.IDP 15 | { 16 | public class Startup 17 | { 18 | public IWebHostEnvironment Environment { get; } 19 | public IConfiguration Configuration { get; } 20 | 21 | public Startup(IWebHostEnvironment environment, IConfiguration configuration) 22 | { 23 | Environment = environment; 24 | Configuration = configuration; 25 | } 26 | 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | // services.AddControllersWithViews(); 30 | services.AddMvc(); 31 | 32 | // configures IIS out-of-proc settings (see https://github.com/aspnet/AspNetCore/issues/14882) 33 | services.Configure(iis => 34 | { 35 | iis.AuthenticationDisplayName = "Windows"; 36 | iis.AutomaticAuthentication = false; 37 | }); 38 | 39 | // configures IIS in-proc settings 40 | services.Configure(iis => 41 | { 42 | iis.AuthenticationDisplayName = "Windows"; 43 | iis.AutomaticAuthentication = false; 44 | }); 45 | 46 | var builder = services.AddIdentityServer(options => 47 | { 48 | options.Events.RaiseErrorEvents = true; 49 | options.Events.RaiseInformationEvents = true; 50 | options.Events.RaiseFailureEvents = true; 51 | options.Events.RaiseSuccessEvents = true; 52 | }).AddAspNetIdentity(); 53 | 54 | // in-memory, code config 55 | builder.AddInMemoryIdentityResources(Config.Ids); 56 | builder.AddInMemoryApiResources(Config.Apis); 57 | builder.AddInMemoryClients(Config.Clients); 58 | 59 | // not recommended for production - you need to store your key material somewhere secure 60 | builder.AddDeveloperSigningCredential(); 61 | 62 | services.AddAuthentication(); 63 | } 64 | 65 | public void Configure(IApplicationBuilder app) 66 | { 67 | if (Environment.IsDevelopment()) 68 | { 69 | app.UseDeveloperExceptionPage(); 70 | } 71 | 72 | app.UseStaticFiles(); 73 | 74 | app.UseRouting(); 75 | app.UseIdentityServer(); 76 | app.UseAuthorization(); 77 | app.UseEndpoints(endpoints => 78 | { 79 | endpoints.MapControllers(); 80 | endpoints.MapDefaultControllerRoute(); 81 | endpoints.MapRazorPages(); 82 | }); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Account/AccessDenied.cshtml: -------------------------------------------------------------------------------- 1 |  2 |
3 | 6 | 7 |

You do not have access to that resource.

8 |
-------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Account/LoggedOut.cshtml: -------------------------------------------------------------------------------- 1 | @model LoggedOutViewModel 2 | 3 | @{ 4 | // set this so the layout rendering sees an anonymous user 5 | ViewData["signed-out"] = true; 6 | } 7 | 8 | 27 | 28 | @section scripts 29 | { 30 | @if (Model.AutomaticRedirectAfterSignOut) 31 | { 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Account/Logout.cshtml: -------------------------------------------------------------------------------- 1 | @model LogoutViewModel 2 | 3 |
4 | 7 | 8 |
9 |
10 |

Would you like to logout of IdentityServer?

11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 |
19 |
20 |
21 |
-------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Consent/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model ConsentViewModel 2 | 3 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Device/Success.cshtml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Device/UserCodeCapture.cshtml: -------------------------------------------------------------------------------- 1 | @model string 2 | 3 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Diagnostics/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model DiagnosticsViewModel 2 | 3 |

Authentication cookie

4 | 5 |

Claims

6 |
7 | @foreach (var claim in Model.AuthenticateResult.Principal.Claims) 8 | { 9 |
@claim.Type
10 |
@claim.Value
11 | } 12 |
13 | 14 |

Properties

15 |
16 | @foreach (var prop in Model.AuthenticateResult.Properties.Items) 17 | { 18 |
@prop.Key
19 |
@prop.Value
20 | } 21 |
22 | 23 | @if (Model.Clients.Any()) 24 | { 25 |

Clients

26 |
    27 | @foreach (var client in Model.Clients) 28 | { 29 |
  • @client
  • 30 | } 31 |
32 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Grants/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model GrantsViewModel 2 | 3 |
4 | 12 | 13 | @if (Model.Grants.Any() == false) 14 | { 15 |
16 |
17 |
18 | You have not given access to any applications 19 |
20 |
21 |
22 | } 23 | else 24 | { 25 | foreach (var grant in Model.Grants) 26 | { 27 |
28 |
29 | @if (grant.ClientLogoUrl != null) 30 | { 31 | 32 | } 33 |
34 |
35 |
@grant.ClientName
36 |
37 | Created: @grant.Created.ToString("yyyy-MM-dd") 38 |
39 | @if (grant.Expires.HasValue) 40 | { 41 |
42 | Expires: @grant.Expires.Value.ToString("yyyy-MM-dd") 43 |
44 | } 45 | @if (grant.IdentityGrantNames.Any()) 46 | { 47 |
48 |
Identity Grants
49 |
    50 | @foreach (var name in grant.IdentityGrantNames) 51 | { 52 |
  • @name
  • 53 | } 54 |
55 |
56 | } 57 | @if (grant.ApiGrantNames.Any()) 58 | { 59 |
60 |
API Grants
61 |
    62 | @foreach (var name in grant.ApiGrantNames) 63 | { 64 |
  • @name
  • 65 | } 66 |
67 |
68 | } 69 |
70 |
71 |
72 | 73 | 74 |
75 |
76 |
77 | } 78 | } 79 |
-------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | var version = typeof(IdentityServer4.Hosting.IdentityServerMiddleware).Assembly.GetName().Version.ToString(); 3 | } 4 | 5 |
6 | 15 | 16 |
17 |
18 |

19 | IdentityServer publishes a 20 | discovery document 21 | where you can find metadata and links to all the endpoints, key material, etc. 22 |

23 |
24 |
25 |

26 | Click here to manage your stored grants. 27 |

28 |
29 |
30 |
31 |
32 |

33 | Here are links to the 34 | source code repository, 35 | and ready to use samples. 36 |

37 |
38 |
39 |
40 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | 3 | @{ 4 | var error = Model?.Error?.Error; 5 | var errorDescription = Model?.Error?.ErrorDescription; 6 | var request_id = Model?.Error?.RequestId; 7 | } 8 | 9 |
10 | 13 | 14 |
15 |
16 |
17 | Sorry, there was an error 18 | 19 | @if (error != null) 20 | { 21 | 22 | 23 | : @error 24 | 25 | 26 | 27 | if (errorDescription != null) 28 | { 29 |
@errorDescription
30 | } 31 | } 32 |
33 | 34 | @if (request_id != null) 35 | { 36 |
Request Id: @request_id
37 | } 38 |
39 |
40 |
41 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Shared/Redirect.cshtml: -------------------------------------------------------------------------------- 1 | @model RedirectViewModel 2 | 3 |

You are now being returned to the application.

4 |

Once complete, you may close this tab

5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Shared/_CookieConsentPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Http.Features 2 | 3 | @{ 4 | var consentFeature = Context.Features.Get(); 5 | var showBanner = !consentFeature?.CanTrack ?? false; 6 | var cookieString = consentFeature?.CreateConsentCookie(); 7 | } 8 | 9 | @if (showBanner) 10 | { 11 | 33 | 41 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @using IdentityServer4.Extensions 2 | @{ 3 | string name = null; 4 | if (!true.Equals(ViewData["signed-out"])) 5 | { 6 | name = Context.User?.GetDisplayName(); 7 | } 8 | } 9 | 10 | 11 | 12 | 13 | 14 | 15 | IdentityServer4 16 | 17 | 18 | 19 | 20 | 21 | 22 | 52 | 53 |
54 | @RenderBody() 55 |
56 | 57 | 58 | 59 | @RenderSection("scripts", required: false) 60 | 61 | 62 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @using Marvin.IDP.Areas.Identity.Data 3 | 4 | @inject SignInManager SignInManager 5 | @inject UserManager UserManager 6 | 7 | @if (SignInManager.IsSignedIn(User)) 8 | { 9 | 19 | } 20 | else 21 | { 22 | 26 | } 27 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Shared/_ScopeListItem.cshtml: -------------------------------------------------------------------------------- 1 | @model ScopeViewModel 2 | 3 |
  • 4 | 24 | @if (Model.Required) 25 | { 26 | (required) 27 | } 28 | @if (Model.Description != null) 29 | { 30 | 33 | } 34 |
  • -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/Shared/_ValidationSummary.cshtml: -------------------------------------------------------------------------------- 1 | @if (ViewContext.ModelState.IsValid == false) 2 | { 3 |
    4 | Error 5 |
    6 |
    7 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using IdentityServer4.Quickstart.UI 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "IdentityResources": [ 3 | { 4 | "Name": "openid", 5 | "DisplayName": "Your user identifier", 6 | "Required": true, 7 | "UserClaims": [ 8 | "sub" 9 | ] 10 | }, 11 | { 12 | "Name": "profile", 13 | "DisplayName": "User profile", 14 | "Description": "Your user profile information (first name, last name, etc.)", 15 | "Emphasize": true, 16 | "UserClaims": [ 17 | "name", 18 | "family_name", 19 | "given_name", 20 | "middle_name", 21 | "preferred_username", 22 | "profile", 23 | "picture", 24 | "website", 25 | "gender", 26 | "birthdate", 27 | "zoneinfo", 28 | "locale", 29 | "updated_at" 30 | ] 31 | } 32 | ], 33 | "ApiResources": [ 34 | { 35 | "Name": "api1", 36 | "DisplayName": "My API #1", 37 | "Scopes": [ 38 | { 39 | "Name": "api1" 40 | } 41 | ] 42 | } 43 | ], 44 | "Clients": [ 45 | { 46 | "ClientId": "client", 47 | "ClientName": "Client Credentials Client", 48 | "ClientSecrets": [ 49 | { 50 | "Value": "fU7fRb+g6YdlniuSqviOLWNkda1M/MuPtH6zNI9inF8=" 51 | } 52 | ], 53 | "AllowedGrantTypes": [ 54 | "client_credentials" 55 | ], 56 | "AllowedScopes": [ 57 | "api1" 58 | ] 59 | }, 60 | { 61 | "ClientId": "mvc", 62 | "ClientName": "MVC Client", 63 | "ClientSecrets": [ 64 | { 65 | "Value": "o90IbCACXKUkunXoa18cODcLKnQTbjOo5ihEw9j58+8=" 66 | } 67 | ], 68 | "AllowedGrantTypes": [ 69 | "code", 70 | "client_credentials" 71 | ], 72 | "RequirePkce": true, 73 | "AllowedScopes": [ 74 | "openid", 75 | "profile", 76 | "api1" 77 | ], 78 | "AllowOfflineAccess": true, 79 | "RedirectUris": [ 80 | "http://localhost:5003/signin-oidc" 81 | ], 82 | "FrontChannelLogoutUris": [ 83 | "http://localhost:5003/signout-oidc" 84 | ], 85 | "PostLogoutRedirectUris": [ 86 | "http://localhost:5003/signout-callback-oidc" 87 | ] 88 | }, 89 | { 90 | "ClientId": "spa", 91 | "ClientName": "SPA Client", 92 | "AllowedGrantTypes": [ 93 | "implicit" 94 | ], 95 | "AllowedScopes": [ 96 | "openid", 97 | "profile", 98 | "api1" 99 | ], 100 | "AllowAccessTokensViaBrowser": true, 101 | "RedirectUris": [ 102 | "http://localhost:5002/index.html", 103 | "http://localhost:5002/callback.html", 104 | "http://localhost:5002/silent.html", 105 | "http://localhost:5002/popup.html" 106 | ], 107 | "FrontChannelLogoutUris": [ 108 | "http://localhost:5002/index.html" 109 | ], 110 | "PostLogoutRedirectUris": [ 111 | "http://localhost:5002" 112 | ], 113 | "AllowedCorsOrigins": [ 114 | "http://localhost:5002" 115 | ] 116 | } 117 | ], 118 | "ConnectionStrings": { 119 | "UserDbContextConnection": "Server=(localdb)\\mssqllocaldb;Database=Marvin.IDP;Trusted_Connection=True;MultipleActiveResultSets=true" 120 | } 121 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/tempkey.rsa: -------------------------------------------------------------------------------- 1 | {"KeyId":"fcauOto8R_dUVSyGIYm_nQ","Parameters":{"D":"s9SNkwUJLOVSCYx1gqwhiFxqA3VkXJ8jwB2lcMy0nzxNNov5jws4ZCrIn+ePWkKzmyknWEoGnvGqRsXY48ohklpx6jQVsdW1BWUwKI8ELFYVC2gAXlEBNIfAVS/eBr9efR/zL43HBbp5PDTgwattVTVkOOqDn23xmxCp/pKipY+B8QzU4xbZVrrkxJ+8+gIboIF3zg+vgBYNroiRyuscSzj4yjxdZh4v+1kRiJSPMkSrF993/K4OS6MAMly1me/G1IhdHhyW18L+Mk3M3jDKE2n3kmvS7bN9Hkgl5krbpJkykQDLsxHFimH7EcF1aj4CFSsK5lCoixd2BbiW8/LUAQ==","DP":"uKu+vNwWDKuUGU3lPRKk48sNPwOlfZ2DU93TX24Vm6FilyzcfWCBP9GrMb5FczTdS4tIeevMqUn8k6TJ5hDrX0W0BbKu3P1BkUtMuXsV5QhEv3vS2TeZeBm3ErW6AXGlNE84DSXfJO0i8TcF6650ZgxF9ED4xJO9trZ3bmIb6I0=","DQ":"GEE9OHcMm1ulH/zpDAbZ0SIKCzrc8/sfNur9dIbMd0SrFp9de9N7wi7ZKI3YD3RSSLfIj8PZet9NE7yX5hIdzEfIrm8UbDJNP1uUxa1gN1hu9ifcxVLDqKycK+JZkvcpPMYzv0ZWJPtUvXWZq8smffqNlgbcSrQueWW4CW0sL60=","Exponent":"AQAB","InverseQ":"Vml/fV7PqCdWrgNuUJZNTEUELHiA+krYlLYQBWI3bZXhsyiuQNu4yCFgigzbXCDIAjHJTMTEUXOrBpHNJsqc+eHVz/ZKYFy/6ShCf2NL3qDwO9N3DiURsI9x60lQRSJmDM9A4dhgfhJCmr2IJcA5cciI2CzqfZ6aGGHd+qQiEeM=","Modulus":"1iBz+rp5rvN+Il/YxwDDhMDUY93z4Q7irPSQvKlAzLrZPbxanmKQl64M2YbExXEuR0cn5SQpkTqvS4kT1xV1HlghqKkUHtzB6X+nW2HYYz9pPB3SfDYGkxfDHIDVY49axj5wS50g1by4g8lc1Jigv0S7c90n70NaiPDXlk9V/dvp0tw2oQivp+Xyn9wPLk5yIlSeb+8dxqrMnOI36YMH9lBur0c/cwd6O2M9SnTKiSurMApKmL9KnBUdd+UbZwzL3RmvA9hT7sMJv0OpngIKeepWpcWsS9Q3bIq+RjcsP+7aeZb210N+0EeuIaVqym4PonK3eiZudos2aAv3+KelZQ==","P":"94fogTwXSvmVvQ4I6psYW/uGCYiq/MetkxSCi8MU26XPGbR6Ea5rNdQ5MWcBVm87eHVNp0koam01PGBIxZfwwRo/qhV9oF+pSYv8ISxSufzOFJcY0BAuqPdLMvLcoglFUmyn0f9qRTKxRq7vP8OEKkRb3CO2r4ySnZ61dPc57rs=","Q":"3XP2XCqxaO8cu4Z+ACOWbrKUH9hY+jma7Zq53cVnJOrmOZQnfMn9NM4eFF1SAN6b0do9wT6+HiDzxLa7Z7aGwTcr8kvadIGVx2TvbNp6JB2czWLAoXjwEtcompay8LDCud0RPjOxXv3ZpzUb8HrEewIyF/uEg4w0IGPpbfYSSl8="}} -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-top: 65px; 3 | } 4 | .navbar-header { 5 | position: relative; 6 | top: -4px; 7 | } 8 | .navbar-brand > .icon-banner { 9 | position: relative; 10 | top: -2px; 11 | display: inline; 12 | } 13 | .icon { 14 | position: relative; 15 | top: -10px; 16 | } 17 | .logged-out iframe { 18 | display: none; 19 | width: 0; 20 | height: 0; 21 | } 22 | .page-consent .client-logo { 23 | float: left; 24 | } 25 | .page-consent .client-logo img { 26 | width: 80px; 27 | height: 80px; 28 | } 29 | .page-consent .consent-buttons { 30 | margin-top: 25px; 31 | } 32 | .page-consent .consent-form .consent-scopecheck { 33 | display: inline-block; 34 | margin-right: 5px; 35 | } 36 | .page-consent .consent-form .consent-description { 37 | margin-left: 25px; 38 | } 39 | .page-consent .consent-form .consent-description label { 40 | font-weight: normal; 41 | } 42 | .page-consent .consent-form .consent-remember { 43 | padding-left: 16px; 44 | } 45 | .grants .page-header { 46 | margin-bottom: 10px; 47 | } 48 | .grants .grant { 49 | margin-top: 20px; 50 | padding-bottom: 20px; 51 | border-bottom: 1px solid lightgray; 52 | } 53 | .grants .grant img { 54 | width: 100px; 55 | height: 100px; 56 | } 57 | .grants .grant .clientname { 58 | font-size: 140%; 59 | font-weight: bold; 60 | } 61 | .grants .grant .granttype { 62 | font-size: 120%; 63 | font-weight: bold; 64 | } 65 | .grants .grant .created { 66 | font-size: 120%; 67 | font-weight: bold; 68 | } 69 | .grants .grant .expires { 70 | font-size: 120%; 71 | font-weight: bold; 72 | } 73 | .grants .grant li { 74 | list-style-type: none; 75 | display: inline; 76 | } 77 | .grants .grant li:after { 78 | content: ', '; 79 | } 80 | .grants .grant li:last-child:after { 81 | content: ''; 82 | } -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/css/site.less: -------------------------------------------------------------------------------- 1 | body { 2 | margin-top: 65px; 3 | } 4 | 5 | .navbar-header { 6 | position: relative; 7 | top: -4px; 8 | } 9 | 10 | .navbar-brand > .icon-banner { 11 | position: relative; 12 | top: -2px; 13 | display: inline; 14 | } 15 | 16 | .icon { 17 | position: relative; 18 | top: -10px; 19 | } 20 | 21 | .logged-out iframe { 22 | display: none; 23 | width: 0; 24 | height: 0; 25 | } 26 | 27 | .page-consent { 28 | .client-logo { 29 | float: left; 30 | 31 | img { 32 | width: 80px; 33 | height: 80px; 34 | } 35 | } 36 | 37 | .consent-buttons { 38 | margin-top: 25px; 39 | } 40 | 41 | .consent-form { 42 | .consent-scopecheck { 43 | display: inline-block; 44 | margin-right: 5px; 45 | } 46 | 47 | .consent-scopecheck[disabled] { 48 | //visibility:hidden; 49 | } 50 | 51 | .consent-description { 52 | margin-left: 25px; 53 | 54 | label { 55 | font-weight: normal; 56 | } 57 | } 58 | 59 | .consent-remember { 60 | padding-left: 16px; 61 | } 62 | } 63 | } 64 | 65 | .grants { 66 | .page-header { 67 | margin-bottom: 10px; 68 | } 69 | 70 | .grant { 71 | margin-top: 20px; 72 | padding-bottom: 20px; 73 | border-bottom: 1px solid lightgray; 74 | 75 | img { 76 | width: 100px; 77 | height: 100px; 78 | } 79 | 80 | .clientname { 81 | font-size: 140%; 82 | font-weight: bold; 83 | } 84 | 85 | .granttype { 86 | font-size: 120%; 87 | font-weight: bold; 88 | } 89 | 90 | .created { 91 | font-size: 120%; 92 | font-weight: bold; 93 | } 94 | 95 | .expires { 96 | font-size: 120%; 97 | font-weight: bold; 98 | } 99 | 100 | li { 101 | list-style-type: none; 102 | display: inline; 103 | 104 | &:after { 105 | content: ', '; 106 | } 107 | 108 | &:last-child:after { 109 | content: ''; 110 | } 111 | 112 | .displayname { 113 | } 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{margin-top:65px;}.navbar-header{position:relative;top:-4px;}.navbar-brand>.icon-banner{position:relative;top:-2px;display:inline;}.icon{position:relative;top:-10px;}.logged-out iframe{display:none;width:0;height:0;}.page-consent .client-logo{float:left;}.page-consent .client-logo img{width:80px;height:80px;}.page-consent .consent-buttons{margin-top:25px;}.page-consent .consent-form .consent-scopecheck{display:inline-block;margin-right:5px;}.page-consent .consent-form .consent-description{margin-left:25px;}.page-consent .consent-form .consent-description label{font-weight:normal;}.page-consent .consent-form .consent-remember{padding-left:16px;}.grants .page-header{margin-bottom:10px;}.grants .grant{margin-top:20px;padding-bottom:20px;border-bottom:1px solid #d3d3d3;}.grants .grant img{width:100px;height:100px;}.grants .grant .clientname{font-size:140%;font-weight:bold;}.grants .grant .granttype{font-size:120%;font-weight:bold;}.grants .grant .created{font-size:120%;font-weight:bold;}.grants .grant .expires{font-size:120%;font-weight:bold;}.grants .grant li{list-style-type:none;display:inline;}.grants .grant li:after{content:', ';}.grants .grant li:last-child:after{content:'';} -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/Marvin.IDP/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/Marvin.IDP/wwwroot/icon.jpg -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/Marvin.IDP/wwwroot/icon.png -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/js/signin-redirect.js: -------------------------------------------------------------------------------- 1 | window.location.href = document.querySelector("meta[http-equiv=refresh]").getAttribute("data-url"); 2 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/js/signout-redirect.js: -------------------------------------------------------------------------------- 1 | window.addEventListener("load", function () { 2 | var a = document.querySelector("a.PostLogoutRedirectUri"); 3 | if (a) { 4 | window.location = a.href; 5 | } 6 | }); 7 | -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/Marvin.IDP/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/Marvin.IDP/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/Marvin.IDP/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Finished sample/Marvin.IDP/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Finished sample/Marvin.IDP/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Kevin Dockx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Authentication and Authorization in Blazor Applications 2 | Fully functioning finished sample code for my Authentication and Authorization in Blazor Applications course. 3 | 4 | This repo is focused on using a variety of best practice techniques for authentication and authorization, including but not limited to logging and out of your Blazor application with cookies; working with ASP.NET Core Identity; implementing token-based security with OAuth2 and OpenID Connect (using IdentityServer4), and dealing with authorization (using policies). 5 | 6 | If you're interested, you can find the course here: https://app.pluralsight.com/library/courses/authentication-authorization-blazor-applications 7 | 8 | ## Retired 9 | This repository should be considered retired. Updated versions can be found in two other repositories: https://github.com/KevinDockx/SecuringBlazorClientSideApplications & https://github.com/KevinDockx/SecuringBlazorServerSideApplications 10 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/BethanysPieShopHRM.Api.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Controllers/CountryController.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 5 | 6 | namespace BethanysPieShopHRM.Api.Controllers 7 | { 8 | [Route("api/[controller]")] 9 | [ApiController] 10 | public class CountryController : Controller 11 | { 12 | private readonly ICountryRepository _countryRepository; 13 | 14 | public CountryController(ICountryRepository countryRepository) 15 | { 16 | _countryRepository = countryRepository; 17 | } 18 | 19 | // GET: api/ 20 | [HttpGet] 21 | public IActionResult GetCountries() 22 | { 23 | return Ok(_countryRepository.GetAllCountries()); 24 | } 25 | 26 | // GET api//5 27 | [HttpGet("{id}")] 28 | public IActionResult GetCountryById(int id) 29 | { 30 | return Ok(_countryRepository.GetCountryById(id)); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Controllers/EmployeeController.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using BethanysPieShopHRM.Shared; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace BethanysPieShopHRM.Api.Controllers 6 | { 7 | [Route("api/[controller]")] 8 | [ApiController] 9 | public class EmployeeController : Controller 10 | { 11 | private readonly IEmployeeRepository _employeeRepository; 12 | 13 | public EmployeeController(IEmployeeRepository employeeRepository) 14 | { 15 | _employeeRepository = employeeRepository; 16 | } 17 | 18 | [HttpGet] 19 | public IActionResult GetAllEmployees() 20 | { 21 | return Ok(_employeeRepository.GetAllEmployees()); 22 | } 23 | 24 | [HttpGet("{id}")] 25 | public IActionResult GetEmployeeById(int id) 26 | { 27 | return Ok(_employeeRepository.GetEmployeeById(id)); 28 | } 29 | 30 | [HttpPost] 31 | public IActionResult CreateEmployee([FromBody] Employee employee) 32 | { 33 | if (employee == null) 34 | return BadRequest(); 35 | 36 | if (employee.FirstName == string.Empty || employee.LastName == string.Empty) 37 | { 38 | ModelState.AddModelError("Name/FirstName", "The name or first name shouldn't be empty"); 39 | } 40 | 41 | if (!ModelState.IsValid) 42 | return BadRequest(ModelState); 43 | 44 | var createdEmployee = _employeeRepository.AddEmployee(employee); 45 | 46 | return Created("employee", createdEmployee); 47 | } 48 | 49 | [HttpPut] 50 | public IActionResult UpdateEmployee([FromBody] Employee employee) 51 | { 52 | if (employee == null) 53 | return BadRequest(); 54 | 55 | if (employee.FirstName == string.Empty || employee.LastName == string.Empty) 56 | { 57 | ModelState.AddModelError("Name/FirstName", "The name or first name shouldn't be empty"); 58 | } 59 | 60 | if (!ModelState.IsValid) 61 | return BadRequest(ModelState); 62 | 63 | var employeeToUpdate = _employeeRepository.GetEmployeeById(employee.EmployeeId); 64 | 65 | if (employeeToUpdate == null) 66 | return NotFound(); 67 | 68 | _employeeRepository.UpdateEmployee(employee); 69 | 70 | return NoContent(); //success 71 | } 72 | 73 | [HttpDelete("{id}")] 74 | public IActionResult DeleteEmployee(int id) 75 | { 76 | if (id == 0) 77 | return BadRequest(); 78 | 79 | var employeeToDelete = _employeeRepository.GetEmployeeById(id); 80 | if (employeeToDelete == null) 81 | return NotFound(); 82 | 83 | _employeeRepository.DeleteEmployee(id); 84 | 85 | return NoContent();//success 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Controllers/JobCategoryController.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 5 | 6 | namespace BethanysPieShopHRM.Api.Controllers 7 | { 8 | [Route("api/[controller]")] 9 | [ApiController] 10 | public class JobCategoryController : Controller 11 | { 12 | private readonly IJobCategoryRepository _jobCategoryRepository; 13 | 14 | public JobCategoryController(IJobCategoryRepository jobCategoryRepository) 15 | { 16 | _jobCategoryRepository = jobCategoryRepository; 17 | } 18 | 19 | 20 | // GET: api/ 21 | [HttpGet] 22 | public IActionResult GetJobCategories() 23 | { 24 | return Ok(_jobCategoryRepository.GetAllJobCategories()); 25 | } 26 | 27 | // GET api//5 28 | [HttpGet("{id}")] 29 | public IActionResult GetJobCategoryById(int id) 30 | { 31 | return Ok(_jobCategoryRepository.GetJobCategoryById(id)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Models/CountryRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Api.Models 6 | { 7 | public class CountryRepository : ICountryRepository 8 | { 9 | private readonly AppDbContext _appDbContext; 10 | 11 | public CountryRepository(AppDbContext appDbContext) 12 | { 13 | _appDbContext = appDbContext; 14 | } 15 | 16 | public IEnumerable GetAllCountries() 17 | { 18 | return _appDbContext.Countries; 19 | } 20 | 21 | public Country GetCountryById(int countryId) 22 | { 23 | return _appDbContext.Countries.FirstOrDefault(c => c.CountryId == countryId); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Models/EmployeeRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Api.Models 6 | { 7 | public class EmployeeRepository : IEmployeeRepository 8 | { 9 | private readonly AppDbContext _appDbContext; 10 | 11 | public EmployeeRepository(AppDbContext appDbContext) 12 | { 13 | _appDbContext = appDbContext; 14 | } 15 | 16 | public IEnumerable GetAllEmployees() 17 | { 18 | return _appDbContext.Employees; 19 | } 20 | 21 | public Employee GetEmployeeById(int employeeId) 22 | { 23 | return _appDbContext.Employees.FirstOrDefault(c => c.EmployeeId == employeeId); 24 | } 25 | 26 | public Employee AddEmployee(Employee employee) 27 | { 28 | var addedEntity = _appDbContext.Employees.Add(employee); 29 | _appDbContext.SaveChanges(); 30 | return addedEntity.Entity; 31 | } 32 | 33 | public Employee UpdateEmployee(Employee employee) 34 | { 35 | var foundEmployee = _appDbContext.Employees.FirstOrDefault(e => e.EmployeeId == employee.EmployeeId); 36 | 37 | if (foundEmployee != null) 38 | { 39 | foundEmployee.CountryId = employee.CountryId; 40 | foundEmployee.MaritalStatus = employee.MaritalStatus; 41 | foundEmployee.BirthDate = employee.BirthDate; 42 | foundEmployee.City = employee.City; 43 | foundEmployee.Email = employee.Email; 44 | foundEmployee.FirstName = employee.FirstName; 45 | foundEmployee.LastName = employee.LastName; 46 | foundEmployee.Gender = employee.Gender; 47 | foundEmployee.PhoneNumber = employee.PhoneNumber; 48 | foundEmployee.Smoker = employee.Smoker; 49 | foundEmployee.Street = employee.Street; 50 | foundEmployee.Zip = employee.Zip; 51 | foundEmployee.JobCategoryId = employee.JobCategoryId; 52 | foundEmployee.Comment = employee.Comment; 53 | foundEmployee.ExitDate = employee.ExitDate; 54 | foundEmployee.JoinedDate = employee.JoinedDate; 55 | 56 | _appDbContext.SaveChanges(); 57 | 58 | return foundEmployee; 59 | } 60 | 61 | return null; 62 | } 63 | 64 | public void DeleteEmployee(int employeeId) 65 | { 66 | var foundEmployee = _appDbContext.Employees.FirstOrDefault(e => e.EmployeeId == employeeId); 67 | if (foundEmployee == null) return; 68 | 69 | _appDbContext.Employees.Remove(foundEmployee); 70 | _appDbContext.SaveChanges(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Models/ICountryRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Api.Models 8 | { 9 | public interface ICountryRepository 10 | { 11 | IEnumerable GetAllCountries(); 12 | Country GetCountryById(int countryId); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Models/IEmployeeRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Api.Models 8 | { 9 | public interface IEmployeeRepository 10 | { 11 | IEnumerable GetAllEmployees(); 12 | Employee GetEmployeeById(int employeeId); 13 | Employee AddEmployee(Employee employee); 14 | Employee UpdateEmployee(Employee employee); 15 | void DeleteEmployee(int employeeId); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Models/IJobCategoryRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using BethanysPieShopHRM.Shared; 3 | 4 | namespace BethanysPieShopHRM.Api.Models 5 | { 6 | public interface IJobCategoryRepository 7 | { 8 | IEnumerable GetAllJobCategories(); 9 | JobCategory GetJobCategoryById(int jobCategoryId); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Models/JobCategoryRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Api.Models 8 | { 9 | public class JobCategoryRepository: IJobCategoryRepository 10 | { 11 | private readonly AppDbContext _appDbContext; 12 | 13 | public JobCategoryRepository(AppDbContext appDbContext) 14 | { 15 | _appDbContext = appDbContext; 16 | } 17 | 18 | public IEnumerable GetAllJobCategories() 19 | { 20 | return _appDbContext.JobCategories; 21 | } 22 | 23 | public JobCategory GetJobCategoryById(int jobCategoryId) 24 | { 25 | return _appDbContext.JobCategories.FirstOrDefault(c => c.JobCategoryId == jobCategoryId); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Program.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Hosting; 5 | 6 | namespace BethanysPieShopHRM.Api 7 | { 8 | public class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | var host = CreateHostBuilder(args).Build(); 13 | 14 | using (var scope = host.Services.CreateScope()) 15 | { 16 | using var context = scope.ServiceProvider.GetService(); 17 | context.Database.EnsureCreated(); 18 | } 19 | 20 | host.Run(); 21 | } 22 | 23 | public static IHostBuilder CreateHostBuilder(string[] args) => 24 | Host.CreateDefaultBuilder(args) 25 | .ConfigureWebHostDefaults(webBuilder => 26 | { 27 | webBuilder.UseStartup(); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:62408", 7 | "sslPort": 44340 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "Project", 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | }, 17 | "applicationUrl": "https://localhost:44340/" 18 | }, 19 | "BethanysPieShopHRM.Api": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "launchUrl": "weatherforecast", 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | }, 26 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/Startup.cs: -------------------------------------------------------------------------------- 1 | using BethanysPieShopHRM.Api.Models; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | 9 | namespace BethanysPieShopHRM.Api 10 | { 11 | public class Startup 12 | { 13 | public Startup(IConfiguration configuration) 14 | { 15 | Configuration = configuration; 16 | } 17 | 18 | public IConfiguration Configuration { get; } 19 | 20 | // This method gets called by the runtime. Use this method to add services to the container. 21 | public void ConfigureServices(IServiceCollection services) 22 | { 23 | //services.AddDbContext(options => options.UseInMemoryDatabase(databaseName: "BethanysPieShopHRM")); 24 | 25 | services.AddDbContext(options => 26 | options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 27 | 28 | services.AddScoped(); 29 | services.AddScoped(); 30 | services.AddScoped(); 31 | 32 | services.AddCors(options => 33 | { 34 | options.AddPolicy("Open", builder => builder.AllowAnyOrigin().AllowAnyHeader()); 35 | }); 36 | 37 | services.AddControllers(); 38 | //.AddJsonOptions(options => options.JsonSerializerOptions.ca); 39 | } 40 | 41 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 42 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 43 | { 44 | if (env.IsDevelopment()) 45 | { 46 | app.UseDeveloperExceptionPage(); 47 | } 48 | 49 | app.UseHttpsRedirection(); 50 | 51 | app.UseRouting(); 52 | 53 | app.UseAuthorization(); 54 | 55 | // app.UseCors("Open"); 56 | 57 | app.UseEndpoints(endpoints => 58 | { 59 | endpoints.MapControllers(); 60 | }); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Api/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=BethanysPieShopHRM3;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | 5 | }, 6 | "Logging": { 7 | "LogLevel": { 8 | "Default": "Information", 9 | "Microsoft": "Warning", 10 | "Microsoft.Hosting.Lifetime": "Information" 11 | } 12 | }, 13 | "AllowedHosts": "*" 14 | } 15 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.ComponentsLibrary/BethanysPieShopHRM.ComponentsLibrary.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 3.0 6 | BethanysPieShopHRM.ComponentsLibrary 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.ComponentsLibrary/Map/Map.razor: -------------------------------------------------------------------------------- 1 | @using System 2 | @using System.Collections.Generic 3 | @using System.Threading.Tasks 4 | @using Microsoft.AspNetCore.Components 5 | @using Microsoft.JSInterop 6 | @using BethanysPieShopHRM.ComponentsLibrary.Map 7 | @inject IJSRuntime JSRuntime 8 | 9 |
    10 | 11 | @code { 12 | 13 | string elementId = $"map-{Guid.NewGuid().ToString("D")}"; 14 | 15 | [Parameter] 16 | public double Zoom { get; set; } 17 | 18 | [Parameter] 19 | public List Markers { get; set; } 20 | 21 | protected override async Task OnAfterRenderAsync(bool firstRender) 22 | { 23 | await JSRuntime.InvokeVoidAsync( 24 | "deliveryMap.showOrUpdate", 25 | elementId, 26 | Markers); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.ComponentsLibrary/Map/Marker.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.ComponentsLibrary.Map 2 | { 3 | public class Marker 4 | { 5 | public string Description { get; set; } 6 | 7 | public double X { get; set; } 8 | 9 | public double Y { get; set; } 10 | 11 | public bool ShowPopup { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.ComponentsLibrary/Map/Point.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.ComponentsLibrary.Map 2 | { 3 | public class Point 4 | { 5 | public double X { get; set; } 6 | 7 | public double Y { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/layers-2x.png -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/layers.png -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-icon-2x.png -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-icon.png -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.ComponentsLibrary/wwwroot/leaflet/images/marker-shadow.png -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 |

    Sorry, there's nothing at this address.

    8 |
    9 |
    10 |
    11 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/BethanysPieShopHRM.Server.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Components/AddEmployeeDialog.razor: -------------------------------------------------------------------------------- 1 |  2 | @inherits AddEmployeeDialogBase 3 | 4 | @if (ShowDialog) 5 | { 6 | 47 | } -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Components/AddEmployeeDialogBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.Server.Services; 4 | using BethanysPieShopHRM.Shared; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace BethanysPieShopHRM.Server.Components 8 | { 9 | public class AddEmployeeDialogBase : ComponentBase 10 | { 11 | public bool ShowDialog { get; set; } 12 | 13 | public Employee Employee { get; set; } = new Employee { CountryId = 1, JobCategoryId = 1, BirthDate = DateTime.Now, JoinedDate = DateTime.Now }; 14 | 15 | [Parameter] 16 | public EventCallback CloseEventCallback { get; set; } 17 | 18 | [Inject] 19 | public IEmployeeDataService EmployeeDataService { get; set; } 20 | 21 | 22 | 23 | public void Show() 24 | { 25 | ResetDialog(); 26 | ShowDialog = true; 27 | StateHasChanged(); 28 | } 29 | 30 | private void ResetDialog() 31 | { 32 | Employee = new Employee { CountryId = 1, JobCategoryId = 1, BirthDate = DateTime.Now, JoinedDate = DateTime.Now }; 33 | } 34 | 35 | public void Close() 36 | { 37 | ShowDialog = false; 38 | StateHasChanged(); 39 | } 40 | 41 | protected async Task HandleValidSubmit() 42 | { 43 | await EmployeeDataService.AddEmployee(Employee); 44 | ShowDialog = false; 45 | 46 | await CloseEventCallback.InvokeAsync(true); 47 | StateHasChanged(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Pages/EmployeeDetailBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.ComponentsLibrary.Map; 4 | using BethanysPieShopHRM.Server.Services; 5 | using BethanysPieShopHRM.Shared; 6 | using Microsoft.AspNetCore.Components; 7 | 8 | namespace BethanysPieShopHRM.Server.Pages 9 | { 10 | public class EmployeeDetailBase : ComponentBase 11 | { 12 | [Inject] 13 | public IEmployeeDataService EmployeeDataService { get; set; } 14 | 15 | [Inject] 16 | public IJobCategoryDataService JobCategoryDataService{ get; set; } 17 | 18 | [Parameter] 19 | public string EmployeeId { get; set; } 20 | 21 | public List MapMarkers { get; set; } = new List(); 22 | 23 | protected string JobCategory = string.Empty; 24 | 25 | public Employee Employee { get; set; } = new Employee(); 26 | 27 | protected override async Task OnInitializedAsync() 28 | { 29 | Employee = await EmployeeDataService.GetEmployeeDetails(int.Parse(EmployeeId)); 30 | 31 | MapMarkers = new List 32 | { 33 | new Marker{Description = $"{Employee.FirstName} {Employee.LastName}", ShowPopup = false, X = Employee.Longitude, Y = Employee.Latitude} 34 | }; 35 | JobCategory = (await JobCategoryDataService.GetJobCategoryById(Employee.JobCategoryId)).JobCategoryName; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Pages/EmployeeOverview.razor: -------------------------------------------------------------------------------- 1 | @page "/employeeoverview" 2 | @inherits EmployeeOverviewBase 3 | 4 |

    All employees

    5 | 6 | @if (Employees == null) 7 | { 8 |

    Loading...

    9 | } 10 | else 11 | { 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | @foreach (var employee in Employees) 24 | { 25 | 26 | 27 | 28 | 29 | 30 | 38 | 39 | } 40 | 41 |
    Employee IDFirst nameLast name
    @employee.EmployeeId@employee.FirstName@employee.LastName 31 | 32 | 33 | 34 | 35 | 36 | 37 |
    42 | } 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Pages/EmployeeOverviewBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Net.Http; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Server.Components; 6 | using BethanysPieShopHRM.Server.Services; 7 | using BethanysPieShopHRM.Shared; 8 | using Microsoft.AspNetCore.Components; 9 | 10 | namespace BethanysPieShopHRM.Server.Pages 11 | { 12 | public class EmployeeOverviewBase: ComponentBase 13 | { 14 | [Inject] 15 | public IEmployeeDataService EmployeeDataService { get; set; } 16 | 17 | public List Employees { get; set; } 18 | 19 | protected AddEmployeeDialog AddEmployeeDialog { get; set; } 20 | 21 | protected override async Task OnInitializedAsync() 22 | { 23 | Employees = (await EmployeeDataService.GetAllEmployees()).ToList(); 24 | } 25 | 26 | public async void AddEmployeeDialog_OnDialogClose() 27 | { 28 | Employees = (await EmployeeDataService.GetAllEmployees()).ToList(); 29 | StateHasChanged(); 30 | } 31 | 32 | protected void QuickAddEmployee() 33 | { 34 | AddEmployeeDialog.Show(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Pages/Error.razor: -------------------------------------------------------------------------------- 1 | @page "/error" 2 | 3 |

    Error.

    4 |

    An error occurred while processing your request.

    5 | 6 |

    Development Mode

    7 |

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

    10 |

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

    -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | 3 |

    Welcome to Bethany's Pie Shop HRM!

    4 |
    5 |

    Using this application, you can manage our wonderful staff working for us all over the world, bringing people the best pies ever!

    6 | 7 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace BethanysPieShopHRM.Server.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Bethany's Pie Shop HR 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | @(await Html.RenderComponentAsync(RenderMode.ServerPrerendered)) 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace BethanysPieShopHRM.Server 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "https://localhost:44329/", 7 | "sslPort": 44329 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "launchUrl": "https://localhost:44329/", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "BethanysPieShopHRM.Server": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Services/CountryDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Server.Services 8 | { 9 | public class CountryDataService : ICountryDataService 10 | { 11 | private readonly HttpClient _httpClient; 12 | 13 | public CountryDataService(HttpClient httpClient) 14 | { 15 | _httpClient = httpClient; 16 | } 17 | 18 | public async Task> GetAllCountries() 19 | { 20 | return await JsonSerializer.DeserializeAsync> 21 | (await _httpClient.GetStreamAsync($"api/country"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 22 | } 23 | 24 | public async Task GetCountryById(int countryId) 25 | { 26 | return await JsonSerializer.DeserializeAsync 27 | (await _httpClient.GetStreamAsync($"api/country{countryId}"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Services/EmployeeDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text; 4 | using System.Text.Json; 5 | using System.Threading.Tasks; 6 | using BethanysPieShopHRM.Shared; 7 | 8 | namespace BethanysPieShopHRM.Server.Services 9 | { 10 | public class EmployeeDataService : IEmployeeDataService 11 | { 12 | private readonly HttpClient _httpClient; 13 | 14 | public EmployeeDataService(HttpClient httpClient) 15 | { 16 | _httpClient = httpClient; 17 | } 18 | 19 | public async Task> GetAllEmployees() 20 | { 21 | return await JsonSerializer.DeserializeAsync> 22 | (await _httpClient.GetStreamAsync($"api/employee"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 23 | } 24 | 25 | public async Task GetEmployeeDetails(int employeeId) 26 | { 27 | return await JsonSerializer.DeserializeAsync 28 | (await _httpClient.GetStreamAsync($"api/employee/{employeeId}"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 29 | } 30 | 31 | public async Task AddEmployee(Employee employee) 32 | { 33 | var employeeJson = 34 | new StringContent(JsonSerializer.Serialize(employee), Encoding.UTF8, "application/json"); 35 | 36 | var response = await _httpClient.PostAsync("api/employee", employeeJson); 37 | 38 | if (response.IsSuccessStatusCode) 39 | { 40 | return await JsonSerializer.DeserializeAsync(await response.Content.ReadAsStreamAsync()); 41 | } 42 | 43 | return null; 44 | } 45 | 46 | public async Task UpdateEmployee(Employee employee) 47 | { 48 | var employeeJson = 49 | new StringContent(JsonSerializer.Serialize(employee), Encoding.UTF8, "application/json"); 50 | 51 | await _httpClient.PutAsync("api/employee", employeeJson); 52 | } 53 | 54 | public async Task DeleteEmployee(int employeeId) 55 | { 56 | await _httpClient.DeleteAsync($"api/employee/{employeeId}"); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Services/ICountryDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Server.Services 6 | { 7 | public interface ICountryDataService 8 | { 9 | Task> GetAllCountries(); 10 | Task GetCountryById(int countryId); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Services/IEmployeeDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Server.Services 6 | { 7 | public interface IEmployeeDataService 8 | { 9 | Task> GetAllEmployees(); 10 | Task GetEmployeeDetails(int employeeId); 11 | Task AddEmployee(Employee employee); 12 | Task UpdateEmployee(Employee employee); 13 | Task DeleteEmployee(int employeeId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Services/IJobCategoryDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using BethanysPieShopHRM.Shared; 4 | 5 | namespace BethanysPieShopHRM.Server.Services 6 | { 7 | public interface IJobCategoryDataService 8 | { 9 | Task> GetAllJobCategories(); 10 | Task GetJobCategoryById(int jobCategoryId); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Services/JobCategoryDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net.Http; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | using BethanysPieShopHRM.Shared; 6 | 7 | namespace BethanysPieShopHRM.Server.Services 8 | { 9 | public class JobCategoryDataService : IJobCategoryDataService 10 | { 11 | private readonly HttpClient _httpClient; 12 | 13 | public JobCategoryDataService(HttpClient httpClient) 14 | { 15 | _httpClient = httpClient; 16 | } 17 | 18 | public async Task> GetAllJobCategories() 19 | { 20 | return await JsonSerializer.DeserializeAsync> 21 | (await _httpClient.GetStreamAsync($"api/jobcategory"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 22 | } 23 | 24 | public async Task GetJobCategoryById(int jobCategoryId) 25 | { 26 | return await JsonSerializer.DeserializeAsync 27 | (await _httpClient.GetStreamAsync($"api/jobcategory/{jobCategoryId}"), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
    4 | 5 | 6 | 7 |
    8 | 9 | 16 | 17 |
    18 | 19 | @Body 20 |
    21 |
    22 | 23 |
    24 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  2 | 26 | 27 | @code { 28 | bool collapseNavMenu = true; 29 | 30 | string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 31 | 32 | void ToggleNavMenu() 33 | { 34 | collapseNavMenu = !collapseNavMenu; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | using BethanysPieShopHRM.Server.Services; 9 | 10 | namespace BethanysPieShopHRM.Server 11 | { 12 | public class Startup 13 | { 14 | public Startup(IConfiguration configuration) 15 | { 16 | Configuration = configuration; 17 | } 18 | 19 | public IConfiguration Configuration { get; } 20 | 21 | // This method gets called by the runtime. Use this method to add services to the container. 22 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 23 | public void ConfigureServices(IServiceCollection services) 24 | { 25 | services.AddRazorPages(); 26 | services.AddServerSideBlazor().AddCircuitOptions(options => { options.DetailedErrors = true; }); 27 | 28 | 29 | services.AddHttpClient(client => 30 | { 31 | client.BaseAddress = new Uri("https://localhost:44340/"); 32 | }); 33 | services.AddHttpClient(client => 34 | { 35 | client.BaseAddress = new Uri("https://localhost:44340/"); 36 | }); 37 | services.AddHttpClient(client => 38 | { 39 | client.BaseAddress = new Uri("https://localhost:44340/"); 40 | }); 41 | } 42 | 43 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 44 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 45 | { 46 | if (env.IsDevelopment()) 47 | { 48 | app.UseDeveloperExceptionPage(); 49 | } 50 | else 51 | { 52 | app.UseExceptionHandler("/Error"); 53 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 54 | app.UseHsts(); 55 | } 56 | 57 | app.UseHttpsRedirection(); 58 | app.UseStaticFiles(); 59 | 60 | app.UseRouting(); 61 | 62 | app.UseEndpoints(endpoints => 63 | { 64 | endpoints.MapBlazorHub(); 65 | endpoints.MapFallbackToPage("/_Host"); 66 | }); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using BethanysPieShopHRM.Server 9 | @using BethanysPieShopHRM.Server.Shared 10 | 11 | @using BethanysPieShopHRM.Server.Components 12 | 13 | @using BethanysPieShopHRM.ComponentsLibrary 14 | @using BethanysPieShopHRM.ComponentsLibrary.Map -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.Server/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.Server/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/wwwroot/images/bethanylogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.Server/wwwroot/images/bethanylogo.png -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/wwwroot/images/pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.Server/wwwroot/images/pattern.png -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Server/wwwroot/images/profilePicture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinDockx/BlazorAuthenticationAndAuthorization/21e3fdfcf549c60f362c45cedd8e3c59eac8be7e/Starter files/BethanysPieShopHRM.Server/wwwroot/images/profilePicture.jpg -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Shared/BethanysPieShopHRM.Shared.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Shared/Country.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.Shared 2 | { 3 | public class Country 4 | { 5 | public int CountryId { get; set; } 6 | public string Name { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Shared/Employee.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace BethanysPieShopHRM.Shared 5 | { 6 | public class Employee 7 | { 8 | public int EmployeeId { get; set; } 9 | [Required] 10 | [StringLength(50, ErrorMessage = "First name is too long.")] 11 | public string FirstName { get; set; } 12 | 13 | [Required] 14 | [StringLength(50, ErrorMessage = "Last name is too long.")] 15 | public string LastName { get; set; } 16 | 17 | public DateTime BirthDate { get; set; } 18 | 19 | [Required] 20 | [EmailAddress] 21 | public string Email { get; set; } 22 | public string Street { get; set; } 23 | public string Zip { get; set; } 24 | public string City { get; set; } 25 | public int CountryId { get; set; } 26 | public Country Country { get; set; } 27 | public string PhoneNumber { get; set; } 28 | public bool Smoker { get; set; } 29 | public MaritalStatus MaritalStatus { get; set; } 30 | public Gender Gender { get; set; } 31 | [StringLength(1000, ErrorMessage = "Comment length can't exceed 1000 characters.")] 32 | public string Comment { get; set; } 33 | public DateTime? JoinedDate { get; set; } 34 | public DateTime? ExitDate { get; set; } 35 | 36 | public int JobCategoryId { get; set; } 37 | public JobCategory JobCategory { get; set; } 38 | 39 | public double Latitude { get; set; } 40 | public double Longitude { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Shared/Gender.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.Shared 2 | { 3 | public enum Gender 4 | { 5 | Male, 6 | Female, 7 | Other 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Shared/JobCategory.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.Shared 2 | { 3 | public class JobCategory 4 | { 5 | public int JobCategoryId { get; set; } 6 | public string JobCategoryName { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.Shared/MaritalStatus.cs: -------------------------------------------------------------------------------- 1 | namespace BethanysPieShopHRM.Shared 2 | { 3 | public enum MaritalStatus 4 | { 5 | Married, 6 | Single, 7 | Other 8 | } 9 | } -------------------------------------------------------------------------------- /Starter files/BethanysPieShopHRM.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29403.142 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BethanysPieShopHRM.Server", "BethanysPieShopHRM.Server\BethanysPieShopHRM.Server.csproj", "{F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BethanysPieShopHRM.Api", "BethanysPieShopHRM.Api\BethanysPieShopHRM.Api.csproj", "{FA4C51A3-7BF1-4577-8575-B43AED0F9A81}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BethanysPieShopHRM.Shared", "BethanysPieShopHRM.Shared\BethanysPieShopHRM.Shared.csproj", "{369581F2-82E5-45E8-BF3C-9E1CC83DD769}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BethanysPieShopHRM.ComponentsLibrary", "BethanysPieShopHRM.ComponentsLibrary\BethanysPieShopHRM.ComponentsLibrary.csproj", "{BD196906-CA10-437E-BBCC-A8BC2A954F13}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {F78BC946-B08B-49D1-8D76-A2E2EB2AAD7E}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {FA4C51A3-7BF1-4577-8575-B43AED0F9A81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {FA4C51A3-7BF1-4577-8575-B43AED0F9A81}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {FA4C51A3-7BF1-4577-8575-B43AED0F9A81}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {FA4C51A3-7BF1-4577-8575-B43AED0F9A81}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {369581F2-82E5-45E8-BF3C-9E1CC83DD769}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {369581F2-82E5-45E8-BF3C-9E1CC83DD769}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {369581F2-82E5-45E8-BF3C-9E1CC83DD769}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {369581F2-82E5-45E8-BF3C-9E1CC83DD769}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {BD196906-CA10-437E-BBCC-A8BC2A954F13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {BD196906-CA10-437E-BBCC-A8BC2A954F13}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {BD196906-CA10-437E-BBCC-A8BC2A954F13}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {BD196906-CA10-437E-BBCC-A8BC2A954F13}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {8FAD6A7F-346C-4B06-9840-20E884BDEB91} 42 | EndGlobalSection 43 | EndGlobal 44 | --------------------------------------------------------------------------------