Repository: moemura/AdminLTE.Core
Branch: master
Commit: 70c980db55d0
Files: 132
Total size: 357.6 KB
Directory structure:
gitextract_2k0n1zd6/
├── .gitignore
├── AdminLTE.sln.DotSettings
├── AdminLTE.slnx
├── LICENSE
├── README.md
└── src/
└── AdminLTE/
├── AdminLTE.csproj
├── Common/
│ ├── Attributes/
│ │ └── HelpDefinitionAttribute.cs
│ ├── CustomClaimTypes.cs
│ ├── Extensions/
│ │ └── IdentityExtension.cs
│ ├── GlobalHelper.cs
│ └── ModuleHelper.cs
├── Controllers/
│ ├── AccountController.cs
│ ├── BaseController.cs
│ ├── HomeController.cs
│ ├── ManageController.cs
│ ├── RoleController.cs
│ ├── SuperAdminController.cs
│ └── UserLogsController.cs
├── Data/
│ ├── AppClaimsPrincipalFactory.cs
│ ├── ApplicationDbContext.cs
│ ├── AuditableSignInManager.cs
│ ├── DataSeed.cs
│ └── Migrations/
│ ├── 00000000000000_CreateIdentitySchema.Designer.cs
│ ├── 00000000000000_CreateIdentitySchema.cs
│ ├── 20160801092435_ExtendASPNetUser.Designer.cs
│ ├── 20160801092435_ExtendASPNetUser.cs
│ ├── 20160802025049_UserAuditTable.Designer.cs
│ ├── 20160802025049_UserAuditTable.cs
│ ├── 20160802083550_AddedAdditionalUserFields.Designer.cs
│ ├── 20160802083550_AddedAdditionalUserFields.cs
│ ├── 20251217031644_UpdateEF10.Designer.cs
│ ├── 20251217031644_UpdateEF10.cs
│ └── ApplicationDbContextModelSnapshot.cs
├── Models/
│ ├── AccountViewModels/
│ │ ├── ExternalLoginConfirmationViewModel.cs
│ │ ├── ForgotPasswordViewModel.cs
│ │ ├── LoginViewModel.cs
│ │ ├── RegisterViewModel.cs
│ │ ├── ResetPasswordViewModel.cs
│ │ ├── SendCodeViewModel.cs
│ │ └── VerifyCodeViewModel.cs
│ ├── ApplicationUser.cs
│ ├── ManageViewModels/
│ │ ├── AddPhoneNumberViewModel.cs
│ │ ├── ChangePasswordViewModel.cs
│ │ ├── ConfigureTwoFactorViewModel.cs
│ │ ├── FactorViewModel.cs
│ │ ├── IndexViewModel.cs
│ │ ├── ManageLoginsViewModel.cs
│ │ ├── RemoveLoginViewModel.cs
│ │ ├── SetPasswordViewModel.cs
│ │ └── VerifyPhoneNumberViewModel.cs
│ ├── Message.cs
│ ├── RoleViewModels/
│ │ ├── EditRoleVm.cs
│ │ └── ModifyRoleVm.cs
│ ├── SalesOrderDetail.cs
│ ├── SidebarMenu.cs
│ ├── SuperAdminViewModels/
│ │ └── CreateVm.cs
│ └── UserAudit.cs
├── Program.cs
├── Project_Readme.html
├── Properties/
│ └── launchSettings.json
├── Services/
│ ├── IEmailSender.cs
│ ├── ISmsSender.cs
│ ├── MessageServices.cs
│ └── RequestLoggingMiddleware.cs
├── ViewComponents/
│ ├── BreadcrumbViewComponent.cs
│ ├── ControlSidebarViewComponent.cs
│ ├── FooterViewComponent.cs
│ ├── HeaderViewComponent.cs
│ ├── MenuMessageViewComponent.cs
│ ├── MenuNotificationViewComponent.cs
│ ├── MenuTaskViewComponent.cs
│ ├── MenuUserViewComponent.cs
│ ├── PageAlertViewComponent.cs
│ ├── PageHeaderViewComponent.cs
│ └── SidebarViewComponent.cs
├── Views/
│ ├── Account/
│ │ ├── ConfirmEmail.cshtml
│ │ ├── ExternalLoginConfirmation.cshtml
│ │ ├── ExternalLoginFailure.cshtml
│ │ ├── ForgotPassword.cshtml
│ │ ├── ForgotPasswordConfirmation.cshtml
│ │ ├── Lockout.cshtml
│ │ ├── Login.cshtml
│ │ ├── Register.cshtml
│ │ ├── ResetPassword.cshtml
│ │ ├── ResetPasswordConfirmation.cshtml
│ │ ├── SendCode.cshtml
│ │ └── VerifyCode.cshtml
│ ├── Home/
│ │ ├── About.cshtml
│ │ ├── Contact.cshtml
│ │ ├── Error.cshtml
│ │ └── Index.cshtml
│ ├── Manage/
│ │ ├── AddPhoneNumber.cshtml
│ │ ├── ChangePassword.cshtml
│ │ ├── Index.cshtml
│ │ ├── ManageLogins.cshtml
│ │ ├── SetPassword.cshtml
│ │ └── VerifyPhoneNumber.cshtml
│ ├── Role/
│ │ ├── Create.cshtml
│ │ ├── Edit.cshtml
│ │ └── Index.cshtml
│ ├── Shared/
│ │ ├── Components/
│ │ │ ├── Breadcrumb/
│ │ │ │ └── Default.cshtml
│ │ │ ├── ControlSidebar/
│ │ │ │ └── Default.cshtml
│ │ │ ├── Footer/
│ │ │ │ └── Default.cshtml
│ │ │ ├── Header/
│ │ │ │ └── Default.cshtml
│ │ │ ├── MenuMessage/
│ │ │ │ └── Default.cshtml
│ │ │ ├── MenuNotification/
│ │ │ │ └── Default.cshtml
│ │ │ ├── MenuTask/
│ │ │ │ └── Default.cshtml
│ │ │ ├── MenuUser/
│ │ │ │ └── Default.cshtml
│ │ │ ├── PageAlert/
│ │ │ │ └── Default.cshtml
│ │ │ ├── PageHeader/
│ │ │ │ └── Default.cshtml
│ │ │ └── Sidebar/
│ │ │ └── Default.cshtml
│ │ ├── Error.cshtml
│ │ ├── _Layout.cshtml
│ │ ├── _LoginPartial.cshtml
│ │ └── _ValidationScriptsPartial.cshtml
│ ├── SuperAdmin/
│ │ ├── ChangePassword.cshtml
│ │ ├── Create.cshtml
│ │ ├── Edit.cshtml
│ │ └── Index.cshtml
│ ├── UserLogs/
│ │ └── Index.cshtml
│ ├── _ViewImports.cshtml
│ └── _ViewStart.cshtml
├── appsettings.json
├── bundleconfig.json
├── libman.json
├── web.config
└── wwwroot/
├── _references.js
├── css/
│ ├── animation.css
│ ├── error.css
│ └── site.css
├── files/
│ └── SalesOrderDetail.txt
└── js/
└── site.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/src/AdminLTE/wwwroot/lib/
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
================================================
FILE: AdminLTE.sln.DotSettings
================================================
URL
================================================
FILE: AdminLTE.slnx
================================================
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2016 Baltazar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# **Admin**LTE - MVC Core
This template is based from AdminLTE of http://almsaeedstudio.com.
Converted as a .Net project.
## Prerequisites
as a minimum, you should have the following installed
* Visual Studio 2022+
_built using .NET
## Installation
Just clone or fork this. Whatever you want. [Restore client side libraries](https://github.com/moemura/AdminLTE.Core/issues/1). Run the solution.
## Features
### Controls are ViewComponent like a **UserControl**
see below the body of **_Layouts.cshtml**
```html
@await Component.InvokeAsync("Header")
@await Component.InvokeAsync("Sidebar")
@await Component.InvokeAsync("Footer")
@await Component.InvokeAsync("ControlSidebar")
@RenderSection("scripts", required: false)
```
### List of ViewComponents
* Header
* Notification
* Messages
* Task
* User Profile
* Footer
* SideBar
* ControlSideBar (converted to HelpBar)
* PageHeader
* Breadcrumb
* Login & Logout
* Error Page
* Registration*
### ViewComponent Usage
Typically, you should inherit your Controller from `BaseController.cs` to enable convenience helpers.
**PageHeader Title & Description**
```cs
declaration:
AddPageHeader(string pageHeader = "", string pageDescription = "")
usage:
AddPageHeader("Dashboard", "");
```
**Page Alerts**
```cs
declaration:
AddPageAlerts(PageAlertType pageAlertType, string description)
usage:
AddPageAlerts(PageAlertType.Info, "you may view the summary here");
```
**Page Breadcrumb**
```cs
declaration:
AddBreadcrumb(string displayName, string urlPath)
usage:
AddBreadcrumb("Register", "/Account/Register");
AddBreadcrumb("Contact", "/Account/Contact");
```
**Sidebar Menus**
```cs
var sidebars = new List();
sidebars.Add(ModuleHelper.AddHeader("MAIN NAVIGATION"));
sidebars.Add(ModuleHelper.AddModule(ModuleHelper.Module.Home));
sidebars.Add(ModuleHelper.AddModule(ModuleHelper.Module.Error, Tuple.Create(0, 0, 1)));
sidebars.Add(ModuleHelper.AddModule(ModuleHelper.Module.About, Tuple.Create(0, 1, 0)));
sidebars.Add(ModuleHelper.AddModule(ModuleHelper.Module.Contact, Tuple.Create(1, 0, 0)));
sidebars.Add(ModuleHelper.AddTree("Account"));
sidebars.Last().TreeChild = new List()
{
ModuleHelper.AddModule(ModuleHelper.Module.Login),
ModuleHelper.AddModule(ModuleHelper.Module.Register, Tuple.Create(1, 1, 1)),
};
```
The above code will create a hierarchical sidebar like...
```
>
> LABEL
> LINK 1
> LINK 1
> LINK 1
> TREE
> > LINK
> > LINK 1|1|1
```
...where 1 is the notification color at the right side of the link via Tuple.
Tuple 0 will not display the notification whereas the position of the items will display its corresponding color notification
**Menu Notification**
This implementation is almost the same with Menu Task and Menu Message.
```cs
public class MenuNotificationViewComponent : ViewComponent
{
public MenuNotificationViewComponent()
{
}
public IViewComponentResult Invoke(string filter)
{
var messages = GetData();
return View(messages);
}
private List GetData()
{
var messages = new List();
messages.Add(new Message
{
Id = 1,
FontAwesomeIcon = "fa fa-users text-aqua",
ShortDesc = "5 new members joined today",
URLPath = "#",
});
return messages;
}
}
```
**Help Pane**
You can add page help or quick links/info by adding `[HelpDefinition]` attribute above the IActionResult method
```cs
public class HomeController : BaseController
{
[HelpDefinition]
public IActionResult Index()
{
return View();
}
```
You can still specify a filename as parameter in case you want to retrieve it on the wwwroot/files/Shared folder.
```cs
[HelpDefinition("helpdefault")]
public IActionResult Contact()
{
```
> By default, no arguments will get the path via ControllerName\CallerMethod which have the equivalent path to wwwroot/files/{ControllerName}/{CallerMethod}.html
### List of Global Javascript Events
* **Submit Button** - disabled when click once. Auto add progress spinner. No additional codes required for that implementation.
> Usage: You just simply declare the submit button. The script name is `useSubmitClass`
```html
```
* Sidebar Collapse/ Expand
* The sidebar will save the expand & collapse state thru cookie. Using `Mozilla cookie helper`.
> The cookie name is `sidebarstate`
### List of Control Templates
* DataTable
* ...more to follow
### User Audit
The project implements middleware that audits user login activity upon `login, logout & failed login`
### Extended User Properties
The project gives some insight on how to implement extended user properties via Claims
### HTTP Logging
The project provides middleware to log `per HTTP request`.
### Authentication
This uses templated individual authentication and customized `ErrorPage` & `LoginPage`.
It also uses dependency injection that requires controllers by default to be ``[Authorized]``
without typing them on each controller/method
## Copyrights
See MIT License
================================================
FILE: src/AdminLTE/AdminLTE.csproj
================================================
net10.0
true
AdminLTE
AdminLTE
enable
aspnet-AdminLTE-c9131f1e-93fb-4772-8c8b-1d4c77bf4354
PreserveNewest
All
All
================================================
FILE: src/AdminLTE/Common/Attributes/HelpDefinitionAttribute.cs
================================================
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace AdminLTE.Common.Attributes
{
[AttributeUsage(AttributeTargets.Method)]
public class HelpDefinitionAttribute : ActionFilterAttribute, IActionFilter
{
private string _fileName { get; set; }
private string _memberName { get; set; }
private string _pageHelpFileName { get; set; }
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
var controller = filterContext.Controller as Controller;
controller.ViewBag.PageHelpFileName = _pageHelpFileName;
}
///
/// By declaring this on the IActionResult method, you are enabling
///
/// specify specific filename located in wwwroot\files\Shared folder
/// THIS MUST BE EMPTY
/// THIS MUST BE EMPTY
public HelpDefinitionAttribute(string fileName = "",[CallerFilePath] string filePath = "", [CallerMemberName] string memberName = "")
{
var controllerName = filePath.Split('\\').Last().Replace("Controller.cs", string.Empty);
if (fileName == string.Empty) //if not specified, will check it on the common help location plus path from class+method.html
{
_pageHelpFileName = controllerName + @"\" + memberName; //ChildController + ActionMethod
}
else //if specified, will check it in the common help location
{
_pageHelpFileName = @"Shared\" + fileName;
}
}
}
}
================================================
FILE: src/AdminLTE/Common/CustomClaimTypes.cs
================================================
namespace AdminLTE.Common
{
public static class CustomClaimTypes
{
#region Default ClaimTypes (taken from ClaimTypes class)
//
// Summary:
// http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor.
public const string Actor = "http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor";
//
// Summary:
// The URI for a claim that specifies the anonymous user; http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous.
public const string Anonymous = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous";
//
// Summary:
// The URI for a claim that specifies details about whether an identity is authenticated,
// http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authenticated.
public const string Authentication = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authentication";
//
// Summary:
// The URI for a claim that specifies the instant at which an entity was authenticated;
// http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant.
public const string AuthenticationInstant = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant";
//
// Summary:
// The URI for a claim that specifies the method with which an entity was authenticated;
// http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod.
public const string AuthenticationMethod = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod";
//
// Summary:
// The URI for a claim that specifies an authorization decision on an entity; http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision.
public const string AuthorizationDecision = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision";
//
// Summary:
// The URI for a claim that specifies the cookie path; http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath.
public const string CookiePath = "http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath";
//
// Summary:
// The URI for a claim that specifies the country/region in which an entity resides,
// http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country.
public const string Country = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country";
//
// Summary:
// The URI for a claim that specifies the date of birth of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth.
public const string DateOfBirth = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth";
//
// Summary:
// The URI for a claim that specifies the deny-only primary group SID on an entity;
// http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid.
// A deny-only SID denies the specified entity to a securable object.
public const string DenyOnlyPrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid";
//
// Summary:
// The URI for a claim that specifies the deny-only primary SID on an entity; http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid.
// A deny-only SID denies the specified entity to a securable object.
public const string DenyOnlyPrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid";
//
// Summary:
// The URI for a claim that specifies a deny-only security identifier (SID) for
// an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid.
// A deny-only SID denies the specified entity to a securable object.
public const string DenyOnlySid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlywindowsdevicegroup.
public const string DenyOnlyWindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlywindowsdevicegroup";
//
// Summary:
// The URI for a claim that specifies the DNS name associated with the computer
// name or with the alternative name of either the subject or issuer of an X.509
// certificate, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dns.
public const string Dns = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dns";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa.
public const string Dsa = "http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa";
//
// Summary:
// The URI for a claim that specifies the email address of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email.
public const string Email = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration.
public const string Expiration = "http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/expired.
public const string Expired = "http://schemas.microsoft.com/ws/2008/06/identity/claims/expired";
//
// Summary:
// The URI for a claim that specifies the gender of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender.
public const string Gender = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender";
//
// Summary:
// The URI for a claim that specifies the given name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname.
public const string GivenName = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname";
//
// Summary:
// The URI for a claim that specifies the SID for the group of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid.
public const string GroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid";
//
// Summary:
// The URI for a claim that specifies a hash value, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/hash.
public const string Hash = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/hash";
//
// Summary:
// The URI for a claim that specifies the home phone number of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/homephone.
public const string HomePhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/homephone";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/ispersistent.
public const string IsPersistent = "http://schemas.microsoft.com/ws/2008/06/identity/claims/ispersistent";
//
// Summary:
// The URI for a claim that specifies the locale in which an entity resides, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality.
public const string Locality = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality";
//
// Summary:
// The URI for a claim that specifies the mobile phone number of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone.
public const string MobilePhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone";
//
// Summary:
// The URI for a claim that specifies the name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name.
public const string Name = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";
//
// Summary:
// The URI for a claim that specifies the name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier.
public const string NameIdentifier = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
//
// Summary:
// The URI for a claim that specifies the alternative phone number of an entity,
// http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone.
public const string OtherPhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone";
//
// Summary:
// The URI for a claim that specifies the postal code of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode.
public const string PostalCode = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode";
//
// Summary:
// The URI for a claim that specifies the primary group SID of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid.
public const string PrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid";
//
// Summary:
// The URI for a claim that specifies the primary SID of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid.
public const string PrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid";
//
// Summary:
// The URI for a claim that specifies the role of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/role.
public const string Role = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
//
// Summary:
// The URI for a claim that specifies an RSA key, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa.
public const string Rsa = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa";
//
// Summary:
// The URI for a claim that specifies a serial number, http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber.
public const string SerialNumber = "http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber";
//
// Summary:
// The URI for a claim that specifies a security identifier (SID), http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid.
public const string Sid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid";
//
// Summary:
// The URI for a claim that specifies a service principal name (SPN) claim, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn.
public const string Spn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn";
//
// Summary:
// The URI for a claim that specifies the state or province in which an entity resides,
// http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince.
public const string StateOrProvince = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince";
//
// Summary:
// The URI for a claim that specifies the street address of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress.
public const string StreetAddress = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress";
//
// Summary:
// The URI for a claim that specifies the surname of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname.
public const string Surname = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname";
//
// Summary:
// The URI for a claim that identifies the system entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system.
public const string System = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system";
//
// Summary:
// The URI for a claim that specifies a thumbprint, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint.
// A thumbprint is a globally unique SHA-1 hash of an X.509 certificate.
public const string Thumbprint = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint";
//
// Summary:
// The URI for a claim that specifies a user principal name (UPN), http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn.
public const string Upn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn";
//
// Summary:
// The URI for a claim that specifies a URI, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri.
public const string Uri = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata.
public const string UserData = "http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/version.
public const string Version = "http://schemas.microsoft.com/ws/2008/06/identity/claims/version";
//
// Summary:
// The URI for a claim that specifies the webpage of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage.
public const string Webpage = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage";
//
// Summary:
// The URI for a claim that specifies the Windows domain account name of an entity,
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname.
public const string WindowsAccountName = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdeviceclaim.
public const string WindowsDeviceClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdeviceclaim";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup.
public const string WindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsfqbnversion.
public const string WindowsFqbnVersion = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsfqbnversion";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowssubauthority.
public const string WindowsSubAuthority = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowssubauthority";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsuserclaim.
public const string WindowsUserClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsuserclaim";
//
// Summary:
// The URI for a distinguished name claim of an X.509 certificate, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/x500distinguishedname.
// The X.500 standard defines the methodology for defining distinguished names that
// are used by X.509 certificates.
public const string X500DistinguishedName = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/x500distinguishedname";
#endregion
public const string AvatarURL = "http://schemas.xmlsoap.org/ws/2009/09/identity/claims/avatarurl";
public const string Position = "http://schemas.xmlsoap.org/ws/2009/09/identity/claims/position";
public const string NickName = "http://schemas.xmlsoap.org/ws/2009/09/identity/claims/nickname";
public const string DateRegistered = "http://schemas.xmlsoap.org/ws/2009/09/identity/claims/dateregistered";
}
}
================================================
FILE: src/AdminLTE/Common/Extensions/IdentityExtension.cs
================================================
using System.Linq;
using System.Security.Claims;
namespace AdminLTE.Common.Extensions
{
public static class IdentityExtension
{
///
/// //Use CustomClaimTypes when using this method
///
///
/// Use [CustomClaimTypes] when using this method
///
public static string GetUserProperty(this ClaimsPrincipal user, string claimType)
{
if (user.Identity.IsAuthenticated)
{
return user.Claims.FirstOrDefault(v => v.Type == claimType)?.Value ?? string.Empty;
}
return string.Empty;
}
}
}
================================================
FILE: src/AdminLTE/Common/GlobalHelper.cs
================================================
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AdminLTE.Common
{
public static class GlobalHelper
{
}
}
================================================
FILE: src/AdminLTE/Common/ModuleHelper.cs
================================================
using AdminLTE.Models;
using System;
using System.Collections.Generic;
namespace AdminLTE.Common
{
///
/// This is where you customize the navigation sidebar
///
public static class ModuleHelper
{
public enum Module
{
Home,
About,
Contact,
Error,
Login,
Register,
SuperAdmin,
Role,
UserLogs
}
public static SidebarMenu AddHeader(string name)
{
return new SidebarMenu
{
Type = SidebarMenuType.Header,
Name = name,
};
}
public static SidebarMenu AddTree(string name, string iconClassName = "bi bi-link")
{
return new SidebarMenu
{
Type = SidebarMenuType.Tree,
IsActive = false,
Name = name,
IconClassName = iconClassName,
URLPath = "#",
};
}
public static SidebarMenu AddModule(Module module, Tuple counter = null)
{
if (counter == null)
counter = Tuple.Create(0, 0, 0);
switch (module)
{
case Module.Home:
return new SidebarMenu
{
Type = SidebarMenuType.Link,
Name = "Home",
IconClassName = "bi bi-house-door-fill",
URLPath = "/",
LinkCounter = counter,
};
case Module.Login:
return new SidebarMenu
{
Type = SidebarMenuType.Link,
Name = "Login",
IconClassName = "bi bi-door-open-fill",
URLPath = "/Account/Login",
LinkCounter = counter,
};
case Module.Register:
return new SidebarMenu
{
Type = SidebarMenuType.Link,
Name = "Register",
IconClassName = "bi bi-person-fill-add",
URLPath = "/Account/Register",
LinkCounter = counter,
};
case Module.About:
return new SidebarMenu
{
Type = SidebarMenuType.Link,
Name = "About",
IconClassName = "bi bi-people-fill",
URLPath = "/Home/About",
LinkCounter = counter,
};
case Module.Contact:
return new SidebarMenu
{
Type = SidebarMenuType.Link,
Name = "Contact",
IconClassName = "bi bi-telephone-fill",
URLPath = "/Home/Contact",
LinkCounter = counter,
};
case Module.Error:
return new SidebarMenu
{
Type = SidebarMenuType.Link,
Name = "Error",
IconClassName = "bi bi-exclamation-triangle-fill",
URLPath = "/Home/Error",
LinkCounter = counter,
};
case Module.SuperAdmin:
return new SidebarMenu
{
Type = SidebarMenuType.Link,
Name = "User",
IconClassName = "bi bi-people-fill",
URLPath = "/SuperAdmin",
LinkCounter = counter,
};
case Module.Role:
return new SidebarMenu
{
Type = SidebarMenuType.Link,
Name = "Role",
IconClassName = "bi bi-person-fill-gear",
URLPath = "/Role",
LinkCounter = counter,
};
case Module.UserLogs:
return new SidebarMenu
{
Type = SidebarMenuType.Link,
Name = "UserLogs",
IconClassName = "bi bi-clock-history",
URLPath = "/UserLogs",
LinkCounter = counter,
};
default:
break;
}
return null;
}
}
}
================================================
FILE: src/AdminLTE/Controllers/AccountController.cs
================================================
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using AdminLTE.Models;
using AdminLTE.Models.AccountViewModels;
using AdminLTE.Services;
using AdminLTE.Common;
using System;
namespace AdminLTE.Controllers
{
[Authorize]
public class AccountController : Controller
{
private readonly UserManager _userManager;
private readonly SignInManager _signInManager;
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
private readonly ILogger _logger;
public AccountController(
UserManager userManager,
SignInManager signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger();
}
//
// GET: /Account/Login
[HttpGet]
[AllowAnonymous]
public IActionResult Login(string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
return View();
}
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task Login(LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation(1, "User logged in.");
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning(2, "User account locked out.");
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
//
// GET: /Account/Register
[HttpGet]
[AllowAnonymous]
public IActionResult Register(string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
return View();
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
var user = new ApplicationUser
{
UserName = model.Email,
Email = model.Email,
//extended properties
FirstName = model.FirstName,
LastName = model.LastName,
AvatarURL = "/images/user.png",
DateRegistered = DateTime.UtcNow.ToString(),
Position = "",
NickName = "",
};
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
// Send an email with this link
//var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
//var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
//await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
// $"Please confirm your account by clicking this link: link");
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation(3, "User created a new account with password.");
await _userManager.AddClaimAsync(user, new Claim(CustomClaimTypes.GivenName, user.FirstName));
await _userManager.AddClaimAsync(user, new Claim(CustomClaimTypes.Surname, user.LastName));
await _userManager.AddClaimAsync(user, new Claim(CustomClaimTypes.AvatarURL, user.AvatarURL));
return RedirectToLocal(returnUrl);
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
//
// POST: /Account/LogOff
[HttpPost]
[ValidateAntiForgeryToken]
public async Task LogOff()
{
await _signInManager.SignOutAsync();
_logger.LogInformation(4, "User logged out.");
return RedirectToAction(nameof(HomeController.Index), "Home");
}
//
// POST: /Account/ExternalLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
// Request a redirect to the external login provider.
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
//
// GET: /Account/ExternalLoginCallback
[HttpGet]
[AllowAnonymous]
public async Task ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
return View(nameof(Login));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction(nameof(Login));
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
if (result.Succeeded)
{
_logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl });
}
if (result.IsLockedOut)
{
return View("Lockout");
}
else
{
// If the user does not have an account, then ask the user to create an account.
ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = info.LoginProvider;
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
}
}
//
// POST: /Account/ExternalLoginConfirmation
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null)
{
if (ModelState.IsValid)
{
// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return View("ExternalLoginFailure");
}
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user);
if (result.Succeeded)
{
result = await _userManager.AddLoginAsync(user, info);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
}
AddErrors(result);
}
ViewData["ReturnUrl"] = returnUrl;
return View(model);
}
// GET: /Account/ConfirmEmail
[HttpGet]
[AllowAnonymous]
public async Task ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
return View("Error");
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
return View("Error");
}
var result = await _userManager.ConfirmEmailAsync(user, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
//
// GET: /Account/ForgotPassword
[HttpGet]
[AllowAnonymous]
public IActionResult ForgotPassword()
{
return View();
}
//
// POST: /Account/ForgotPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.FindByNameAsync(model.Email);
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
{
// Don't reveal that the user does not exist or is not confirmed
return View("ForgotPasswordConfirmation");
}
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
// Send an email with this link
//var code = await _userManager.GeneratePasswordResetTokenAsync(user);
//var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
//await _emailSender.SendEmailAsync(model.Email, "Reset Password",
// $"Please reset your password by clicking here: link");
//return View("ForgotPasswordConfirmation");
}
// If we got this far, something failed, redisplay form
return View(model);
}
//
// GET: /Account/ForgotPasswordConfirmation
[HttpGet]
[AllowAnonymous]
public IActionResult ForgotPasswordConfirmation()
{
return View();
}
//
// GET: /Account/ResetPassword
[HttpGet]
[AllowAnonymous]
public IActionResult ResetPassword(string code = null)
{
return code == null ? View("Error") : View();
}
//
// POST: /Account/ResetPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.FindByNameAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
}
var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
if (result.Succeeded)
{
return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
}
AddErrors(result);
return View();
}
//
// GET: /Account/ResetPasswordConfirmation
[HttpGet]
[AllowAnonymous]
public IActionResult ResetPasswordConfirmation()
{
return View();
}
//
// GET: /Account/SendCode
[HttpGet]
[AllowAnonymous]
public async Task SendCode(string returnUrl = null, bool rememberMe = false)
{
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
return View("Error");
}
var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);
var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList();
return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe });
}
//
// POST: /Account/SendCode
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task SendCode(SendCodeViewModel model)
{
if (!ModelState.IsValid)
{
return View();
}
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
return View("Error");
}
// Generate the token and send it
var code = await _userManager.GenerateTwoFactorTokenAsync(user, model.SelectedProvider);
if (string.IsNullOrWhiteSpace(code))
{
return View("Error");
}
var message = "Your security code is: " + code;
if (model.SelectedProvider == "Email")
{
await _emailSender.SendEmailAsync(await _userManager.GetEmailAsync(user), "Security Code", message);
}
else if (model.SelectedProvider == "Phone")
{
await _smsSender.SendSmsAsync(await _userManager.GetPhoneNumberAsync(user), message);
}
return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe });
}
//
// GET: /Account/VerifyCode
[HttpGet]
[AllowAnonymous]
public async Task VerifyCode(string provider, bool rememberMe, string returnUrl = null)
{
// Require that the user has already logged in via username/password or external login
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
return View("Error");
}
return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe });
}
//
// POST: /Account/VerifyCode
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task VerifyCode(VerifyCodeViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// The following code protects for brute force attacks against the two factor codes.
// If a user enters incorrect codes for a specified amount of time then the user account
// will be locked out for a specified amount of time.
var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser);
if (result.Succeeded)
{
return RedirectToLocal(model.ReturnUrl);
}
if (result.IsLockedOut)
{
_logger.LogWarning(7, "User account locked out.");
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid code.");
return View(model);
}
}
#region Helpers
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
private Task GetCurrentUserAsync()
{
return _userManager.GetUserAsync(HttpContext.User);
}
private IActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction(nameof(HomeController.Index), "Home");
}
}
#endregion
}
}
================================================
FILE: src/AdminLTE/Controllers/BaseController.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using AdminLTE.Models;
using System.Runtime.CompilerServices;
namespace AdminLTE.Controllers
{
public class BaseController : Controller
{
internal void AddBreadcrumb(string displayName, string urlPath)
{
List messages;
if (ViewBag.Breadcrumb == null)
{
messages = new List();
}
else
{
messages = ViewBag.Breadcrumb as List;
}
messages.Add(new Message { DisplayName = displayName, URLPath = urlPath });
ViewBag.Breadcrumb = messages;
}
internal void AddPageHeader(string pageHeader = "", string pageDescription = "")
{
ViewBag.PageHeader = Tuple.Create(pageHeader, pageDescription);
}
internal enum PageAlertType
{
Error,
Info,
Warning,
Success
}
internal void AddPageAlerts(PageAlertType pageAlertType, string description)
{
List messages;
if (ViewBag.PageAlerts == null)
{
messages = new List();
}
else
{
messages = ViewBag.PageAlerts as List;
}
messages.Add(new Message { Type = pageAlertType.ToString().ToLower(), ShortDesc = description });
ViewBag.PageAlerts = messages;
}
}
}
================================================
FILE: src/AdminLTE/Controllers/HomeController.cs
================================================
using AdminLTE.Common.Attributes;
using AdminLTE.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace AdminLTE.Controllers
{
public class HomeController : BaseController
{
[HelpDefinition]
public IActionResult Index()
{
AddPageHeader("Dashboard", "");
return View();
}
[HttpPost]
public IActionResult Index(object model)
{
AddPageAlerts(PageAlertType.Info, "you may view the summary here");
return View("Index");
}
[HelpDefinition]
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
AddBreadcrumb("About", "/Account/About");
return View();
}
[HelpDefinition("helpdefault")]
public IActionResult Contact()
{
AddBreadcrumb("Contact", "/Account/Contact");
ViewData["Message"] = "Your contact page.";
return View();
}
public IActionResult Error()
{
return View();
}
#region Get data method.
///
/// GET: /Home/GetData
///
/// Return data
public ActionResult GetData()
{
try
{
// Initialization.
string search = Request.Form["search[value]"][0];
string draw = Request.Form["draw"][0];
string order = Request.Form["order[0][column]"][0];
string orderDir = Request.Form["order[0][dir]"][0];
int startRec = Convert.ToInt32(Request.Form["start"][0]);
int pageSize = Convert.ToInt32(Request.Form["length"][0]);
// Loading.
List data = this.LoadData();
// Total record count.
int totalRecords = data.Count;
// Verification.
if (!string.IsNullOrEmpty(search) &&
!string.IsNullOrWhiteSpace(search))
{
// Apply search
data = data.Where(p => p.sr.ToString().ToLower().Contains(search.ToLower()) ||
p.ordertracknumber.ToLower().Contains(search.ToLower()) ||
p.quantity.ToString().ToLower().Contains(search.ToLower()) ||
p.productname.ToLower().Contains(search.ToLower()) ||
p.specialoffer.ToLower().Contains(search.ToLower()) ||
p.unitprice.ToString().ToLower().Contains(search.ToLower()) ||
p.unitpricediscount.ToString().ToLower().Contains(search.ToLower())).ToList();
}
// Sorting.
data = this.SortByColumnWithOrder(order, orderDir, data);
// Filter record count.
int recFilter = data.Count;
// Apply pagination.
data = data.Skip(startRec).Take(pageSize).ToList();
// Loading drop down lists.
var result = this.Json(new { draw = Convert.ToInt32(draw), recordsTotal = totalRecords, recordsFiltered = recFilter, data = data });
return result;
}
catch (Exception ex)
{
// Info
Console.Write(ex);
return null;
}
}
#endregion
#region Helpers
#region Load Data
///
/// Load data method.
///
/// Returns - Data
private List LoadData()
{
// Initialization.
List lst = new List();
try
{
// Initialization.
string line = string.Empty;
//string srcFilePath = "content/files/SalesOrderDetail.txt";
//var rootPath = Path.GetDirectoryName(AppContext.BaseDirectory);
//var fullPath = Path.Combine(rootPath, srcFilePath);
//string filePath = new Uri(fullPath).LocalPath;
StreamReader sr = new StreamReader(new FileStream(@"wwwroot\files\SalesOrderDetail.txt", FileMode.Open, FileAccess.Read));
// Read file.
while ((line = sr.ReadLine()) != null)
{
// Initialization.
SalesOrderDetail infoObj = new SalesOrderDetail();
string[] info = line.Split(',');
// Setting.
infoObj.sr = Convert.ToInt32(info[0].ToString());
infoObj.ordertracknumber = info[1].ToString();
infoObj.quantity = Convert.ToInt32(info[2].ToString());
infoObj.productname = info[3].ToString();
infoObj.specialoffer = info[4].ToString();
infoObj.unitprice = Convert.ToDouble(info[5].ToString());
infoObj.unitpricediscount = Convert.ToDouble(info[6].ToString());
// Adding.
lst.Add(infoObj);
}
// Closing.
sr.Dispose();
}
catch (Exception ex)
{
// info.
Console.Write(ex);
}
// info.
return lst;
}
#endregion
#region Sort by column with order method
///
/// Sort by column with order method.
///
/// Order parameter
/// Order direction parameter
/// Data parameter
/// Returns - Data
private List SortByColumnWithOrder(string order, string orderDir, List data)
{
// Initialization.
List lst = new List();
try
{
// Sorting
switch (order)
{
case "0":
// Setting.
lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.sr).ToList()
: data.OrderBy(p => p.sr).ToList();
break;
case "1":
// Setting.
lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.ordertracknumber).ToList()
: data.OrderBy(p => p.ordertracknumber).ToList();
break;
case "2":
// Setting.
lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.quantity).ToList()
: data.OrderBy(p => p.quantity).ToList();
break;
case "3":
// Setting.
lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.productname).ToList()
: data.OrderBy(p => p.productname).ToList();
break;
case "4":
// Setting.
lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.specialoffer).ToList()
: data.OrderBy(p => p.specialoffer).ToList();
break;
case "5":
// Setting.
lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.unitprice).ToList()
: data.OrderBy(p => p.unitprice).ToList();
break;
case "6":
// Setting.
lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.unitpricediscount).ToList()
: data.OrderBy(p => p.unitpricediscount).ToList();
break;
default:
// Setting.
lst = orderDir.Equals("DESC", StringComparison.CurrentCultureIgnoreCase) ? data.OrderByDescending(p => p.sr).ToList()
: data.OrderBy(p => p.sr).ToList();
break;
}
}
catch (Exception ex)
{
// info.
Console.Write(ex);
}
// info.
return lst;
}
#endregion
#endregion
}
}
================================================
FILE: src/AdminLTE/Controllers/ManageController.cs
================================================
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using AdminLTE.Models;
using AdminLTE.Models.ManageViewModels;
using AdminLTE.Services;
namespace AdminLTE.Controllers
{
[Authorize]
public class ManageController : Controller
{
private readonly UserManager _userManager;
private readonly SignInManager _signInManager;
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
private readonly ILogger _logger;
public ManageController(
UserManager userManager,
SignInManager signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger();
}
//
// GET: /Manage/Index
[HttpGet]
public async Task Index(ManageMessageId? message = null)
{
ViewData["StatusMessage"] =
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
: message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set."
: message == ManageMessageId.Error ? "An error has occurred."
: message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added."
: message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed."
: "";
var user = await GetCurrentUserAsync();
if (user == null)
{
return View("Error");
}
var model = new IndexViewModel
{
HasPassword = await _userManager.HasPasswordAsync(user),
PhoneNumber = await _userManager.GetPhoneNumberAsync(user),
TwoFactor = await _userManager.GetTwoFactorEnabledAsync(user),
Logins = await _userManager.GetLoginsAsync(user),
BrowserRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user)
};
return View(model);
}
//
// POST: /Manage/RemoveLogin
[HttpPost]
[ValidateAntiForgeryToken]
public async Task RemoveLogin(RemoveLoginViewModel account)
{
ManageMessageId? message = ManageMessageId.Error;
var user = await GetCurrentUserAsync();
if (user != null)
{
var result = await _userManager.RemoveLoginAsync(user, account.LoginProvider, account.ProviderKey);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
message = ManageMessageId.RemoveLoginSuccess;
}
}
return RedirectToAction(nameof(ManageLogins), new { Message = message });
}
//
// GET: /Manage/AddPhoneNumber
public IActionResult AddPhoneNumber()
{
return View();
}
//
// POST: /Manage/AddPhoneNumber
[HttpPost]
[ValidateAntiForgeryToken]
public async Task AddPhoneNumber(AddPhoneNumberViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// Generate the token and send it
var user = await GetCurrentUserAsync();
if (user == null)
{
return View("Error");
}
var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, model.PhoneNumber);
await _smsSender.SendSmsAsync(model.PhoneNumber, "Your security code is: " + code);
return RedirectToAction(nameof(VerifyPhoneNumber), new { PhoneNumber = model.PhoneNumber });
}
//
// POST: /Manage/EnableTwoFactorAuthentication
[HttpPost]
[ValidateAntiForgeryToken]
public async Task EnableTwoFactorAuthentication()
{
var user = await GetCurrentUserAsync();
if (user != null)
{
await _userManager.SetTwoFactorEnabledAsync(user, true);
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation(1, "User enabled two-factor authentication.");
}
return RedirectToAction(nameof(Index), "Manage");
}
//
// POST: /Manage/DisableTwoFactorAuthentication
[HttpPost]
[ValidateAntiForgeryToken]
public async Task DisableTwoFactorAuthentication()
{
var user = await GetCurrentUserAsync();
if (user != null)
{
await _userManager.SetTwoFactorEnabledAsync(user, false);
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation(2, "User disabled two-factor authentication.");
}
return RedirectToAction(nameof(Index), "Manage");
}
//
// GET: /Manage/VerifyPhoneNumber
[HttpGet]
public async Task VerifyPhoneNumber(string phoneNumber)
{
var user = await GetCurrentUserAsync();
if (user == null)
{
return View("Error");
}
var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, phoneNumber);
// Send an SMS to verify the phone number
return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber });
}
//
// POST: /Manage/VerifyPhoneNumber
[HttpPost]
[ValidateAntiForgeryToken]
public async Task VerifyPhoneNumber(VerifyPhoneNumberViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await GetCurrentUserAsync();
if (user != null)
{
var result = await _userManager.ChangePhoneNumberAsync(user, model.PhoneNumber, model.Code);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.AddPhoneSuccess });
}
}
// If we got this far, something failed, redisplay the form
ModelState.AddModelError(string.Empty, "Failed to verify phone number");
return View(model);
}
//
// POST: /Manage/RemovePhoneNumber
[HttpPost]
[ValidateAntiForgeryToken]
public async Task RemovePhoneNumber()
{
var user = await GetCurrentUserAsync();
if (user != null)
{
var result = await _userManager.SetPhoneNumberAsync(user, null);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess });
}
}
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
}
//
// GET: /Manage/ChangePassword
[HttpGet]
public IActionResult ChangePassword()
{
return View();
}
//
// POST: /Manage/ChangePassword
[HttpPost]
[ValidateAntiForgeryToken]
public async Task ChangePassword(ChangePasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await GetCurrentUserAsync();
if (user != null)
{
var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation(3, "User changed their password successfully.");
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangePasswordSuccess });
}
AddErrors(result);
return View(model);
}
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
}
//
// GET: /Manage/SetPassword
[HttpGet]
public IActionResult SetPassword()
{
return View();
}
//
// POST: /Manage/SetPassword
[HttpPost]
[ValidateAntiForgeryToken]
public async Task SetPassword(SetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await GetCurrentUserAsync();
if (user != null)
{
var result = await _userManager.AddPasswordAsync(user, model.NewPassword);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.SetPasswordSuccess });
}
AddErrors(result);
return View(model);
}
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
}
//GET: /Manage/ManageLogins
[HttpGet]
public async Task ManageLogins(ManageMessageId? message = null)
{
ViewData["StatusMessage"] =
message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
: message == ManageMessageId.AddLoginSuccess ? "The external login was added."
: message == ManageMessageId.Error ? "An error has occurred."
: "";
var user = await GetCurrentUserAsync();
if (user == null)
{
return View("Error");
}
var userLogins = await _userManager.GetLoginsAsync(user);
var schemes = await _signInManager.GetExternalAuthenticationSchemesAsync();
var otherLogins = schemes.Where(auth => userLogins.All(ul => auth.Name != ul.LoginProvider)).ToList();
ViewData["ShowRemoveButton"] = user.PasswordHash != null || userLogins.Count > 1;
return View(new ManageLoginsViewModel
{
CurrentLogins = userLogins,
OtherLogins = otherLogins
});
}
//
// POST: /Manage/LinkLogin
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult LinkLogin(string provider)
{
// Request a redirect to the external login provider to link a login for the current user
var redirectUrl = Url.Action("LinkLoginCallback", "Manage");
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
return Challenge(properties, provider);
}
//
// GET: /Manage/LinkLoginCallback
[HttpGet]
public async Task LinkLoginCallback()
{
var user = await GetCurrentUserAsync();
if (user == null)
{
return View("Error");
}
var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user));
if (info == null)
{
return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error });
}
var result = await _userManager.AddLoginAsync(user, info);
var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error;
return RedirectToAction(nameof(ManageLogins), new { Message = message });
}
#region Helpers
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
public enum ManageMessageId
{
AddPhoneSuccess,
AddLoginSuccess,
ChangePasswordSuccess,
SetTwoFactorSuccess,
SetPasswordSuccess,
RemoveLoginSuccess,
RemovePhoneSuccess,
Error
}
private Task GetCurrentUserAsync()
{
return _userManager.GetUserAsync(HttpContext.User);
}
#endregion
}
}
================================================
FILE: src/AdminLTE/Controllers/RoleController.cs
================================================
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using AdminLTE.Models;
using AdminLTE.Models.RoleViewModels;
namespace AdminLTE.Controllers
{
[Authorize(Roles = "SuperAdmins")]
public class RoleController : Controller
{
private RoleManager roleManager;
private UserManager userManager;
public RoleController(RoleManager roleMgr, UserManager userMgr)
{
roleManager = roleMgr;
userManager = userMgr;
}
public IActionResult Index()
{
return View(roleManager.Roles);
}
private void AddErrors(IdentityResult result)
{
foreach (IdentityError error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
}
public IActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task Create([Required] string name)
{
if (ModelState.IsValid)
{
IdentityResult result = await roleManager.CreateAsync(new IdentityRole(name));
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
AddErrors(result);
}
}
return View(name);
}
public async Task Edit(string id)
{
IdentityRole role = await roleManager.FindByIdAsync(id);
List members = new List();
List nonMember = new List();
foreach (ApplicationUser user in userManager.Users.ToArray())
{
var list = await userManager.IsInRoleAsync(user, role.Name)
? members
: nonMember;
list.Add(user);
}
return View(new EditRoleVm
{
Role = role,
Members = members,
NonMembers = nonMember
});
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task Edit(ModifyRoleVm modifyRole)
{
IdentityResult result;
if (ModelState.IsValid)
{
IdentityRole role = await roleManager.FindByIdAsync(modifyRole.RoleId);
role.Name = modifyRole.RoleName;
result = await roleManager.UpdateAsync(role);
if (!result.Succeeded)
{
AddErrors(result);
}
foreach (string userId in modifyRole.IdsToAdd ?? new string[] { })
{
ApplicationUser user = await userManager.FindByIdAsync(userId);
if (user != null)
{
result = await userManager.AddToRoleAsync(user, modifyRole.RoleName);
if (!result.Succeeded)
{
AddErrors(result);
}
}
}
foreach (string userId in modifyRole.IdsToRemove ?? new string[] { })
{
ApplicationUser user = await userManager.FindByIdAsync(userId);
if (user != null)
{
result = await userManager.RemoveFromRoleAsync(user, modifyRole.RoleName);
if (!result.Succeeded)
{
AddErrors(result);
}
}
}
}
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
return View(modifyRole.RoleId);
}
public async Task Delete(string id)
{
IdentityRole role = await roleManager.FindByIdAsync(id);
if (role != null)
{
IdentityResult result = await roleManager.DeleteAsync(role);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
AddErrors(result);
}
}
else
{
ModelState.AddModelError("", "No role found");
}
return View("Index", roleManager.Roles);
}
}
}
================================================
FILE: src/AdminLTE/Controllers/SuperAdminController.cs
================================================
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using AdminLTE.Models;
using AdminLTE.Models.SuperAdminViewModels;
namespace AdminLTE.Controllers
{
[Authorize(Roles = "SuperAdmins")]
public class SuperAdminController : Controller
{
private UserManager userManager;
private IUserValidator userValidator;
private IPasswordValidator passwordValidator;
private IPasswordHasher passwordHasher;
private ApplicationUser testUser = new ApplicationUser
{
UserName = "TestTestForPassword",
Email = "testForPassword@test.test"
};
public SuperAdminController(UserManager userMgr,
IUserValidator userValid, IPasswordValidator passValid,
IPasswordHasher passHasher)
{
userManager = userMgr;
userValidator = userValid;
passwordValidator = passValid;
passwordHasher = passHasher;
}
// GET: //
public ViewResult Index()
{
return View(userManager.Users);
}
public ViewResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task Create(CreateVm createVm)
{
if (ModelState.IsValid)
{
ApplicationUser user = new ApplicationUser
{
UserName = createVm.Email,
Email = createVm.Email,
//extended properties
FirstName = createVm.FirstName,
LastName = createVm.LastName,
AvatarURL = "/images/user.png",
DateRegistered = DateTime.UtcNow.ToString(),
Position = "",
NickName = "",
};
IdentityResult result = await userManager.CreateAsync(user, createVm.Password);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
foreach (IdentityError error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
}
}
return View(createVm);
}
private void AddErrors(IdentityResult result)
{
foreach (IdentityError error in result.Errors)
{
ModelState.TryAddModelError("", error.Description);
}
}
public async Task Delete(string id)
{
ApplicationUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
IdentityResult result = await userManager.DeleteAsync(user);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
AddErrors(result);
}
}
else
{
ModelState.AddModelError("", "User Not Found");
}
return View("Index", userManager.Users);
}
public async Task Edit(string id)
{
ApplicationUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
return View(user);
}
else
{
return RedirectToAction("Index");
}
}
[HttpPost]
[ValidateAntiForgeryToken]
// the names of its parameters must be the same as the property of the User class if we use asp-for in the view
// otherwise form values won't be passed properly
public async Task Edit(string id, string userName, string email)
{
ApplicationUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
// Validate UserName and Email
user.UserName = userName; // UserName won't be changed in the database until UpdateAsync is executed successfully
user.Email = email;
IdentityResult validUseResult = await userValidator.ValidateAsync(userManager, user);
if (!validUseResult.Succeeded)
{
AddErrors(validUseResult);
}
// Update user info
if (validUseResult.Succeeded)
{
// UpdateAsync validates user info such as UserName and Email except password since it's been hashed
IdentityResult result = await userManager.UpdateAsync(user);
if (result.Succeeded)
{
return RedirectToAction("Index", "SuperAdmin");
}
else
{
AddErrors(result);
}
}
}
else
{
ModelState.AddModelError("", "User Not Found");
}
;
return View(user);
}
public async Task ChangePassword(string id)
{
ApplicationUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
return View(user);
}
else
{
return RedirectToAction("Index");
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task ChangePassword(string id, string password)
{
ApplicationUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
// Validate password
// Step 1: using built in validations
IdentityResult passwordResult = await userManager.CreateAsync(testUser, password);
if (passwordResult.Succeeded)
{
await userManager.DeleteAsync(testUser);
}
else
{
AddErrors(passwordResult);
}
/* Step 2: Because of DI, IPasswordValidator is injected into the custom password validator.
So the built in password validation stop working here */
IdentityResult validPasswordResult = await passwordValidator.ValidateAsync(userManager, user, password);
if (validPasswordResult.Succeeded)
{
user.PasswordHash = passwordHasher.HashPassword(user, password);
}
else
{
AddErrors(validPasswordResult);
}
// Update user info
if (passwordResult.Succeeded && validPasswordResult.Succeeded)
{
// UpdateAsync validates user info such as UserName and Email except password since it's been hashed
IdentityResult result = await userManager.UpdateAsync(user);
if (result.Succeeded)
{
return RedirectToAction("Index", "SuperAdmin");
}
else
{
AddErrors(result);
}
}
}
else
{
ModelState.AddModelError("", "User Not Found");
}
return View(user);
}
}
}
================================================
FILE: src/AdminLTE/Controllers/UserLogsController.cs
================================================
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using AdminLTE.Models;
using AdminLTE.Models.SuperAdminViewModels;
using AdminLTE.Data;
namespace AdminLTE.Controllers
{
[Authorize(Roles = "SuperAdmins")]
public class UserLogsController : Controller
{
private readonly ApplicationDbContext _context;
public UserLogsController(ApplicationDbContext context)
{
_context = context;
}
// GET: //
public ViewResult Index()
{
return View(_context.UserAuditEvents.ToList());
}
}
}
================================================
FILE: src/AdminLTE/Data/AppClaimsPrincipalFactory.cs
================================================
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using AdminLTE.Common;
using AdminLTE.Models;
namespace AdminLTE.Data
{
public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory
{
public AppClaimsPrincipalFactory(
UserManager userManager,
RoleManager roleManager,
IOptions optionsAccessor) : base(userManager, roleManager, optionsAccessor)
{
}
public override async Task CreateAsync(ApplicationUser user)
{
var principal = await base.CreateAsync(user);
((ClaimsIdentity)principal.Identity).AddClaims(new[] {
new Claim(CustomClaimTypes.GivenName, user.FirstName),
new Claim(CustomClaimTypes.Surname, user.LastName),
new Claim(CustomClaimTypes.AvatarURL, user.AvatarURL),
new Claim(CustomClaimTypes.Position, user.Position),
new Claim(CustomClaimTypes.NickName, user.NickName),
new Claim(CustomClaimTypes.DateRegistered, user.DateRegistered),
});
return principal;
}
}
}
================================================
FILE: src/AdminLTE/Data/ApplicationDbContext.cs
================================================
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using AdminLTE.Models;
namespace AdminLTE.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public DbSet UserAuditEvents { get; set; }
public ApplicationDbContext(DbContextOptions options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}
}
================================================
FILE: src/AdminLTE/Data/AuditableSignInManager.cs
================================================
using AdminLTE.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Threading.Tasks;
using AdminLTE.Common;
using AdminLTE.Common.Extensions;
using Microsoft.AspNetCore.Authentication;
namespace AdminLTE.Data
{
public class AuditableSignInManager : SignInManager where TUser : class
{
private readonly UserManager _userManager;
private readonly ApplicationDbContext _db;
private readonly IHttpContextAccessor _contextAccessor;
public AuditableSignInManager(UserManager userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory claimsFactory, IOptions optionsAccessor, ILogger> logger, ApplicationDbContext dbContext)
: base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, null, null)
{
if (userManager == null)
throw new ArgumentNullException(nameof(userManager));
if (dbContext == null)
throw new ArgumentNullException(nameof(dbContext));
if (contextAccessor == null)
throw new ArgumentNullException(nameof(contextAccessor));
_userManager = userManager;
_contextAccessor = contextAccessor;
_db = dbContext;
}
public override async Task PasswordSignInAsync(TUser user, string password, bool isPersistent, bool lockoutOnFailure)
{
var result = await base.PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure);
var appUser = user as IdentityUser;
if (appUser != null) // We can only log an audit record if we can access the user object and it's ID
{
var ip = _contextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
UserAudit auditRecord = null;
switch (result.ToString())
{
case "Succeeded":
auditRecord = UserAudit.CreateAuditEvent(appUser.Id, UserAuditEventType.Login, ip);
break;
case "Failed":
auditRecord = UserAudit.CreateAuditEvent(appUser.Id, UserAuditEventType.FailedLogin, ip);
break;
}
if (auditRecord != null)
{
_db.UserAuditEvents.Add(auditRecord);
await _db.SaveChangesAsync();
}
}
return result;
}
public override async Task SignOutAsync()
{
await _contextAccessor.HttpContext.SignOutAsync(_contextAccessor.HttpContext.Features.Get().AuthenticateResult?.Ticket?.AuthenticationScheme);
var user = await _userManager.FindByIdAsync(_userManager.GetUserId(_contextAccessor.HttpContext.User)) as IdentityUser;
if (user != null)
{
var ip = _contextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
var auditRecord = UserAudit.CreateAuditEvent(user.Id, UserAuditEventType.LogOut, ip);
_db.UserAuditEvents.Add(auditRecord);
await _db.SaveChangesAsync();
}
}
}
}
================================================
FILE: src/AdminLTE/Data/DataSeed.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using AdminLTE.Models;
using AdminLTE.Common;
namespace AdminLTE.Data
{
public static class DataSeed
{
public static async Task Seed(IServiceProvider serviceProvider)
{
IServiceScopeFactory scopeFactory = serviceProvider.GetRequiredService();
using (IServiceScope scope = scopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService();
context.Database.Migrate();
UserManager _userManager = scope.ServiceProvider.GetRequiredService>();
RoleManager roleManager = scope.ServiceProvider.GetRequiredService>();
// Seed database code goes here
// User Info
//string userName = "SuperAdmin";
string firstName = "Super";
string lastName = "Admin";
string email = "superadmin@admin.com";
string password = "Qwaszx123$";
string role = "SuperAdmins";
string role2 = "SeniorManagers";
string role3 = "Managers";
if (await _userManager.FindByNameAsync(email) == null)
{
// Create SuperAdmins role if it doesn't exist
if (await roleManager.FindByNameAsync(role) == null)
{
await roleManager.CreateAsync(new IdentityRole(role));
}
if (await roleManager.FindByNameAsync(role2) == null)
{
await roleManager.CreateAsync(new IdentityRole(role2));
}
if (await roleManager.FindByNameAsync(role3) == null)
{
await roleManager.CreateAsync(new IdentityRole(role3));
}
// Create user account if it doesn't exist
ApplicationUser user = new ApplicationUser
{
UserName = email,
Email = email,
//extended properties
FirstName = firstName,
LastName = lastName,
AvatarURL = "/images/user.png",
DateRegistered = DateTime.UtcNow.ToString(),
Position = "",
NickName = "",
};
IdentityResult result = await _userManager.CreateAsync(user, password);
// Assign role to the user
if (result.Succeeded)
{
await _userManager.AddClaimAsync(user, new Claim(CustomClaimTypes.GivenName, user.FirstName));
await _userManager.AddClaimAsync(user, new Claim(CustomClaimTypes.Surname, user.LastName));
await _userManager.AddClaimAsync(user, new Claim(CustomClaimTypes.AvatarURL, user.AvatarURL));
//SignInManager _signInManager = serviceProvider.GetRequiredService>();
//await _signInManager.SignInAsync(user, isPersistent: false);
await _userManager.AddToRoleAsync(user, role);
}
}
}
}
}
}
================================================
FILE: src/AdminLTE/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace AdminLTE.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("00000000000000_CreateIdentitySchema")]
partial class CreateIdentitySchema
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.0.0-rc3")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
{
b.Property("Id");
b.Property("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property("Name")
.HasAnnotation("MaxLength", 256);
b.Property("NormalizedName")
.HasAnnotation("MaxLength", 256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd();
b.Property("ClaimType");
b.Property("ClaimValue");
b.Property("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd();
b.Property("ClaimType");
b.Property("ClaimValue");
b.Property("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
{
b.Property("LoginProvider");
b.Property("ProviderKey");
b.Property("ProviderDisplayName");
b.Property("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
{
b.Property("UserId");
b.Property("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.HasIndex("UserId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b =>
{
b.Property("UserId");
b.Property("LoginProvider");
b.Property("Name");
b.Property("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("AdminLTE.Models.ApplicationUser", b =>
{
b.Property("Id");
b.Property("AccessFailedCount");
b.Property("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property("Email")
.HasAnnotation("MaxLength", 256);
b.Property("EmailConfirmed");
b.Property("LockoutEnabled");
b.Property("LockoutEnd");
b.Property("NormalizedEmail")
.HasAnnotation("MaxLength", 256);
b.Property("NormalizedUserName")
.HasAnnotation("MaxLength", 256);
b.Property("PasswordHash");
b.Property("PhoneNumber");
b.Property("PhoneNumberConfirmed");
b.Property("SecurityStamp");
b.Property("TwoFactorEnabled");
b.Property("UserName")
.HasAnnotation("MaxLength", 256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
.WithMany("Claims")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
{
b.HasOne("AdminLTE.Models.ApplicationUser")
.WithMany("Claims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
{
b.HasOne("AdminLTE.Models.ApplicationUser")
.WithMany("Logins")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
.WithMany("Users")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("AdminLTE.Models.ApplicationUser")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
}
}
}
================================================
FILE: src/AdminLTE/Data/Migrations/00000000000000_CreateIdentitySchema.cs
================================================
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace AdminLTE.Data.Migrations
{
public partial class CreateIdentitySchema : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column(nullable: false),
ConcurrencyStamp = table.Column(nullable: true),
Name = table.Column(maxLength: 256, nullable: true),
NormalizedName = table.Column(maxLength: 256, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column(nullable: false),
LoginProvider = table.Column(nullable: false),
Name = table.Column(nullable: false),
Value = table.Column(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column(nullable: false),
AccessFailedCount = table.Column(nullable: false),
ConcurrencyStamp = table.Column(nullable: true),
Email = table.Column(maxLength: 256, nullable: true),
EmailConfirmed = table.Column(nullable: false),
LockoutEnabled = table.Column(nullable: false),
LockoutEnd = table.Column(nullable: true),
NormalizedEmail = table.Column(maxLength: 256, nullable: true),
NormalizedUserName = table.Column(maxLength: 256, nullable: true),
PasswordHash = table.Column(nullable: true),
PhoneNumber = table.Column(nullable: true),
PhoneNumberConfirmed = table.Column(nullable: false),
SecurityStamp = table.Column(nullable: true),
TwoFactorEnabled = table.Column(nullable: false),
UserName = table.Column(maxLength: 256, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
ClaimType = table.Column(nullable: true),
ClaimValue = table.Column(nullable: true),
RoleId = table.Column(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
ClaimType = table.Column(nullable: true),
ClaimValue = table.Column(nullable: true),
UserId = table.Column(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column(nullable: false),
ProviderKey = table.Column(nullable: false),
ProviderDisplayName = table.Column(nullable: true),
UserId = table.Column(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column(nullable: false),
RoleId = table.Column(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName");
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_UserId",
table: "AspNetUserRoles",
column: "UserId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}
================================================
FILE: src/AdminLTE/Data/Migrations/20160801092435_ExtendASPNetUser.Designer.cs
================================================
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using AdminLTE.Data;
namespace AdminLTE.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20160801092435_ExtendASPNetUser")]
partial class ExtendASPNetUser
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.0.0-rtm-21431")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("AdminLTE.Models.ApplicationUser", b =>
{
b.Property("Id");
b.Property("AccessFailedCount");
b.Property("AvatarURL");
b.Property("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property("Email")
.HasAnnotation("MaxLength", 256);
b.Property("EmailConfirmed");
b.Property("FirstName");
b.Property("LastName");
b.Property("LockoutEnabled");
b.Property("LockoutEnd");
b.Property("NormalizedEmail")
.HasAnnotation("MaxLength", 256);
b.Property("NormalizedUserName")
.HasAnnotation("MaxLength", 256);
b.Property("PasswordHash");
b.Property("PhoneNumber");
b.Property("PhoneNumberConfirmed");
b.Property("SecurityStamp");
b.Property("TwoFactorEnabled");
b.Property("UserName")
.HasAnnotation("MaxLength", 256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
{
b.Property("Id");
b.Property("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property("Name")
.HasAnnotation("MaxLength", 256);
b.Property("NormalizedName")
.HasAnnotation("MaxLength", 256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd();
b.Property("ClaimType");
b.Property("ClaimValue");
b.Property("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd();
b.Property("ClaimType");
b.Property("ClaimValue");
b.Property("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
{
b.Property("LoginProvider");
b.Property("ProviderKey");
b.Property("ProviderDisplayName");
b.Property("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
{
b.Property("UserId");
b.Property("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.HasIndex("UserId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b =>
{
b.Property("UserId");
b.Property("LoginProvider");
b.Property("Name");
b.Property("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
.WithMany("Claims")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
{
b.HasOne("AdminLTE.Models.ApplicationUser")
.WithMany("Claims")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
{
b.HasOne("AdminLTE.Models.ApplicationUser")
.WithMany("Logins")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
.WithMany("Users")
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("AdminLTE.Models.ApplicationUser")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
}
}
}
================================================
FILE: src/AdminLTE/Data/Migrations/20160801092435_ExtendASPNetUser.cs
================================================
using Microsoft.EntityFrameworkCore.Migrations;
namespace AdminLTE.Data.Migrations
{
public partial class ExtendASPNetUser : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn(
name: "AvatarURL",
table: "AspNetUsers",
nullable: true);
migrationBuilder.AddColumn(
name: "FirstName",
table: "AspNetUsers",
nullable: true);
migrationBuilder.AddColumn(
name: "LastName",
table: "AspNetUsers",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AvatarURL",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "FirstName",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "LastName",
table: "AspNetUsers");
}
}
}
================================================
FILE: src/AdminLTE/Data/Migrations/20160802025049_UserAuditTable.Designer.cs
================================================
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using AdminLTE.Data;
namespace AdminLTE.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20160802025049_UserAuditTable")]
partial class UserAuditTable
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.0.0-rtm-21431")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("AdminLTE.Models.ApplicationUser", b =>
{
b.Property("Id");
b.Property("AccessFailedCount");
b.Property("AvatarURL");
b.Property("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property("Email")
.HasAnnotation("MaxLength", 256);
b.Property("EmailConfirmed");
b.Property("FirstName");
b.Property("LastName");
b.Property("LockoutEnabled");
b.Property