Index: NetTiers.cst =================================================================== --- NetTiers.cst (revision 711) +++ NetTiers.cst (working copy) @@ -1,4 +1,4 @@ -<%@ CodeTemplate Src="TemplateLib/CommonSqlCode.cs" Inherits="MoM.Templates.CommonSqlCode" Language="C#" TargetLanguage="Text" Description="NetTiers main template." Debug="True" ResponseEncoding="UTF-8" NoWarn="0108,0618,1572,1573,1574,0162,2002"%> +<%@ CodeTemplate Src="TemplateLib/CommonSqlCode.cs" Inherits="MoM.Templates.CommonSqlCode" Language="C#" TargetLanguage="Text" Description="NetTiers main template." Debug="True" ResponseEncoding="UTF-8" NoWarn="0108,0618,1572,1573,1574,0162,2002"%> <%@ Assembly Name="SchemaExplorer" %> <%@ Assembly Name="System.Design" %> <%@ Assembly Name="System.DirectoryServices" %> @@ -448,8 +448,77 @@ base.OnPropertyChanged(propertyName); } #endif - #endregion + #endregion + private bool _generateWebSecurity = true; + + [Category("10. WebLibrary.Security - Optional")] + [Description("Indicates if the Web.Security library should be generated. This contains the EntityMembershipProvider class and other classes helpful to ASP.NET Membership services.")] + [CodeTemplateProperty(CodeTemplatePropertyOption.Optional)] + public bool GenerateWebSecurity + { + get + { + return _generateWebSecurity; + } + set + { + _generateWebSecurity = value; + } + } + + private ColumnSchema _entityMembershipUserPKCol = null; + + [Category("10. WebLibrary.Security - Optional")] + [Description("Primary key column from the table that will become the EntityMembershipUser's user entity.")] + [CodeTemplateProperty(CodeTemplatePropertyOption.Optional)] + public ColumnSchema EntityMembershipUserPKCol + { + get + { + return this._entityMembershipUserPKCol; + } + set + { + _entityMembershipUserPKCol = value; + } + } + + private string _membershipUserMapFile; + + [Editor(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(System.Drawing.Design.UITypeEditor))] + [Category("10. WebLibrary.Security - Optional")] + [Description("Optional File Path to a MembershipUserProperty/EntityProperty alias file")] + [CodeTemplateProperty(CodeTemplatePropertyOption.Optional)] + public string MembershipUserMapFile + { + get + { + return this._membershipUserMapFile; + } + set + { + _membershipUserMapFile = value; + } + } + + private bool _membershipUseMD5 = false; + + [Category("10. WebLibrary.Security - Optional")] + [Description("Use MD5 hash for passwords. False defaults to SHA1.")] + [CodeTemplateProperty(CodeTemplatePropertyOption.Optional)] + public bool UseMD5Hash + { + get + { + return this._membershipUseMD5; + } + set + { + _membershipUseMD5 = value; + } + } + #region Properties used by the wizard to report progression private int _counter = 0; @@ -716,6 +785,8 @@ string WinLibNameSpace = NameSpace + ".Windows.Forms"; string SQLNamespace = NameSpace + "." + (SQLFolderName.Length > 0 ? SQLFolderName : "SQL"); + string WebSecurityLibNameSpace = WebLibNameSpace + ".Security"; + string factoryType = (ComponentPattern == MoM.Templates.ComponentPatternType.DomainModel ? string.Format("{0}.{1}", ComponentsNameSpace, "ComponentEntityFactory") : string.Format("{0}.{1}", BLLNameSpace, "EntityFactory")); #endregion Build Namespaces @@ -732,6 +803,8 @@ string rootPathUT = OutputDirectory + "\\" + UTNameSpace; string rootPathSQL = OutputDirectory + "\\" + SQLNamespace; + string rootPathWebSecurityLib = OutputDirectory + "\\" + WebLibNameSpace + ".Security"; + string rootPathWS = WebServiceOutputPath; string specialPath = vsnetIntegration == VSNetIntegration.SeparatedProjects ? ((IncludeUnitTest != MoM.Templates.UnitTestStyle.None) ? rootPathUT : rootPathDAL) : OutputDirectory; @@ -800,6 +873,16 @@ XmlElement parametersNode = AddMessageNode(initNode, 0, "Validating parameters.", false); + if ( GenerateWebSecurity ) + { + // make sure MembershipUser primary key column is selected + if ( EntityMembershipUserPKCol == null ) + { + AddMessageNode(parametersNode, 1, "EntityMembershipUserPKCol has not been specified, so the Web.Security library will not be generated.", true); + GenerateWebSecurity = false; + } + } + #region Build the correct list of used tables (filtering tables without primary key) _CurrentPhase = "Check datasource"; DebugWriteLine("Current Phase: "+_CurrentPhase); @@ -1086,6 +1169,13 @@ } #endregion Set up web library directories + #region Set up web security library directory + if (GenerateWebSecurity) + { + SafeCreateDirectory(rootPathWebSecurityLib); + } + #endregion Set up web security library directory + #region Set up website directories if (GenerateWebsite) { @@ -2291,6 +2381,36 @@ } + if ( GenerateWebSecurity ) + { + AddFileNode(commonNode, "EntityMembershipProvider.cs"); + this.GetTemplate("EntityMembershipProvider.cst").SetProperty("BLLNameSpace", BLLNameSpace); + this.GetTemplate("EntityMembershipProvider.cst").SetProperty("DALNameSpace", DALNameSpace); + this.GetTemplate("EntityMembershipProvider.cst").SetProperty("WebNameSpace", WebLibNameSpace); + this.GetTemplate("EntityMembershipProvider.cst").SetProperty("EntityMembershipUserPKCol", EntityMembershipUserPKCol); + this.GetTemplate("EntityMembershipProvider.cst").SetProperty("MembershipUserMapFile", MembershipUserMapFile); + this.GetTemplate("EntityMembershipProvider.cst").SetProperty("UseMD5Hash", UseMD5Hash); + this.RenderToFile("EntityMembershipProvider.cst", rootPathWebSecurityLib + "\\EntityMembershipProvider.cs", true); + + AddFileNode(commonNode, "EntityMembershipUser.cs"); + this.GetTemplate("EntityMembershipUser.cst").SetProperty("BLLNameSpace", BLLNameSpace); + this.GetTemplate("EntityMembershipUser.cst").SetProperty("DALNameSpace", DALNameSpace); + this.GetTemplate("EntityMembershipUser.cst").SetProperty("WebNameSpace", WebLibNameSpace); + this.GetTemplate("EntityMembershipUser.cst").SetProperty("EntityMembershipUserPKCol", EntityMembershipUserPKCol); + this.GetTemplate("EntityMembershipUser.cst").SetProperty("MembershipUserMapFile", MembershipUserMapFile); + this.GetTemplate("EntityMembershipUser.cst").SetProperty("UseMD5Hash", UseMD5Hash); + this.RenderToFile("EntityMembershipUser.cst", rootPathWebSecurityLib + "\\EntityMembershipUser.cs", true); + + AddFileNode(commonNode, "EntityMembershipProperty.cs"); + this.GetTemplate("EntityMembershipProperty.cst").SetProperty("BLLNameSpace", BLLNameSpace); + this.GetTemplate("EntityMembershipProperty.cst").SetProperty("DALNameSpace", DALNameSpace); + this.GetTemplate("EntityMembershipProperty.cst").SetProperty("WebNameSpace", WebLibNameSpace); + this.GetTemplate("EntityMembershipProperty.cst").SetProperty("EntityMembershipUserPKCol", EntityMembershipUserPKCol); + this.GetTemplate("EntityMembershipProperty.cst").SetProperty("MembershipUserMapFile", MembershipUserMapFile); + this.GetTemplate("EntityMembershipProperty.cst").SetProperty("UseMD5Hash", UseMD5Hash); + this.RenderToFile("EntityMembershipProperty.cst", rootPathWebSecurityLib + "\\EntityMembershipProperty.cs", true); + } + #endregion Web Library Classes #region Generate WebSite @@ -2522,6 +2642,7 @@ string websiteGuid = "1DCAB031-308A-4581-AFA8-BD29F45A1357"; string componentGuid = "794327CE-DC0A-4381-89EE-4C00AFB08D5A"; string winLibGuid = "43FE3BE8-3E46-47CA-8494-473315867DD0"; //Guid.NewGuid().ToString(); + string websecurityGuid = "417D82D0-4E13-4836-99A2-13062B945C49"; // ADDED BY CHARLIE #endregion Set Guids #region Set solution and project template names @@ -2545,6 +2666,7 @@ this.GetTemplate(solutionTemplate).SetProperty("WebLibNameSpace", WebLibNameSpace); this.GetTemplate(solutionTemplate).SetProperty("WinLibNameSpace", WinLibNameSpace); this.GetTemplate(solutionTemplate).SetProperty("WebsiteNameSpace", WebsiteNameSpace); + this.GetTemplate(solutionTemplate).SetProperty("WebSecurityLibNameSpace", WebSecurityLibNameSpace); this.GetTemplate(solutionTemplate).SetProperty("UTNameSpace", UTNameSpace); this.GetTemplate(solutionTemplate).SetProperty("WSNameSpace", WSNameSpace); this.GetTemplate(solutionTemplate).SetProperty("BLLGuid", bllGuid); @@ -2557,6 +2679,7 @@ this.GetTemplate(solutionTemplate).SetProperty("WebLibGuid", webLibGuid); this.GetTemplate(solutionTemplate).SetProperty("WebsiteGuid", websiteGuid); this.GetTemplate(solutionTemplate).SetProperty("WinLibGuid", winLibGuid); + this.GetTemplate(solutionTemplate).SetProperty("WebSecurityLibGuid", websecurityGuid); this.GetTemplate(solutionTemplate).SetProperty("ComponentsGuid", componentGuid); this.GetTemplate(solutionTemplate).SetProperty("ComponentPattern", IncludeComponentLayer); this.GetTemplate(solutionTemplate).SetProperty("ComponentLayerNameSpace", ComponentsNameSpace); @@ -2568,6 +2691,7 @@ this.GetTemplate(solutionTemplate).SetProperty("IncludeWebservice", GenerateWebservice); this.GetTemplate(solutionTemplate).SetProperty("IncludeWebserviceClient", GenerateWebservice); this.GetTemplate(solutionTemplate).SetProperty("IncludeWebLibrary", GenerateWebLibrary); + this.GetTemplate(solutionTemplate).SetProperty("IncludeWebSecurity", GenerateWebSecurity); this.GetTemplate(solutionTemplate).SetProperty("IncludeWebsite", GenerateWebsite); this.GetTemplate(solutionTemplate).SetProperty("IncludeUnitTest", IncludeUnitTest); this.GetTemplate(solutionTemplate).SetProperty("UseWebAppProject", UseWebAppProject); @@ -2602,6 +2726,7 @@ this.GetTemplate(projectTemplate).SetProperty("UTGuid", utGuid); this.GetTemplate(projectTemplate).SetProperty("WSGuid", wsGuid); this.GetTemplate(projectTemplate).SetProperty("WebLibGuid", webLibGuid); + this.GetTemplate(projectTemplate).SetProperty("WebSecurityLibGuid", websecurityGuid); this.GetTemplate(projectTemplate).SetProperty("WinLibGuid", winLibGuid); this.GetTemplate(projectTemplate).SetProperty("WebsiteGuid", websiteGuid); this.GetTemplate(projectTemplate).SetProperty("ComponentsGuid", componentGuid); @@ -2615,6 +2740,7 @@ this.GetTemplate(projectTemplate).SetProperty("DALGenericNameSpace", DALGenericNameSpace); this.GetTemplate(projectTemplate).SetProperty("DALWSNameSpace", DALWSNameSpace); this.GetTemplate(projectTemplate).SetProperty("WebLibNameSpace", WebLibNameSpace); + this.GetTemplate(projectTemplate).SetProperty("WebSecurityLibNameSpace", WebSecurityLibNameSpace); this.GetTemplate(projectTemplate).SetProperty("WinLibNameSpace", WinLibNameSpace); this.GetTemplate(projectTemplate).SetProperty("WebsiteNameSpace", WebsiteNameSpace); this.GetTemplate(projectTemplate).SetProperty("UTNameSpace", UTNameSpace); @@ -2647,6 +2773,7 @@ this.GetTemplate(projectTemplate).SetProperty("IncludeWebservice", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebserviceClient", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebLibrary", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebSecurity", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWinLibrary", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebsite", false); this.GetTemplate(projectTemplate).SetProperty("IncludeComponents", true); @@ -2670,6 +2797,7 @@ this.GetTemplate(projectTemplate).SetProperty("IncludeWebservice", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebserviceClient", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebLibrary", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebSecurity", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWinLibrary", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebsite", false); this.GetTemplate(projectTemplate).SetProperty("IncludeComponents", false); @@ -2699,6 +2827,7 @@ this.GetTemplate(projectTemplate).SetProperty("IncludeWebservice", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebserviceClient", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebLibrary", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebSecurity", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebsite", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWinLibrary", false); this.GetTemplate(projectTemplate).SetProperty("IncludeComponents", false); @@ -2722,6 +2851,7 @@ this.GetTemplate(projectTemplate).SetProperty("IncludeWebserviceClient", false); this.GetTemplate(projectTemplate).SetProperty("IncludeComponents", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebLibrary", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebSecurity", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebsite", false); this.GetTemplate(projectTemplate).SetProperty("IncludeUnitTest", MoM.Templates.UnitTestStyle.None); this.GetTemplate(projectTemplate).SetProperty("IncludeWCFDataAttributes", false); @@ -2744,6 +2874,7 @@ this.GetTemplate(projectTemplate).SetProperty("IncludeWebserviceClient", false); this.GetTemplate(projectTemplate).SetProperty("IncludeComponents", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebLibrary", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebSecurity", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebsite", false); this.GetTemplate(projectTemplate).SetProperty("IncludeUnitTest", MoM.Templates.UnitTestStyle.None); this.GetTemplate(projectTemplate).SetProperty("IncludeWCFDataAttributes", false); @@ -2766,6 +2897,7 @@ this.GetTemplate(projectTemplate).SetProperty("IncludeWebserviceClient", true); this.GetTemplate(projectTemplate).SetProperty("IncludeComponents", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebLibrary", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebSecurity", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebsite", false); this.GetTemplate(projectTemplate).SetProperty("IncludeUnitTest", MoM.Templates.UnitTestStyle.None); this.GetTemplate(projectTemplate).SetProperty("IncludeWCFDataAttributes", false); @@ -2792,6 +2924,7 @@ this.GetTemplate(projectTemplate).SetProperty("IncludeWebserviceClient", false); this.GetTemplate(projectTemplate).SetProperty("IncludeComponents", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebLibrary", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebSecurity", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWinLibrary", true); this.GetTemplate(projectTemplate).SetProperty("IncludeWebsite", false); this.GetTemplate(projectTemplate).SetProperty("IncludeUnitTest", MoM.Templates.UnitTestStyle.None); @@ -2802,6 +2935,30 @@ } #endregion Win Library project + #region Web.Security Library Library project file + if (GenerateWebSecurity) + { + AddFileNode(commonNode, WebSecurityLibNameSpace + ".csproj"); + + this.GetTemplate(projectTemplate).SetProperty("IncludeBll", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeDALBase", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeSqlClient", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeGenericClient", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebservice", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebserviceClient", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeComponents", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebLibrary", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebSecurity", true); + this.GetTemplate(projectTemplate).SetProperty("IncludeWinLibrary", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebsite", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeUnitTest", MoM.Templates.UnitTestStyle.None); + this.GetTemplate(projectTemplate).SetProperty("IncludeWCFDataAttributes", false); + this.GetTemplate(projectTemplate).SetProperty("IncludeDesignTimeSupport", false); + + this.RenderToFile(projectTemplate, rootPathWebSecurityLib + "\\" + WebSecurityLibNameSpace + ".csproj", true); + } + #endregion Web.Security Library project file + #region Web Library project if (GenerateWebLibrary) { @@ -2815,6 +2972,7 @@ this.GetTemplate(projectTemplate).SetProperty("IncludeWebserviceClient", false); this.GetTemplate(projectTemplate).SetProperty("IncludeComponents", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebLibrary", true); + this.GetTemplate(projectTemplate).SetProperty("IncludeWebSecurity", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWinLibrary", false); this.GetTemplate(projectTemplate).SetProperty("IncludeWebsite", false); this.GetTemplate(projectTemplate).SetProperty("IncludeUnitTest", MoM.Templates.UnitTestStyle.None); Index: TemplateLib/CreateTemplates.cs =================================================================== --- TemplateLib/CreateTemplates.cs (revision 711) +++ TemplateLib/CreateTemplates.cs (working copy) @@ -223,6 +223,10 @@ CodeTemplates.Add("TableGridView.cst", base.CreateTemplate()); this.PerformStep(); CodeTemplates.Add("TableGridViewBase.cst", base.CreateTemplate()); this.PerformStep(); CodeTemplates.Add("TypedDataSource.cst", base.CreateTemplate()); this.PerformStep(); + + CodeTemplates.Add("EntityMembershipProvider.cst", base.CreateTemplate()); this.PerformStep(); + CodeTemplates.Add("EntityMembershipUser.cst", base.CreateTemplate()); this.PerformStep(); + CodeTemplates.Add("EntityMembershipProperty.cst", base.CreateTemplate()); this.PerformStep(); #endregion Index: TemplateLib/FrameworkTemplates.cst =================================================================== --- TemplateLib/FrameworkTemplates.cst (revision 711) +++ TemplateLib/FrameworkTemplates.cst (working copy) @@ -220,4 +220,7 @@ <%@ Register Name="TableGridView" Template="../WinformsLibrary/UI/TableGridView.cst" MergeProperties="False" ExcludeProperties="" %> <%@ Register Name="TableGridViewBase" Template="../WinformsLibrary/UI/TableGridViewBase.cst" MergeProperties="False" ExcludeProperties="" %> <%@ Register Name="TypedDataSource" Template="../WinformsLibrary/Data/TypedDataSource.cst" MergeProperties="False" ExcludeProperties="" %> - + +<%@ Register Name="EntityMembershipProvider" Template="../WebLibrarySecurity/EntityMembershipProvider.cst" MergeProperties="False" ExcludeProperties="" %> +<%@ Register Name="EntityMembershipUser" Template="../WebLibrarySecurity/EntityMembershipUser.cst" MergeProperties="False" ExcludeProperties="" %> +<%@ Register Name="EntityMembershipProperty" Template="../WebLibrarySecurity/EntityMembershipProperty.cst" MergeProperties="False" ExcludeProperties="" %> Index: VisualStudio/vsnet2005.project.cst =================================================================== --- VisualStudio/vsnet2005.project.cst (revision 711) +++ VisualStudio/vsnet2005.project.cst (working copy) @@ -1,4 +1,4 @@ -<%@ CodeTemplate Src="../TemplateLib/CommonSqlCode.cs" Inherits="MoM.Templates.CommonSqlCode" Language="C#" TargetLanguage="Xml" Description="Template description here." Debug="True" ResponseEncoding="UTF-8" NoWarn="0108,0618,1572,1573,1574,0162,2002" %> +<%@ CodeTemplate Src="../TemplateLib/CommonSqlCode.cs" Inherits="MoM.Templates.CommonSqlCode" Language="C#" TargetLanguage="Xml" Description="Template description here." Debug="True" ResponseEncoding="UTF-8" NoWarn="0108,0618,1572,1573,1574,0162,2002" %> <%@ Property Name="SourceDatabase" Type="SchemaExplorer.DatabaseSchema" Optional="True" Category="Context" Description="Database that the stored procedures should be based on." %> <%@ Property Name="SourceTables" Type="SchemaExplorer.TableSchemaCollection" Category="Context" Description="Tables that the stored procedures should be based on." %> @@ -14,6 +14,7 @@ <%@ Property Name="UTGuid" Type="System.String" Category="Context" Description="Unit tests Project Guid" %> <%@ Property Name="WSGuid" Type="System.String" Category="Context" Description="WebService Project Guid" %> <%@ Property Name="WebLibGuid" Type="System.String" Category="Context" Description="Web Library Project Guid" %> +<%@ Property Name="WebSecurityLibGuid" Type="System.String" Category="Context" Description="Web Security Library Project Guid" %> <%@ Property Name="WebsiteGuid" Type="System.String" Category="Context" Description="Website Project Guid" %> <%@ Property Name="ComponentsGuid" Type="System.String" Category="Context" Description="Components Guid" %> @@ -28,6 +29,7 @@ <%@ Property Name="UTNameSpace" Type="System.String" Category="Data" Description="UT Namespace." %> <%@ Property Name="WSNameSpace" Type="System.String" Category="Data" Description="WebService Namespace." %> <%@ Property Name="WebLibNameSpace" Type="System.String" Category="Data" Description="Web Library Namespace." %> +<%@ Property Name="WebSecurityLibNameSpace" Type="System.String" Category="Data" Description="Web Security Library Namespace." %> <%@ Property Name="WebsiteNameSpace" Type="System.String" Category="Data" Description="Website Namespace." %> <%@ Property Name="ComponentLayerNameSpace" Type="System.String" Category="Data" Description="Component Layer Namespace." %> <%@ Property Name="ComponentPattern" Default="None" Type="MoM.Templates.ComponentPatternType" Category="Data" Description="Component Layer Pattern Type." %> @@ -43,6 +45,7 @@ <%@ Property Name="IncludeSqlClient" Type="System.Boolean" Category="Option" Description="" %> <%@ Property Name="IncludeGenericClient" Type="System.Boolean" Category="Option" Description="" %> <%@ Property Name="IncludeWebLibrary" Type="System.Boolean" Category="Option" Description="" %> +<%@ Property Name="IncludeWebSecurity" Type="System.Boolean" Category="Option" Description="" %> <%@ Property Name="IncludeWebsite" Type="System.Boolean" Category="Option" Description="" %> <%@ Property Name="IncludeWebservice" Type="System.Boolean" Category="Option" Description="" %> <%@ Property Name="IncludeComponents" Type="System.Boolean" Category="Option" Description="Determines whether or not a component library is being used." %> @@ -112,6 +115,10 @@ { fileName = WebLibNameSpace; } + else if (IncludeWebSecurity) + { + fileName = WebSecurityLibNameSpace; + } else if (IncludeWinLibrary) { fileName = WinLibNameSpace; @@ -137,6 +144,7 @@ string ComponentsSubFolder = string.Empty; string UTSubFolder = string.Empty; string WebLibSubFolder = string.Empty; + string WebSecurityLibSubFolder = string.Empty; string WinLibSubFolder = string.Empty; %> @@ -146,7 +154,7 @@ AnyCPU <%= GetVisualStudioProductVersionString( VisualStudioVersion ) %> 2.0 - {<% if (IncludeBll) Response.Write(BLLGuid); else if (IncludeComponents) Response.Write(ComponentsGuid); else if (IncludeDALBase) Response.Write(DALGuid); else if (IncludeSqlClient) Response.Write(DALSqlGuid); else if (IncludeGenericClient) Response.Write(DALGenericGuid); else if (IncludeUnitTest != MoM.Templates.UnitTestStyle.None) Response.Write(UTGuid); else if (IncludeWebservice) Response.Write(WSGuid);else if (IncludeWebserviceClient) Response.Write(DALWSGuid); else if (IncludeWebLibrary) Response.Write(WebLibGuid); else if (IncludeWinLibrary) Response.Write(WinLibGuid); else if (IncludeWebsite) Response.Write(WebsiteGuid); %>} + {<% if (IncludeBll) Response.Write(BLLGuid); else if (IncludeComponents) Response.Write(ComponentsGuid); else if (IncludeDALBase) Response.Write(DALGuid); else if (IncludeSqlClient) Response.Write(DALSqlGuid); else if (IncludeGenericClient) Response.Write(DALGenericGuid); else if (IncludeUnitTest != MoM.Templates.UnitTestStyle.None) Response.Write(UTGuid); else if (IncludeWebservice) Response.Write(WSGuid);else if (IncludeWebserviceClient) Response.Write(DALWSGuid); else if (IncludeWebLibrary) Response.Write(WebLibGuid); else if (IncludeWebSecurity) Response.Write(WebSecurityLibGuid); else if (IncludeWinLibrary) Response.Write(WinLibGuid); else if (IncludeWebsite) Response.Write(WebsiteGuid); %>} <% if ( IncludeWebsite ) { %> {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} <% } else { %> @@ -348,7 +356,7 @@ <%}%> - <% if (IncludeSqlClient || IncludeGenericClient || IncludeWebserviceClient || IncludeWebLibrary) { %> + <% if (IncludeSqlClient || IncludeGenericClient || IncludeWebserviceClient || IncludeWebLibrary || IncludeWebSecurity) { %> <%=DALNameSpace%> {<%=DALGuid%>} @@ -378,7 +386,7 @@ <% } %> <% } %> - <% if ( (IncludeWebLibrary || IncludeWebsite) && ComponentPattern != MoM.Templates.ComponentPatternType.None ) { %> + <% if ( (IncludeWebLibrary || IncludeWebSecurity || IncludeWebsite) && ComponentPattern != MoM.Templates.ComponentPatternType.None ) { %> <%=ComponentLayerNameSpace%> {<%=ComponentsGuid%>} @@ -986,6 +994,18 @@ <%}%> + <% if (IncludeWebSecurity) { %> + + Code + + + Code + + + Code + + <%}%> + <% if (IncludeWebLibrary) { %> Code Index: VisualStudio/vsnet2005.solution.cst =================================================================== --- VisualStudio/vsnet2005.solution.cst (revision 711) +++ VisualStudio/vsnet2005.solution.cst (working copy) @@ -11,6 +11,7 @@ <%@ Property Name="DALGenericNameSpace" Type="System.String" Category="Data" Description="DAL sql Namespace." %> <%@ Property Name="DALWSNameSpace" Type="System.String" Category="Data" Description="DAL ws Namespace." %> <%@ Property Name="WebLibNameSpace" Type="System.String" Category="Data" Description="Web Library Namespace." %> +<%@ Property Name="WebSecurityLibNameSpace" Type="System.String" Category="Data" Description="Web Security Namespace." %> <%@ Property Name="WebsiteNameSpace" Type="System.String" Category="Data" Description="Website Namespace." %> <%@ Property Name="WinLibNameSpace" Type="System.String" Category="Data" Description="Win Library Namespace." %> <%@ Property Name="UTNameSpace" Type="System.String" Category="Data" Description="UT Namespace." %> @@ -25,12 +26,14 @@ <%@ Property Name="WSGuid" Type="System.String" Category="Context" Description="WS Project Guid" %> <%@ Property Name="UTGuid" Type="System.String" Category="Context" Description="Unit tests Project Guid" %> <%@ Property Name="WebLibGuid" Type="System.String" Category="Context" Description="Web Library Project Guid" %> +<%@ Property Name="WebSecurityLibGuid" Type="System.String" Category="Context" Description="Web Security Project Guid" %> <%@ Property Name="WebsiteGuid" Type="System.String" Category="Context" Description="Website Project Guid" %> <%@ Property Name="WinLibGuid" Type="System.String" Category="Context" Description="Win Library Project Guid" %> <%@ Property Name="IncludeUnitTest" Type="MoM.Templates.UnitTestStyle" Default="NUnit" Category="General" Description="Indicates type of Unit tests to be generated." %> <%@ Property Name="IncludeSqlClient" Type="System.Boolean" Category="Option" Description="" %> <%@ Property Name="IncludeGenericClient" Type="System.Boolean" Category="Option" Description="" %> <%@ Property Name="IncludeWebLibrary" Type="System.Boolean" Category="Option" Description="" %> +<%@ Property Name="IncludeWebSecurity" Type="System.Boolean" Category="Option" Description="" %> <%@ Property Name="IncludeWebsite" Type="System.Boolean" Category="Option" Description="" %> <%@ Property Name="IncludeComponents" Type="System.Boolean" Default="False" Category="Option" Description="Determines whether or not a component library is being used." %> <%@ Property Name="IncludeWebservice" Type="System.Boolean" Category="Option" Description="" %> @@ -71,6 +74,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "<%=WebLibNameSpace%>", "<%=WebLibNameSpace%>\<%=WebLibNameSpace%>.csproj", "{<%=WebLibGuid%>}" EndProject <% } %> +<% if (IncludeWebSecurity) { %> +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "<%=WebSecurityLibNameSpace%>", "<%=WebSecurityLibNameSpace%>\<%=WebSecurityLibNameSpace%>.csproj", "{<%=WebSecurityLibGuid%>}" +EndProject +<% } %> <% if (IncludeWinLibrary) { %> Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "<%=WinLibNameSpace%>", "<%=WinLibNameSpace%>\<%=WinLibNameSpace%>.csproj", "{<%=WinLibGuid%>}" EndProject @@ -204,6 +211,12 @@ {<%=WebLibGuid%>}.Release|Any CPU.ActiveCfg = Release|Any CPU {<%=WebLibGuid%>}.Release|Any CPU.Build.0 = Release|Any CPU <%}%> + <% if (IncludeWebSecurity) { %> + {<%=WebSecurityLibGuid%>}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {<%=WebSecurityLibGuid%>}.Debug|Any CPU.Build.0 = Debug|Any CPU + {<%=WebSecurityLibGuid%>}.Release|Any CPU.ActiveCfg = Release|Any CPU + {<%=WebSecurityLibGuid%>}.Release|Any CPU.Build.0 = Release|Any CPU + <%}%> <% if (IncludeWebsite) { %> {<%=WebsiteGuid%>}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {<%=WebsiteGuid%>}.Debug|Any CPU.Build.0 = Debug|Any CPU @@ -250,6 +263,9 @@ <% if (IncludeWebLibrary) { %> {<%=WebLibGuid%>} = {F3A10C8D-3227-449F-A2CB-014DE2D7F415} <%}%> + <% if (IncludeWebSecurity) { %> + {<%=WebSecurityLibGuid%>} = {F3A10C8D-3227-449F-A2CB-014DE2D7F415} + <%}%> <% if (IncludeWebsite) { %> {<%= WebsiteGuid %>} = {F3A10C8D-3227-449F-A2CB-014DE2D7F415} <% } %> Index: WebLibrarySecurity/EntityMembershipUser.cst =================================================================== --- WebLibrarySecurity/EntityMembershipUser.cst (revision 0) +++ WebLibrarySecurity/EntityMembershipUser.cst (revision 0) @@ -0,0 +1,321 @@ +<%-- +Name: +Author: Charlie Kilian +Description: + +--%> +<%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="./CommonMembershipCode.cs" Inherits="MoM.Templates.CommonMembershipCode" Debug="True" Description="Generates the EntityMembershipUser class." %> +<%@ Assembly Name="System.Data" %> +<%@ Assembly Name="System.Design" %> +<%@ Assembly Name="SchemaExplorer" %> +<%@ Import Namespace="System.Data" %> +<%@ Import Namespace="System.IO" %> +<%@ Import Namespace="System.Collections" %> +<%@ Import Namespace="SchemaExplorer" %> + +<%@ Property Name="BLLNameSpace" Optional="False" Type="System.String" Category="Style" Description="BLL Namespace." %> +<%@ Property Name="DALNameSpace" Optional="False" Type="System.String" Category="Style" Description="DAL Namespace." %> +<%@ Property Name="WebNameSpace" Optional="False" Type="System.String" Category="Style" Description="Web Namespace." %> +#region Using Directives +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Web.Security; +using <%= BLLNameSpace %>; +using <%= DALNameSpace %>; +#endregion + +namespace <%= WebNameSpace %>.Security +{ + /// + /// Exposes and updates membership user information in the membership data store. + /// + [Serializable] + public class EntityMembershipUser : MembershipUser, ISerializable + { + #region Private Declarations + /// + /// Stores the <%= EntityClass %> entity that this instance of EntityMembershipUser uses to store its properties in. + /// + <%= EntityClass %> user; + #endregion + + #region Public Constructors + + /// + /// Creates a new instance of an EntityMembershipUser object with default properties. + /// + public EntityMembershipUser() + { + user = new <%= EntityClass %>(); + } + + /// + /// Creates a new instance of an EntityMembershipUser object with the specified property values. + /// + /// The ProviderName string for the membership user. + /// The Username string for the membership user. + /// The ProviderUserKey identifier for the membership user. + /// The Email string for the membership user. + /// The PasswordQuestion string for the membership user. + /// The Comment string for the membership user. + /// The IsApproved value for the membership user. + /// true to lock out the membership user; otherwise, false. + /// The CreationDateDateTime object for the membership user. + /// The LastLoginDateDateTime object for the membership user. + /// The LastActivityDateDateTime object for the membership user. + /// The LastPasswordChangedDateDateTime object for the membership user. + /// The LastLockoutDateDateTime object for the membership user. + public EntityMembershipUser( + string providerName, + string name, + Object providerUserKey, + string email, + string passwordQuestion, + string comment, + bool isApproved, + bool isLockedOut, + DateTime creationDate, + DateTime lastLoginDate, + DateTime lastActivityDate, + DateTime lastPasswordChangedDate, + DateTime lastLockoutDate) + { + if ( providerName != ProviderName ) + throw new MembershipCreateUserException( "Provider must be EntityMembershipProvider to create a EntityMembershipUser" ); + + if ( !(providerUserKey is <%= GetPKType("Membership") %>) ) + throw new MembershipCreateUserException( "ProviderUserKey must be of type <%= GetPKType("Membership") %>" ); + + user = new <%= EntityClass %>(); + user.<%= GetMappedColumn("Username") %> = name; + user.<%= GetMappedColumn("ProviderUserKey") %> = (<%= GetPKType("Membership") %>) providerUserKey; + user.<%= GetMappedColumn("Email") %> = email; + user.<%= GetMappedColumn("PasswordQuestion") %> = passwordQuestion; + user.<%= GetMappedColumn("Comment") %> = comment; + user.<%= GetMappedColumn("IsApproved") %> = <%=GetBoolExp(IsApprovedType, "isApproved")%>; + user.<%= GetMappedColumn("IsLockedOut") %> = <%=GetBoolExp(IsLockedOutType, "isLockedOut")%>; + user.<%= GetMappedColumn("CreationDate") %> = creationDate; + user.<%= GetMappedColumn("LastLoginDate") %> = lastLoginDate; + user.<%= GetMappedColumn("LastActivityDate") %> = lastActivityDate; + user.<%= GetMappedColumn("LastPasswordChangedDate") %> = lastPasswordChangedDate; + user.<%= GetMappedColumn("LastLockoutDate") %> = lastLockoutDate; + user.AcceptChanges(); + } + + /// + /// Creates a new instance of an EntityMembershipUser object from the specified <%= EntityClass %> object. + /// + /// The <%= EntityClass %> object from which to create an EntityMembershipUser + public EntityMembershipUser(<%= EntityClass %> user) + { + this.user = user; + } + + #endregion + + #region Public Properties + + /// + /// Returns the <%= EntityClass %> object that this instance of EntityMembershipUser uses to store its values. + /// + public <%= EntityClass %> UserEntity + { + get { return user; } + set { user = value; } + } + + /// + /// Gets or sets application-specific information for the membership user. + /// + public override string Comment + { + get { return user.<%= GetMappedColumn("Comment") %>; } + set { user.<%= GetMappedColumn("Comment") %> = value; } + } + + /// + /// Gets the date and time when the user was added to the membership data store. + /// + public override DateTime CreationDate + { + get { return (DateTime)user.<%= GetMappedColumn("CreationDate") %>; } + } + + /// + /// Gets or sets the e-mail address for the membership user. + /// + public override string Email + { + get { return user.<%= GetMappedColumn("Email") %>; } + set { user.<%= GetMappedColumn("Email") %> = value; } + } + + /// + /// Gets or sets whether the membership user can be authenticated. + /// + public override bool IsApproved + { + get { return user.<%= GetMappedColumn("IsApproved") %> == <%=GetBoolExp(IsApprovedType, true)%>; } + set { user.<%= GetMappedColumn("IsApproved") %> = <%=GetBoolExp(IsApprovedType, "value")%>; } + } + + /// + /// Gets a value indicating whether the membership user is locked out and unable to be validated. + /// + public override bool IsLockedOut + { + get { return user.<%= GetMappedColumn("IsLockedOut") %> == <%=GetBoolExp(IsLockedOutType, true)%>; } + } + + /// + /// Gets or sets the date and time when the membership user was last authenticated or accessed the application. + /// + public override DateTime LastActivityDate + { + get + { + if ( user.<%= GetMappedColumn("LastActivityDate") %> == null ) + return (DateTime)user.<%= GetMappedColumn("CreationDate") %>; + return (DateTime)user.<%= GetMappedColumn("LastActivityDate") %>.Value; + } + set + { + user.<%= GetMappedColumn("LastActivityDate") %> = value; + } + } + + /// + /// Gets the most recent date and time that the membership user was locked out. + /// + public override DateTime LastLockoutDate + { + get + { + if ( user.<%= GetMappedColumn("LastLockoutDate") %> == null ) + return DateTime.MinValue; + return (DateTime)user.<%= GetMappedColumn("LastLockoutDate") %>.Value; + } + } + + /// + /// Gets or sets the date and time when the user was last authenticated. + /// + public override DateTime LastLoginDate + { + get + { + if ( user.<%= GetMappedColumn("LastLoginDate") %> == null ) + return (DateTime)user.<%= GetMappedColumn("CreationDate") %>; + return (DateTime)user.<%= GetMappedColumn("LastLoginDate") %>.Value; + } + set + { + user.<%= GetMappedColumn("LastLoginDate") %> = value; + } + } + + /// + /// Gets the date and time when the membership user's password was last updated. + /// + public override DateTime LastPasswordChangedDate + { + get + { + if ( user.<%= GetMappedColumn("LastPasswordChangedDate") %> == null ) + return (DateTime)user.<%= GetMappedColumn("CreationDate") %>; + return (DateTime)user.<%= GetMappedColumn("LastPasswordChangedDate") %>.Value; + } + } + + /// + /// Gets the password question for the membership user. + /// + public override string PasswordQuestion + { + get { return user.<%= GetMappedColumn("PasswordQuestion") %>; } + } + + /// + /// Gets the name of the membership provider that stores and retrieves user information for the membership user. + /// Always returns the string "EntityMembershipProvider". + /// + public override string ProviderName + { + get + { + return "EntityMembershipProvider"; + } + } + + /// + /// Gets the user identifier from the membership data source for the user. + /// + public override object ProviderUserKey + { + get + { + return user.<%= GetMappedColumn("ProviderUserKey") %>; + } + } + + /// + /// Gets the logon name of the membership user. + /// + public override string UserName + { + get { return user.<%= GetMappedColumn("UserName") %>; } + } + + + #endregion + + #region Public Methods + + /// + /// Clears the locked-out state of the user so that the membership user can be validated. + /// + /// true if the user was successfully unlocked; otherwise false. + public override bool UnlockUser() + { + try + { + user.<%= GetMappedColumn("IsLockedOut") %> = <%=GetBoolExp(IsLockedOutType, false)%>; + DataRepository.<%= EntityClass %>Provider.Save(user); + return true; + } + catch ( Exception ) + { + return false; + } + } + + #endregion + + #region ISerializable + + /// + /// Constructor used during deserialization. + /// + /// A SerializationInfo object containing the information required to serialize the EntityMembershipUser. + /// A StreamingContext object containing the source and destination of the serialized stream associated with the EntityMembershipUser. + protected EntityMembershipUser(SerializationInfo info, StreamingContext ctxt) + { + user = (<%= EntityClass %>) info.GetValue( "User", typeof( <%= EntityClass %> ) ); + } + + /// + /// Populates a SerializationInfo with the data needed to serialize the EntityMembershipUser object. + /// + /// The SerializationInfo to populate with data. + /// The destination (see StreamingContext) for this serialization. + public void GetObjectData(SerializationInfo info, StreamingContext ctxt) + { + info.AddValue( "User", user ); + } + + #endregion + } +} Index: WebLibrarySecurity/fieldNameMap.txt =================================================================== --- WebLibrarySecurity/fieldNameMap.txt (revision 0) +++ WebLibrarySecurity/fieldNameMap.txt (revision 0) @@ -0,0 +1,18 @@ +ApplicationName:applicationName +Comment:comment +CreationDate:creationDate +Email:email +FailedPasswordAttemptCount:failedPasswordAttemptCount +FailedPasswordAttemptWindowStart:failedPasswordAttemptWindowStart +FailedPasswordAnswerAttemptCount:failedPasswordAnswerAttemptCount +FailedPasswordAnswerAttemptWindowStart:failedPasswordAnswerAttemptWindowStart +IsApproved:isApproved +IsLockedOut:isLockedOut +LastActivityDate:lastActivityDate +LastLockoutDate:lastLockoutDate +LastLoginDate:lastLoginDate +LastPasswordChangedDate:lastPasswordChangedDate +PasswordQuestion:passwordQuestion +PasswordAnswer:passwordAnswer +ProviderUserKey:id +UserName:username \ No newline at end of file Index: WebLibrarySecurity/CommonMembershipCode.cs =================================================================== --- WebLibrarySecurity/CommonMembershipCode.cs (revision 0) +++ WebLibrarySecurity/CommonMembershipCode.cs (revision 0) @@ -0,0 +1,442 @@ +using CodeSmith.Engine; +using SchemaExplorer; +using System; +using System.Windows.Forms.Design; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Data.SqlClient; +using System.Design; +using System.Text; +using System.Text.RegularExpressions; +using System.IO; +using System.Diagnostics; + + +namespace MoM.Templates +{ + /// + /// Summary description for Class1 + /// + public class CommonMembershipCode : CommonSqlCode //CodeTemplate + { + private DbType _isApprDbType; + private DbType _isLockedOutDbType; + private bool _initAttrRun; + + public CommonMembershipCode() + { + _initAttrRun = false; + } + + private void InitAttrTypes() + { + if(!_initAttrRun) + { + _isApprDbType = DbType.Boolean; + _isLockedOutDbType = DbType.Boolean; + + string aprCol = GetMappedColumn("IsApproved").ToLower(); + string loCol = GetMappedColumn("IsLockedOut").ToLower(); + + foreach (ColumnSchema sch in MembershipTable.Columns) + { + if(sch.Name.ToLower() == aprCol) + _isApprDbType = sch.DataType; + if(sch.Name.ToLower() == loCol) + _isLockedOutDbType = sch.DataType; + } + } + } + + #region Copied from CommonSqlCode.cs + + private string aliasFilePath = ""; + + [Editor( typeof( System.Windows.Forms.Design.FileNameEditor ), typeof( System.Drawing.Design.UITypeEditor ) )] + [Category( "09. Code style - Advanced" )] + [OptionalAttribute] + [DefaultValue( "" )] + [Description( "Optional File Path to a table/object alias file." )] + public string AliasFilePath + { + get { return this.aliasFilePath; } + set { this.aliasFilePath = value; } + } + + /// + /// Convert database types to C# types + /// + /// Column or parameter + /// The C# (rough) equivalent of the field's data type + public string GetCSType(DataObjectBase field) + { + if ( field.NativeType.ToLower() == "real" ) + return "System.Single" + ( field.AllowDBNull?"?":"" ); + else if ( field.NativeType.ToLower() == "xml" ) + return "string"; + //else if (field.NativeType.ToLower() == "xml") + // return "System.Xml.XmlNode"; + else if ( !IsCSReferenceDataType( field ) && field.AllowDBNull ) + return field.SystemType.ToString() + "?"; + else + return field.SystemType.ToString(); + //return GetCSType(field.DataType); + } + + /// + /// Returns true if the column is represented as a reference data type + /// rather than a value type. In other words, the C# code can set a + /// column of this data type to 'null' + /// + public bool IsCSReferenceDataType(DataObjectBase column) + { + if (column.NativeType.ToLower() == "real") + return false; + else if (column.NativeType.ToLower() == "xml") + return true; + else + { + DbType dataType = column.DataType; + switch (dataType) + { + case DbType.AnsiString: + case DbType.AnsiStringFixedLength: + case DbType.String: + case DbType.StringFixedLength: + case DbType.Binary: + return true; + + case DbType.Boolean: + case DbType.Guid: + case DbType.Byte: + case DbType.Currency: + case DbType.Date: + case DbType.DateTime: + case DbType.Decimal: + case DbType.Double: + case DbType.Int16: + case DbType.Int32: + case DbType.Int64: + case DbType.Object: + case DbType.Single: + case DbType.Time: + case DbType.VarNumeric: + return false; + + default: + return false; + } + } + } + + /// + /// Transform a name into a public class property name. + /// + public string GetPropertyName(string name) + { + name = Regex.Replace(name, @"[\W]", ""); + name = name.TrimStart(new char[] {'_', '-', '+', '=', '*'}); + name = GetPascalCaseName(name); + + if (Regex.IsMatch(name, @"^[\d]")) + name="Data" + name; + return name; + } + + /// + /// Get the Pascal cased version of a name. + /// + /// Name to be changed + /// PascalCased version of the name + public string GetPascalCaseName(string name) + { + return name.Substring(0, 1).ToUpper() + name.Substring(1); + } + + #endregion + + private ColumnSchema _entityMembershipUserPrimaryKey = null; + + [Category("10. WebLibrary.Security - Optional")] + [OptionalAttribute] + [DefaultValue("")] + [Description("Primary key column from the table that will become the EntityMembershipUser's user entity.")] + public ColumnSchema EntityMembershipUserPKCol + { + get + { + return this._entityMembershipUserPrimaryKey; + } + set + { + _entityMembershipUserPrimaryKey = value; + } + } + + + private string _membershipUserMapFile; + + [Editor(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(System.Drawing.Design.UITypeEditor))] + [Category("10. WebLibrary.Security - Optional")] + [OptionalAttribute] + [DefaultValue("")] + [Description("Optional File Path to a MembershipUserProperty/EntityProperty alias file")] + public string MembershipUserMapFile + { + get + { + return this._membershipUserMapFile; + } + set + { + _membershipUserMapFile = value; + } + } + + private bool _membershipUseMD5 = false; + + [Category("10. WebLibrary.Security - Optional")] + [Description("Use MD5 hash for passwords. False defaults to SHA1.")] + public bool UseMD5Hash + { + get + { + return this._membershipUseMD5; + } + set + { + _membershipUseMD5 = value; + } + } + + public TableSchema MembershipTable + { + get + { + return EntityMembershipUserPKCol.Table; + } + } + + private Hashtable membershipUserMap = null; + + public string GetEntityAlias(string providerType) + { + if ( providerType == "Membership" ) + { + return GetClassName(EntityMembershipUserPKCol.Table); + } + + return null; + } + + protected string EntityClass + { + get + { + return GetEntityAlias( "Membership" ); + } + } + + protected string EntityKeyType + { + get + { + return EntityMembershipUserPKCol.GetType().ToString(); + } + } + + public DbType IsApprovedType + { + get + { + InitAttrTypes(); + return _isApprDbType; + } + } + + public DbType IsLockedOutType + { + get + { + InitAttrTypes(); + return _isLockedOutDbType; + } + } + + public string GetBoolExp(DbType type, bool expected) + { + if(type == DbType.Boolean) + { + if(expected) return "true"; + else return "false"; + } + else + { + if(expected) return "1"; + else return "0"; + } + } + + public string GetBoolExp(DbType type, string subj) + { + if(type == DbType.Boolean) + { + return subj; + } + else + { + string cast = GetCast(type); + return subj +"?" + cast + "1:"+ cast +"0"; + } + } + + protected string GetCast(DbType type) + { + switch (type) + { + case DbType.AnsiString: + case DbType.AnsiStringFixedLength: + case DbType.String: + case DbType.StringFixedLength: + return "(string)"; + + case DbType.Boolean: + return "(bool)"; + + //Answer modified was just 0 + case DbType.Byte: + return "(byte)"; + + case DbType.Decimal: + return "(float)"; + + case DbType.Double: + return "(double)"; + + case DbType.Int16: + return "(short)"; + + case DbType.Int32: + return "(int)"; + + case DbType.Int64: + return "(long)"; + + case DbType.SByte: + return "(sbyte)"; + + case DbType.UInt16: + return "(ushort)"; + + case DbType.UInt32: + return "(uint)"; + + case DbType.UInt64: + return "(ulong)"; + } + return ""; + } + + /// + /// This function gets the name of the property in the user entity that corresponds to + /// the selected MembershipUser property name. + /// + public string GetMappedColumn(string propertyName) + { + // If the mappings aren't loaded yet, and the filepath exists, then load the hashtable of mappings + if ( membershipUserMap == null && File.Exists( MembershipUserMapFile ) ) + { + membershipUserMap = new Hashtable(); + using ( StreamReader sr = new StreamReader( MembershipUserMapFile ) ) + { + string line; + while ( ( line = sr.ReadLine() ) != null ) + { + if ( line.IndexOf( ":" ) > 0 ) + { + string lvalue = line.Split( ':' )[0]; + string rvalue = line.Split( ':' )[1]; + + if ( IsValidLValue( "Membership", lvalue ) && IsValidRValue( "Membership", rvalue ) ) + { + membershipUserMap.Add( lvalue, GetPropertyName(rvalue) ); + } + } + } + } + } + + // See if our tablename is in the aliases hashtable, and if so, replace it. + if ( membershipUserMap != null ) + { + IDictionaryEnumerator mapping = membershipUserMap.GetEnumerator(); + while ( mapping.MoveNext() ) + { + if ( propertyName.ToLower() == mapping.Key.ToString().ToLower() ) + { + propertyName = mapping.Value.ToString(); + break; + } + } + } + + return propertyName; + } + + + private bool IsValidLValue(string providerType, string lvalue) + { + if ( providerType == "Membership" ) + { + switch ( lvalue ) + { + case "ApplicationName": + case "Comment": + case "CreationDate": + case "Email": + case "FailedPasswordAttemptCount": + case "FailedPasswordAttemptWindowStart": + case "FailedPasswordAnswerAttemptCount": + case "FailedPasswordAnswerAttemptWindowStart": + case "IsApproved": + case "IsLockedOut": + case "LastActivityDate": + case "LastLockoutDate": + case "LastLoginDate": + case "LastPasswordChangedDate": + case "PasswordQuestion": + case "PasswordAnswer": + case "ProviderUserKey": + case "UserName": + return true; + } + } + + return false; + } + + + private bool IsValidRValue(string providerType, string rvalue) + { + if ( providerType == "Membership" ) + { + if ( EntityMembershipUserPKCol.Table.Columns[rvalue] != null ) + return true; + } + + return false; + } + + public string GetPKType(string providerType) + { + if ( providerType == "Membership" ) + { + return GetCSType( EntityMembershipUserPKCol.Table.PrimaryKey.MemberColumns[0] ); + } + + return null; + } + + } +} \ No newline at end of file Index: WebLibrarySecurity/EntityMembershipProperty.cst =================================================================== --- WebLibrarySecurity/EntityMembershipProperty.cst (revision 0) +++ WebLibrarySecurity/EntityMembershipProperty.cst (revision 0) @@ -0,0 +1,111 @@ +<%-- +Name: +Author: Charlie Kilian +Description: + +--%> +<%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="./CommonMembershipCode.cs" Inherits="MoM.Templates.CommonMembershipCode" Debug="True" Description="Generates the EntityMembershipUser class." %> +<%@ Assembly Name="System.Data" %> +<%@ Assembly Name="System.Design" %> +<%@ Assembly Name="SchemaExplorer" %> +<%@ Import Namespace="System.Data" %> +<%@ Import Namespace="System.IO" %> +<%@ Import Namespace="System.Collections" %> +<%@ Import Namespace="SchemaExplorer" %> + +<%@ Property Name="BLLNameSpace" Optional="False" Type="System.String" Category="Style" Description="BLL Namespace." %> +<%@ Property Name="DALNameSpace" Optional="False" Type="System.String" Category="Style" Description="DAL Namespace." %> +<%@ Property Name="WebNameSpace" Optional="False" Type="System.String" Category="Style" Description="Web Namespace." %> +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; +using System.Web; +using System.Web.UI; +using System.Web.Security; +using System.Web.UI.WebControls; +using System.Reflection; +using <%= BLLNameSpace %>; +using <%= DALNameSpace %>; + +namespace <%= WebNameSpace %>.Security +{ + /// + /// Displays the value of the specified EntityMembershipUser property. + /// + [DefaultProperty( "Text" )] + [ToolboxData( "<{0}:EntityMembershipProperty runat=server>" )] + public class EntityMembershipProperty : WebControl + { + private <%= EntityClass %>Column _propertyName; + private string _formatString = ""; + + /// + /// The property to display + /// + [System.ComponentModel.Bindable( true )] + [Category( "Misc" )] + [DefaultValue( "" )] + [Localizable( true )] + public <%= EntityClass %>Column PropertyName + { + get { return _propertyName; } + set { _propertyName = value; } + } + + /// + /// The string to use to format the property + /// + [System.ComponentModel.Bindable( true )] + [Category( "Misc" )] + [DefaultValue( "" )] + [Localizable( true )] + public string FormatString + { + get { return _formatString; } + set { _formatString = value; } + } + + /// + /// Renders the contents of the control to the specified writer. + /// + /// A HtmlTextWriter that represents the output stream to render HTML content on the client. + protected override void RenderContents(HtmlTextWriter output) + { + MembershipUser member = Membership.GetUser(); + if ( member == null ) + return; + + if ( !( member is EntityMembershipUser ) ) + throw new Exception( "EntityMembershipProperty requires the current membership provider to be EntityMembershipProvider" ); + + <%= EntityClass %> user = ((EntityMembershipUser) member).UserEntity; + string propname = _propertyName.ToString(); + + Type type = user.GetType(); + object objvalue = type.InvokeMember(propname, BindingFlags.GetProperty, null, user, null); + + if ( objvalue == null ) + return; + + string strvalue = ""; + + switch ( objvalue.GetType().ToString() ) + { + case "System.Int32": + strvalue = ((int) objvalue).ToString(_formatString); + break; + + case "System.DateTime": + strvalue = ((DateTime) objvalue).ToString(_formatString); + break; + + default: + strvalue = objvalue.ToString(); + break; + } + + output.Write( strvalue ); + } + } +} Index: WebLibrarySecurity/EntityMembershipProvider.cst =================================================================== --- WebLibrarySecurity/EntityMembershipProvider.cst (revision 0) +++ WebLibrarySecurity/EntityMembershipProvider.cst (revision 0) @@ -0,0 +1,1062 @@ +<%-- +Name: +Author: Charlie Kilian +Description: + +--%> +<%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="./CommonMembershipCode.cs" Inherits="MoM.Templates.CommonMembershipCode" Debug="True" Description="Generates the EntityMembershipUser class." %> +<%@ Assembly Name="System.Data" %> +<%@ Assembly Name="System.Design" %> +<%@ Assembly Name="SchemaExplorer" %> +<%@ Import Namespace="System.Data" %> +<%@ Import Namespace="System.IO" %> +<%@ Import Namespace="System.Collections" %> +<%@ Import Namespace="SchemaExplorer" %> + +<%@ Property Name="BLLNameSpace" Optional="False" Type="System.String" Category="Style" Description="BLL Namespace." %> +<%@ Property Name="DALNameSpace" Optional="False" Type="System.String" Category="Style" Description="DAL Namespace." %> +<%@ Property Name="WebNameSpace" Optional="False" Type="System.String" Category="Style" Description="Web Namespace." %> + +<% +// string entityClassName = GetClassName(SourceTable); +%> + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Configuration; +using System.Configuration.Provider; +using System.Security.Cryptography; +using System.Text; +using System.Web.Security; +using System.Web.Configuration; +using <%= BLLNameSpace %>; +using <%= DALNameSpace %>; + +namespace <%= WebNameSpace %>.Security +{ + public class EntityMembershipProvider : MembershipProvider + { + #region Variable Declarations + + /// + /// Stores the value of the ApplicationName configuration property + /// required to implement MembershipProvider. + /// + private string _applicationName; + + /// + /// Stores the value of the EnablePasswordReset configuration property + /// required to implement MembershipProvider. + /// + private bool _enablePasswordReset; + + /// + /// Stores the value of the EnablePasswordRetrieval configuration property + /// required to implement MembershipProvider. + /// + private bool _enablePasswordRetrieval; + + /// + /// Stores the value of the MaxInvalidPasswordAttempts configuration property + /// required to implement MembershipProvider. + /// + private int _maxInvalidPasswordAttempts; + + /// + /// Stores the value of the MinRequiredNonAlphanumericCharacters configuration property + /// required to implement MembershipProvider. + /// + private int _minRequiredNonAlphanumericCharacters; + + /// + /// Stores the value of the MinRequiredPasswordLength configuration property + /// required to implement MembershipProvider. + /// + private int _minRequiredPasswordLength; + + /// + /// Stores the value of the PasswordAttemptWindow configuration property + /// required to implement MembershipProvider. + /// + private int _passwordAttemptWindow; + + /// + /// Stores the value of the PasswordFormat configuration property + /// required to implement MembershipProvider. + /// + private MembershipPasswordFormat _passwordFormat; + + /// + /// Stores the value of the PasswordStrengthRegularExpression configuration property + /// required to implement MembershipProvider. + /// + private string _passwordStrengthRegularExpression; + + /// + /// Stores the value of the RequiresQuestionAndAnswer configuration property + /// required to implement MembershipProvider. + /// + private bool _requiresQuestionAndAnswer; + + /// + /// Stores the value of the RequiresUniqueEmail configuration property + /// required to implement MembershipProvider. + /// + private bool _requiresUniqueEmail; + + /// + /// Stores the value of the MachineKey configuration property + /// required to implement MembershipProvider. + /// + private MachineKeySection _machineKey; + + #endregion + + #region Public Constructors and Initialialization + + /// + /// Initializes the provider. + /// + /// The friendly name of the provider. For EntityMembershipProvider, this is always the string "EntityMembershipProvider". + /// A collection of the name/value pairs representing the attributes specified in the configuration for this provider. + public override void Initialize(string name, NameValueCollection config) + { + _applicationName = Convert.ToString( GetConfigValue( config["applicationName"], System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath ) ); + _enablePasswordReset = Convert.ToBoolean( GetConfigValue( config["enablePasswordReset"], "true" ) ); + _enablePasswordRetrieval = Convert.ToBoolean( GetConfigValue( config["enablePasswordRetrieval"], "true" ) ); + _maxInvalidPasswordAttempts = Convert.ToInt32( GetConfigValue( config["maxInvalidPasswordAttempts"], "5" ) ); + _minRequiredNonAlphanumericCharacters = Convert.ToInt32( GetConfigValue( config["minRequiredNonAlphanumericCharacters"], "1" ) ); + _minRequiredPasswordLength = Convert.ToInt32( GetConfigValue( config["minRequiredPasswordLength"], "7" ) ); + _passwordAttemptWindow = Convert.ToInt32( GetConfigValue( config["passwordAttemptWindow"], "10" ) ); + _passwordStrengthRegularExpression = Convert.ToString( GetConfigValue( config["passwordStrengthRegularExpression"], "" ) ); + _requiresQuestionAndAnswer = Convert.ToBoolean( GetConfigValue( config["requiresQuestionAndAnswer"], "true" ) ); + _requiresUniqueEmail = Convert.ToBoolean( GetConfigValue( config["requiresUniqueEmail"], "true" ) ); + + string pformat = config["passwordFormat"]; + if ( pformat == null ) + pformat = "Hashed"; + + switch ( pformat ) + { + case "Hashed": + _passwordFormat = MembershipPasswordFormat.Hashed; + break; + + case "Encrypted": + _passwordFormat = MembershipPasswordFormat.Encrypted; + break; + + case "Clear": + _passwordFormat = MembershipPasswordFormat.Clear; + break; + + default: + throw new ProviderException( "Password format not supported." ); + } + + <% if(!UseMD5Hash){ %> + // FIXME: I have no idea what the next section does + // See: http://msdn2.microsoft.com/en-us/library/6tc47t75.aspx + + // Get encryption and decryption key information from the configuration. + Configuration cfg = WebConfigurationManager.OpenWebConfiguration( System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath ); + _machineKey = (MachineKeySection) cfg.GetSection( "system.web/machineKey" ); + + if ( _machineKey.ValidationKey.Contains( "AutoGenerate" ) && + PasswordFormat != MembershipPasswordFormat.Clear ) + { + throw new ProviderException( "Hashed or Encrypted passwords are not supported with auto-generated keys." ); + } + + <%}%> + + + } + + #endregion + + #region Public Properties + + /// + /// The name of the application using the EntityMembershipProvider. + /// + public override string ApplicationName + { + get { return _applicationName; } + set { _applicationName = value; } + } + + /// + /// Gets a brief, friendly description suitable for display in administrative tools + /// or other user interfaces (UIs). + /// + public override string Description + { + get { return "EntityMembershipProvider, a typed MembershipProvider generated by .netTiers"; } + } + + /// + /// Indicates whether the EntityMembershipProvider is configured to allow users to reset their passwords. + /// + public override bool EnablePasswordReset + { + get { return _enablePasswordReset; } + } + + /// + /// Indicates whether the EntityMembershipProvider is configured to allow users to retrieve their passwords. + /// + public override bool EnablePasswordRetrieval + { + get { return _enablePasswordRetrieval; } + } + + /// + /// Gets the number of invalid password or password-answer attempts allowed before the + /// membership user is locked out. + /// + public override int MaxInvalidPasswordAttempts + { + get { return _maxInvalidPasswordAttempts; } + } + + /// + /// Gets the minimum number of special characters that must be present in a valid password. + /// + public override int MinRequiredNonAlphanumericCharacters + { + get { return _minRequiredNonAlphanumericCharacters; } + } + + /// + /// Gets the minimum length required for a password. + /// + public override int MinRequiredPasswordLength + { + get { return _minRequiredPasswordLength; } + } + + /// + /// Gets the friendly name used to refer to the provider during configuration. + /// Always returns the string "EntityMembershipProvider". + /// + public override string Name + { + get { return "EntityMembershipProvider"; } + } + + /// + /// Gets the number of minutes in which a maximum number of invalid password or + /// password-answer attempts are allowed before the membership user is locked out. + /// + public override int PasswordAttemptWindow + { + get { return _passwordAttemptWindow; } + } + + /// + /// Gets a value indicating the format for storing passwords in the membership data store. + /// + public override MembershipPasswordFormat PasswordFormat + { + get { return _passwordFormat; } + } + + /// + /// Gets the regular expression used to evaluate a password. + /// + public override string PasswordStrengthRegularExpression + { + get { return _passwordStrengthRegularExpression; } + } + + /// + /// Gets a value indicating whether the EntityMembershipProvider is configured + /// to require the user to answer a password question for password reset and retrieval. + /// + public override bool RequiresQuestionAndAnswer + { + get { return _requiresQuestionAndAnswer; } + } + + /// + /// Gets a value indicating whether the EntityMembershipProvider is configured + /// to require a unique e-mail address for each user name. + /// + public override bool RequiresUniqueEmail + { + get { return _requiresUniqueEmail; } + } + + #endregion + + #region Public Methods + + /// + /// Processes a request to update the password for a membership user. + /// + /// The user to update the password for. + /// The current password for the specified user. + /// The new password for the specified user. + /// true if the password was updated successfully; otherwise, false. + /// Takes, as input, a user name, a current password, and a new password, and updates the password in the data source if the supplied user name and current password are valid. + public override bool ChangePassword(string username, string oldPassword, string newPassword) + { + // attempt to validate old password + if ( !ValidateUser( username, oldPassword ) ) + return false; + + // attempt to validate the strength of the new password + ValidatePasswordEventArgs args = new ValidatePasswordEventArgs( username, newPassword, true ); + OnValidatingPassword( args ); + + if ( args.Cancel ) + { + if ( args.FailureInformation != null ) + throw args.FailureInformation; + else + throw new MembershipPasswordException( "Change password canceled due to new password validation failure." ); + } + + try + { + // retrieve the user entity and set the new password + // retrieve the user entity and set the new password + <%= EntityClass %> user = GetUserByUsername(username); + if ( user == null ) + return false; + user.<%= GetMappedColumn("Password") %> = EncodePassword( newPassword ); + user.<%= GetMappedColumn("LastPasswordChangedDate") %> = DateTime.Now; + DataRepository.<%= EntityClass %>Provider.Save(user); + return true; + } + catch ( Exception ) + { + return false; + } + } + + /// + /// Processes a request to update the password question and answer for a membership user. + /// + /// The user to change the password question and answer for. + /// The password for the specified user. + /// The new password question for the specified user. + /// The new password answer for the specified user. + /// true if the password question and answer are updated successfully; otherwise, false. + public override bool ChangePasswordQuestionAndAnswer( + string username, + string password, + string newPasswordQuestion, + string newPasswordAnswer) + { + if ( !ValidateUser( username, password ) ) + return false; + + try + { + // retrieve the user entity and set the new password + <%= EntityClass %> user = GetUserByUsername(username); + if ( user == null ) + return false; + user.<%= GetMappedColumn("PasswordQuestion") %> = newPasswordQuestion; + user.<%= GetMappedColumn("PasswordAnswer") %> = newPasswordAnswer; + DataRepository.<%= EntityClass %>Provider.Save( user ); + return true; + } + catch ( Exception ) + { + return false; + } + } + + /// + /// Adds a new membership user to the data source. + /// + /// The user name for the new user. + /// The password for the new user. + /// The e-mail address for the new user. + /// The password question for the new user. + /// The password answer for the new user + /// Whether or not the new user is approved to be validated. + /// The unique identifier from the membership data source for the user. + /// A MembershipCreateStatus enumeration value indicating whether the user was created successfully. + /// A MembershipUser object populated with the information for the newly created user. + public override MembershipUser CreateUser( + string username, + string password, + string email, + string passwordQuestion, + string passwordAnswer, + bool isApproved, + Object providerUserKey, + out MembershipCreateStatus status) + { + // make sure the selected password passes validation + ValidatePasswordEventArgs args = new ValidatePasswordEventArgs( username, password, true ); + OnValidatingPassword( args ); + + if ( args.Cancel ) + { + status = MembershipCreateStatus.InvalidPassword; + return null; + } + + + // if the email address is supposed to be unique, + // check to make sure it doesn't already exist + if ( RequiresUniqueEmail && GetUserNameByEmail( email ) != "" ) + { + status = MembershipCreateStatus.DuplicateEmail; + return null; + } + + // check to see if the username already exists + if ( GetUser( username, false ) != null ) + { + status = MembershipCreateStatus.DuplicateUserName; + return null; + } + + // if there was no User ID supplied, get one now + // otherwise check to make sure the supplied ID is valid + if ( providerUserKey == null ) + { + <% + if ( GetPKType("Membership") == "System.Guid" ) + { + %> + providerUserKey = Guid.NewGuid(); + <% + } + else + { + %> + providerUserKey = new <%= GetPKType("Membership") %>(); + <% + } + %> + } + else + { + if ( !( providerUserKey is <%= GetPKType("Membership") %> ) ) + { + status = MembershipCreateStatus.InvalidProviderUserKey; + return null; + } + } + + <%= EntityClass %> user = new <%= EntityClass %>(); + user.<%= GetMappedColumn("ProviderUserKey") %> = (<%= GetPKType("Membership") %>) providerUserKey; + user.<%= GetMappedColumn("Username") %> = username; + user.<%= GetMappedColumn("ApplicationName") %> = _applicationName; + user.<%= GetMappedColumn("Email") %> = email; + user.<%= GetMappedColumn("Comment") %> = null; + user.<%= GetMappedColumn("Password") %> = EncodePassword( password ); + user.<%= GetMappedColumn("PasswordQuestion") %> = passwordQuestion; + user.<%= GetMappedColumn("PasswordAnswer") %> = passwordAnswer; + user.<%= GetMappedColumn("IsApproved") %> = <%=GetBoolExp(IsApprovedType, "isApproved")%>; + user.<%= GetMappedColumn("LastActivityDate") %> = null; + user.<%= GetMappedColumn("LastLoginDate") %> = null; + user.<%= GetMappedColumn("LastPasswordChangedDate") %> = null; + user.<%= GetMappedColumn("CreationDate") %> = DateTime.Now; + user.<%= GetMappedColumn("IsLockedOut") %> = <%=GetBoolExp(IsLockedOutType, false)%>; + user.<%= GetMappedColumn("LastLockoutDate") %> = null; + user.<%= GetMappedColumn("FailedPasswordAnswerAttemptCount") %> = 0; + user.<%= GetMappedColumn("FailedPasswordAnswerAttemptWindowStart") %> = null; + + try + { + DataRepository.<%= EntityClass %>Provider.Save(user); + user = null; + status = MembershipCreateStatus.Success; + return GetUser( username, false ); + } + catch ( Exception ) + { + status = MembershipCreateStatus.ProviderError; + return null; + } + } + + /// + /// Removes a user from the membership data source. + /// + /// The name of the user to delete. + /// true to delete data related to the user from the database; false to leave data related to the user in the database. + /// true if the user was successfully deleted; otherwise, false. + public override bool DeleteUser(string username, bool deleteAllRelatedData) + { + try + { + // FIXME: this should all be handled with a transaction object + if ( deleteAllRelatedData ) + { + // FIXME: raise an event to delete all data related to the user + } + + <%= EntityClass %> user = GetUserByUsername(username); + if ( user == null ) + return false; + user.MarkToDelete(); + DataRepository.<%= EntityClass %>Provider.Save(user); + + return true; + } + catch ( Exception ) + { + return false; + } + } + + /// + /// Gets a collection of membership users where the e-mail address contains the specified e-mail address to match. + /// + /// The e-mail address to search for. + /// The index of the page of results to return. pageIndex is zero-based. + /// The size of the page of results to return. + /// The total number of matched users. + /// A MembershipUserCollection collection that contains a page of pageSizeMembershipUser objects beginning at the page specified by pageIndex. + public override MembershipUserCollection FindUsersByEmail( + string emailToMatch, + int pageIndex, + int pageSize, + out int totalRecords) + { + MembershipUserCollection members = new MembershipUserCollection(); + + try + { + // FIXME: use new parameter builder so single quotes are escaped + // FIXME: this will only work if GetPaged methods are generated, need to also code for when they don't exist + string whereClause = "<%= GetMappedColumn("Email") %> = '" + emailToMatch + "' AND <%= GetMappedColumn("ApplicationName") %> = '" + _applicationName + "'"; + TList<<%= EntityClass %>> users = DataRepository.<%= EntityClass %>Provider.GetPaged(whereClause, null, pageIndex, pageSize, out totalRecords); + + foreach ( <%= EntityClass %> user in users ) + { + EntityMembershipUser member = new EntityMembershipUser(user); + members.Add(member); + } + } + catch ( Exception ) + { + totalRecords = 0; + } + + return members; + } + + /// + /// Gets a collection of membership users where the user name contains the specified user name to match. + /// + /// The user name to search for. + /// The index of the page of results to return. pageIndex is zero-based. + /// The size of the page of results to return. + /// The total number of matched users. + /// A MembershipUserCollection collection that contains a page of pageSizeMembershipUser objects beginning at the page specified by pageIndex. + public override MembershipUserCollection FindUsersByName( + string usernameToMatch, + int pageIndex, + int pageSize, + out int totalRecords) + { + MembershipUserCollection members = new MembershipUserCollection(); + + try + { + // FIXME: use new parameter builder so single quotes are escaped + // FIXME: this will only work if GetPaged methods are generated, need to also code for when they don't exist + string whereClause = "UserName = '" + usernameToMatch + "' AND ApplicationName = '" + _applicationName + "'"; + TList<<%= EntityClass %>> users = DataRepository.<%= EntityClass %>Provider.GetPaged( whereClause, null, pageIndex, pageSize, out totalRecords ); + + foreach ( <%= EntityClass %> user in users ) + { + EntityMembershipUser member = new EntityMembershipUser( user ); + members.Add( member ); + } + } + catch ( Exception ) + { + totalRecords = 0; + } + + return members; + } + + /// + /// Gets a collection of all the users in the data source in pages of data. + /// + /// The index of the page of results to return. pageIndex is zero-based. + /// The size of the page of results to return. + /// The total number of matched users. + /// A MembershipUserCollection collection that contains a page of pageSizeMembershipUser objects beginning at the page specified by pageIndex. + public override MembershipUserCollection GetAllUsers( + int pageIndex, + int pageSize, + out int totalRecords) + { + MembershipUserCollection members = new MembershipUserCollection(); + + try + { + // FIXME: use new parameter builder so single quotes are escaped + // FIXME: this will only work if GetPaged methods are generated, need to also code for when they don't exist + string whereClause = "ApplicationName = '" + _applicationName + "'"; + TList<<%= EntityClass %>> users = DataRepository.<%= EntityClass %>Provider.GetPaged( whereClause, null, pageIndex, pageSize, out totalRecords ); + + foreach ( <%= EntityClass %> user in users ) + { + EntityMembershipUser member = new EntityMembershipUser( user ); + members.Add( member ); + } + } + catch ( Exception ) + { + totalRecords = 0; + } + + return members; + } + + /// + /// Gets the number of users currently accessing the application. + /// + /// Returns an integer value that is the count of all the users in the data source where the LastActivityDate is greater than the current date and time minus the UserIsOnlineTimeWindow. The UserIsOnlineTimeWindow is a positive integer value specifying the number of minutes to use when determining whether a user is online. + public override int GetNumberOfUsersOnline() + { + try + { + string whereClause = GetOnlineWhereClause(); + int userCount = 0; + DataRepository.<%= EntityClass %>Provider.GetTotalItems(whereClause, out userCount); + return userCount; + } + catch ( Exception ex ) + { + throw new ProviderException( "An error occured while attempting to determine the number of users online.", ex ); + } + } + + /// + /// Gets the password for the specified user name from the data source. + /// + /// The user to retrieve the password for. + /// The password answer for the user. + /// The password for the specified user name. + public override string GetPassword(string username, string answer) + { + if ( !EnablePasswordRetrieval ) + { + throw new ProviderException( "Password retrieval not enabled." ); + } + + if ( PasswordFormat == MembershipPasswordFormat.Hashed ) + { + throw new ProviderException( "Cannot retrieve Hashed passwords." ); + } + + <%= EntityClass %> user = GetUserByUsername(username); + if ( user == null ) + { + throw new MembershipPasswordException( "The supplied user name is not found." ); + } + + if ( user.<%= GetMappedColumn("IsLockedOut") %> == <%=GetBoolExp(IsLockedOutType, true)%>) + { + throw new MembershipPasswordException( "The supplied user is locked out." ); + } + + if ( RequiresQuestionAndAnswer && !CheckPassword( answer, user.<%= GetMappedColumn("PasswordAnswer") %> ) ) + { + UpdateFailureCount( username ); + throw new MembershipPasswordException( "Incorrect password answer." ); + } + + string password = user.<%= GetMappedColumn("Password") %>; + if ( PasswordFormat == MembershipPasswordFormat.Encrypted ) + { + password = UnEncodePassword( password ); + } + + return password; + } + + /// + /// Gets user information from the data source based on the unique identifier for the membership user. Provides an option to update the last-activity date/time stamp for the user. + /// + /// The unique identifier for the membership user to get information for. + /// true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user. + /// A MembershipUser object populated with the specified user's information from the data source. + public override MembershipUser GetUser(Object providerUserKey, bool userIsOnline) + { + if ( !( providerUserKey is <%= GetPKType("Membership") %> ) ) + throw new ProviderException("ProviderUserKey must be of type <%= GetPKType("Membership") %>."); + + <%= EntityClass %> user = DataRepository.<%= EntityClass %>Provider.GetBy<%= GetMappedColumn("ProviderUserKey") %>( (<%= GetPKType("Membership") %>) providerUserKey ); + + if ( userIsOnline ) + { + user.<%= GetMappedColumn("LastActivityDate") %> = DateTime.Now; + DataRepository.<%= EntityClass %>Provider.Save(user); + } + + EntityMembershipUser member = new EntityMembershipUser( user ); + return member; + } + + /// + /// Gets information from the data source for a user. Provides an option to update the last-activity date/time stamp for the user. + /// + /// The name of the user to get information for. + /// true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user. + /// A MembershipUser object populated with the specified user's information from the data source. + public override MembershipUser GetUser(string username, bool userIsOnline) + { + <%= EntityClass %> user = GetUserByUsername(username); + if ( user == null ) + return null; + + if ( userIsOnline ) + { + user.<%= GetMappedColumn("LastActivityDate") %> = DateTime.Now; + DataRepository.<%= EntityClass %>Provider.Save( user ); + } + + EntityMembershipUser member = new EntityMembershipUser( user ); + return member; + } + + /// + /// Gets the user name associated with the specified e-mail address. + /// + /// The e-mail address to search for. + /// The user name associated with the specified e-mail address. If no match is found, return a null reference + public override string GetUserNameByEmail(string email) + { + // FIXME: what is the correct behavior when email is not unique? + string whereClause = "Email = '" + email + "' AND ApplicationName = '" + _applicationName + "'"; + TList<<%= EntityClass %>> users = DataRepository.<%= EntityClass %>Provider.Find(whereClause); + if ( users.Count == 0 ) + return null; + return users[0].Username; + } + + /// + /// Resets a user's password to a new, automatically generated password. + /// + /// The user to reset the password for. + /// The password answer for the specified user. + /// The new password for the specified user. + public override string ResetPassword(string username, string answer) + { + // FIXME: are these the correct exceptions? + if ( !EnablePasswordReset ) + { + throw new NotSupportedException( "Password reset is not enabled." ); + } + + if ( answer == null && RequiresQuestionAndAnswer ) + { + UpdateFailureCount( username ); + throw new ProviderException( "Password answer required for password reset." ); + } + + <%= EntityClass %> user = GetUserByUsername(username); + if ( user == null ) + { + throw new MembershipPasswordException( "The supplied user name is not found." ); + } + + // FIXME: allow NewPasswordLength to be configurable + string newPassword = System.Web.Security.Membership.GeneratePassword( 8, _minRequiredNonAlphanumericCharacters ); + + ValidatePasswordEventArgs args = new ValidatePasswordEventArgs( username, newPassword, true ); + OnValidatingPassword( args ); + + if ( args.Cancel ) + { + if ( args.FailureInformation != null ) + throw args.FailureInformation; + else + throw new MembershipPasswordException( "Reset password canceled due to password validation failure." ); + } + + if ( RequiresQuestionAndAnswer && !CheckPassword( answer, user.<%= GetMappedColumn("PasswordAnswer") %> ) ) + { + UpdateFailureCount( username ); + throw new MembershipPasswordException( "Incorrect password answer." ); + } + + user.<%= GetMappedColumn("Password") %> = EncodePassword(newPassword); + DataRepository.<%= EntityClass %>Provider.Save(user); + + return newPassword; + } + + /// + /// Clears a lock so that the membership user can be validated. + /// + /// The membership user whose lock status you want to clear. + /// true if the membership user was successfully unlocked; otherwise, false. + public override bool UnlockUser(string userName) + { + <%= EntityClass %> user = GetUserByUsername( userName ); + if ( user == null ) + return false; + + user.<%= GetMappedColumn("IsLockedOut") %> = <%=GetBoolExp(IsLockedOutType, false)%>; + try + { + DataRepository.<%= EntityClass %>Provider.Save(user); + } + catch ( Exception ) + { + return false; + } + + return true; + } + + /// + /// Updates information about a user in the data source. + /// + /// A MembershipUser object that represents the user to update and the updated information for the user. + public override void UpdateUser(MembershipUser user) + { + if ( !( user is EntityMembershipUser ) ) + throw new ProviderException( "EntityMembershipProvider can only update users of type EntityMembershipUser" ); + + EntityMembershipUser member = (EntityMembershipUser) user; + DataRepository.<%= EntityClass %>Provider.Save( member.UserEntity ); + } + + /// + /// Verifies that the specified user name and password exist in the data source. + /// + /// The name of the user to validate. + /// The password for the specified user. + /// true if the specified username and password are valid; otherwise, false. + public override bool ValidateUser(string username, string password) + { + if ( username == null ) + return false; + + if ( password == null ) + return false; + + <%= EntityClass %> user = GetUserByUsername( username ); + if ( user == null ) + return false; + + if ( user.<%= GetMappedColumn("IsApproved") %> != <%=GetBoolExp(IsApprovedType, true)%>) + return false; + + if ( user.<%= GetMappedColumn("IsLockedOut") %> == <%=GetBoolExp(IsLockedOutType, true)%>) + return false; + + if ( !CheckPassword(password, user.<%= GetMappedColumn("Password") %>) ) + { + UpdateFailureCount( username ); + return false; + } + + user.<%= GetMappedColumn("LastLoginDate") %> = DateTime.Now; + DataRepository.<%= EntityClass %>Provider.Save(user); + + return true; + } + + #endregion + + #region Private Methods + + /// + /// Gets a value from the config file if it is not empty or null. + /// + /// The value from the config file to return, if it exists. + /// The value to return if the config file parameter is empty or null. + /// the value of configValue, if it is not empty or null; otherwise, the value of defaultValue + private string GetConfigValue(string configValue, string defaultValue) + { + if ( String.IsNullOrEmpty( configValue ) ) + return defaultValue; + + return configValue; + } + + /// + /// Gets a Where Clause capable of being used with .netTiers EntityProvider's Find method + /// that will restrict results to show only users who are online. + /// + /// a Where Clause that restricts results to show users who are online. + private string GetOnlineWhereClause() + { + TimeSpan onlineSpan = new TimeSpan( 0, System.Web.Security.Membership.UserIsOnlineTimeWindow, 0 ); + DateTime compareTime = DateTime.Now.Subtract( onlineSpan ); + + // FIXME: this is provider specific, use a parameter builder instead + string whereClause = "LastActivityDate > '" + compareTime.ToShortDateString() + " " + compareTime.ToShortTimeString() + "'"; + + return whereClause; + } + + /// + /// Updates the failure count for a membership user. + /// + /// The name of the user for which to update the failure count. + private void UpdateFailureCount(string username) + { + <%= EntityClass %> user = GetUserByUsername( username ); + if ( user == null ) + throw new ProviderException("User not found"); + + user.<%= GetMappedColumn("FailedPasswordAttemptCount") %>++; + DataRepository.<%= EntityClass %>Provider.Save(user); + } + + /// + /// Helper function to check password equivilency regardless of the format the password is stored in. + /// + /// The first password to check + /// The second password to check + /// true if the passwords match; otherwise, false. + private bool CheckPassword(string password, string dbpassword) + { + string pass1 = password; + string pass2 = dbpassword; + + if ( pass1 == null ) + pass1 = ""; + + if ( dbpassword == null ) + pass2 = ""; + + switch ( PasswordFormat ) + { + case MembershipPasswordFormat.Encrypted: + pass2 = UnEncodePassword( dbpassword ); + break; + + case MembershipPasswordFormat.Hashed: + pass1 = EncodePassword( password ); + break; + + default: + break; + } + + if ( pass1 == pass2 ) + return true; + + return false; + } + + /// + /// Helper method to return a password encoded in the correct format, + /// regardless of the whether the passwords are stored in clear text, hashed, or encrypted. + /// + /// the password to encode + /// the password encoded using the current password storage format. + private string EncodePassword(string newPassword) + { + string encodedPassword = newPassword; + + switch ( PasswordFormat ) + { + case MembershipPasswordFormat.Clear: + break; + + case MembershipPasswordFormat.Encrypted: + encodedPassword = Convert.ToBase64String( EncryptPassword( Encoding.Unicode.GetBytes( newPassword ) ) ); + break; + + case MembershipPasswordFormat.Hashed: + <% if(!UseMD5Hash){ %> + HMACSHA1 hash = new HMACSHA1(); + hash.Key = HexToByte( _machineKey.ValidationKey ); + encodedPassword = Convert.ToBase64String( hash.ComputeHash( Encoding.Unicode.GetBytes( newPassword ) ) ); + <%}else{%> + MD5 md5 = new MD5CryptoServiceProvider(); + Byte[] originalBytes; + Byte[] encodedBytes; + + originalBytes = ASCIIEncoding.Default.GetBytes(newPassword); + encodedBytes = md5.ComputeHash(originalBytes); + + //Convert encoded bytes back to a 'readable' string + encodedPassword = BitConverter.ToString(encodedBytes); + <%}%> + break; + + default: + throw new ProviderException( "Unsupported password format." ); + } + + return encodedPassword; + } + + /// + /// Helper method to return a decoded password, + /// regardless of the whether the passwords are stored in clear text, hashed, or encrypted. + /// + /// the password to decode + /// the decoded password + private string UnEncodePassword(string encodedPassword) + { + string password = encodedPassword; + + switch ( PasswordFormat ) + { + case MembershipPasswordFormat.Clear: + break; + + case MembershipPasswordFormat.Encrypted: + password = Encoding.Unicode.GetString( DecryptPassword( Convert.FromBase64String( password ) ) ); + break; + + case MembershipPasswordFormat.Hashed: + throw new ProviderException( "Cannot unencode a hashed password." ); + + default: + throw new ProviderException( "Unsupported password format." ); + } + + return password; + } + + /// + /// Converts a hexadecimal string to a byte array. Used to convert encryption key values from the configuration. + /// + /// the hexidecimal string to convert into a byte array + /// a byte array representing the hexadecimal string + private byte[] HexToByte(string hexString) + { + byte[] returnBytes = new byte[hexString.Length / 2]; + for ( int i = 0; i < returnBytes.Length; i++ ) + returnBytes[i] = Convert.ToByte( hexString.Substring( i*2, 2 ), 16 ); + return returnBytes; + } + + /// + /// Helper function to retrieve a user based on their username without having to also specify application name + /// + /// The username to retrieve + /// A <%= EntityClass %> if the user could be found; otherwise null + private <%=EntityClass%> GetUserByUsername(string username) + { + string whereClause = "<%= GetMappedColumn("Username") %> = '" + username + "' AND <%= GetMappedColumn("ApplicationName") %> = '" + _applicationName + "'"; + TList<<%= EntityClass %>> users = DataRepository.<%= EntityClass %>Provider.Find( whereClause ); + if ( users.Count > 1 ) + throw new ProviderException("Found too many users with the same username and application name"); + + if ( users.Count == 0 ) + return null; + + return users[0]; + } + + #endregion + } + +} Index: WebLibrarySecurity/CommonMembershipCode.cs =================================================================== --- WebLibrarySecurity/CommonMembershipCode.cs (revision 0) +++ WebLibrarySecurity/CommonMembershipCode.cs (revision 0) @@ -0,0 +1,442 @@ +using CodeSmith.Engine; +using SchemaExplorer; +using System; +using System.Windows.Forms.Design; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Data.SqlClient; +using System.Design; +using System.Text; +using System.Text.RegularExpressions; +using System.IO; +using System.Diagnostics; + + +namespace MoM.Templates +{ + /// + /// Summary description for Class1 + /// + public class CommonMembershipCode : CommonSqlCode //CodeTemplate + { + private DbType _isApprDbType; + private DbType _isLockedOutDbType; + private bool _initAttrRun; + + public CommonMembershipCode() + { + _initAttrRun = false; + } + + private void InitAttrTypes() + { + if(!_initAttrRun) + { + _isApprDbType = DbType.Boolean; + _isLockedOutDbType = DbType.Boolean; + + string aprCol = GetMappedColumn("IsApproved").ToLower(); + string loCol = GetMappedColumn("IsLockedOut").ToLower(); + + foreach (ColumnSchema sch in MembershipTable.Columns) + { + if(sch.Name.ToLower() == aprCol) + _isApprDbType = sch.DataType; + if(sch.Name.ToLower() == loCol) + _isLockedOutDbType = sch.DataType; + } + } + } + + #region Copied from CommonSqlCode.cs + + private string aliasFilePath = ""; + + [Editor( typeof( System.Windows.Forms.Design.FileNameEditor ), typeof( System.Drawing.Design.UITypeEditor ) )] + [Category( "09. Code style - Advanced" )] + [OptionalAttribute] + [DefaultValue( "" )] + [Description( "Optional File Path to a table/object alias file." )] + public string AliasFilePath + { + get { return this.aliasFilePath; } + set { this.aliasFilePath = value; } + } + + /// + /// Convert database types to C# types + /// + /// Column or parameter + /// The C# (rough) equivalent of the field's data type + public string GetCSType(DataObjectBase field) + { + if ( field.NativeType.ToLower() == "real" ) + return "System.Single" + ( field.AllowDBNull?"?":"" ); + else if ( field.NativeType.ToLower() == "xml" ) + return "string"; + //else if (field.NativeType.ToLower() == "xml") + // return "System.Xml.XmlNode"; + else if ( !IsCSReferenceDataType( field ) && field.AllowDBNull ) + return field.SystemType.ToString() + "?"; + else + return field.SystemType.ToString(); + //return GetCSType(field.DataType); + } + + /// + /// Returns true if the column is represented as a reference data type + /// rather than a value type. In other words, the C# code can set a + /// column of this data type to 'null' + /// + public bool IsCSReferenceDataType(DataObjectBase column) + { + if (column.NativeType.ToLower() == "real") + return false; + else if (column.NativeType.ToLower() == "xml") + return true; + else + { + DbType dataType = column.DataType; + switch (dataType) + { + case DbType.AnsiString: + case DbType.AnsiStringFixedLength: + case DbType.String: + case DbType.StringFixedLength: + case DbType.Binary: + return true; + + case DbType.Boolean: + case DbType.Guid: + case DbType.Byte: + case DbType.Currency: + case DbType.Date: + case DbType.DateTime: + case DbType.Decimal: + case DbType.Double: + case DbType.Int16: + case DbType.Int32: + case DbType.Int64: + case DbType.Object: + case DbType.Single: + case DbType.Time: + case DbType.VarNumeric: + return false; + + default: + return false; + } + } + } + + /// + /// Transform a name into a public class property name. + /// + public string GetPropertyName(string name) + { + name = Regex.Replace(name, @"[\W]", ""); + name = name.TrimStart(new char[] {'_', '-', '+', '=', '*'}); + name = GetPascalCaseName(name); + + if (Regex.IsMatch(name, @"^[\d]")) + name="Data" + name; + return name; + } + + /// + /// Get the Pascal cased version of a name. + /// + /// Name to be changed + /// PascalCased version of the name + public string GetPascalCaseName(string name) + { + return name.Substring(0, 1).ToUpper() + name.Substring(1); + } + + #endregion + + private ColumnSchema _entityMembershipUserPrimaryKey = null; + + [Category("10. WebLibrary.Security - Optional")] + [OptionalAttribute] + [DefaultValue("")] + [Description("Primary key column from the table that will become the EntityMembershipUser's user entity.")] + public ColumnSchema EntityMembershipUserPKCol + { + get + { + return this._entityMembershipUserPrimaryKey; + } + set + { + _entityMembershipUserPrimaryKey = value; + } + } + + + private string _membershipUserMapFile; + + [Editor(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(System.Drawing.Design.UITypeEditor))] + [Category("10. WebLibrary.Security - Optional")] + [OptionalAttribute] + [DefaultValue("")] + [Description("Optional File Path to a MembershipUserProperty/EntityProperty alias file")] + public string MembershipUserMapFile + { + get + { + return this._membershipUserMapFile; + } + set + { + _membershipUserMapFile = value; + } + } + + private bool _membershipUseMD5 = false; + + [Category("10. WebLibrary.Security - Optional")] + [Description("Use MD5 hash for passwords. False defaults to SHA1.")] + public bool UseMD5Hash + { + get + { + return this._membershipUseMD5; + } + set + { + _membershipUseMD5 = value; + } + } + + public TableSchema MembershipTable + { + get + { + return EntityMembershipUserPKCol.Table; + } + } + + private Hashtable membershipUserMap = null; + + public string GetEntityAlias(string providerType) + { + if ( providerType == "Membership" ) + { + return GetClassName(EntityMembershipUserPKCol.Table); + } + + return null; + } + + protected string EntityClass + { + get + { + return GetEntityAlias( "Membership" ); + } + } + + protected string EntityKeyType + { + get + { + return EntityMembershipUserPKCol.GetType().ToString(); + } + } + + public DbType IsApprovedType + { + get + { + InitAttrTypes(); + return _isApprDbType; + } + } + + public DbType IsLockedOutType + { + get + { + InitAttrTypes(); + return _isLockedOutDbType; + } + } + + public string GetBoolExp(DbType type, bool expected) + { + if(type == DbType.Boolean) + { + if(expected) return "true"; + else return "false"; + } + else + { + if(expected) return "1"; + else return "0"; + } + } + + public string GetBoolExp(DbType type, string subj) + { + if(type == DbType.Boolean) + { + return subj; + } + else + { + string cast = GetCast(type); + return subj +"?" + cast + "1:"+ cast +"0"; + } + } + + protected string GetCast(DbType type) + { + switch (type) + { + case DbType.AnsiString: + case DbType.AnsiStringFixedLength: + case DbType.String: + case DbType.StringFixedLength: + return "(string)"; + + case DbType.Boolean: + return "(bool)"; + + //Answer modified was just 0 + case DbType.Byte: + return "(byte)"; + + case DbType.Decimal: + return "(float)"; + + case DbType.Double: + return "(double)"; + + case DbType.Int16: + return "(short)"; + + case DbType.Int32: + return "(int)"; + + case DbType.Int64: + return "(long)"; + + case DbType.SByte: + return "(sbyte)"; + + case DbType.UInt16: + return "(ushort)"; + + case DbType.UInt32: + return "(uint)"; + + case DbType.UInt64: + return "(ulong)"; + } + return ""; + } + + /// + /// This function gets the name of the property in the user entity that corresponds to + /// the selected MembershipUser property name. + /// + public string GetMappedColumn(string propertyName) + { + // If the mappings aren't loaded yet, and the filepath exists, then load the hashtable of mappings + if ( membershipUserMap == null && File.Exists( MembershipUserMapFile ) ) + { + membershipUserMap = new Hashtable(); + using ( StreamReader sr = new StreamReader( MembershipUserMapFile ) ) + { + string line; + while ( ( line = sr.ReadLine() ) != null ) + { + if ( line.IndexOf( ":" ) > 0 ) + { + string lvalue = line.Split( ':' )[0]; + string rvalue = line.Split( ':' )[1]; + + if ( IsValidLValue( "Membership", lvalue ) && IsValidRValue( "Membership", rvalue ) ) + { + membershipUserMap.Add( lvalue, GetPropertyName(rvalue) ); + } + } + } + } + } + + // See if our tablename is in the aliases hashtable, and if so, replace it. + if ( membershipUserMap != null ) + { + IDictionaryEnumerator mapping = membershipUserMap.GetEnumerator(); + while ( mapping.MoveNext() ) + { + if ( propertyName.ToLower() == mapping.Key.ToString().ToLower() ) + { + propertyName = mapping.Value.ToString(); + break; + } + } + } + + return propertyName; + } + + + private bool IsValidLValue(string providerType, string lvalue) + { + if ( providerType == "Membership" ) + { + switch ( lvalue ) + { + case "ApplicationName": + case "Comment": + case "CreationDate": + case "Email": + case "FailedPasswordAttemptCount": + case "FailedPasswordAttemptWindowStart": + case "FailedPasswordAnswerAttemptCount": + case "FailedPasswordAnswerAttemptWindowStart": + case "IsApproved": + case "IsLockedOut": + case "LastActivityDate": + case "LastLockoutDate": + case "LastLoginDate": + case "LastPasswordChangedDate": + case "PasswordQuestion": + case "PasswordAnswer": + case "ProviderUserKey": + case "UserName": + return true; + } + } + + return false; + } + + + private bool IsValidRValue(string providerType, string rvalue) + { + if ( providerType == "Membership" ) + { + if ( EntityMembershipUserPKCol.Table.Columns[rvalue] != null ) + return true; + } + + return false; + } + + public string GetPKType(string providerType) + { + if ( providerType == "Membership" ) + { + return GetCSType( EntityMembershipUserPKCol.Table.PrimaryKey.MemberColumns[0] ); + } + + return null; + } + + } +} \ No newline at end of file Index: WebLibrarySecurity/EntityMembershipProperty.cst =================================================================== --- WebLibrarySecurity/EntityMembershipProperty.cst (revision 0) +++ WebLibrarySecurity/EntityMembershipProperty.cst (revision 0) @@ -0,0 +1,111 @@ +<%-- +Name: +Author: Charlie Kilian +Description: + +--%> +<%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="./CommonMembershipCode.cs" Inherits="MoM.Templates.CommonMembershipCode" Debug="True" Description="Generates the EntityMembershipUser class." %> +<%@ Assembly Name="System.Data" %> +<%@ Assembly Name="System.Design" %> +<%@ Assembly Name="SchemaExplorer" %> +<%@ Import Namespace="System.Data" %> +<%@ Import Namespace="System.IO" %> +<%@ Import Namespace="System.Collections" %> +<%@ Import Namespace="SchemaExplorer" %> + +<%@ Property Name="BLLNameSpace" Optional="False" Type="System.String" Category="Style" Description="BLL Namespace." %> +<%@ Property Name="DALNameSpace" Optional="False" Type="System.String" Category="Style" Description="DAL Namespace." %> +<%@ Property Name="WebNameSpace" Optional="False" Type="System.String" Category="Style" Description="Web Namespace." %> +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; +using System.Web; +using System.Web.UI; +using System.Web.Security; +using System.Web.UI.WebControls; +using System.Reflection; +using <%= BLLNameSpace %>; +using <%= DALNameSpace %>; + +namespace <%= WebNameSpace %>.Security +{ + /// + /// Displays the value of the specified EntityMembershipUser property. + /// + [DefaultProperty( "Text" )] + [ToolboxData( "<{0}:EntityMembershipProperty runat=server>" )] + public class EntityMembershipProperty : WebControl + { + private <%= EntityClass %>Column _propertyName; + private string _formatString = ""; + + /// + /// The property to display + /// + [System.ComponentModel.Bindable( true )] + [Category( "Misc" )] + [DefaultValue( "" )] + [Localizable( true )] + public <%= EntityClass %>Column PropertyName + { + get { return _propertyName; } + set { _propertyName = value; } + } + + /// + /// The string to use to format the property + /// + [System.ComponentModel.Bindable( true )] + [Category( "Misc" )] + [DefaultValue( "" )] + [Localizable( true )] + public string FormatString + { + get { return _formatString; } + set { _formatString = value; } + } + + /// + /// Renders the contents of the control to the specified writer. + /// + /// A HtmlTextWriter that represents the output stream to render HTML content on the client. + protected override void RenderContents(HtmlTextWriter output) + { + MembershipUser member = Membership.GetUser(); + if ( member == null ) + return; + + if ( !( member is EntityMembershipUser ) ) + throw new Exception( "EntityMembershipProperty requires the current membership provider to be EntityMembershipProvider" ); + + <%= EntityClass %> user = ((EntityMembershipUser) member).UserEntity; + string propname = _propertyName.ToString(); + + Type type = user.GetType(); + object objvalue = type.InvokeMember(propname, BindingFlags.GetProperty, null, user, null); + + if ( objvalue == null ) + return; + + string strvalue = ""; + + switch ( objvalue.GetType().ToString() ) + { + case "System.Int32": + strvalue = ((int) objvalue).ToString(_formatString); + break; + + case "System.DateTime": + strvalue = ((DateTime) objvalue).ToString(_formatString); + break; + + default: + strvalue = objvalue.ToString(); + break; + } + + output.Write( strvalue ); + } + } +} Index: WebLibrarySecurity/EntityMembershipProvider.cst =================================================================== --- WebLibrarySecurity/EntityMembershipProvider.cst (revision 0) +++ WebLibrarySecurity/EntityMembershipProvider.cst (revision 0) @@ -0,0 +1,1062 @@ +<%-- +Name: +Author: Charlie Kilian +Description: + +--%> +<%@ CodeTemplate Language="C#" TargetLanguage="C#" Src="./CommonMembershipCode.cs" Inherits="MoM.Templates.CommonMembershipCode" Debug="True" Description="Generates the EntityMembershipUser class." %> +<%@ Assembly Name="System.Data" %> +<%@ Assembly Name="System.Design" %> +<%@ Assembly Name="SchemaExplorer" %> +<%@ Import Namespace="System.Data" %> +<%@ Import Namespace="System.IO" %> +<%@ Import Namespace="System.Collections" %> +<%@ Import Namespace="SchemaExplorer" %> + +<%@ Property Name="BLLNameSpace" Optional="False" Type="System.String" Category="Style" Description="BLL Namespace." %> +<%@ Property Name="DALNameSpace" Optional="False" Type="System.String" Category="Style" Description="DAL Namespace." %> +<%@ Property Name="WebNameSpace" Optional="False" Type="System.String" Category="Style" Description="Web Namespace." %> + +<% +// string entityClassName = GetClassName(SourceTable); +%> + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Configuration; +using System.Configuration.Provider; +using System.Security.Cryptography; +using System.Text; +using System.Web.Security; +using System.Web.Configuration; +using <%= BLLNameSpace %>; +using <%= DALNameSpace %>; + +namespace <%= WebNameSpace %>.Security +{ + public class EntityMembershipProvider : MembershipProvider + { + #region Variable Declarations + + /// + /// Stores the value of the ApplicationName configuration property + /// required to implement MembershipProvider. + /// + private string _applicationName; + + /// + /// Stores the value of the EnablePasswordReset configuration property + /// required to implement MembershipProvider. + /// + private bool _enablePasswordReset; + + /// + /// Stores the value of the EnablePasswordRetrieval configuration property + /// required to implement MembershipProvider. + /// + private bool _enablePasswordRetrieval; + + /// + /// Stores the value of the MaxInvalidPasswordAttempts configuration property + /// required to implement MembershipProvider. + /// + private int _maxInvalidPasswordAttempts; + + /// + /// Stores the value of the MinRequiredNonAlphanumericCharacters configuration property + /// required to implement MembershipProvider. + /// + private int _minRequiredNonAlphanumericCharacters; + + /// + /// Stores the value of the MinRequiredPasswordLength configuration property + /// required to implement MembershipProvider. + /// + private int _minRequiredPasswordLength; + + /// + /// Stores the value of the PasswordAttemptWindow configuration property + /// required to implement MembershipProvider. + /// + private int _passwordAttemptWindow; + + /// + /// Stores the value of the PasswordFormat configuration property + /// required to implement MembershipProvider. + /// + private MembershipPasswordFormat _passwordFormat; + + /// + /// Stores the value of the PasswordStrengthRegularExpression configuration property + /// required to implement MembershipProvider. + /// + private string _passwordStrengthRegularExpression; + + /// + /// Stores the value of the RequiresQuestionAndAnswer configuration property + /// required to implement MembershipProvider. + /// + private bool _requiresQuestionAndAnswer; + + /// + /// Stores the value of the RequiresUniqueEmail configuration property + /// required to implement MembershipProvider. + /// + private bool _requiresUniqueEmail; + + /// + /// Stores the value of the MachineKey configuration property + /// required to implement MembershipProvider. + /// + private MachineKeySection _machineKey; + + #endregion + + #region Public Constructors and Initialialization + + /// + /// Initializes the provider. + /// + /// The friendly name of the provider. For EntityMembershipProvider, this is always the string "EntityMembershipProvider". + /// A collection of the name/value pairs representing the attributes specified in the configuration for this provider. + public override void Initialize(string name, NameValueCollection config) + { + _applicationName = Convert.ToString( GetConfigValue( config["applicationName"], System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath ) ); + _enablePasswordReset = Convert.ToBoolean( GetConfigValue( config["enablePasswordReset"], "true" ) ); + _enablePasswordRetrieval = Convert.ToBoolean( GetConfigValue( config["enablePasswordRetrieval"], "true" ) ); + _maxInvalidPasswordAttempts = Convert.ToInt32( GetConfigValue( config["maxInvalidPasswordAttempts"], "5" ) ); + _minRequiredNonAlphanumericCharacters = Convert.ToInt32( GetConfigValue( config["minRequiredNonAlphanumericCharacters"], "1" ) ); + _minRequiredPasswordLength = Convert.ToInt32( GetConfigValue( config["minRequiredPasswordLength"], "7" ) ); + _passwordAttemptWindow = Convert.ToInt32( GetConfigValue( config["passwordAttemptWindow"], "10" ) ); + _passwordStrengthRegularExpression = Convert.ToString( GetConfigValue( config["passwordStrengthRegularExpression"], "" ) ); + _requiresQuestionAndAnswer = Convert.ToBoolean( GetConfigValue( config["requiresQuestionAndAnswer"], "true" ) ); + _requiresUniqueEmail = Convert.ToBoolean( GetConfigValue( config["requiresUniqueEmail"], "true" ) ); + + string pformat = config["passwordFormat"]; + if ( pformat == null ) + pformat = "Hashed"; + + switch ( pformat ) + { + case "Hashed": + _passwordFormat = MembershipPasswordFormat.Hashed; + break; + + case "Encrypted": + _passwordFormat = MembershipPasswordFormat.Encrypted; + break; + + case "Clear": + _passwordFormat = MembershipPasswordFormat.Clear; + break; + + default: + throw new ProviderException( "Password format not supported." ); + } + + <% if(!UseMD5Hash){ %> + // FIXME: I have no idea what the next section does + // See: http://msdn2.microsoft.com/en-us/library/6tc47t75.aspx + + // Get encryption and decryption key information from the configuration. + Configuration cfg = WebConfigurationManager.OpenWebConfiguration( System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath ); + _machineKey = (MachineKeySection) cfg.GetSection( "system.web/machineKey" ); + + if ( _machineKey.ValidationKey.Contains( "AutoGenerate" ) && + PasswordFormat != MembershipPasswordFormat.Clear ) + { + throw new ProviderException( "Hashed or Encrypted passwords are not supported with auto-generated keys." ); + } + + <%}%> + + + } + + #endregion + + #region Public Properties + + /// + /// The name of the application using the EntityMembershipProvider. + /// + public override string ApplicationName + { + get { return _applicationName; } + set { _applicationName = value; } + } + + /// + /// Gets a brief, friendly description suitable for display in administrative tools + /// or other user interfaces (UIs). + /// + public override string Description + { + get { return "EntityMembershipProvider, a typed MembershipProvider generated by .netTiers"; } + } + + /// + /// Indicates whether the EntityMembershipProvider is configured to allow users to reset their passwords. + /// + public override bool EnablePasswordReset + { + get { return _enablePasswordReset; } + } + + /// + /// Indicates whether the EntityMembershipProvider is configured to allow users to retrieve their passwords. + /// + public override bool EnablePasswordRetrieval + { + get { return _enablePasswordRetrieval; } + } + + /// + /// Gets the number of invalid password or password-answer attempts allowed before the + /// membership user is locked out. + /// + public override int MaxInvalidPasswordAttempts + { + get { return _maxInvalidPasswordAttempts; } + } + + /// + /// Gets the minimum number of special characters that must be present in a valid password. + /// + public override int MinRequiredNonAlphanumericCharacters + { + get { return _minRequiredNonAlphanumericCharacters; } + } + + /// + /// Gets the minimum length required for a password. + /// + public override int MinRequiredPasswordLength + { + get { return _minRequiredPasswordLength; } + } + + /// + /// Gets the friendly name used to refer to the provider during configuration. + /// Always returns the string "EntityMembershipProvider". + /// + public override string Name + { + get { return "EntityMembershipProvider"; } + } + + /// + /// Gets the number of minutes in which a maximum number of invalid password or + /// password-answer attempts are allowed before the membership user is locked out. + /// + public override int PasswordAttemptWindow + { + get { return _passwordAttemptWindow; } + } + + /// + /// Gets a value indicating the format for storing passwords in the membership data store. + /// + public override MembershipPasswordFormat PasswordFormat + { + get { return _passwordFormat; } + } + + /// + /// Gets the regular expression used to evaluate a password. + /// + public override string PasswordStrengthRegularExpression + { + get { return _passwordStrengthRegularExpression; } + } + + /// + /// Gets a value indicating whether the EntityMembershipProvider is configured + /// to require the user to answer a password question for password reset and retrieval. + /// + public override bool RequiresQuestionAndAnswer + { + get { return _requiresQuestionAndAnswer; } + } + + /// + /// Gets a value indicating whether the EntityMembershipProvider is configured + /// to require a unique e-mail address for each user name. + /// + public override bool RequiresUniqueEmail + { + get { return _requiresUniqueEmail; } + } + + #endregion + + #region Public Methods + + /// + /// Processes a request to update the password for a membership user. + /// + /// The user to update the password for. + /// The current password for the specified user. + /// The new password for the specified user. + /// true if the password was updated successfully; otherwise, false. + /// Takes, as input, a user name, a current password, and a new password, and updates the password in the data source if the supplied user name and current password are valid. + public override bool ChangePassword(string username, string oldPassword, string newPassword) + { + // attempt to validate old password + if ( !ValidateUser( username, oldPassword ) ) + return false; + + // attempt to validate the strength of the new password + ValidatePasswordEventArgs args = new ValidatePasswordEventArgs( username, newPassword, true ); + OnValidatingPassword( args ); + + if ( args.Cancel ) + { + if ( args.FailureInformation != null ) + throw args.FailureInformation; + else + throw new MembershipPasswordException( "Change password canceled due to new password validation failure." ); + } + + try + { + // retrieve the user entity and set the new password + // retrieve the user entity and set the new password + <%= EntityClass %> user = GetUserByUsername(username); + if ( user == null ) + return false; + user.<%= GetMappedColumn("Password") %> = EncodePassword( newPassword ); + user.<%= GetMappedColumn("LastPasswordChangedDate") %> = DateTime.Now; + DataRepository.<%= EntityClass %>Provider.Save(user); + return true; + } + catch ( Exception ) + { + return false; + } + } + + /// + /// Processes a request to update the password question and answer for a membership user. + /// + /// The user to change the password question and answer for. + /// The password for the specified user. + /// The new password question for the specified user. + /// The new password answer for the specified user. + /// true if the password question and answer are updated successfully; otherwise, false. + public override bool ChangePasswordQuestionAndAnswer( + string username, + string password, + string newPasswordQuestion, + string newPasswordAnswer) + { + if ( !ValidateUser( username, password ) ) + return false; + + try + { + // retrieve the user entity and set the new password + <%= EntityClass %> user = GetUserByUsername(username); + if ( user == null ) + return false; + user.<%= GetMappedColumn("PasswordQuestion") %> = newPasswordQuestion; + user.<%= GetMappedColumn("PasswordAnswer") %> = newPasswordAnswer; + DataRepository.<%= EntityClass %>Provider.Save( user ); + return true; + } + catch ( Exception ) + { + return false; + } + } + + /// + /// Adds a new membership user to the data source. + /// + /// The user name for the new user. + /// The password for the new user. + /// The e-mail address for the new user. + /// The password question for the new user. + /// The password answer for the new user + /// Whether or not the new user is approved to be validated. + /// The unique identifier from the membership data source for the user. + /// A MembershipCreateStatus enumeration value indicating whether the user was created successfully. + /// A MembershipUser object populated with the information for the newly created