11 |
RolesViewModel
12 |
13 |
14 |
15 | @Html.DisplayNameFor(model => model.RoleName)
16 |
17 |
18 |
19 | @Html.DisplayFor(model => model.RoleName)
20 |
21 |
22 |
23 | @Html.DisplayNameFor(model => model.Description)
24 |
25 |
26 |
27 | @Html.DisplayFor(model => model.Description)
28 |
29 |
30 |
31 |
32 | @using (Html.BeginForm()) {
33 | @Html.AntiForgeryToken()
34 |
35 |
36 | |
37 | @Html.ActionLink("Back to List", "Index")
38 |
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Account/_SetPasswordPartial.cshtml:
--------------------------------------------------------------------------------
1 | @model AspNetExtendingIdentityRoles.Models.ManageUserViewModel
2 |
3 |
4 | You do not have a local username/password for this site. Add a local
5 | account so you can log in without an external login.
6 |
7 |
8 | @using (Html.BeginForm("Manage", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
9 | {
10 | @Html.AntiForgeryToken()
11 |
12 |
11 |
EditUserViewModel
12 |
13 |
14 |
15 | @Html.DisplayNameFor(model => model.UserName)
16 |
17 |
18 |
19 | @Html.DisplayFor(model => model.UserName)
20 |
21 |
22 |
23 | @Html.DisplayNameFor(model => model.FirstName)
24 |
25 |
26 |
27 | @Html.DisplayFor(model => model.FirstName)
28 |
29 |
30 |
31 | @Html.DisplayNameFor(model => model.LastName)
32 |
33 |
34 |
35 | @Html.DisplayFor(model => model.LastName)
36 |
37 |
38 |
39 | @Html.DisplayNameFor(model => model.Email)
40 |
41 |
42 |
43 | @Html.DisplayFor(model => model.Email)
44 |
45 |
46 |
47 |
48 | @using (Html.BeginForm()) {
49 | @Html.AntiForgeryToken()
50 |
51 |
52 | |
53 | @Html.ActionLink("Back to List", "Index")
54 |
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Account/Index.cshtml:
--------------------------------------------------------------------------------
1 | @model IEnumerable
2 |
3 | @{
4 | ViewBag.Title = "Index";
5 | }
6 |
7 | Index
8 |
9 |
10 | @Html.ActionLink("Create New", "Register")
11 |
12 |
13 |
14 |
15 | @Html.DisplayNameFor(model => model.UserName)
16 |
17 |
18 | @Html.DisplayNameFor(model => model.FirstName)
19 |
20 |
21 | @Html.DisplayNameFor(model => model.LastName)
22 |
23 |
24 | @Html.DisplayNameFor(model => model.Email)
25 |
26 |
27 |
28 |
29 | @foreach (var item in Model) {
30 |
31 |
32 | @Html.DisplayFor(modelItem => item.UserName)
33 |
34 |
35 | @Html.DisplayFor(modelItem => item.FirstName)
36 |
37 |
38 | @Html.DisplayFor(modelItem => item.LastName)
39 |
40 |
41 | @Html.DisplayFor(modelItem => item.Email)
42 |
43 |
44 | @Html.ActionLink("Edit", "Edit", new { id = item.UserName }) |
45 | @Html.ActionLink("Roles", "UserRoles", new { id = item.UserName }) |
46 | @Html.ActionLink("Delete", "Delete", new { id = item.UserName })
47 |
48 |
49 | }
50 |
51 |
52 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Account/_ChangePasswordPartial.cshtml:
--------------------------------------------------------------------------------
1 | @using Microsoft.AspNet.Identity
2 | @model AspNetExtendingIdentityRoles.Models.ManageUserViewModel
3 |
4 | You're logged in as @User.Identity.GetUserName() .
5 |
6 | @using (Html.BeginForm("Manage", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
7 | {
8 | @Html.AntiForgeryToken()
9 | Change Password Form
10 |
11 | @Html.ValidationSummary()
12 |
18 |
24 |
30 |
31 |
36 | }
37 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("AspNetExtendingIdentityRoles")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("AspNetExtendingIdentityRoles")]
13 | [assembly: AssemblyCopyright("Copyright © 2013")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("007b4066-9928-4140-a3cb-4cc527b22a69")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Revision and Build Numbers
33 | // by using the '*' as shown below:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Account/UserRoles.cshtml:
--------------------------------------------------------------------------------
1 | @model AspNetExtendingIdentityRoles.Models.SelectUserRolesViewModel
2 |
3 | @{
4 | ViewBag.Title = "User Roles";
5 | }
6 |
7 | Roles for user @Html.DisplayFor(model => model.UserName)
8 |
9 |
10 | @using (Html.BeginForm("UserRoles", "Account", FormMethod.Post, new { encType = "multipart/form-data", name = "myform" }))
11 | {
12 | @Html.AntiForgeryToken()
13 |
14 |
51 | }
52 |
53 |
54 | @Html.ActionLink("Back to List", "Index")
55 |
56 |
57 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewBag.Title = "Home Page";
3 | }
4 |
5 |
6 |
ASP.NET
7 |
ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.
8 |
Learn more »
9 |
10 |
11 |
12 |
13 |
Getting started
14 |
15 | ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that
16 | enables a clean separation of concerns and gives you full control over markup
17 | for enjoyable, agile development.
18 |
19 |
Learn more »
20 |
21 |
22 |
Get more libraries
23 |
NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.
24 |
Learn more »
25 |
26 |
27 |
Web Hosting
28 |
You can easily find a web hosting company that offers the right mix of features and price for your applications.
29 |
Learn more »
30 |
31 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/App_Start/Startup.Auth.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNet.Identity;
2 | using Microsoft.Owin;
3 | using Microsoft.Owin.Security.Cookies;
4 | using Owin;
5 |
6 | namespace AspNetExtendingIdentityRoles
7 | {
8 | public partial class Startup
9 | {
10 | // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
11 | public void ConfigureAuth(IAppBuilder app)
12 | {
13 | // Enable the application to use a cookie to store information for the signed in user
14 | app.UseCookieAuthentication(new CookieAuthenticationOptions
15 | {
16 | AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
17 | LoginPath = new PathString("/Account/Login")
18 | });
19 | // Use a cookie to temporarily store information about a user logging in with a third party login provider
20 | app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
21 |
22 | // Uncomment the following lines to enable logging in with third party login providers
23 | //app.UseMicrosoftAccountAuthentication(
24 | // clientId: "",
25 | // clientSecret: "");
26 |
27 | //app.UseTwitterAuthentication(
28 | // consumerKey: "",
29 | // consumerSecret: "");
30 |
31 | //app.UseFacebookAuthentication(
32 | // appId: "",
33 | // appSecret: "");
34 |
35 | //app.UseGoogleAuthentication();
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetExtendingIdentityRoles", "AspNetExtendingIdentityRoles\AspNetExtendingIdentityRoles.csproj", "{D7ADA016-6E82-4F70-B6CF-B687A3B6F6EA}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{6DCF7BBA-8C8E-4E64-A6F0-3CB2A778DA69}"
9 | ProjectSection(SolutionItems) = preProject
10 | .nuget\NuGet.Config = .nuget\NuGet.Config
11 | .nuget\NuGet.exe = .nuget\NuGet.exe
12 | .nuget\NuGet.targets = .nuget\NuGet.targets
13 | EndProjectSection
14 | EndProject
15 | Global
16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
17 | Debug|Any CPU = Debug|Any CPU
18 | Release|Any CPU = Release|Any CPU
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {D7ADA016-6E82-4F70-B6CF-B687A3B6F6EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22 | {D7ADA016-6E82-4F70-B6CF-B687A3B6F6EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
23 | {D7ADA016-6E82-4F70-B6CF-B687A3B6F6EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {D7ADA016-6E82-4F70-B6CF-B687A3B6F6EA}.Release|Any CPU.Build.0 = Release|Any CPU
25 | EndGlobalSection
26 | GlobalSection(SolutionProperties) = preSolution
27 | HideSolutionNode = FALSE
28 | EndGlobalSection
29 | GlobalSection(NestedProjects) = preSolution
30 | {D7ADA016-6E82-4F70-B6CF-B687A3B6F6EA} = {6DCF7BBA-8C8E-4E64-A6F0-3CB2A778DA69}
31 | EndGlobalSection
32 | EndGlobal
33 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Roles/Edit.cshtml:
--------------------------------------------------------------------------------
1 | @model AspNetExtendingIdentityRoles.Models.EditRoleViewModel
2 |
3 | @{
4 | ViewBag.Title = "Edit";
5 | }
6 |
7 | Edit
8 |
9 |
10 | @using (Html.BeginForm())
11 | {
12 | @Html.AntiForgeryToken()
13 |
14 |
44 | }
45 |
46 |
47 | @Html.ActionLink("Back to List", "Index")
48 |
49 |
50 | @section Scripts {
51 | @Scripts.Render("~/bundles/jqueryval")
52 | }
53 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Roles/Create.cshtml:
--------------------------------------------------------------------------------
1 | @model AspNetExtendingIdentityRoles.Models.RoleViewModel
2 |
3 | @{
4 | ViewBag.Title = "Create";
5 | }
6 |
7 | Create Role
8 |
9 |
10 | @using (Html.BeginForm())
11 | {
12 | @Html.AntiForgeryToken()
13 |
14 |
45 | }
46 |
47 |
48 | @Html.ActionLink("Back to List", "Index")
49 |
50 |
51 | @section Scripts {
52 | @Scripts.Render("~/bundles/jqueryval")
53 | }
54 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | @ViewBag.Title - My ASP.NET Application
7 | @Styles.Render("~/Content/css")
8 | @Scripts.Render("~/bundles/modernizr")
9 |
10 |
11 |
12 |
13 |
14 |
22 |
23 |
24 | @Html.ActionLink("Home", "Index", "Home")
25 | @Html.ActionLink("About", "About", "Home")
26 | @Html.ActionLink("Contact", "Contact", "Home")
27 | @Html.ActionLink("Users", "Index", "Account")
28 | @Html.ActionLink("Roles", "Index", "Roles")
29 |
30 | @Html.Partial("_LoginPartial")
31 |
32 |
33 |
34 |
35 | @RenderBody()
36 |
37 |
40 |
41 |
42 | @Scripts.Render("~/bundles/jquery")
43 | @Scripts.Render("~/bundles/bootstrap")
44 | @RenderSection("scripts", required: false)
45 |
46 |
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ASP.NET Extending Identity Roles
2 | ======================================
3 |
4 | This is an example project to accompany a blog post describing how to extend the `AspNet.Identity.EntityFramework.IdentityRole` class as implemented in the ASP.NET MVC 5 Identity system.
5 |
6 | This project builds upon the foundation created by another example, [ASP.NET Role-Based Security Example][3], covered in the article [Extending Identity Accounts and Implementing Role-Based Authentication in ASP.NET MVC 5][1]. You can see in the commit history the basic steps taken to move from the previous project structure to one where I have added some very basic extensions to the `IdentityRole` class.
7 |
8 | In the previous article, we discuss the relative ease with which the `IdentityUser` class may be extended to add additional properties, and the implementation of very basic role management. Unlike `IdentityUser`, extension of the `IdentityRole` class requires a bit more effort, a little insight into the internals of the ASP.NET 5 Identity system, and a few work-arounds.
9 |
10 | You will need to enable Nuget Package Restore in Visual Studio in order to download and restore Nuget packages during build. If you are not sure how to do this, see [Keep Nuget Packages Out of Source Control with Nuget Package Manager Restore][2]
11 |
12 | You will also need to run Entity Framework Migrations `Update-Database` command per the article. The migration files are included in the repo, so you will NOT need to `Enable-Migrations` or run `Add-Migration Init`.
13 |
14 | [1]: http://www.typecastexception.com/post/2013/11/11/Extending-Identity-Accounts-and-Implementing-Role-Based-Authentication-in-ASPNET-MVC-5.aspx "Extending Identity Accounts and Implementing Role-Based Authentication in ASP.NET MVC 5"
15 |
16 | [2]: http://www.typecastexception.com/post/2013/11/10/Keep-Nuget-Packages-Out-of-Source-Control-with-Nuget-Package-Manager-Restore.aspx "Keep Nuget Packages Out of Source Control with Nuget Package Manager Restore"
17 |
18 | [3]: https://github.com/xivSolutions/AspNetRoleBasedSecurityExample "ASP.NET Role-Based Security Example"
19 |
20 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Account/Edit.cshtml:
--------------------------------------------------------------------------------
1 | @model AspNetExtendingIdentityRoles.Models.EditUserViewModel
2 |
3 | @{
4 | ViewBag.Title = "Edit";
5 | }
6 |
7 | Edit
8 |
9 |
10 | @using (Html.BeginForm())
11 | {
12 | @Html.AntiForgeryToken()
13 |
14 |
56 | }
57 |
58 |
59 | @Html.ActionLink("Back to List", "Index")
60 |
61 |
62 | @section Scripts {
63 | @Scripts.Render("~/bundles/jqueryval")
64 | }
65 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Migrations/Configuration.cs:
--------------------------------------------------------------------------------
1 | using AspNetExtendingIdentityRoles.Models;
2 | using System.Data.Entity.Migrations;
3 |
4 | namespace AspNetExtendingIdentityRoles.Migrations
5 | {
6 | using System;
7 | using System.Data.Entity;
8 | using System.Data.Entity.Migrations;
9 | using System.Linq;
10 |
11 | internal sealed class Configuration : DbMigrationsConfiguration
12 | {
13 | public Configuration()
14 | {
15 | AutomaticMigrationsEnabled = true;
16 | }
17 |
18 |
19 | protected override void Seed(ApplicationDbContext context)
20 | {
21 | this.AddUserAndRoles();
22 | }
23 |
24 |
25 | bool AddUserAndRoles()
26 | {
27 | bool success = false;
28 |
29 | var idManager = new IdentityManager();
30 | success = idManager.CreateRole("Admin", "Global Access");
31 | if (!success == true) return success;
32 |
33 | success = idManager.CreateRole("CanEdit", "Edit existing records");
34 | if (!success == true) return success;
35 |
36 | success = idManager.CreateRole("User", "Restricted to business domain activity");
37 | if (!success) return success;
38 |
39 |
40 | var newUser = new ApplicationUser()
41 | {
42 | UserName = "jatten",
43 | FirstName = "John",
44 | LastName = "Atten",
45 | Email = "jatten@typecastexception.com"
46 | };
47 |
48 | // Be careful here - you will need to use a password which will
49 | // be valid under the password rules for the application,
50 | // or the process will abort:
51 | success = idManager.CreateUser(newUser, "Password1");
52 | if (!success) return success;
53 |
54 | success = idManager.AddUserToRole(newUser.Id, "Admin");
55 | if (!success) return success;
56 |
57 | success = idManager.AddUserToRole(newUser.Id, "CanEdit");
58 | if (!success) return success;
59 |
60 | success = idManager.AddUserToRole(newUser.Id, "User");
61 | if (!success) return success;
62 |
63 | return success;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Account/Register.cshtml:
--------------------------------------------------------------------------------
1 | @model AspNetExtendingIdentityRoles.Models.RegisterViewModel
2 | @{
3 | ViewBag.Title = "Register";
4 | }
5 |
6 | @ViewBag.Title.
7 |
8 | @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
9 | {
10 | @Html.AntiForgeryToken()
11 | Create a new account.
12 |
13 | @Html.ValidationSummary()
14 |
20 |
26 |
32 |
33 | //Add the LastName, FirstName, and Email Properties:
34 |
40 |
41 |
47 |
48 |
54 |
55 |
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Views/Account/Login.cshtml:
--------------------------------------------------------------------------------
1 | @model AspNetExtendingIdentityRoles.Models.LoginViewModel
2 |
3 | @{
4 | ViewBag.Title = "Log in";
5 | }
6 |
7 | @ViewBag.Title.
8 |
51 | @section Scripts {
52 | @Scripts.Render("~/bundles/jqueryval")
53 | }
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Models/IdentityManager.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNet.Identity.EntityFramework;
2 | using Microsoft.AspNet.Identity;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Collections.Generic;
5 | using AspNetExtendingIdentityRoles.Models;
6 | using System.Linq;
7 |
8 | namespace AspNetExtendingIdentityRoles.Models
9 | {
10 | public class IdentityManager
11 | {
12 | // Swap ApplicationRole for IdentityRole:
13 | RoleManager _roleManager = new RoleManager(
14 | new RoleStore(new ApplicationDbContext()));
15 |
16 | UserManager _userManager = new UserManager(
17 | new UserStore(new ApplicationDbContext()));
18 |
19 | ApplicationDbContext _db = new ApplicationDbContext();
20 |
21 |
22 | public bool RoleExists(string name)
23 | {
24 | return _roleManager.RoleExists(name);
25 | }
26 |
27 |
28 | public bool CreateRole(string name, string description = "")
29 | {
30 | // Swap ApplicationRole for IdentityRole:
31 | var idResult = _roleManager.Create(new ApplicationRole(name, description));
32 | return idResult.Succeeded;
33 | }
34 |
35 |
36 | public bool CreateUser(ApplicationUser user, string password)
37 | {
38 | var idResult = _userManager.Create(user, password);
39 | return idResult.Succeeded;
40 | }
41 |
42 |
43 | public bool AddUserToRole(string userId, string roleName)
44 | {
45 | var idResult = _userManager.AddToRole(userId, roleName);
46 | return idResult.Succeeded;
47 | }
48 |
49 |
50 | public void ClearUserRoles(string userId)
51 | {
52 | var user = _userManager.FindById(userId);
53 | var currentRoles = new List();
54 |
55 | currentRoles.AddRange(user.Roles);
56 | foreach (var role in currentRoles)
57 | {
58 | _userManager.RemoveFromRole(userId, role.Role.Name);
59 | }
60 | }
61 |
62 |
63 | public void RemoveFromRole(string userId, string roleName)
64 | {
65 | _userManager.RemoveFromRole(userId, roleName);
66 | }
67 |
68 |
69 | public void DeleteRole(string roleId)
70 | {
71 | var roleUsers = _db.Users.Where(u => u.Roles.Any(r => r.RoleId == roleId));
72 | var role = _db.Roles.Find(roleId);
73 |
74 | foreach (var user in roleUsers)
75 | {
76 | this.RemoveFromRole(user.Id, role.Name);
77 | }
78 | _db.Roles.Remove(role);
79 | _db.SaveChanges();
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Models/ApplicationDbContext.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNet.Identity.EntityFramework;
2 | using Microsoft.AspNet.Identity;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Collections.Generic;
5 | using System.Data.Entity;
6 | using System;
7 | using System.Data.Entity.Infrastructure;
8 | using System.Data.Entity.ModelConfiguration;
9 | using System.Data.Entity.ModelConfiguration.Configuration;
10 | using System.Data.Entity.Validation;
11 | using System.Globalization;
12 | using System.Linq;
13 | using System.Linq.Expressions;
14 | using System.Reflection;
15 | using System.Runtime.CompilerServices;
16 |
17 | namespace AspNetExtendingIdentityRoles.Models
18 | {
19 | public class ApplicationDbContext : IdentityDbContext
20 | {
21 | // Add an instance IDbSet using the 'new' keyword:
22 | new public virtual IDbSet Roles { get; set; }
23 |
24 | public ApplicationDbContext()
25 | : base("DefaultConnection")
26 | {
27 |
28 | }
29 |
30 |
31 | protected override void OnModelCreating(DbModelBuilder modelBuilder)
32 | {
33 | if (modelBuilder == null)
34 | {
35 | throw new ArgumentNullException("modelBuilder");
36 | }
37 |
38 | // Keep this:
39 | modelBuilder.Entity().ToTable("AspNetUsers");
40 |
41 | // Change TUser to ApplicationUser everywhere else - IdentityUser and ApplicationUser essentially 'share' the AspNetUsers Table in the database:
42 | EntityTypeConfiguration table =
43 | modelBuilder.Entity().ToTable("AspNetUsers");
44 |
45 | table.Property((ApplicationUser u) => u.UserName).IsRequired();
46 |
47 | // EF won't let us swap out IdentityUserRole for ApplicationUserRole here:
48 | modelBuilder.Entity().HasMany((ApplicationUser u) => u.Roles);
49 | modelBuilder.Entity().HasKey((IdentityUserRole r) =>
50 | new { UserId = r.UserId, RoleId = r.RoleId }).ToTable("AspNetUserRoles");
51 |
52 | // Leave this alone:
53 | EntityTypeConfiguration entityTypeConfiguration =
54 | modelBuilder.Entity().HasKey((IdentityUserLogin l) =>
55 | new { UserId = l.UserId, LoginProvider = l.LoginProvider, ProviderKey = l.ProviderKey }).ToTable("AspNetUserLogins");
56 |
57 | entityTypeConfiguration.HasRequired((IdentityUserLogin u) => u.User);
58 | EntityTypeConfiguration table1 = modelBuilder.Entity().ToTable("AspNetUserClaims");
59 | table1.HasRequired((IdentityUserClaim u) => u.User);
60 |
61 | // Add this, so that IdentityRole can share a table with ApplicationRole:
62 | modelBuilder.Entity().ToTable("AspNetRoles");
63 |
64 | // Change these from IdentityRole to ApplicationRole:
65 | EntityTypeConfiguration entityTypeConfiguration1 = modelBuilder.Entity().ToTable("AspNetRoles");
66 | entityTypeConfiguration1.Property((ApplicationRole r) => r.Name).IsRequired();
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Controllers/RolesController.cs:
--------------------------------------------------------------------------------
1 | using AspNetExtendingIdentityRoles.Models;
2 | using System.Collections.Generic;
3 | using System.Data.Entity;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Web.Mvc;
7 |
8 | namespace AspNetExtendingIdentityRoles.Controllers
9 | {
10 | public class RolesController : Controller
11 | {
12 | private ApplicationDbContext _db = new ApplicationDbContext();
13 |
14 | public ActionResult Index()
15 | {
16 | var rolesList = new List();
17 | foreach(var role in _db.Roles)
18 | {
19 | var roleModel = new RoleViewModel(role);
20 | rolesList.Add(roleModel);
21 | }
22 | return View(rolesList);
23 | }
24 |
25 |
26 | [Authorize(Roles = "Admin")]
27 | public ActionResult Create(string message = "")
28 | {
29 | ViewBag.Message = message;
30 | return View();
31 | }
32 |
33 |
34 | [HttpPost]
35 | [Authorize(Roles = "Admin")]
36 | public ActionResult Create([Bind(Include =
37 | "RoleName,Description")]RoleViewModel model)
38 | {
39 | string message = "That role name has already been used";
40 | if (ModelState.IsValid)
41 | {
42 | var role = new ApplicationRole(model.RoleName, model.Description);
43 | var idManager = new IdentityManager();
44 |
45 | if(idManager.RoleExists(model.RoleName))
46 | {
47 | return View(message);
48 | }
49 | else
50 | {
51 | idManager.CreateRole(model.RoleName, model.Description);
52 | return RedirectToAction("Index", "Account");
53 | }
54 | }
55 | return View();
56 | }
57 |
58 |
59 | [Authorize(Roles = "Admin")]
60 | public ActionResult Edit(string id)
61 | {
62 | // It's actually the Role.Name tucked into the id param:
63 | var role = _db.Roles.First(r => r.Name == id);
64 | var roleModel = new EditRoleViewModel(role);
65 | return View(roleModel);
66 | }
67 |
68 |
69 | [HttpPost]
70 | [Authorize(Roles = "Admin")]
71 | public ActionResult Edit([Bind(Include =
72 | "RoleName,OriginalRoleName,Description")] EditRoleViewModel model)
73 | {
74 | if (ModelState.IsValid)
75 | {
76 | var role = _db.Roles.First(r => r.Name == model.OriginalRoleName);
77 | role.Name = model.RoleName;
78 | role.Description = model.Description;
79 | _db.Entry(role).State = EntityState.Modified;
80 | _db.SaveChanges();
81 | return RedirectToAction("Index");
82 | }
83 | return View(model);
84 | }
85 |
86 |
87 | [Authorize(Roles = "Admin")]
88 | public ActionResult Delete(string id)
89 | {
90 | if (id == null)
91 | {
92 | return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
93 | }
94 | var role = _db.Roles.First(r => r.Name == id);
95 | var model = new RoleViewModel(role);
96 | if (role == null)
97 | {
98 | return HttpNotFound();
99 | }
100 | return View(model);
101 | }
102 |
103 |
104 | [Authorize(Roles = "Admin")]
105 | [HttpPost, ActionName("Delete")]
106 | public ActionResult DeleteConfirmed(string id)
107 | {
108 | var role = _db.Roles.First(r => r.Name == id);
109 | var idManager = new IdentityManager();
110 | idManager.DeleteRole(role.Id);
111 | return RedirectToAction("Index");
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Migrations/201402130341319_init.cs:
--------------------------------------------------------------------------------
1 | namespace AspNetExtendingIdentityRoles.Migrations
2 | {
3 | using System;
4 | using System.Data.Entity.Migrations;
5 |
6 | public partial class init : DbMigration
7 | {
8 | public override void Up()
9 | {
10 | CreateTable(
11 | "dbo.AspNetRoles",
12 | c => new
13 | {
14 | Id = c.String(nullable: false, maxLength: 128),
15 | Name = c.String(),
16 | Description = c.String(),
17 | Discriminator = c.String(nullable: false, maxLength: 128),
18 | })
19 | .PrimaryKey(t => t.Id);
20 |
21 | CreateTable(
22 | "dbo.AspNetUsers",
23 | c => new
24 | {
25 | Id = c.String(nullable: false, maxLength: 128),
26 | UserName = c.String(),
27 | PasswordHash = c.String(),
28 | SecurityStamp = c.String(),
29 | FirstName = c.String(),
30 | LastName = c.String(),
31 | Email = c.String(),
32 | Discriminator = c.String(nullable: false, maxLength: 128),
33 | })
34 | .PrimaryKey(t => t.Id);
35 |
36 | CreateTable(
37 | "dbo.AspNetUserClaims",
38 | c => new
39 | {
40 | Id = c.Int(nullable: false, identity: true),
41 | ClaimType = c.String(),
42 | ClaimValue = c.String(),
43 | User_Id = c.String(nullable: false, maxLength: 128),
44 | })
45 | .PrimaryKey(t => t.Id)
46 | .ForeignKey("dbo.AspNetUsers", t => t.User_Id, cascadeDelete: true)
47 | .Index(t => t.User_Id);
48 |
49 | CreateTable(
50 | "dbo.AspNetUserLogins",
51 | c => new
52 | {
53 | UserId = c.String(nullable: false, maxLength: 128),
54 | LoginProvider = c.String(nullable: false, maxLength: 128),
55 | ProviderKey = c.String(nullable: false, maxLength: 128),
56 | })
57 | .PrimaryKey(t => new { t.UserId, t.LoginProvider, t.ProviderKey })
58 | .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
59 | .Index(t => t.UserId);
60 |
61 | CreateTable(
62 | "dbo.AspNetUserRoles",
63 | c => new
64 | {
65 | UserId = c.String(nullable: false, maxLength: 128),
66 | RoleId = c.String(nullable: false, maxLength: 128),
67 | })
68 | .PrimaryKey(t => new { t.UserId, t.RoleId })
69 | .ForeignKey("dbo.AspNetRoles", t => t.RoleId, cascadeDelete: true)
70 | .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
71 | .Index(t => t.RoleId)
72 | .Index(t => t.UserId);
73 |
74 | }
75 |
76 | public override void Down()
77 | {
78 | DropForeignKey("dbo.AspNetUserClaims", "User_Id", "dbo.AspNetUsers");
79 | DropForeignKey("dbo.AspNetUserRoles", "UserId", "dbo.AspNetUsers");
80 | DropForeignKey("dbo.AspNetUserRoles", "RoleId", "dbo.AspNetRoles");
81 | DropForeignKey("dbo.AspNetUserLogins", "UserId", "dbo.AspNetUsers");
82 | DropIndex("dbo.AspNetUserClaims", new[] { "User_Id" });
83 | DropIndex("dbo.AspNetUserRoles", new[] { "UserId" });
84 | DropIndex("dbo.AspNetUserRoles", new[] { "RoleId" });
85 | DropIndex("dbo.AspNetUserLogins", new[] { "UserId" });
86 | DropTable("dbo.AspNetUserRoles");
87 | DropTable("dbo.AspNetUserLogins");
88 | DropTable("dbo.AspNetUserClaims");
89 | DropTable("dbo.AspNetUsers");
90 | DropTable("dbo.AspNetRoles");
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Scripts/respond.min.js:
--------------------------------------------------------------------------------
1 | /* NUGET: BEGIN LICENSE TEXT
2 | *
3 | * Microsoft grants you the right to use these script files for the sole
4 | * purpose of either: (i) interacting through your browser with the Microsoft
5 | * website or online service, subject to the applicable licensing or use
6 | * terms; or (ii) using the files as included with a Microsoft product subject
7 | * to that product's license terms. Microsoft reserves all other rights to the
8 | * files not expressly granted by Microsoft, whether by implication, estoppel
9 | * or otherwise. Insofar as a script file is dual licensed under GPL,
10 | * Microsoft neither took the code under GPL nor distributes it thereunder but
11 | * under the terms set out in this paragraph. All notices and licenses
12 | * below are for informational purposes only.
13 | *
14 | * NUGET: END LICENSE TEXT */
15 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
16 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
17 | window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document);
18 |
19 | /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
20 | (function(e){e.respond={};respond.update=function(){};respond.mediaQueriesSupported=e.matchMedia&&e.matchMedia("only all").matches;if(respond.mediaQueriesSupported){return}var w=e.document,s=w.documentElement,i=[],k=[],q=[],o={},h=30,f=w.getElementsByTagName("head")[0]||s,g=w.getElementsByTagName("base")[0],b=f.getElementsByTagName("link"),d=[],a=function(){var D=b,y=D.length,B=0,A,z,C,x;for(;B-1,minw:F.match(/\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:F.match(/\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}}j()},l,r,v=function(){var z,A=w.createElement("div"),x=w.body,y=false;A.style.cssText="position:absolute;font-size:1em;width:1em";if(!x){x=y=w.createElement("body");x.style.background="none"}x.appendChild(A);s.insertBefore(x,s.firstChild);z=A.offsetWidth;if(y){s.removeChild(x)}else{x.removeChild(A)}z=p=parseFloat(z);return z},p,j=function(I){var x="clientWidth",B=s[x],H=w.compatMode==="CSS1Compat"&&B||w.body[x]||B,D={},G=b[b.length-1],z=(new Date()).getTime();if(I&&l&&z-l-1?(p||v()):1)}if(!!J){J=parseFloat(J)*(J.indexOf(y)>-1?(p||v()):1)}if(!K.hasquery||(!A||!L)&&(A||H>=C)&&(L||H<=J)){if(!D[K.media]){D[K.media]=[]}D[K.media].push(k[K.rules])}}for(var E in q){if(q[E]&&q[E].parentNode===f){f.removeChild(q[E])}}for(var E in D){var M=w.createElement("style"),F=D[E].join("\n");M.type="text/css";M.media=E;f.insertBefore(M,G.nextSibling);if(M.styleSheet){M.styleSheet.cssText=F}else{M.appendChild(w.createTextNode(F))}q.push(M)}},n=function(x,z){var y=c();if(!y){return}y.open("GET",x,true);y.onreadystatechange=function(){if(y.readyState!=4||y.status!=200&&y.status!=304){return}z(y.responseText)};if(y.readyState==4){return}y.send(null)},c=(function(){var x=false;try{x=new XMLHttpRequest()}catch(y){x=new ActiveXObject("Microsoft.XMLHTTP")}return function(){return x}})();a();respond.update=a;function t(){j(true)}if(e.addEventListener){e.addEventListener("resize",t,false)}else{if(e.attachEvent){e.attachEvent("onresize",t)}}})(this);
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Scripts/jquery.validate.unobtrusive.min.js:
--------------------------------------------------------------------------------
1 | /* NUGET: BEGIN LICENSE TEXT
2 | *
3 | * Microsoft grants you the right to use these script files for the sole
4 | * purpose of either: (i) interacting through your browser with the Microsoft
5 | * website or online service, subject to the applicable licensing or use
6 | * terms; or (ii) using the files as included with a Microsoft product subject
7 | * to that product's license terms. Microsoft reserves all other rights to the
8 | * files not expressly granted by Microsoft, whether by implication, estoppel
9 | * or otherwise. Insofar as a script file is dual licensed under GPL,
10 | * Microsoft neither took the code under GPL nor distributes it thereunder but
11 | * under the terms set out in this paragraph. All notices and licenses
12 | * below are for informational purposes only.
13 | *
14 | * NUGET: END LICENSE TEXT */
15 | /*
16 | ** Unobtrusive validation support library for jQuery and jQuery Validate
17 | ** Copyright (C) Microsoft Corporation. All rights reserved.
18 | */
19 | (function(a){var d=a.validator,b,e="unobtrusiveValidation";function c(a,b,c){a.rules[b]=c;if(a.message)a.messages[b]=a.message}function j(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function f(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function h(a){return a.substr(0,a.lastIndexOf(".")+1)}function g(a,b){if(a.indexOf("*.")===0)a=a.replace("*.",b);return a}function m(c,e){var b=a(this).find("[data-valmsg-for='"+f(e[0].name)+"']"),d=b.attr("data-valmsg-replace"),g=d?a.parseJSON(d)!==false:null;b.removeClass("field-validation-valid").addClass("field-validation-error");c.data("unobtrusiveContainer",b);if(g){b.empty();c.removeClass("input-validation-error").appendTo(b)}else c.hide()}function l(e,d){var c=a(this).find("[data-valmsg-summary=true]"),b=c.find("ul");if(b&&b.length&&d.errorList.length){b.empty();c.addClass("validation-summary-errors").removeClass("validation-summary-valid");a.each(d.errorList,function(){a(" ").html(this.message).appendTo(b)})}}function k(d){var b=d.data("unobtrusiveContainer"),c=b.attr("data-valmsg-replace"),e=c?a.parseJSON(c):null;if(b){b.addClass("field-validation-valid").removeClass("field-validation-error");d.removeData("unobtrusiveContainer");e&&b.empty()}}function n(){var b=a(this);b.data("validator").resetForm();b.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors");b.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}function i(c){var b=a(c),d=b.data(e),f=a.proxy(n,c);if(!d){d={options:{errorClass:"input-validation-error",errorElement:"span",errorPlacement:a.proxy(m,c),invalidHandler:a.proxy(l,c),messages:{},rules:{},success:a.proxy(k,c)},attachValidation:function(){b.unbind("reset."+e,f).bind("reset."+e,f).validate(this.options)},validate:function(){b.validate();return b.valid()}};b.data(e,d)}return d}d.unobtrusive={adapters:[],parseElement:function(b,h){var d=a(b),f=d.parents("form")[0],c,e,g;if(!f)return;c=i(f);c.options.rules[b.name]=e={};c.options.messages[b.name]=g={};a.each(this.adapters,function(){var c="data-val-"+this.name,i=d.attr(c),h={};if(i!==undefined){c+="-";a.each(this.params,function(){h[this]=d.attr(c+this)});this.adapt({element:b,form:f,message:i,params:h,rules:e,messages:g})}});a.extend(e,{__dummy__:true});!h&&c.attachValidation()},parse:function(b){var c=a(b).parents("form").andSelf().add(a(b).find("form")).filter("form");a(b).find(":input").filter("[data-val=true]").each(function(){d.unobtrusive.parseElement(this,true)});c.each(function(){var a=i(this);a&&a.attachValidation()})}};b=d.unobtrusive.adapters;b.add=function(c,a,b){if(!b){b=a;a=[]}this.push({name:c,params:a,adapt:b});return this};b.addBool=function(a,b){return this.add(a,function(d){c(d,b||a,true)})};b.addMinMax=function(e,g,f,a,d,b){return this.add(e,[d||"min",b||"max"],function(b){var e=b.params.min,d=b.params.max;if(e&&d)c(b,a,[e,d]);else if(e)c(b,g,e);else d&&c(b,f,d)})};b.addSingleVal=function(a,b,d){return this.add(a,[b||"val"],function(e){c(e,d||a,e.params[b])})};d.addMethod("__dummy__",function(){return true});d.addMethod("regex",function(b,c,d){var a;if(this.optional(c))return true;a=(new RegExp(d)).exec(b);return a&&a.index===0&&a[0].length===b.length});d.addMethod("nonalphamin",function(c,d,b){var a;if(b){a=c.match(/\W/g);a=a&&a.length>=b}return a});if(d.methods.extension){b.addSingleVal("accept","mimtype");b.addSingleVal("extension","extension")}else b.addSingleVal("extension","extension","accept");b.addSingleVal("regex","pattern");b.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");b.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range");b.add("equalto",["other"],function(b){var i=h(b.element.name),j=b.params.other,d=g(j,i),e=a(b.form).find(":input").filter("[name='"+f(d)+"']")[0];c(b,"equalTo",e)});b.add("required",function(a){(a.element.tagName.toUpperCase()!=="INPUT"||a.element.type.toUpperCase()!=="CHECKBOX")&&c(a,"required",true)});b.add("remote",["url","type","additionalfields"],function(b){var d={url:b.params.url,type:b.params.type||"GET",data:{}},e=h(b.element.name);a.each(j(b.params.additionalfields||b.element.name),function(i,h){var c=g(h,e);d.data[c]=function(){return a(b.form).find(":input").filter("[name='"+f(c)+"']").val()}});c(b,"remote",d)});b.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&c(a,"minlength",a.params.min);a.params.nonalphamin&&c(a,"nonalphamin",a.params.nonalphamin);a.params.regex&&c(a,"regex",a.params.regex)});a(function(){d.unobtrusive.parse(document)})})(jQuery);
20 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Project_Readme.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Your ASP.NET application
6 |
95 |
96 |
97 |
98 |
102 |
103 |
104 |
105 |
This application consists of:
106 |
107 | Sample pages showing basic nav between Home, About, and Contact
108 | Theming using Bootstrap
109 | Authentication , if selected, shows how to register and sign in
110 | ASP.NET features managed using NuGet
111 |
112 |
113 |
114 |
115 |
Customize app
116 |
130 |
131 |
132 |
140 |
141 |
142 |
Get help
143 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Models/AccountViewModels.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | // New namespace imports:
4 | using Microsoft.AspNet.Identity.EntityFramework;
5 | using System.Collections.Generic;
6 |
7 | namespace AspNetExtendingIdentityRoles.Models
8 | {
9 | public class ManageUserViewModel
10 | {
11 | [Required]
12 | [DataType(DataType.Password)]
13 | [Display(Name = "Current password")]
14 | public string OldPassword { get; set; }
15 |
16 | [Required]
17 | [StringLength(100, ErrorMessage =
18 | "The {0} must be at least {2} characters long.", MinimumLength = 6)]
19 | [DataType(DataType.Password)]
20 | [Display(Name = "New password")]
21 | public string NewPassword { get; set; }
22 |
23 | [DataType(DataType.Password)]
24 | [Display(Name = "Confirm new password")]
25 | [Compare("NewPassword", ErrorMessage =
26 | "The new password and confirmation password do not match.")]
27 | public string ConfirmPassword { get; set; }
28 | }
29 |
30 |
31 | public class LoginViewModel
32 | {
33 | [Required]
34 | [Display(Name = "User name")]
35 | public string UserName { get; set; }
36 |
37 | [Required]
38 | [DataType(DataType.Password)]
39 | [Display(Name = "Password")]
40 | public string Password { get; set; }
41 |
42 | [Display(Name = "Remember me?")]
43 | public bool RememberMe { get; set; }
44 | }
45 |
46 |
47 | public class RegisterViewModel
48 | {
49 | [Required]
50 | [Display(Name = "User name")]
51 | public string UserName { get; set; }
52 |
53 | [Required]
54 | [StringLength(100, ErrorMessage =
55 | "The {0} must be at least {2} characters long.", MinimumLength = 6)]
56 | [DataType(DataType.Password)]
57 | [Display(Name = "Password")]
58 | public string Password { get; set; }
59 |
60 | [DataType(DataType.Password)]
61 | [Display(Name = "Confirm password")]
62 | [Compare("Password", ErrorMessage =
63 | "The password and confirmation password do not match.")]
64 | public string ConfirmPassword { get; set; }
65 |
66 | // New Fields added to extend Application User class:
67 |
68 | [Required]
69 | [Display(Name = "First Name")]
70 | public string FirstName { get; set; }
71 |
72 | [Required]
73 | [Display(Name = "Last Name")]
74 | public string LastName { get; set; }
75 |
76 | [Required]
77 | public string Email { get; set; }
78 |
79 | // Return a pre-poulated instance of AppliationUser:
80 | public ApplicationUser GetUser()
81 | {
82 | var user = new ApplicationUser()
83 | {
84 | UserName = this.UserName,
85 | FirstName = this.FirstName,
86 | LastName = this.LastName,
87 | Email = this.Email,
88 | };
89 | return user;
90 | }
91 | }
92 |
93 |
94 | public class EditUserViewModel
95 | {
96 | public EditUserViewModel() { }
97 |
98 | // Allow Initialization with an instance of ApplicationUser:
99 | public EditUserViewModel(ApplicationUser user)
100 | {
101 | this.UserName = user.UserName;
102 | this.FirstName = user.FirstName;
103 | this.LastName = user.LastName;
104 | this.Email = user.Email;
105 | }
106 |
107 | [Required]
108 | [Display(Name = "User Name")]
109 | public string UserName { get; set; }
110 |
111 | [Required]
112 | [Display(Name = "First Name")]
113 | public string FirstName { get; set; }
114 |
115 | [Required]
116 | [Display(Name = "Last Name")]
117 | public string LastName { get; set; }
118 |
119 | [Required]
120 | public string Email { get; set; }
121 | }
122 |
123 |
124 | public class SelectUserRolesViewModel
125 | {
126 | public SelectUserRolesViewModel()
127 | {
128 | this.Roles = new List();
129 | }
130 |
131 |
132 | // Enable initialization with an instance of ApplicationUser:
133 | public SelectUserRolesViewModel(ApplicationUser user)
134 | : this()
135 | {
136 | this.UserName = user.UserName;
137 | this.FirstName = user.FirstName;
138 | this.LastName = user.LastName;
139 |
140 | var Db = new ApplicationDbContext();
141 |
142 | // Add all available roles to the list of EditorViewModels:
143 | var allRoles = Db.Roles;
144 | foreach (var role in allRoles)
145 | {
146 | // An EditorViewModel will be used by Editor Template:
147 | var rvm = new SelectRoleEditorViewModel(role);
148 | this.Roles.Add(rvm);
149 | }
150 |
151 | // Set the Selected property to true for those roles for
152 | // which the current user is a member:
153 | foreach (var userRole in user.Roles)
154 | {
155 | var checkUserRole =
156 | this.Roles.Find(r => r.RoleName == userRole.Role.Name);
157 | checkUserRole.Selected = true;
158 | }
159 | }
160 |
161 | public string UserName { get; set; }
162 | public string FirstName { get; set; }
163 | public string LastName { get; set; }
164 | public List Roles { get; set; }
165 | }
166 |
167 | // Used to display a single role with a checkbox, within a list structure:
168 | public class SelectRoleEditorViewModel
169 | {
170 | public SelectRoleEditorViewModel() { }
171 |
172 | // Update this to accept an argument of type ApplicationRole:
173 | public SelectRoleEditorViewModel(ApplicationRole role)
174 | {
175 | this.RoleName = role.Name;
176 |
177 | // Assign the new Descrption property:
178 | this.Description = role.Description;
179 | }
180 |
181 | public bool Selected { get; set; }
182 |
183 | [Required]
184 | public string RoleName { get; set; }
185 |
186 | // Add the new Description property:
187 | public string Description { get; set; }
188 | }
189 |
190 |
191 | public class RoleViewModel
192 | {
193 | public string RoleName { get; set; }
194 | public string Description { get; set; }
195 |
196 | public RoleViewModel() { }
197 | public RoleViewModel(ApplicationRole role)
198 | {
199 | this.RoleName = role.Name;
200 | this.Description = role.Description;
201 | }
202 | }
203 |
204 |
205 | public class EditRoleViewModel
206 | {
207 | public string OriginalRoleName { get; set; }
208 | public string RoleName { get; set; }
209 | public string Description { get; set; }
210 |
211 | public EditRoleViewModel() { }
212 | public EditRoleViewModel(ApplicationRole role)
213 | {
214 | this.OriginalRoleName = role.Name;
215 | this.RoleName = role.Name;
216 | this.Description = role.Description;
217 | }
218 | }
219 | }
--------------------------------------------------------------------------------
/.nuget/NuGet.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildProjectDirectory)\..\
5 |
6 |
7 | false
8 |
9 |
10 | false
11 |
12 |
13 | true
14 |
15 |
16 | false
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
31 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config"))
32 |
33 |
34 |
35 |
36 | $(SolutionDir).nuget
37 | packages.config
38 |
39 |
40 |
41 |
42 | $(NuGetToolsPath)\NuGet.exe
43 | @(PackageSource)
44 |
45 | "$(NuGetExePath)"
46 | mono --runtime=v4.0.30319 $(NuGetExePath)
47 |
48 | $(TargetDir.Trim('\\'))
49 |
50 | -RequireConsent
51 | -NonInteractive
52 |
53 | "$(SolutionDir) "
54 | "$(SolutionDir)"
55 |
56 |
57 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
58 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
59 |
60 |
61 |
62 | RestorePackages;
63 | $(BuildDependsOn);
64 |
65 |
66 |
67 |
68 | $(BuildDependsOn);
69 | BuildPackage;
70 |
71 |
72 |
73 |
74 |
75 |
76 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
98 |
100 |
101 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
133 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Migrations/201402130341319_init.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | H4sIAAAAAAAEAN1cy27cNhTdF+g/CFolBTKynU0azCRwxnZrNLYDj5NtQEucMVGJUkWOO/62LvpJ/YWSelIiKVEjaR7ZGDZFnvvg4SV1den//vl3+nET+NYzjAkK8cw+nZzYFsRu6CG8mtlrunzzzv744eefppdesLG+5f3e8n5sJCYz+4nS6L3jEPcJBoBMAuTGIQmXdOKGgQO80Dk7OfnVOT11IIOwGZZlTe/XmKIAJn+wP+chdmFE18C/CT3ok6ydPVkkqNYtCCCJgAtn9jmJbiG93FCIuZLXHmRQ9OU+9CGZpMNt69xHgKm2gP7StgDGIQWUKf7+K4ELGod4tYhYA/AfXiLI+i2BT2Bm0Puyu6ltJ2fcNqccuJVv7MJqZvdlYhRXL7GdmR1FPnITdG6qbX0CBPLnqZUT0Q8iEsP6EocRjOlLhnQBiRujKNUzQ6Axc6Vt3YDNZ4hX9Glms19t6wptoJe3ZE76ihGjBxtE4zX70xG1dkq1G41pUPYP+FJpEPS/h8tifFUwF10fWDebj9Fae3r2zsja27Xvg0cfFs+dRpn85758LBCGsT7WEiZ52GjFFYoJHciUjg78DPYl+TIAyB9bbOcFwydr7gMU7H7VXGP69kxhjxBdFzSM4W8QwxhQ6H0BlMIYl8q3uTwxjAsbeMloJH0D/noEUbfgGa0Sf9SEpqvwHvrJQ/KEIsVKTDT7nna9isOAR0jF9Cc9vi/CdexyE8LGbg8gXkE6APN+5FDN7RshXMuCvgBC/g5j73dAnkYXtoDuOmazt6AgiHbI9YR9ZFi25zRuYXu+KExV/RyuEG5XNenWqGrZo1FVoVtXVZMzbqumvFejokWHRj3LXio1t4ofienbBBE+WA4kyq6JDNb8jDzuAYMReWemSfdQlWu263BVM3PX4is+G114vy2108pt2lIVC7z3ktj2DajDiuAittmF90XtXN/90Sp9wTYJs2nPhjCb/GgiVdlLxane5O+wGbRq2Zn554SELkrU0+0G3xXnykvsWWaLVP02m24z1s3ap4i/A7Pmmf2L5NhWMcXuqHlprkk4tetr8Q5fQB9SaJ27aTppDogLPJmJzH9etYUtXxhzWcCfs8mlMUCYymsdYRdFwDeyozba8LTOtSvk1J9cwAhiLtRovkwU0MY1p5BVc12bp6aOQENzdpbL24Q1irWuJk0aMLajphwqdPm/g2amZMaOiSnNlYl89Sa6L14aB01FdB+Jl8cfMSUz9sHLo42Xwqu8CWdUWSw1adJ055bUVKUPds1NrUPTQxObBMqmAMZy3v7ikT+EGyq5lA9cQFrNC5SHMOWeIDmsCiK5rQlRmJgOsG2IncDyvE0jYnYU7ADb5ssyWNZAhUluUDg7iwudm99Y6yQ0PhsXNqq9JsUL49OwBljCrNCede/oLeH1qtlZmoNah6OaxqKMCYaekg9nAqwSaggHmbBJc2LocGYYzkH7YJKYZG72lG4P67KLaYzKI6qhsxT71gDeyt/Tiy2neDZ10kKLrGHqaCoypjcgihBeCRUaWYu1SMsz5m8W3asfghTDcYmiCKLQtpBEwxisYO0pE800Tb5VXwAKHgHP+My9QOrWZYPNRYr7rDyD+VaR9+a/Z5t5e7HKpF7ZIR/7MtwrZnXAz47Jd1YFH9TDLV5FA3wQK76yzUN/HWD9UVY/ulJFIsJUHijxmM89lBwjk0+witqWCh7ieAHCgFmtQpw6Nf9IR2FphrpM4TXhv98tX5nMpdj4+khmMv3qKY5PW3bu6a4OPjz/SsyunsB3Suv8eRnFjGJcdW8ZMdapttkOM6gePs4KEQqgRBCh2RyrrGgSocpWc6SsQkmEyZo6R930cHT0UZeb0Sfq7pJTXJbMg7LVHKlaUCKiVZ+YI9aqRkTI2qOD3iMOM8Jo94g9LMIB9ojsxWbMOVQUPHaeSA3GOGtbKGQUQYTmjlhZqaIElrUfJDGyTNOYxFDUE3UmhgajKWzXyaHLwetRatU7lZNAc/2SHrNSklPZBfT1TQdClXHeq5vLbDoTpdsrwzA8yb86iii6L5Hjz2Q1r9SyJWQJt55RP0PpHNl5Wk0K6U3pNdmZRvtCAqH+/iZosLVy2g+BW29aer3qeUOZAlL6sN6lIGCRRqylC6dZ6q79lpeUy0u72FYezdhR9IVQGEx4h8niL3/uI+bDssMNwGgJCX0I/4R4Zp+dnJ7V7oVtcUfLIcTzmy9q6VMMuyiYx88gdp9ALBfM9bi6lIO+CsDmtYhkUoKuuG7WD696KO5l9pHcghhsUsvXywEmQnWRoReg8rJCL0Tp5lovtPpltF5glftlx70g9nQhDfFo33rlrOMKke6g9Zoa+Z5ZL7jitLH7Of7hr24MFmOVNzMGQ1dcvNglDY7musJgDq/eRhjY14MWyO+n7LKhbqhvgX7vis69lLwfV9mmeZl7+glzHxXn+nqinuXMvQimSSmNXiL8I5erH1II2ze/9hHAjPl1MPGrY9n5IREsq5/uV/Z+dBTTfcxTc0yTWx2cZLXEZv76JhUUaj5tqFJ/beX4aUJzZnuPISNBenRMc+TqamGdsJS9WmFZAl0rTF1D2iQsY2ajxKxPs1h1TWx70b9ZzX+zbHUdfOvNAKOLAc2S1bO7z9sD2tribtcEmu8cHMP1AHGG5XLBLoXujTXzx3IRoD8vdu2KEUv9+zujEjc1nzFHqeWXP7qxnVL4B4xsvyZoVULwEiUM3coeWfS5xssw36trGuVdahmUG0iBxzbQ85iiJXApe+xCQpL/6pCVQF0Gj9C7xndrGq0pMxkGj34lo8e3/Cb5yYWFqs7Tu+SbExnCBKYmYibAO/xpjXyv0PtKkerRQPCzRJan5nNJeb569VIg3YbYEChzX3EEeoBB5DMwcocX4BnqdWv3YdVj0wsEVjEISIZRjmd/Mvp5webD/xa6be1CVAAA
122 |
123 |
124 | dbo
125 |
126 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Scripts/respond.js:
--------------------------------------------------------------------------------
1 | /* NUGET: BEGIN LICENSE TEXT
2 | *
3 | * Microsoft grants you the right to use these script files for the sole
4 | * purpose of either: (i) interacting through your browser with the Microsoft
5 | * website or online service, subject to the applicable licensing or use
6 | * terms; or (ii) using the files as included with a Microsoft product subject
7 | * to that product's license terms. Microsoft reserves all other rights to the
8 | * files not expressly granted by Microsoft, whether by implication, estoppel
9 | * or otherwise. Insofar as a script file is dual licensed under GPL,
10 | * Microsoft neither took the code under GPL nor distributes it thereunder but
11 | * under the terms set out in this paragraph. All notices and licenses
12 | * below are for informational purposes only.
13 | *
14 | * NUGET: END LICENSE TEXT */
15 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
16 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
17 | window.matchMedia = window.matchMedia || (function(doc, undefined){
18 |
19 | var bool,
20 | docElem = doc.documentElement,
21 | refNode = docElem.firstElementChild || docElem.firstChild,
22 | // fakeBody required for
23 | fakeBody = doc.createElement('body'),
24 | div = doc.createElement('div');
25 |
26 | div.id = 'mq-test-1';
27 | div.style.cssText = "position:absolute;top:-100em";
28 | fakeBody.style.background = "none";
29 | fakeBody.appendChild(div);
30 |
31 | return function(q){
32 |
33 | div.innerHTML = '';
34 |
35 | docElem.insertBefore(fakeBody, refNode);
36 | bool = div.offsetWidth == 42;
37 | docElem.removeChild(fakeBody);
38 |
39 | return { matches: bool, media: q };
40 | };
41 |
42 | })(document);
43 |
44 |
45 |
46 |
47 | /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
48 | (function( win ){
49 | //exposed namespace
50 | win.respond = {};
51 |
52 | //define update even in native-mq-supporting browsers, to avoid errors
53 | respond.update = function(){};
54 |
55 | //expose media query support flag for external use
56 | respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches;
57 |
58 | //if media queries are supported, exit here
59 | if( respond.mediaQueriesSupported ){ return; }
60 |
61 | //define vars
62 | var doc = win.document,
63 | docElem = doc.documentElement,
64 | mediastyles = [],
65 | rules = [],
66 | appendedEls = [],
67 | parsedSheets = {},
68 | resizeThrottle = 30,
69 | head = doc.getElementsByTagName( "head" )[0] || docElem,
70 | base = doc.getElementsByTagName( "base" )[0],
71 | links = head.getElementsByTagName( "link" ),
72 | requestQueue = [],
73 |
74 | //loop stylesheets, send text content to translate
75 | ripCSS = function(){
76 | var sheets = links,
77 | sl = sheets.length,
78 | i = 0,
79 | //vars for loop:
80 | sheet, href, media, isCSS;
81 |
82 | for( ; i < sl; i++ ){
83 | sheet = sheets[ i ],
84 | href = sheet.href,
85 | media = sheet.media,
86 | isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
87 |
88 | //only links plz and prevent re-parsing
89 | if( !!href && isCSS && !parsedSheets[ href ] ){
90 | // selectivizr exposes css through the rawCssText expando
91 | if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
92 | translate( sheet.styleSheet.rawCssText, href, media );
93 | parsedSheets[ href ] = true;
94 | } else {
95 | if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base)
96 | || href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){
97 | requestQueue.push( {
98 | href: href,
99 | media: media
100 | } );
101 | }
102 | }
103 | }
104 | }
105 | makeRequests();
106 | },
107 |
108 | //recurse through request queue, get css text
109 | makeRequests = function(){
110 | if( requestQueue.length ){
111 | var thisRequest = requestQueue.shift();
112 |
113 | ajax( thisRequest.href, function( styles ){
114 | translate( styles, thisRequest.href, thisRequest.media );
115 | parsedSheets[ thisRequest.href ] = true;
116 | makeRequests();
117 | } );
118 | }
119 | },
120 |
121 | //find media blocks in css text, convert to style blocks
122 | translate = function( styles, href, media ){
123 | var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ),
124 | ql = qs && qs.length || 0,
125 | //try to get CSS path
126 | href = href.substring( 0, href.lastIndexOf( "/" )),
127 | repUrls = function( css ){
128 | return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" );
129 | },
130 | useMedia = !ql && media,
131 | //vars used in loop
132 | i = 0,
133 | j, fullq, thisq, eachq, eql;
134 |
135 | //if path exists, tack on trailing slash
136 | if( href.length ){ href += "/"; }
137 |
138 | //if no internal queries exist, but media attr does, use that
139 | //note: this currently lacks support for situations where a media attr is specified on a link AND
140 | //its associated stylesheet has internal CSS media queries.
141 | //In those cases, the media attribute will currently be ignored.
142 | if( useMedia ){
143 | ql = 1;
144 | }
145 |
146 |
147 | for( ; i < ql; i++ ){
148 | j = 0;
149 |
150 | //media attr
151 | if( useMedia ){
152 | fullq = media;
153 | rules.push( repUrls( styles ) );
154 | }
155 | //parse for styles
156 | else{
157 | fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1;
158 | rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
159 | }
160 |
161 | eachq = fullq.split( "," );
162 | eql = eachq.length;
163 |
164 | for( ; j < eql; j++ ){
165 | thisq = eachq[ j ];
166 | mediastyles.push( {
167 | media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all",
168 | rules : rules.length - 1,
169 | hasquery: thisq.indexOf("(") > -1,
170 | minw : thisq.match( /\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
171 | maxw : thisq.match( /\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
172 | } );
173 | }
174 | }
175 |
176 | applyMedia();
177 | },
178 |
179 | lastCall,
180 |
181 | resizeDefer,
182 |
183 | // returns the value of 1em in pixels
184 | getEmValue = function() {
185 | var ret,
186 | div = doc.createElement('div'),
187 | body = doc.body,
188 | fakeUsed = false;
189 |
190 | div.style.cssText = "position:absolute;font-size:1em;width:1em";
191 |
192 | if( !body ){
193 | body = fakeUsed = doc.createElement( "body" );
194 | body.style.background = "none";
195 | }
196 |
197 | body.appendChild( div );
198 |
199 | docElem.insertBefore( body, docElem.firstChild );
200 |
201 | ret = div.offsetWidth;
202 |
203 | if( fakeUsed ){
204 | docElem.removeChild( body );
205 | }
206 | else {
207 | body.removeChild( div );
208 | }
209 |
210 | //also update eminpx before returning
211 | ret = eminpx = parseFloat(ret);
212 |
213 | return ret;
214 | },
215 |
216 | //cached container for 1em value, populated the first time it's needed
217 | eminpx,
218 |
219 | //enable/disable styles
220 | applyMedia = function( fromResize ){
221 | var name = "clientWidth",
222 | docElemProp = docElem[ name ],
223 | currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp,
224 | styleBlocks = {},
225 | lastLink = links[ links.length-1 ],
226 | now = (new Date()).getTime();
227 |
228 | //throttle resize calls
229 | if( fromResize && lastCall && now - lastCall < resizeThrottle ){
230 | clearTimeout( resizeDefer );
231 | resizeDefer = setTimeout( applyMedia, resizeThrottle );
232 | return;
233 | }
234 | else {
235 | lastCall = now;
236 | }
237 |
238 | for( var i in mediastyles ){
239 | var thisstyle = mediastyles[ i ],
240 | min = thisstyle.minw,
241 | max = thisstyle.maxw,
242 | minnull = min === null,
243 | maxnull = max === null,
244 | em = "em";
245 |
246 | if( !!min ){
247 | min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
248 | }
249 | if( !!max ){
250 | max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
251 | }
252 |
253 | // if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true
254 | if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){
255 | if( !styleBlocks[ thisstyle.media ] ){
256 | styleBlocks[ thisstyle.media ] = [];
257 | }
258 | styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
259 | }
260 | }
261 |
262 | //remove any existing respond style element(s)
263 | for( var i in appendedEls ){
264 | if( appendedEls[ i ] && appendedEls[ i ].parentNode === head ){
265 | head.removeChild( appendedEls[ i ] );
266 | }
267 | }
268 |
269 | //inject active styles, grouped by media type
270 | for( var i in styleBlocks ){
271 | var ss = doc.createElement( "style" ),
272 | css = styleBlocks[ i ].join( "\n" );
273 |
274 | ss.type = "text/css";
275 | ss.media = i;
276 |
277 | //originally, ss was appended to a documentFragment and sheets were appended in bulk.
278 | //this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one!
279 | head.insertBefore( ss, lastLink.nextSibling );
280 |
281 | if ( ss.styleSheet ){
282 | ss.styleSheet.cssText = css;
283 | }
284 | else {
285 | ss.appendChild( doc.createTextNode( css ) );
286 | }
287 |
288 | //push to appendedEls to track for later removal
289 | appendedEls.push( ss );
290 | }
291 | },
292 | //tweaked Ajax functions from Quirksmode
293 | ajax = function( url, callback ) {
294 | var req = xmlHttp();
295 | if (!req){
296 | return;
297 | }
298 | req.open( "GET", url, true );
299 | req.onreadystatechange = function () {
300 | if ( req.readyState != 4 || req.status != 200 && req.status != 304 ){
301 | return;
302 | }
303 | callback( req.responseText );
304 | }
305 | if ( req.readyState == 4 ){
306 | return;
307 | }
308 | req.send( null );
309 | },
310 | //define ajax obj
311 | xmlHttp = (function() {
312 | var xmlhttpmethod = false;
313 | try {
314 | xmlhttpmethod = new XMLHttpRequest();
315 | }
316 | catch( e ){
317 | xmlhttpmethod = new ActiveXObject( "Microsoft.XMLHTTP" );
318 | }
319 | return function(){
320 | return xmlhttpmethod;
321 | };
322 | })();
323 |
324 | //translate CSS
325 | ripCSS();
326 |
327 | //expose update for re-running respond later on
328 | respond.update = ripCSS;
329 |
330 | //adjust on resize
331 | function callMedia(){
332 | applyMedia( true );
333 | }
334 | if( win.addEventListener ){
335 | win.addEventListener( "resize", callMedia, false );
336 | }
337 | else if( win.attachEvent ){
338 | win.attachEvent( "onresize", callMedia );
339 | }
340 | })(this);
341 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Controllers/AccountController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNet.Identity;
2 | using Microsoft.AspNet.Identity.EntityFramework;
3 | using Microsoft.Owin.Security;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Web;
8 | using System.Web.Mvc;
9 | using AspNetExtendingIdentityRoles.Models;
10 |
11 | namespace AspNetExtendingIdentityRoles.Controllers
12 | {
13 | [Authorize]
14 | public class AccountController : Controller
15 | {
16 | public AccountController()
17 | : this(new UserManager(new UserStore(new ApplicationDbContext())))
18 | {
19 | }
20 |
21 |
22 | public AccountController(UserManager userManager)
23 | {
24 | UserManager = userManager;
25 | }
26 |
27 |
28 | public UserManager UserManager { get; private set; }
29 |
30 |
31 | [AllowAnonymous]
32 | public ActionResult Login(string returnUrl)
33 | {
34 | ViewBag.ReturnUrl = returnUrl;
35 | return View();
36 | }
37 |
38 |
39 | [HttpPost]
40 | [AllowAnonymous]
41 | [ValidateAntiForgeryToken]
42 | public async Task Login(LoginViewModel model, string returnUrl)
43 | {
44 | if (ModelState.IsValid)
45 | {
46 | var user = await UserManager.FindAsync(model.UserName, model.Password);
47 | if (user != null)
48 | {
49 | await SignInAsync(user, model.RememberMe);
50 | return RedirectToLocal(returnUrl);
51 | }
52 | else
53 | {
54 | ModelState.AddModelError("", "Invalid username or password.");
55 | }
56 | }
57 |
58 | // If we got this far, something failed, redisplay form
59 | return View(model);
60 | }
61 |
62 |
63 | [Authorize(Roles = "Admin")]
64 | public ActionResult Register()
65 | {
66 | return View();
67 | }
68 |
69 |
70 | [HttpPost]
71 | [Authorize(Roles = "Admin")]
72 | [ValidateAntiForgeryToken]
73 | public async Task Register(RegisterViewModel model)
74 | {
75 | if (ModelState.IsValid)
76 | {
77 | var user = model.GetUser();
78 | var result = await UserManager.CreateAsync(user, model.Password);
79 | if (result.Succeeded)
80 | {
81 | return RedirectToAction("Index", "Account");
82 | }
83 |
84 | }
85 |
86 | // If we got this far, something failed, redisplay form
87 | return View(model);
88 | }
89 |
90 |
91 | [Authorize(Roles = "Admin")]
92 | public ActionResult Manage(ManageMessageId? message)
93 | {
94 | ViewBag.StatusMessage =
95 | message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
96 | : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
97 | : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
98 | : message == ManageMessageId.Error ? "An error has occurred."
99 | : "";
100 | ViewBag.HasLocalPassword = HasPassword();
101 | ViewBag.ReturnUrl = Url.Action("Manage");
102 | return View();
103 | }
104 |
105 |
106 | [HttpPost]
107 | [ValidateAntiForgeryToken]
108 | [Authorize(Roles = "Admin")]
109 | public async Task Manage(ManageUserViewModel model)
110 | {
111 | bool hasPassword = HasPassword();
112 | ViewBag.HasLocalPassword = hasPassword;
113 | ViewBag.ReturnUrl = Url.Action("Manage");
114 | if (hasPassword)
115 | {
116 | if (ModelState.IsValid)
117 | {
118 | IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
119 | if (result.Succeeded)
120 | {
121 | return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
122 | }
123 | else
124 | {
125 | AddErrors(result);
126 | }
127 | }
128 | }
129 | else
130 | {
131 | // User does not have a password so remove any validation errors caused by a missing OldPassword field
132 | ModelState state = ModelState["OldPassword"];
133 | if (state != null)
134 | {
135 | state.Errors.Clear();
136 | }
137 |
138 | if (ModelState.IsValid)
139 | {
140 | IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
141 | if (result.Succeeded)
142 | {
143 | return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
144 | }
145 | else
146 | {
147 | AddErrors(result);
148 | }
149 | }
150 | }
151 |
152 | // If we got this far, something failed, redisplay form
153 | return View(model);
154 | }
155 |
156 |
157 | [HttpPost]
158 | [ValidateAntiForgeryToken]
159 | public ActionResult LogOff()
160 | {
161 | AuthenticationManager.SignOut();
162 | return RedirectToAction("Index", "Home");
163 | }
164 |
165 |
166 | protected override void Dispose(bool disposing)
167 | {
168 | if (disposing && UserManager != null)
169 | {
170 | UserManager.Dispose();
171 | UserManager = null;
172 | }
173 | base.Dispose(disposing);
174 | }
175 |
176 |
177 | [Authorize(Roles = "Admin")]
178 | public ActionResult Index()
179 | {
180 | var Db = new ApplicationDbContext();
181 | var users = Db.Users;
182 | var model = new List();
183 | foreach (var user in users)
184 | {
185 | var u = new EditUserViewModel(user);
186 | model.Add(u);
187 | }
188 | return View(model);
189 | }
190 |
191 |
192 | [Authorize(Roles = "Admin")]
193 | public ActionResult Edit(string id, ManageMessageId? Message = null)
194 | {
195 | var Db = new ApplicationDbContext();
196 | var user = Db.Users.First(u => u.UserName == id);
197 | var model = new EditUserViewModel(user);
198 | ViewBag.MessageId = Message;
199 | return View(model);
200 | }
201 |
202 |
203 | [HttpPost]
204 | [Authorize(Roles = "Admin")]
205 | [ValidateAntiForgeryToken]
206 | public async Task Edit(EditUserViewModel model)
207 | {
208 | if (ModelState.IsValid)
209 | {
210 | var Db = new ApplicationDbContext();
211 | var user = Db.Users.First(u => u.UserName == model.UserName);
212 | user.FirstName = model.FirstName;
213 | user.LastName = model.LastName;
214 | user.Email = model.Email;
215 | Db.Entry(user).State = System.Data.Entity.EntityState.Modified;
216 | await Db.SaveChangesAsync();
217 | return RedirectToAction("Index");
218 | }
219 |
220 | // If we got this far, something failed, redisplay form
221 | return View(model);
222 | }
223 |
224 |
225 | [Authorize(Roles = "Admin")]
226 | public ActionResult Delete(string id = null)
227 | {
228 | var Db = new ApplicationDbContext();
229 | var user = Db.Users.First(u => u.UserName == id);
230 | var model = new EditUserViewModel(user);
231 | if (user == null)
232 | {
233 | return HttpNotFound();
234 | }
235 | return View(model);
236 | }
237 |
238 |
239 | [HttpPost, ActionName("Delete")]
240 | [ValidateAntiForgeryToken]
241 | [Authorize(Roles = "Admin")]
242 | public ActionResult DeleteConfirmed(string id)
243 | {
244 | var Db = new ApplicationDbContext();
245 | var user = Db.Users.First(u => u.UserName == id);
246 | Db.Users.Remove(user);
247 | Db.SaveChanges();
248 | return RedirectToAction("Index");
249 | }
250 |
251 |
252 | [Authorize(Roles = "Admin")]
253 | public ActionResult UserRoles(string id)
254 | {
255 | var Db = new ApplicationDbContext();
256 | var user = Db.Users.First(u => u.UserName == id);
257 | var model = new SelectUserRolesViewModel(user);
258 | return View(model);
259 | }
260 |
261 |
262 | [HttpPost]
263 | [Authorize(Roles = "Admin")]
264 | [ValidateAntiForgeryToken]
265 | public ActionResult UserRoles(SelectUserRolesViewModel model)
266 | {
267 | if (ModelState.IsValid)
268 | {
269 | var idManager = new IdentityManager();
270 | var Db = new ApplicationDbContext();
271 | var user = Db.Users.First(u => u.UserName == model.UserName);
272 | idManager.ClearUserRoles(user.Id);
273 | foreach (var role in model.Roles)
274 | {
275 | if (role.Selected)
276 | {
277 | idManager.AddUserToRole(user.Id, role.RoleName);
278 | }
279 | }
280 | return RedirectToAction("index");
281 | }
282 | return View();
283 | }
284 |
285 |
286 | #region Helpers
287 |
288 | private IAuthenticationManager AuthenticationManager
289 | {
290 | get
291 | {
292 | return HttpContext.GetOwinContext().Authentication;
293 | }
294 | }
295 |
296 |
297 | private async Task SignInAsync(ApplicationUser user, bool isPersistent)
298 | {
299 | AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
300 | var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
301 | AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
302 | }
303 |
304 |
305 | private void AddErrors(IdentityResult result)
306 | {
307 | foreach (var error in result.Errors)
308 | {
309 | ModelState.AddModelError("", error);
310 | }
311 | }
312 |
313 |
314 | private bool HasPassword()
315 | {
316 | var user = UserManager.FindById(User.Identity.GetUserId());
317 | if (user != null)
318 | {
319 | return user.PasswordHash != null;
320 | }
321 | return false;
322 | }
323 |
324 |
325 | public enum ManageMessageId
326 | {
327 | ChangePasswordSuccess,
328 | SetPasswordSuccess,
329 | RemoveLoginSuccess,
330 | Error
331 | }
332 |
333 |
334 | private ActionResult RedirectToLocal(string returnUrl)
335 | {
336 | if (Url.IsLocalUrl(returnUrl))
337 | {
338 | return Redirect(returnUrl);
339 | }
340 | else
341 | {
342 | return RedirectToAction("Index", "Home");
343 | }
344 | }
345 |
346 | #endregion
347 | }
348 | }
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Scripts/jquery.validate.unobtrusive.js:
--------------------------------------------------------------------------------
1 | /* NUGET: BEGIN LICENSE TEXT
2 | *
3 | * Microsoft grants you the right to use these script files for the sole
4 | * purpose of either: (i) interacting through your browser with the Microsoft
5 | * website or online service, subject to the applicable licensing or use
6 | * terms; or (ii) using the files as included with a Microsoft product subject
7 | * to that product's license terms. Microsoft reserves all other rights to the
8 | * files not expressly granted by Microsoft, whether by implication, estoppel
9 | * or otherwise. Insofar as a script file is dual licensed under GPL,
10 | * Microsoft neither took the code under GPL nor distributes it thereunder but
11 | * under the terms set out in this paragraph. All notices and licenses
12 | * below are for informational purposes only.
13 | *
14 | * NUGET: END LICENSE TEXT */
15 | /*!
16 | ** Unobtrusive validation support library for jQuery and jQuery Validate
17 | ** Copyright (C) Microsoft Corporation. All rights reserved.
18 | */
19 | /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
20 | /*global document: false, jQuery: false */
21 | (function ($) {
22 | var $jQval = $.validator,
23 | adapters,
24 | data_validation = "unobtrusiveValidation";
25 | function setValidationValues(options, ruleName, value) {
26 | options.rules[ruleName] = value;
27 | if (options.message) {
28 | options.messages[ruleName] = options.message;
29 | }
30 | }
31 | function splitAndTrim(value) {
32 | return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g);
33 | }
34 | function escapeAttributeValue(value) {
35 | // As mentioned on http://api.jquery.com/category/selectors/
36 | return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
37 | }
38 | function getModelPrefix(fieldName) {
39 | return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
40 | }
41 | function appendModelPrefix(value, prefix) {
42 | if (value.indexOf("*.") === 0) {
43 | value = value.replace("*.", prefix);
44 | }
45 | return value;
46 | }
47 | function onError(error, inputElement) { // 'this' is the form element
48 | var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"),
49 | replaceAttrValue = container.attr("data-valmsg-replace"),
50 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;
51 | container.removeClass("field-validation-valid").addClass("field-validation-error");
52 | error.data("unobtrusiveContainer", container);
53 | if (replace) {
54 | container.empty();
55 | error.removeClass("input-validation-error").appendTo(container);
56 | }
57 | else {
58 | error.hide();
59 | }
60 | }
61 | function onErrors(event, validator) { // 'this' is the form element
62 | var container = $(this).find("[data-valmsg-summary=true]"),
63 | list = container.find("ul");
64 | if (list && list.length && validator.errorList.length) {
65 | list.empty();
66 | container.addClass("validation-summary-errors").removeClass("validation-summary-valid");
67 | $.each(validator.errorList, function () {
68 | $(" ").html(this.message).appendTo(list);
69 | });
70 | }
71 | }
72 | function onSuccess(error) { // 'this' is the form element
73 | var container = error.data("unobtrusiveContainer"),
74 | replaceAttrValue = container.attr("data-valmsg-replace"),
75 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;
76 | if (container) {
77 | container.addClass("field-validation-valid").removeClass("field-validation-error");
78 | error.removeData("unobtrusiveContainer");
79 | if (replace) {
80 | container.empty();
81 | }
82 | }
83 | }
84 | function onReset(event) { // 'this' is the form element
85 | var $form = $(this);
86 | $form.data("validator").resetForm();
87 | $form.find(".validation-summary-errors")
88 | .addClass("validation-summary-valid")
89 | .removeClass("validation-summary-errors");
90 | $form.find(".field-validation-error")
91 | .addClass("field-validation-valid")
92 | .removeClass("field-validation-error")
93 | .removeData("unobtrusiveContainer")
94 | .find(">*") // If we were using valmsg-replace, get the underlying error
95 | .removeData("unobtrusiveContainer");
96 | }
97 | function validationInfo(form) {
98 | var $form = $(form),
99 | result = $form.data(data_validation),
100 | onResetProxy = $.proxy(onReset, form);
101 | if (!result) {
102 | result = {
103 | options: { // options structure passed to jQuery Validate's validate() method
104 | errorClass: "input-validation-error",
105 | errorElement: "span",
106 | errorPlacement: $.proxy(onError, form),
107 | invalidHandler: $.proxy(onErrors, form),
108 | messages: {},
109 | rules: {},
110 | success: $.proxy(onSuccess, form)
111 | },
112 | attachValidation: function () {
113 | $form
114 | .unbind("reset." + data_validation, onResetProxy)
115 | .bind("reset." + data_validation, onResetProxy)
116 | .validate(this.options);
117 | },
118 | validate: function () { // a validation function that is called by unobtrusive Ajax
119 | $form.validate();
120 | return $form.valid();
121 | }
122 | };
123 | $form.data(data_validation, result);
124 | }
125 | return result;
126 | }
127 | $jQval.unobtrusive = {
128 | adapters: [],
129 | parseElement: function (element, skipAttach) {
130 | ///
131 | /// Parses a single HTML element for unobtrusive validation attributes.
132 | ///
133 | /// The HTML element to be parsed.
134 | /// [Optional] true to skip attaching the
135 | /// validation to the form. If parsing just this single element, you should specify true.
136 | /// If parsing several elements, you should specify false, and manually attach the validation
137 | /// to the form when you are finished. The default is false.
138 | var $element = $(element),
139 | form = $element.parents("form")[0],
140 | valInfo, rules, messages;
141 | if (!form) { // Cannot do client-side validation without a form
142 | return;
143 | }
144 | valInfo = validationInfo(form);
145 | valInfo.options.rules[element.name] = rules = {};
146 | valInfo.options.messages[element.name] = messages = {};
147 | $.each(this.adapters, function () {
148 | var prefix = "data-val-" + this.name,
149 | message = $element.attr(prefix),
150 | paramValues = {};
151 | if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy)
152 | prefix += "-";
153 | $.each(this.params, function () {
154 | paramValues[this] = $element.attr(prefix + this);
155 | });
156 | this.adapt({
157 | element: element,
158 | form: form,
159 | message: message,
160 | params: paramValues,
161 | rules: rules,
162 | messages: messages
163 | });
164 | }
165 | });
166 | $.extend(rules, { "__dummy__": true });
167 | if (!skipAttach) {
168 | valInfo.attachValidation();
169 | }
170 | },
171 | parse: function (selector) {
172 | ///
173 | /// Parses all the HTML elements in the specified selector. It looks for input elements decorated
174 | /// with the [data-val=true] attribute value and enables validation according to the data-val-*
175 | /// attribute values.
176 | ///
177 | /// Any valid jQuery selector.
178 | var $forms = $(selector)
179 | .parents("form")
180 | .andSelf()
181 | .add($(selector).find("form"))
182 | .filter("form");
183 | // :input is a psuedoselector provided by jQuery which selects input and input-like elements
184 | // combining :input with other selectors significantly decreases performance.
185 | $(selector).find(":input").filter("[data-val=true]").each(function () {
186 | $jQval.unobtrusive.parseElement(this, true);
187 | });
188 | $forms.each(function () {
189 | var info = validationInfo(this);
190 | if (info) {
191 | info.attachValidation();
192 | }
193 | });
194 | }
195 | };
196 | adapters = $jQval.unobtrusive.adapters;
197 | adapters.add = function (adapterName, params, fn) {
198 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.
199 | /// The name of the adapter to be added. This matches the name used
200 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).
201 | /// [Optional] An array of parameter names (strings) that will
202 | /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and
203 | /// mmmm is the parameter name).
204 | /// The function to call, which adapts the values from the HTML
205 | /// attributes into jQuery Validate rules and/or messages.
206 | ///
207 | if (!fn) { // Called with no params, just a function
208 | fn = params;
209 | params = [];
210 | }
211 | this.push({ name: adapterName, params: params, adapt: fn });
212 | return this;
213 | };
214 | adapters.addBool = function (adapterName, ruleName) {
215 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
216 | /// the jQuery Validate validation rule has no parameter values.
217 | /// The name of the adapter to be added. This matches the name used
218 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).
219 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value
220 | /// of adapterName will be used instead.
221 | ///
222 | return this.add(adapterName, function (options) {
223 | setValidationValues(options, ruleName || adapterName, true);
224 | });
225 | };
226 | adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {
227 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
228 | /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and
229 | /// one for min-and-max). The HTML parameters are expected to be named -min and -max.
230 | /// The name of the adapter to be added. This matches the name used
231 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).
232 | /// The name of the jQuery Validate rule to be used when you only
233 | /// have a minimum value.
234 | /// The name of the jQuery Validate rule to be used when you only
235 | /// have a maximum value.
236 | /// The name of the jQuery Validate rule to be used when you
237 | /// have both a minimum and maximum value.
238 | /// [Optional] The name of the HTML attribute that
239 | /// contains the minimum value. The default is "min".
240 | /// [Optional] The name of the HTML attribute that
241 | /// contains the maximum value. The default is "max".
242 | ///
243 | return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) {
244 | var min = options.params.min,
245 | max = options.params.max;
246 | if (min && max) {
247 | setValidationValues(options, minMaxRuleName, [min, max]);
248 | }
249 | else if (min) {
250 | setValidationValues(options, minRuleName, min);
251 | }
252 | else if (max) {
253 | setValidationValues(options, maxRuleName, max);
254 | }
255 | });
256 | };
257 | adapters.addSingleVal = function (adapterName, attribute, ruleName) {
258 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where
259 | /// the jQuery Validate validation rule has a single value.
260 | /// The name of the adapter to be added. This matches the name used
261 | /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).
262 | /// [Optional] The name of the HTML attribute that contains the value.
263 | /// The default is "val".
264 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value
265 | /// of adapterName will be used instead.
266 | ///
267 | return this.add(adapterName, [attribute || "val"], function (options) {
268 | setValidationValues(options, ruleName || adapterName, options.params[attribute]);
269 | });
270 | };
271 | $jQval.addMethod("__dummy__", function (value, element, params) {
272 | return true;
273 | });
274 | $jQval.addMethod("regex", function (value, element, params) {
275 | var match;
276 | if (this.optional(element)) {
277 | return true;
278 | }
279 | match = new RegExp(params).exec(value);
280 | return (match && (match.index === 0) && (match[0].length === value.length));
281 | });
282 | $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) {
283 | var match;
284 | if (nonalphamin) {
285 | match = value.match(/\W/g);
286 | match = match && match.length >= nonalphamin;
287 | }
288 | return match;
289 | });
290 | if ($jQval.methods.extension) {
291 | adapters.addSingleVal("accept", "mimtype");
292 | adapters.addSingleVal("extension", "extension");
293 | } else {
294 | // for backward compatibility, when the 'extension' validation method does not exist, such as with versions
295 | // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for
296 | // validating the extension, and ignore mime-type validations as they are not supported.
297 | adapters.addSingleVal("extension", "extension", "accept");
298 | }
299 | adapters.addSingleVal("regex", "pattern");
300 | adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
301 | adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
302 | adapters.add("equalto", ["other"], function (options) {
303 | var prefix = getModelPrefix(options.element.name),
304 | other = options.params.other,
305 | fullOtherName = appendModelPrefix(other, prefix),
306 | element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0];
307 | setValidationValues(options, "equalTo", element);
308 | });
309 | adapters.add("required", function (options) {
310 | // jQuery Validate equates "required" with "mandatory" for checkbox elements
311 | if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") {
312 | setValidationValues(options, "required", true);
313 | }
314 | });
315 | adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
316 | var value = {
317 | url: options.params.url,
318 | type: options.params.type || "GET",
319 | data: {}
320 | },
321 | prefix = getModelPrefix(options.element.name);
322 | $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
323 | var paramName = appendModelPrefix(fieldName, prefix);
324 | value.data[paramName] = function () {
325 | return $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']").val();
326 | };
327 | });
328 | setValidationValues(options, "remote", value);
329 | });
330 | adapters.add("password", ["min", "nonalphamin", "regex"], function (options) {
331 | if (options.params.min) {
332 | setValidationValues(options, "minlength", options.params.min);
333 | }
334 | if (options.params.nonalphamin) {
335 | setValidationValues(options, "nonalphamin", options.params.nonalphamin);
336 | }
337 | if (options.params.regex) {
338 | setValidationValues(options, "regex", options.params.regex);
339 | }
340 | });
341 | $(function () {
342 | $jQval.unobtrusive.parse(document);
343 | });
344 | }(jQuery));
345 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/AspNetExtendingIdentityRoles.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 |
8 |
9 | 2.0
10 | {D7ADA016-6E82-4F70-B6CF-B687A3B6F6EA}
11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
12 | Library
13 | Properties
14 | AspNetExtendingIdentityRoles
15 | AspNetExtendingIdentityRoles
16 | v4.5
17 | false
18 | true
19 |
20 |
21 |
22 |
23 | ..\
24 | true
25 |
26 |
27 | true
28 | full
29 | false
30 | bin\
31 | DEBUG;TRACE
32 | prompt
33 | 4
34 |
35 |
36 | pdbonly
37 | true
38 | bin\
39 | TRACE
40 | prompt
41 | 4
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | True
65 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
66 |
67 |
68 |
69 |
70 |
71 |
72 | True
73 | ..\packages\Microsoft.AspNet.WebPages.3.0.0\lib\net45\System.Web.Helpers.dll
74 |
75 |
76 | True
77 | ..\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll
78 |
79 |
80 | ..\packages\Microsoft.AspNet.Web.Optimization.1.1.1\lib\net40\System.Web.Optimization.dll
81 |
82 |
83 | True
84 | ..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll
85 |
86 |
87 | True
88 | ..\packages\Microsoft.AspNet.WebPages.3.0.0\lib\net45\System.Web.WebPages.dll
89 |
90 |
91 | True
92 | ..\packages\Microsoft.AspNet.WebPages.3.0.0\lib\net45\System.Web.WebPages.Deployment.dll
93 |
94 |
95 | True
96 | ..\packages\Microsoft.AspNet.WebPages.3.0.0\lib\net45\System.Web.WebPages.Razor.dll
97 |
98 |
99 | True
100 | ..\packages\Newtonsoft.Json.5.0.6\lib\net45\Newtonsoft.Json.dll
101 |
102 |
103 | True
104 | ..\packages\WebGrease.1.5.2\lib\WebGrease.dll
105 |
106 |
107 | True
108 | ..\packages\Antlr.3.4.1.9004\lib\Antlr3.Runtime.dll
109 |
110 |
111 |
112 |
113 | ..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.dll
114 |
115 |
116 | ..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.SqlServer.dll
117 |
118 |
119 | ..\packages\Microsoft.AspNet.Identity.Core.1.0.0\lib\net45\Microsoft.AspNet.Identity.Core.dll
120 |
121 |
122 | ..\packages\Microsoft.AspNet.Identity.Owin.1.0.0\lib\net45\Microsoft.AspNet.Identity.Owin.dll
123 |
124 |
125 | ..\packages\Microsoft.AspNet.Identity.EntityFramework.1.0.0\lib\net45\Microsoft.AspNet.Identity.EntityFramework.dll
126 |
127 |
128 | ..\packages\Owin.1.0\lib\net40\Owin.dll
129 |
130 |
131 | ..\packages\Microsoft.Owin.2.0.0\lib\net45\Microsoft.Owin.dll
132 |
133 |
134 | ..\packages\Microsoft.Owin.Host.SystemWeb.2.0.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll
135 |
136 |
137 | ..\packages\Microsoft.Owin.Security.2.0.0\lib\net45\Microsoft.Owin.Security.dll
138 |
139 |
140 | ..\packages\Microsoft.Owin.Security.Facebook.2.0.0\lib\net45\Microsoft.Owin.Security.Facebook.dll
141 |
142 |
143 | ..\packages\Microsoft.Owin.Security.Cookies.2.0.0\lib\net45\Microsoft.Owin.Security.Cookies.dll
144 |
145 |
146 | ..\packages\Microsoft.Owin.Security.OAuth.2.0.0\lib\net45\Microsoft.Owin.Security.OAuth.dll
147 |
148 |
149 | ..\packages\Microsoft.Owin.Security.Google.2.0.0\lib\net45\Microsoft.Owin.Security.Google.dll
150 |
151 |
152 | ..\packages\Microsoft.Owin.Security.Twitter.2.0.0\lib\net45\Microsoft.Owin.Security.Twitter.dll
153 |
154 |
155 | ..\packages\Microsoft.Owin.Security.MicrosoftAccount.2.0.0\lib\net45\Microsoft.Owin.Security.MicrosoftAccount.dll
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 | Global.asax
168 |
169 |
170 |
171 | 201402130341319_init.cs
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 | Web.config
207 |
208 |
209 | Web.config
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 | 201402130341319_init.cs
248 |
249 |
250 |
251 | 10.0
252 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 | True
265 | True
266 | 58980
267 | /
268 | http://localhost:58980/
269 | False
270 | False
271 |
272 |
273 | False
274 |
275 |
276 |
277 |
278 |
279 |
285 |
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Scripts/jquery.validate.min.js:
--------------------------------------------------------------------------------
1 | /* NUGET: BEGIN LICENSE TEXT
2 | *
3 | * Microsoft grants you the right to use these script files for the sole
4 | * purpose of either: (i) interacting through your browser with the Microsoft
5 | * website or online service, subject to the applicable licensing or use
6 | * terms; or (ii) using the files as included with a Microsoft product subject
7 | * to that product's license terms. Microsoft reserves all other rights to the
8 | * files not expressly granted by Microsoft, whether by implication, estoppel
9 | * or otherwise. Insofar as a script file is dual licensed under GPL,
10 | * Microsoft neither took the code under GPL nor distributes it thereunder but
11 | * under the terms set out in this paragraph. All notices and licenses
12 | * below are for informational purposes only.
13 | *
14 | * NUGET: END LICENSE TEXT */
15 | /*! jQuery Validation Plugin - v1.11.1 - 3/22/2013\n* https://github.com/jzaefferer/jquery-validation
16 | * Copyright (c) 2013 Jörn Zaefferer; Licensed MIT */(function(t){t.extend(t.fn,{validate:function(e){if(!this.length)return e&&e.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."),void 0;var i=t.data(this[0],"validator");return i?i:(this.attr("novalidate","novalidate"),i=new t.validator(e,this[0]),t.data(this[0],"validator",i),i.settings.onsubmit&&(this.validateDelegate(":submit","click",function(e){i.settings.submitHandler&&(i.submitButton=e.target),t(e.target).hasClass("cancel")&&(i.cancelSubmit=!0),void 0!==t(e.target).attr("formnovalidate")&&(i.cancelSubmit=!0)}),this.submit(function(e){function s(){var s;return i.settings.submitHandler?(i.submitButton&&(s=t(" ").attr("name",i.submitButton.name).val(t(i.submitButton).val()).appendTo(i.currentForm)),i.settings.submitHandler.call(i,i.currentForm,e),i.submitButton&&s.remove(),!1):!0}return i.settings.debug&&e.preventDefault(),i.cancelSubmit?(i.cancelSubmit=!1,s()):i.form()?i.pendingRequest?(i.formSubmitted=!0,!1):s():(i.focusInvalid(),!1)})),i)},valid:function(){if(t(this[0]).is("form"))return this.validate().form();var e=!0,i=t(this[0].form).validate();return this.each(function(){e=e&&i.element(this)}),e},removeAttrs:function(e){var i={},s=this;return t.each(e.split(/\s/),function(t,e){i[e]=s.attr(e),s.removeAttr(e)}),i},rules:function(e,i){var s=this[0];if(e){var r=t.data(s.form,"validator").settings,n=r.rules,a=t.validator.staticRules(s);switch(e){case"add":t.extend(a,t.validator.normalizeRule(i)),delete a.messages,n[s.name]=a,i.messages&&(r.messages[s.name]=t.extend(r.messages[s.name],i.messages));break;case"remove":if(!i)return delete n[s.name],a;var u={};return t.each(i.split(/\s/),function(t,e){u[e]=a[e],delete a[e]}),u}}var o=t.validator.normalizeRules(t.extend({},t.validator.classRules(s),t.validator.attributeRules(s),t.validator.dataRules(s),t.validator.staticRules(s)),s);if(o.required){var l=o.required;delete o.required,o=t.extend({required:l},o)}return o}}),t.extend(t.expr[":"],{blank:function(e){return!t.trim(""+t(e).val())},filled:function(e){return!!t.trim(""+t(e).val())},unchecked:function(e){return!t(e).prop("checked")}}),t.validator=function(e,i){this.settings=t.extend(!0,{},t.validator.defaults,e),this.currentForm=i,this.init()},t.validator.format=function(e,i){return 1===arguments.length?function(){var i=t.makeArray(arguments);return i.unshift(e),t.validator.format.apply(this,i)}:(arguments.length>2&&i.constructor!==Array&&(i=t.makeArray(arguments).slice(1)),i.constructor!==Array&&(i=[i]),t.each(i,function(t,i){e=e.replace(RegExp("\\{"+t+"\\}","g"),function(){return i})}),e)},t.extend(t.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:t([]),errorLabelContainer:t([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(t){this.lastActive=t,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,t,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(t)).hide())},onfocusout:function(t){this.checkable(t)||!(t.name in this.submitted)&&this.optional(t)||this.element(t)},onkeyup:function(t,e){(9!==e.which||""!==this.elementValue(t))&&(t.name in this.submitted||t===this.lastElement)&&this.element(t)},onclick:function(t){t.name in this.submitted?this.element(t):t.parentNode.name in this.submitted&&this.element(t.parentNode)},highlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).addClass(i).removeClass(s):t(e).addClass(i).removeClass(s)},unhighlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).removeClass(i).addClass(s):t(e).removeClass(i).addClass(s)}},setDefaults:function(e){t.extend(t.validator.defaults,e)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:t.validator.format("Please enter no more than {0} characters."),minlength:t.validator.format("Please enter at least {0} characters."),rangelength:t.validator.format("Please enter a value between {0} and {1} characters long."),range:t.validator.format("Please enter a value between {0} and {1}."),max:t.validator.format("Please enter a value less than or equal to {0}."),min:t.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function e(e){var i=t.data(this[0].form,"validator"),s="on"+e.type.replace(/^validate/,"");i.settings[s]&&i.settings[s].call(i,this[0],e)}this.labelContainer=t(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||t(this.currentForm),this.containers=t(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var i=this.groups={};t.each(this.settings.groups,function(e,s){"string"==typeof s&&(s=s.split(/\s/)),t.each(s,function(t,s){i[s]=e})});var s=this.settings.rules;t.each(s,function(e,i){s[e]=t.validator.normalizeRule(i)}),t(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",e).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",e),this.settings.invalidHandler&&t(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),t.extend(this.submitted,this.errorMap),this.invalid=t.extend({},this.errorMap),this.valid()||t(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var t=0,e=this.currentElements=this.elements();e[t];t++)this.check(e[t]);return this.valid()},element:function(e){e=this.validationTargetFor(this.clean(e)),this.lastElement=e,this.prepareElement(e),this.currentElements=t(e);var i=this.check(e)!==!1;return i?delete this.invalid[e.name]:this.invalid[e.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),i},showErrors:function(e){if(e){t.extend(this.errorMap,e),this.errorList=[];for(var i in e)this.errorList.push({message:e[i],element:this.findByName(i)[0]});this.successList=t.grep(this.successList,function(t){return!(t.name in e)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){t.fn.resetForm&&t(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(t){var e=0;for(var i in t)e++;return e},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{t(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(e){}},findLastActive:function(){var e=this.lastActive;return e&&1===t.grep(this.errorList,function(t){return t.element.name===e.name}).length&&e},elements:function(){var e=this,i={};return t(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&e.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in i||!e.objectLength(t(this).rules())?!1:(i[this.name]=!0,!0)})},clean:function(e){return t(e)[0]},errors:function(){var e=this.settings.errorClass.replace(" ",".");return t(this.settings.errorElement+"."+e,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=t([]),this.toHide=t([]),this.currentElements=t([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(t){this.reset(),this.toHide=this.errorsFor(t)},elementValue:function(e){var i=t(e).attr("type"),s=t(e).val();return"radio"===i||"checkbox"===i?t("input[name='"+t(e).attr("name")+"']:checked").val():"string"==typeof s?s.replace(/\r/g,""):s},check:function(e){e=this.validationTargetFor(this.clean(e));var i,s=t(e).rules(),r=!1,n=this.elementValue(e);for(var a in s){var u={method:a,parameters:s[a]};try{if(i=t.validator.methods[a].call(this,n,e,u.parameters),"dependency-mismatch"===i){r=!0;continue}if(r=!1,"pending"===i)return this.toHide=this.toHide.not(this.errorsFor(e)),void 0;if(!i)return this.formatAndAdd(e,u),!1}catch(o){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+e.id+", check the '"+u.method+"' method.",o),o}}return r?void 0:(this.objectLength(s)&&this.successList.push(e),!0)},customDataMessage:function(e,i){return t(e).data("msg-"+i.toLowerCase())||e.attributes&&t(e).attr("data-msg-"+i.toLowerCase())},customMessage:function(t,e){var i=this.settings.messages[t];return i&&(i.constructor===String?i:i[e])},findDefined:function(){for(var t=0;arguments.length>t;t++)if(void 0!==arguments[t])return arguments[t];return void 0},defaultMessage:function(e,i){return this.findDefined(this.customMessage(e.name,i),this.customDataMessage(e,i),!this.settings.ignoreTitle&&e.title||void 0,t.validator.messages[i],"Warning: No message defined for "+e.name+" ")},formatAndAdd:function(e,i){var s=this.defaultMessage(e,i.method),r=/\$?\{(\d+)\}/g;"function"==typeof s?s=s.call(this,i.parameters,e):r.test(s)&&(s=t.validator.format(s.replace(r,"{$1}"),i.parameters)),this.errorList.push({message:s,element:e}),this.errorMap[e.name]=s,this.submitted[e.name]=s},addWrapper:function(t){return this.settings.wrapper&&(t=t.add(t.parent(this.settings.wrapper))),t},defaultShowErrors:function(){var t,e;for(t=0;this.errorList[t];t++){var i=this.errorList[t];this.settings.highlight&&this.settings.highlight.call(this,i.element,this.settings.errorClass,this.settings.validClass),this.showLabel(i.element,i.message)}if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(t=0;this.successList[t];t++)this.showLabel(this.successList[t]);if(this.settings.unhighlight)for(t=0,e=this.validElements();e[t];t++)this.settings.unhighlight.call(this,e[t],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return t(this.errorList).map(function(){return this.element})},showLabel:function(e,i){var s=this.errorsFor(e);s.length?(s.removeClass(this.settings.validClass).addClass(this.settings.errorClass),s.html(i)):(s=t("<"+this.settings.errorElement+">").attr("for",this.idOrName(e)).addClass(this.settings.errorClass).html(i||""),this.settings.wrapper&&(s=s.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(s).length||(this.settings.errorPlacement?this.settings.errorPlacement(s,t(e)):s.insertAfter(e))),!i&&this.settings.success&&(s.text(""),"string"==typeof this.settings.success?s.addClass(this.settings.success):this.settings.success(s,e)),this.toShow=this.toShow.add(s)},errorsFor:function(e){var i=this.idOrName(e);return this.errors().filter(function(){return t(this).attr("for")===i})},idOrName:function(t){return this.groups[t.name]||(this.checkable(t)?t.name:t.id||t.name)},validationTargetFor:function(t){return this.checkable(t)&&(t=this.findByName(t.name).not(this.settings.ignore)[0]),t},checkable:function(t){return/radio|checkbox/i.test(t.type)},findByName:function(e){return t(this.currentForm).find("[name='"+e+"']")},getLength:function(e,i){switch(i.nodeName.toLowerCase()){case"select":return t("option:selected",i).length;case"input":if(this.checkable(i))return this.findByName(i.name).filter(":checked").length}return e.length},depend:function(t,e){return this.dependTypes[typeof t]?this.dependTypes[typeof t](t,e):!0},dependTypes:{"boolean":function(t){return t},string:function(e,i){return!!t(e,i.form).length},"function":function(t,e){return t(e)}},optional:function(e){var i=this.elementValue(e);return!t.validator.methods.required.call(this,i,e)&&"dependency-mismatch"},startRequest:function(t){this.pending[t.name]||(this.pendingRequest++,this.pending[t.name]=!0)},stopRequest:function(e,i){this.pendingRequest--,0>this.pendingRequest&&(this.pendingRequest=0),delete this.pending[e.name],i&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(t(this.currentForm).submit(),this.formSubmitted=!1):!i&&0===this.pendingRequest&&this.formSubmitted&&(t(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(e){return t.data(e,"previousValue")||t.data(e,"previousValue",{old:null,valid:!0,message:this.defaultMessage(e,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(e,i){e.constructor===String?this.classRuleSettings[e]=i:t.extend(this.classRuleSettings,e)},classRules:function(e){var i={},s=t(e).attr("class");return s&&t.each(s.split(" "),function(){this in t.validator.classRuleSettings&&t.extend(i,t.validator.classRuleSettings[this])}),i},attributeRules:function(e){var i={},s=t(e),r=s[0].getAttribute("type");for(var n in t.validator.methods){var a;"required"===n?(a=s.get(0).getAttribute(n),""===a&&(a=!0),a=!!a):a=s.attr(n),/min|max/.test(n)&&(null===r||/number|range|text/.test(r))&&(a=Number(a)),a?i[n]=a:r===n&&"range"!==r&&(i[n]=!0)}return i.maxlength&&/-1|2147483647|524288/.test(i.maxlength)&&delete i.maxlength,i},dataRules:function(e){var i,s,r={},n=t(e);for(i in t.validator.methods)s=n.data("rule-"+i.toLowerCase()),void 0!==s&&(r[i]=s);return r},staticRules:function(e){var i={},s=t.data(e.form,"validator");return s.settings.rules&&(i=t.validator.normalizeRule(s.settings.rules[e.name])||{}),i},normalizeRules:function(e,i){return t.each(e,function(s,r){if(r===!1)return delete e[s],void 0;if(r.param||r.depends){var n=!0;switch(typeof r.depends){case"string":n=!!t(r.depends,i.form).length;break;case"function":n=r.depends.call(i,i)}n?e[s]=void 0!==r.param?r.param:!0:delete e[s]}}),t.each(e,function(s,r){e[s]=t.isFunction(r)?r(i):r}),t.each(["minlength","maxlength"],function(){e[this]&&(e[this]=Number(e[this]))}),t.each(["rangelength","range"],function(){var i;e[this]&&(t.isArray(e[this])?e[this]=[Number(e[this][0]),Number(e[this][1])]:"string"==typeof e[this]&&(i=e[this].split(/[\s,]+/),e[this]=[Number(i[0]),Number(i[1])]))}),t.validator.autoCreateRanges&&(e.min&&e.max&&(e.range=[e.min,e.max],delete e.min,delete e.max),e.minlength&&e.maxlength&&(e.rangelength=[e.minlength,e.maxlength],delete e.minlength,delete e.maxlength)),e},normalizeRule:function(e){if("string"==typeof e){var i={};t.each(e.split(/\s/),function(){i[this]=!0}),e=i}return e},addMethod:function(e,i,s){t.validator.methods[e]=i,t.validator.messages[e]=void 0!==s?s:t.validator.messages[e],3>i.length&&t.validator.addClassRules(e,t.validator.normalizeRule(e))},methods:{required:function(e,i,s){if(!this.depend(s,i))return"dependency-mismatch";if("select"===i.nodeName.toLowerCase()){var r=t(i).val();return r&&r.length>0}return this.checkable(i)?this.getLength(e,i)>0:t.trim(e).length>0},email:function(t,e){return this.optional(e)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(t)},url:function(t,e){return this.optional(e)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(t)},date:function(t,e){return this.optional(e)||!/Invalid|NaN/.test(""+new Date(t))},dateISO:function(t,e){return this.optional(e)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(t)},number:function(t,e){return this.optional(e)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(t)},digits:function(t,e){return this.optional(e)||/^\d+$/.test(t)},creditcard:function(t,e){if(this.optional(e))return"dependency-mismatch";if(/[^0-9 \-]+/.test(t))return!1;var i=0,s=0,r=!1;t=t.replace(/\D/g,"");for(var n=t.length-1;n>=0;n--){var a=t.charAt(n);s=parseInt(a,10),r&&(s*=2)>9&&(s-=9),i+=s,r=!r}return 0===i%10},minlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s},maxlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||s>=r},rangelength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s[0]&&s[1]>=r},min:function(t,e,i){return this.optional(e)||t>=i},max:function(t,e,i){return this.optional(e)||i>=t},range:function(t,e,i){return this.optional(e)||t>=i[0]&&i[1]>=t},equalTo:function(e,i,s){var r=t(s);return this.settings.onfocusout&&r.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){t(i).valid()}),e===r.val()},remote:function(e,i,s){if(this.optional(i))return"dependency-mismatch";var r=this.previousValue(i);if(this.settings.messages[i.name]||(this.settings.messages[i.name]={}),r.originalMessage=this.settings.messages[i.name].remote,this.settings.messages[i.name].remote=r.message,s="string"==typeof s&&{url:s}||s,r.old===e)return r.valid;r.old=e;var n=this;this.startRequest(i);var a={};return a[i.name]=e,t.ajax(t.extend(!0,{url:s,mode:"abort",port:"validate"+i.name,dataType:"json",data:a,success:function(s){n.settings.messages[i.name].remote=r.originalMessage;var a=s===!0||"true"===s;if(a){var u=n.formSubmitted;n.prepareElement(i),n.formSubmitted=u,n.successList.push(i),delete n.invalid[i.name],n.showErrors()}else{var o={},l=s||n.defaultMessage(i,"remote");o[i.name]=r.message=t.isFunction(l)?l(e):l,n.invalid[i.name]=!0,n.showErrors(o)}r.valid=a,n.stopRequest(i,a)}},s)),"pending"}}}),t.format=t.validator.format})(jQuery),function(t){var e={};if(t.ajaxPrefilter)t.ajaxPrefilter(function(t,i,s){var r=t.port;"abort"===t.mode&&(e[r]&&e[r].abort(),e[r]=s)});else{var i=t.ajax;t.ajax=function(s){var r=("mode"in s?s:t.ajaxSettings).mode,n=("port"in s?s:t.ajaxSettings).port;return"abort"===r?(e[n]&&e[n].abort(),e[n]=i.apply(this,arguments),e[n]):i.apply(this,arguments)}}}(jQuery),function(t){t.extend(t.fn,{validateDelegate:function(e,i,s){return this.bind(i,function(i){var r=t(i.target);return r.is(e)?s.apply(r,arguments):void 0})}})}(jQuery);
--------------------------------------------------------------------------------
/AspNetExtendingIdentityRoles/Scripts/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /* NUGET: BEGIN LICENSE TEXT
2 | *
3 | * Microsoft grants you the right to use these script files for the sole
4 | * purpose of either: (i) interacting through your browser with the Microsoft
5 | * website or online service, subject to the applicable licensing or use
6 | * terms; or (ii) using the files as included with a Microsoft product subject
7 | * to that product's license terms. Microsoft reserves all other rights to the
8 | * files not expressly granted by Microsoft, whether by implication, estoppel
9 | * or otherwise. Insofar as a script file is dual licensed under GPL,
10 | * Microsoft neither took the code under GPL nor distributes it thereunder but
11 | * under the terms set out in this paragraph. All notices and licenses
12 | * below are for informational purposes only.
13 | *
14 | * NUGET: END LICENSE TEXT */
15 |
16 | /**
17 | * bootstrap.js v3.0.0 by @fat and @mdo
18 | * Copyright 2013 Twitter Inc.
19 | * http://www.apache.org/licenses/LICENSE-2.0
20 | */
21 | if(!jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(window.jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('
').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i ').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(window.jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focus",i="hover"==g?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show),void 0):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide),void 0):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d="function"==typeof this.options.placement?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m="body"==this.options.container?window.innerWidth:j.outerWidth(),n="body"==this.options.container?window.innerHeight:j.outerHeight(),o="body"==this.options.container?0:j.offset().left;d="bottom"==d&&g.top+g.height+i-l>n?"top":"top"==d&&g.top-l-i<0?"bottom":"right"==d&&g.right+h>m?"left":"left"==d&&g.left-h
'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery);
--------------------------------------------------------------------------------