Constable Authorization Engine CAZE.NET

Posts   
 
    
omar avatar
omar
User
Posts: 569
Joined: 15-Oct-2004
# Posted on: 03-Mar-2006 21:35:32   

I am considering utilizing the CAZE engine to implement authorization security in a future application. Hoped to check if any LLBL'ers have used it in their own applications? http://lamarvin.com/caze_default.asp

alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 05-Mar-2006 15:30:39   

Is your project a web app? If so, why not use the built in security mechanisms that come with .NET 2.0? They're very easy to use.

erichar11
User
Posts: 268
Joined: 08-Dec-2003
# Posted on: 05-Mar-2006 22:59:44   

pardon me for jumping in, but Alex did you ever get permission to release your ASP.net membership code using llblgen. I would really like to take a look at it. I can be reached at eric_richards @ mail dot com.

Thanks.

sparmar2000 avatar
Posts: 341
Joined: 30-Nov-2003
# Posted on: 06-Mar-2006 02:19:17   

I am keenly interested as well...I lost the thread on the subject Alex. Did you finish the membership project?

alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 06-Mar-2006 19:23:59   

Finally got approval to post this code.

First, the disclaimer. MSDN provides sample membership and role provider classes. I simply copy/pasted their code and replaced their ADO.NET related code with LLBLGen specific code. The end result has worked great for me so far, but I do not guarantee it to be bug free. Heck, I fixed a spelling mistake after pasting the code into this window! simple_smile Please let me know if you find any bugs or add any enhancements as I'd like to update my code with your changes.

One thing I know that can be enhanced is in the role provider. My app won't ever have more than like 5 roles total so I don't see a problem caching that information in the Application object thus speeding up the Membership.IsInRole functions.

Other than that, it should be pretty straight forward. I removed all traces of my current project, but may have accidently introduced a bug in the process (A global search/replace will do that sometimes).

Place all of the files in your project and go through the code to make sure objects and namespaces are named according to your application. For example, you will probably want to use something other than YourProject and MyMembershipProvider.

Below is the code for the membership provider.

Imports System.Web.Security
Imports System.Configuration.Provider
Imports System.Collections.Specialized
Imports System
Imports System.Data
Imports System.Data.Odbc
Imports System.Configuration
Imports System.Diagnostics
Imports System.Web
Imports System.Globalization
Imports System.Security.Cryptography
Imports System.Text
Imports System.Web.Configuration

Imports SD.LLBLGen.Pro.ORMSupportClasses
Imports YourProject.DAL
Imports YourProject.DAL.DatabaseSpecific
Imports YourProject.DAL.EntityClasses
Imports YourProject.DAL.HelperClasses
Imports YourProject.DAL.FactoryClasses
Imports YourProject.DAL.RelationClasses
Imports YourProject.DAL.ValidatorClasses



Namespace YourProject.Providers


    Public NotInheritable Class MyMembershipProvider
        Inherits MembershipProvider

        Private _adapter As DataAccessAdapter2
        Private newPasswordLength As Integer = 8


        Private machineKey As MachineKeySection

        Public Overrides Sub Initialize(ByVal name As String, ByVal config As NameValueCollection)


            If config Is Nothing Then _
              Throw New ArgumentNullException("config")

            If name Is Nothing OrElse name.Length = 0 Then _
              name = "MyMembershipProvider"

            If String.IsNullOrEmpty(config("description")) Then
                config.Remove("description")
                config.Add("description", "Interacts with custom tables in the Membership database")
            End If

            ' Initialize the abstract base class.
            MyBase.Initialize(name, config)


            pApplicationName = GetConfigValue(config("applicationName"), _
                                            System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath)
            pMaxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config("maxInvalidPasswordAttempts"), "5"))
            pPasswordAttemptWindow = Convert.ToInt32(GetConfigValue(config("passwordAttemptWindow"), "10"))
            pMinRequiredNonAlphanumericCharacters = Convert.ToInt32(GetConfigValue(config("minRequiredAlphaNumericCharacters"), "1"))
            pMinRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config("minRequiredPasswordLength"), "7"))
            pPasswordStrengthRegularExpression = Convert.ToString(GetConfigValue(config("passwordStrengthRegularExpression"), ""))
            pEnablePasswordReset = Convert.ToBoolean(GetConfigValue(config("enablePasswordReset"), "True"))
            pEnablePasswordRetrieval = Convert.ToBoolean(GetConfigValue(config("enablePasswordRetrieval"), "True"))
            pRequiresQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config("requiresQuestionAndAnswer"), "False"))
            pRequiresUniqueEmail = Convert.ToBoolean(GetConfigValue(config("requiresUniqueEmail"), "True"))


            Dim temp_format As String = config("passwordFormat")
            If temp_format Is Nothing Then
                temp_format = "Hashed"
            End If

            Select Case temp_format
                Case "Hashed"
                    pPasswordFormat = MembershipPasswordFormat.Hashed
                Case "Encrypted"
                    pPasswordFormat = MembershipPasswordFormat.Encrypted
                Case "Clear"
                    pPasswordFormat = MembershipPasswordFormat.Clear
                Case Else
                    Throw New ProviderException("Password format not supported.")
            End Select



            _adapter = New DataAccessAdapter2()


            ' Get encryption and decryption key information from the configuration.
            Dim cfg As System.Configuration.Configuration = _
              WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath)
            machineKey = CType(cfg.GetSection("system.web/machineKey"), MachineKeySection)
        End Sub


        '
        ' A helper function to retrieve config values from the configuration file.
        '

        Private Function GetConfigValue(ByVal configValue As String, ByVal defaultValue As String) As String
            If String.IsNullOrEmpty(configValue) Then _
              Return defaultValue

            Return configValue
        End Function


        '
        ' System.Web.Security.MembershipProvider properties.
        '


        Private pApplicationName As String
        Private pEnablePasswordReset As Boolean
        Private pEnablePasswordRetrieval As Boolean
        Private pRequiresQuestionAndAnswer As Boolean
        Private pRequiresUniqueEmail As Boolean
        Private pMaxInvalidPasswordAttempts As Integer
        Private pPasswordAttemptWindow As Integer
        Private pPasswordFormat As MembershipPasswordFormat

        Public Overrides Property ApplicationName() As String
            Get
                Return pApplicationName
            End Get
            Set(ByVal value As String)
                pApplicationName = value
            End Set
        End Property

        Public Overrides ReadOnly Property EnablePasswordReset() As Boolean
            Get
                Return pEnablePasswordReset
            End Get
        End Property


        Public Overrides ReadOnly Property EnablePasswordRetrieval() As Boolean
            Get
                Return pEnablePasswordRetrieval
            End Get
        End Property


        Public Overrides ReadOnly Property RequiresQuestionAndAnswer() As Boolean
            Get
                Return pRequiresQuestionAndAnswer
            End Get
        End Property


        Public Overrides ReadOnly Property RequiresUniqueEmail() As Boolean
            Get
                Return pRequiresUniqueEmail
            End Get
        End Property


        Public Overrides ReadOnly Property MaxInvalidPasswordAttempts() As Integer
            Get
                Return pMaxInvalidPasswordAttempts
            End Get
        End Property


        Public Overrides ReadOnly Property PasswordAttemptWindow() As Integer
            Get
                Return pPasswordAttemptWindow
            End Get
        End Property


        Public Overrides ReadOnly Property PasswordFormat() As MembershipPasswordFormat
            Get
                Return pPasswordFormat
            End Get
        End Property

        Private pMinRequiredNonAlphanumericCharacters As Integer

        Public Overrides ReadOnly Property MinRequiredNonAlphanumericCharacters() As Integer
            Get
                Return pMinRequiredNonAlphanumericCharacters
            End Get
        End Property

        Private pMinRequiredPasswordLength As Integer

        Public Overrides ReadOnly Property MinRequiredPasswordLength() As Integer
            Get
                Return pMinRequiredPasswordLength
            End Get
        End Property

        Private pPasswordStrengthRegularExpression As String

        Public Overrides ReadOnly Property PasswordStrengthRegularExpression() As String
            Get
                Return pPasswordStrengthRegularExpression
            End Get
        End Property

        '
        ' System.Web.Security.MembershipProvider methods.
        '

        '
        ' MembershipProvider.ChangePassword
        '

        Public Overrides Function ChangePassword(ByVal username As String, _
        ByVal oldPwd As String, _
        ByVal newPassword As String) As Boolean
            If Not ValidateUser(username, oldPwd) Then _
              Return False


            Dim args As ValidatePasswordEventArgs = _
              New ValidatePasswordEventArgs(username, newPassword, True)

            OnValidatingPassword(args)

            If args.Cancel Then
                If Not args.FailureInformation Is Nothing Then
                    Throw args.FailureInformation
                Else
                    Throw New ProviderException("Change password canceled due to New password validation failure.")
                End If
            End If

            ' Update users matching the specified username and application name
            Dim bucket As New RelationPredicateBucket()
            bucket.PredicateExpression.Add(PredicateFactory.CompareValue(UserFieldIndex.UserName, ComparisonOperator.Equal, username))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Dim user As New UserEntity()
            user.LastPasswordChangeDate = DateTime.Now
            user.Password = EncodePassword(newPassword)

            Dim rowsAffected As Integer = 0

            Try
                _adapter.OpenConnection()

                rowsAffected = _adapter.UpdateEntitiesDirectly(user, bucket)

            Catch ex As Exception
                Throw New ProviderException("Error updating password", ex)
            Finally
                _adapter.CloseConnection()
            End Try

            If rowsAffected > 0 Then
                Return True
            End If

            Return False
        End Function



        '
        ' MembershipProvider.ChangePasswordQuestionAndAnswer
        '

        Public Overrides Function ChangePasswordQuestionAndAnswer(ByVal username As String, _
        ByVal password As String, _
        ByVal newPwdQuestion As String, _
        ByVal newPwdAnswer As String) As Boolean

            If Not ValidateUser(username, password) Then _
              Return False

            ' Update users matching the specified username and application name
            Dim bucket As New RelationPredicateBucket()
            bucket.PredicateExpression.Add(PredicateFactory.CompareValue(UserFieldIndex.UserName, ComparisonOperator.Equal, username))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Dim user As New UserEntity()
            user.PasswordQuestion = newPwdQuestion
            user.Password = newPwdAnswer

            Dim rowsAffected As Integer = 0

            Try
                _adapter.OpenConnection()

                rowsAffected = _adapter.UpdateEntitiesDirectly(user, bucket)

            Catch ex As Exception
                Throw New ProviderException("Error updating password question and answer", ex)
            Finally
                _adapter.CloseConnection()
            End Try
            If rowsAffected > 0 Then
                Return True
            End If

            Return False
        End Function



        '
        ' MembershipProvider.CreateUser
        '

        Public Overrides Function CreateUser(ByVal username As String, _
        ByVal password As String, _
        ByVal email As String, _
        ByVal passwordQuestion As String, _
        ByVal passwordAnswer As String, _
        ByVal isApproved As Boolean, _
        ByVal providerUserKey As Object, _
                 ByRef status As MembershipCreateStatus) As MembershipUser

            Dim Args As ValidatePasswordEventArgs = _
              New ValidatePasswordEventArgs(username, password, True)

            OnValidatingPassword(Args)

            If Args.Cancel Then
                status = MembershipCreateStatus.InvalidPassword
                Return Nothing
            End If


            If RequiresUniqueEmail AndAlso GetUserNameByEmail(email) <> "" Then
                status = MembershipCreateStatus.DuplicateEmail
                Return Nothing
            End If

            Dim u As MembershipUser = GetUser(username, False)

            If u Is Nothing Then

                Dim user As New UserEntity()
                user.UserName = username
                user.Password = EncodePassword(password)
                user.Email = email
                user.SchoolId = 0
                user.PasswordQuestion = passwordQuestion
                user.PasswordAnswer = EncodePassword(passwordAnswer)
                user.IsApproved = isApproved
                user.Description = ""
                user.LastPasswordChangeDate = DateTime.Now
                user.LastActivityDate = DateTime.Now
                user.ApplicationName = Me.ApplicationName
                user.IsLockedOut = False
                user.LastLockedOutDate = DateTime.Now
                user.FailedPasswordAttemptCount = 0
                user.FailedPasswordAttemptWindowStart = DateTime.Now
                user.FailedPasswordAnswerAttemptCount = 0
                user.FailedPasswordAnswerAttemptWindowStart = DateTime.Now

                Dim userCreated As Boolean = False

                Try
                    _adapter.OpenConnection()

                    userCreated = _adapter.SaveEntity(user)

                    If (userCreated) Then
                        status = MembershipCreateStatus.Success
                    Else
                        status = MembershipCreateStatus.UserRejected
                    End If

                Catch e As Exception

                    status = MembershipCreateStatus.ProviderError
                    Throw New ProviderException("Error creating user", e)

                Finally
                    _adapter.CloseConnection()
                End Try


                Return GetUser(username, False)
            Else
                status = MembershipCreateStatus.DuplicateUserName
            End If

            Return Nothing
        End Function



        '
        ' MembershipProvider.DeleteUser
        '

        Public Overrides Function DeleteUser(ByVal username As String, _
        ByVal deleteAllRelatedData As Boolean) As Boolean

            Dim bucket As New RelationPredicateBucket
            bucket.PredicateExpression.Add(PredicateFactory.CompareValue(UserFieldIndex.UserName, ComparisonOperator.Equal, username))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Dim rowsAffected As Integer = 0

            Try
                _adapter.OpenConnection()

                rowsAffected = _adapter.DeleteEntitiesDirectly("User", bucket)

                If deleteAllRelatedData Then
                    ' Process commands to delete all data for the user in the database.
                End If
            Catch e As Exception

                Throw New ProviderException("Erorr deleting user", e)
            Finally
                _adapter.CloseConnection()
            End Try

            If rowsAffected > 0 Then _
              Return True

            Return False
        End Function



        '
        ' MembershipProvider.GetAllUsers
        '

        Public Overrides Function GetAllUsers(ByVal pageIndex As Integer, _
        ByVal pageSize As Integer, _
                                              ByRef totalRecords As Integer) _
                                  As MembershipUserCollection

            Dim allUsers As New EntityCollection(New UserEntityFactory())
            Dim bucket As New RelationPredicateBucket()
            bucket.PredicateExpression.Add(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Dim sorter As New SortExpression(SortClauseFactory.Create(UserFieldIndex.UserName, SortOperator.Ascending))

            Dim users As MembershipUserCollection = New MembershipUserCollection()

            totalRecords = 0

            Try
                _adapter.OpenConnection()

                _adapter.FetchEntityCollection(allUsers, bucket, 0, sorter)

                totalRecords = allUsers.Count

                If totalRecords <= 0 Then Return users

                Dim counter As Integer = 0
                Dim startIndex As Integer = pageSize * pageIndex
                Dim endIndex As Integer = startIndex + pageSize - 1

                Do While counter < totalRecords
                    If counter >= startIndex Then
                        Dim u As MembershipUser = GetMembershipUserFromEntity(allUsers(counter))
                        users.Add(u)
                    End If

                    counter += 1
                Loop
            Catch e As Exception
                Throw New ProviderException("Error getting all users", e)

            Finally

                _adapter.CloseConnection()
            End Try

            Return users
        End Function

        '
        ' GetMembershipUserFromEntity
        '   A helper function that takes the current user entity
        ' and hydrates a MembershiUser from the values. Called by the 
        ' MembershipUser.GetUser implementation.
        '

        Private Function GetMembershipUserFromEntity(ByVal user As UserEntity) As MembershipUser
            Dim providerUserKey As Object = user.UserId
            Dim username As String = user.UserName
            Dim email As String = user.Email

            Dim passwordQuestion As String = user.PasswordQuestion

            Dim comment As String = user.Description

            Dim isApproved As Boolean = user.IsApproved
            Dim isLockedOut As Boolean = user.IsLockedOut
            Dim creationDate As DateTime = user.CreatedDate

            Dim lastLoginDate As DateTime = user.LastLoginDate

            Dim lastActivityDate As DateTime = user.LastActivityDate
            Dim lastPasswordChangedDate As DateTime = user.LastPasswordChangeDate

            Dim lastLockedOutDate As DateTime = user.LastLockedOutDate

            Dim u As MembershipUser = New MembershipUser(Me.Name, _
                                                  username, _
                                                  providerUserKey, _
                                                  email, _
                                                  passwordQuestion, _
                                                  comment, _
                                                  isApproved, _
                                                  isLockedOut, _
                                                  creationDate, _
                                                  lastLoginDate, _
                                                  lastActivityDate, _
                                                  lastPasswordChangedDate, _
                                                  lastLockedOutDate)

            Return u
        End Function

        '
        ' MembershipProvider.GetNumberOfUsersOnline
        '

        Public Overrides Function GetNumberOfUsersOnline() As Integer

            Dim onlineSpan As TimeSpan = New TimeSpan(0, System.Web.Security.Membership.UserIsOnlineTimeWindow, 0)
            Dim compareTime As DateTime = DateTime.Now.Subtract(onlineSpan)

            Dim lastActiveUsers As New EntityCollection(New UserEntityFactory())
            Dim bucket As New RelationPredicateBucket()
            bucket.PredicateExpression.Add(PredicateFactory.CompareValue(UserFieldIndex.LastActivityDate, ComparisonOperator.GreaterThan, compareTime))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Dim numOnline As Integer = 0

            Try
                _adapter.OpenConnection()
                _adapter.FetchEntityCollection(lastActiveUsers, bucket)

                numOnline = lastActiveUsers.Count

            Catch e As Exception
                Throw New ProviderException("Error getting users onlnie", e)
            Finally
                _adapter.CloseConnection()
            End Try

            Return numOnline
        End Function



        '
        ' MembershipProvider.GetPassword
        '

        Public Overrides Function GetPassword(ByVal username As String, ByVal answer As String) As String

            If Not EnablePasswordRetrieval Then
                Throw New ProviderException("Password Retrieval Not Enabled.")
            End If

            If PasswordFormat = MembershipPasswordFormat.Hashed Then
                Throw New ProviderException("Cannot retrieve Hashed passwords.")
            End If

            Dim user As New UserEntity()
            user.UserName = username
            user.ApplicationName = Me.ApplicationName

            Dim password As String = ""
            Dim passwordAnswer As String = ""

            Dim foundUser As Boolean = False

            Try
                _adapter.OpenConnection()

                foundUser = _adapter.FetchEntityUsingUniqueConstraint(user, user.ConstructFilterForUCUserNameApplicationName())

                If foundUser Then

                    If user.IsLockedOut Then _
                      Throw New MembershipPasswordException("The supplied user is locked out.")

                    password = user.Password
                    passwordAnswer = user.PasswordAnswer
                Else
                    Throw New MembershipPasswordException("The supplied user name is not found.")
                End If
            Catch e As Exception
                Throw New ProviderException("Error getting password", e)
            Finally
                _adapter.CloseConnection()
            End Try


            If RequiresQuestionAndAnswer AndAlso Not CheckPassword(answer, passwordAnswer) Then
                UpdateFailureCount(username, "passwordAnswer")

                Throw New MembershipPasswordException("Incorrect password answer.")
            End If


            If PasswordFormat = MembershipPasswordFormat.Encrypted Then
                password = UnEncodePassword(password)
            End If

            Return password
        End Function



        '
        ' MembershipProvider.GetUser(String, Boolean)
        '

        Public Overrides Function GetUser(ByVal username As String, _
        ByVal userIsOnline As Boolean) As MembershipUser

            Dim user As New UserEntity()
            user.UserName = username
            user.ApplicationName = Me.ApplicationName

            Dim u As MembershipUser = Nothing

            Try
                _adapter.OpenConnection()
                Dim foundUser As Boolean = False
                foundUser = _adapter.FetchEntityUsingUniqueConstraint(user, user.ConstructFilterForUCUserNameApplicationName())


                If foundUser Then
                    u = GetMembershipUserFromEntity(user)

                    If userIsOnline Then
                        user.LastActivityDate = DateTime.Now
                        _adapter.SaveEntity(user)
                    End If
                End If
            Catch e As Exception
                Throw New ProviderException("Error getting user", e)
            Finally
                _adapter.CloseConnection()
            End Try

            Return u
        End Function


        '
        ' MembershipProvider.GetUser(Object, Boolean)
        '

        Public Overrides Function GetUser(ByVal providerUserKey As Object, _
        ByVal userIsOnline As Boolean) As MembershipUser

            Dim user As New UserEntity(Convert.ToInt32(providerUserKey))

            Dim u As MembershipUser = Nothing

            Try
                _adapter.OpenConnection()

                Dim foundUser As Boolean = _adapter.FetchEntity(user)

                If foundUser Then
                    u = GetMembershipUserFromEntity(user)

                    If userIsOnline Then
                        user.LastActivityDate = DateTime.Now
                        _adapter.SaveEntity(user)
                    End If
                End If
            Catch e As Exception
                Throw New ProviderException("Error getting user", e)
            Finally
                _adapter.CloseConnection()
            End Try

            Return u
        End Function


        '
        '
        ' MembershipProvider.UnlockUser
        '

        Public Overrides Function UnlockUser(ByVal username As String) As Boolean

            Dim user As New UserEntity
            user.IsLockedOut = False

            Dim bucket As New RelationPredicateBucket()
            bucket.PredicateExpression.Add(PredicateFactory.CompareValue(UserFieldIndex.UserName, ComparisonOperator.Equal, username))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Dim rowsAffected As Integer = 0

            Try
                rowsAffected = _adapter.UpdateEntitiesDirectly(user, bucket)
            Catch e As Exception
                Throw New ProviderException("Error unlocking user", e)
            Finally
                _adapter.CloseConnection()
            End Try

            If rowsAffected > 0 Then _
              Return True

            Return False
        End Function


        '
        ' MembershipProvider.GetUserNameByEmail
        '

        Public Overrides Function GetUserNameByEmail(ByVal email As String) As String

            Dim users As New EntityCollection(New UserEntityFactory())
            Dim bucket As New RelationPredicateBucket()
            bucket.PredicateExpression.Add(PredicateFactory.CompareValue(UserFieldIndex.Email, ComparisonOperator.Equal, email))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Dim username As String = ""

            Try
                _adapter.OpenConnection()
                _adapter.FetchEntityCollection(users, bucket)

                If (users.Count > 0) Then
                    username = CType(users(0), UserEntity).UserName
                End If
            Catch e As Exception
                Throw New ProviderException("Error getting user by email", e)
            Finally
                _adapter.CloseConnection()
            End Try

            If username Is Nothing Then _
              username = ""

            Return username
        End Function




        '
        ' MembershipProvider.ResetPassword
        '

        Public Overrides Function ResetPassword(ByVal username As String, ByVal answer As String) As String

            If Not EnablePasswordReset Then
                Throw New NotSupportedException("Password Reset is not enabled.")
            End If

            If answer Is Nothing AndAlso RequiresQuestionAndAnswer Then
                UpdateFailureCount(username, "passwordAnswer")

                Throw New ProviderException("Password answer required for password Reset.")
            End If

            Dim newPassword As String = _
              System.Web.Security.Membership.GeneratePassword(newPasswordLength, MinRequiredNonAlphanumericCharacters)


            Dim Args As ValidatePasswordEventArgs = _
              New ValidatePasswordEventArgs(username, newPassword, True)

            OnValidatingPassword(Args)

            If Args.Cancel Then
                If Not Args.FailureInformation Is Nothing Then
                    Throw Args.FailureInformation
                Else
                    Throw New MembershipPasswordException("Reset password canceled due to password validation failure.")
                End If
            End If


            Dim user As New UserEntity()
            user.UserName = username
            user.ApplicationName = Me.ApplicationName

            Dim userUpdated As Boolean = False
            Dim passwordAnswer As String = ""

            Try
                _adapter.OpenConnection()

                Dim foundUser As Boolean = _adapter.FetchEntityUsingUniqueConstraint(user, user.ConstructFilterForUCUserNameApplicationName())

                If foundUser Then

                    If user.IsLockedOut Then
                        Throw New MembershipPasswordException("The supplied user is locked out.")
                    End If

                    passwordAnswer = user.PasswordAnswer
                Else
                    Throw New MembershipPasswordException("The supplied user name is not found.")
                End If

                If RequiresQuestionAndAnswer AndAlso Not CheckPassword(answer, passwordAnswer) Then
                    UpdateFailureCount(username, "passwordAnswer")

                    Throw New MembershipPasswordException("Incorrect password answer.")
                End If

                user.LastPasswordChangeDate = DateTime.Now
                user.Password = EncodePassword(newPassword)

                userUpdated = _adapter.SaveEntity(user)
            Catch e As Exception
                Throw New ProviderException("Error resetting password", e)
            Finally
                _adapter.CloseConnection()
            End Try

            If userUpdated Then
                Return newPassword
            Else
                Throw New MembershipPasswordException("User not found, or user is locked out. Password not Reset.")
            End If
        End Function


        '
        ' MembershipProvider.UpdateUser
        '

        Public Overrides Sub UpdateUser(ByVal user As MembershipUser)

            Dim userEntity As New UserEntity()
            userEntity.Email = user.Email
            userEntity.Description = user.Comment
            userEntity.IsApproved = user.IsApproved

            Dim bucket As New RelationPredicateBucket()
            bucket.PredicateExpression.Add(PredicateFactory.CompareValue(UserFieldIndex.UserName, ComparisonOperator.Equal, user.UserName))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Try
                _adapter.OpenConnection()

                _adapter.UpdateEntitiesDirectly(userEntity, bucket)

            Catch e As Exception
                Throw New ProviderException("Error updating user", e)
            Finally
                _adapter.CloseConnection()
            End Try
        End Sub


        '
        ' MembershipProvider.ValidateUser
        '

        Public Overrides Function ValidateUser(ByVal username As String, ByVal password As String) As Boolean
            Dim isValid As Boolean = False

            Dim users As New EntityCollection(New UserEntityFactory())
            Dim bucket As New RelationPredicateBucket
            bucket.PredicateExpression.Add(PredicateFactory.CompareValue(UserFieldIndex.UserName, ComparisonOperator.Equal, username))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.IsLockedOut, ComparisonOperator.Equal, False))

            Dim isApproved As Boolean = False
            Dim pwd As String = ""

            Try
                _adapter.OpenConnection()

                _adapter.FetchEntityCollection(users, bucket)

                If users.Count > 0 Then
                    Dim user As UserEntity = CType(users(0), UserEntity)
                    pwd = user.Password
                    isApproved = user.IsApproved
                Else
                    Return False
                End If


                If CheckPassword(password, pwd) Then
                    If isApproved Then
                        isValid = True

                        Dim user As UserEntity = CType(users(0), UserEntity)
                        user.LastLoginDate = DateTime.Now
                        _adapter.SaveEntity(user)

                    End If
                Else
                    UpdateFailureCount(username, "password")
                End If
            Catch e As Exception
                Throw New ProviderException("Error validating user", e)
            Finally

                _adapter.CloseConnection()
            End Try

            Return isValid
        End Function


        '
        ' UpdateFailureCount
        '   A helper method that performs the checks and updates associated with
        ' password failure tracking.
        '

        Private Sub UpdateFailureCount(ByVal username As String, ByVal failureType As String)

            Dim user As New UserEntity()
            user.UserName = username
            user.ApplicationName = Me.ApplicationName

            Dim windowStart As DateTime = New DateTime()
            Dim failureCount As Integer = 0

            Try
                _adapter.OpenConnection()

                Dim foundUser As Boolean = False

                foundUser = _adapter.FetchEntityUsingUniqueConstraint(user, user.ConstructFilterForUCUserNameApplicationName())

                If foundUser Then

                    If failureType = "password" Then
                        failureCount = user.FailedPasswordAttemptCount
                        windowStart = user.FailedPasswordAttemptWindowStart
                    End If

                    If failureType = "passwordAnswer" Then
                        failureCount = user.FailedPasswordAnswerAttemptCount
                        windowStart = user.FailedPasswordAnswerAttemptWindowStart
                    End If
                End If

                Dim windowEnd As DateTime = windowStart.AddMinutes(PasswordAttemptWindow)

                If failureCount = 0 OrElse DateTime.Now > windowEnd Then
                    ' First password failure or outside of PasswordAttemptWindow. 
                    ' Start a New password failure count from 1 and a New window starting now.

                    If failureType = "password" Then
                        user.FailedPasswordAttemptCount = 1
                        user.FailedPasswordAttemptWindowStart = DateTime.Now
                    End If

                    If failureType = "passwordAnswer" Then
                        user.FailedPasswordAnswerAttemptCount = 1
                        user.FailedPasswordAnswerAttemptWindowStart = DateTime.Now
                    End If


                    If _adapter.SaveEntity(user) = False Then _
                      Throw New ProviderException("Unable to update failure count and window start.")
                Else
                    failureCount += 1

                    If failureCount >= MaxInvalidPasswordAttempts Then
                        ' Password attempts have exceeded the failure threshold. Lock out
                        ' the user.

                        user.IsLockedOut = True
                        user.LastLockedOutDate = DateTime.Now

                        If _adapter.SaveEntity(user) = False Then _
                          Throw New ProviderException("Unable to lock out user.")
                    Else
                        ' Password attempts have not exceeded the failure threshold. Update
                        ' the failure counts. Leave the window the same.

                        If failureType = "password" Then
                            user.FailedPasswordAttemptCount = failureCount
                        End If

                        If failureType = "passwordAnswer" Then
                            user.FailedPasswordAnswerAttemptCount = failureCount
                        End If

                        If _adapter.SaveEntity(user) = False Then _
                          Throw New ProviderException("Unable to update failure count.")
                    End If
                End If
            Catch e As Exception
                Throw New ProviderException("Error updating failure count", e)
            Finally
                _adapter.CloseConnection()
            End Try
        End Sub


        '
        ' CheckPassword
        '   Compares password values based on the MembershipPasswordFormat.
        '

        Private Function CheckPassword(ByVal password As String, ByVal dbpassword As String) As Boolean
            Dim pass1 As String = password
            Dim pass2 As String = dbpassword

            Select Case PasswordFormat
                Case MembershipPasswordFormat.Encrypted
                    pass2 = UnEncodePassword(dbpassword)
                Case MembershipPasswordFormat.Hashed
                    pass1 = EncodePassword(password)
                Case Else
            End Select

            If pass1 = pass2 Then
                Return True
            End If

            Return False
        End Function


        '
        ' EncodePassword
        '   Encrypts, Hashes, or leaves the password clear based on the PasswordFormat.
        '

        Private Function EncodePassword(ByVal password As String) As String
            Dim encodedPassword As String = password

            Select Case PasswordFormat
                Case MembershipPasswordFormat.Clear

                Case MembershipPasswordFormat.Encrypted
                    encodedPassword = _
                      Convert.ToBase64String(EncryptPassword(Encoding.Unicode.GetBytes(password)))
                Case MembershipPasswordFormat.Hashed
                    Dim hash As HMACSHA1 = New HMACSHA1()
                    hash.Key = HexToByte(machineKey.ValidationKey)
                    encodedPassword = _
                      Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password)))
                Case Else
                    Throw New ProviderException("Unsupported password format.")
            End Select

            Return encodedPassword
        End Function


        '
        ' UnEncodePassword
        '   Decrypts or leaves the password clear based on the PasswordFormat.
        '

        Private Function UnEncodePassword(ByVal encodedPassword As String) As String
            Dim password As String = encodedPassword

            Select Case PasswordFormat
                Case MembershipPasswordFormat.Clear

                Case MembershipPasswordFormat.Encrypted
                    password = _
                      Encoding.Unicode.GetString(DecryptPassword(Convert.FromBase64String(password)))
                Case MembershipPasswordFormat.Hashed
                    Throw New ProviderException("Cannot unencode a hashed password.")
                Case Else
                    Throw New ProviderException("Unsupported password format.")
            End Select

            Return password
        End Function

        '
        ' HexToByte
        '   Converts a hexadecimal string to a byte array. Used to convert encryption
        ' key values from the configuration.
        '

        Private Function HexToByte(ByVal hexString As String) As Byte()
            Dim ReturnBytes(hexString.Length \ 2) As Byte
            For i As Integer = 0 To ReturnBytes.Length - 1
                ReturnBytes(i) = Convert.ToByte(hexString.Substring(i * 2, 2), 16)
            Next
            Return ReturnBytes
        End Function


        '
        ' MembershipProvider.FindUsersByName
        '

        Public Overrides Function FindUsersByName(ByVal usernameToMatch As String, _
        ByVal pageIndex As Integer, _
        ByVal pageSize As Integer, _
                                                  ByRef totalRecords As Integer) _
                                  As MembershipUserCollection

            Dim usersByName As New EntityCollection(New UserEntityFactory())
            Dim bucket As New RelationPredicateBucket()
            bucket.PredicateExpression.Add(PredicateFactory.Like(UserFieldIndex.UserName, "%" & usernameToMatch & "%"))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Dim users As MembershipUserCollection = New MembershipUserCollection()

            Try
                _adapter.OpenConnection()

                _adapter.FetchEntityCollection(usersByName, bucket)

                totalRecords = usersByName.Count

                If totalRecords <= 0 Then Return users

                Dim counter As Integer = 0
                Dim startIndex As Integer = pageSize * pageIndex
                Dim endIndex As Integer = startIndex + pageSize - 1

                Do While counter < totalRecords
                    If counter >= startIndex Then
                        Dim u As MembershipUser = GetMembershipUserFromEntity(usersByName(counter))
                        users.Add(u)
                    End If

                    counter += 1
                Loop
            Catch e As Exception
                Throw New ProviderException("Error finding users by name", e)
            Finally
                _adapter.CloseConnection()
            End Try

            Return users
        End Function

        '
        ' MembershipProvider.FindUsersByEmail
        '

        Public Overrides Function FindUsersByEmail(ByVal emailToMatch As String, _
        ByVal pageIndex As Integer, _
        ByVal pageSize As Integer, _
                                                   ByRef totalRecords As Integer) _
                                  As MembershipUserCollection

            Dim usersByEmail As New EntityCollection(New UserEntityFactory())
            Dim bucket As New RelationPredicateBucket()
            bucket.PredicateExpression.Add(PredicateFactory.Like(UserFieldIndex.Email, "%" & emailToMatch & "%"))
            bucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Dim users As MembershipUserCollection = New MembershipUserCollection()

            totalRecords = 0

            Try
                _adapter.OpenConnection()

                _adapter.FetchEntityCollection(usersByEmail, bucket)

                totalRecords = usersByEmail.Count

                If totalRecords <= 0 Then Return users

                Dim counter As Integer = 0
                Dim startIndex As Integer = pageSize * pageIndex
                Dim endIndex As Integer = startIndex + pageSize - 1

                Do While counter < totalRecords
                    If counter >= startIndex Then
                        Dim u As MembershipUser = GetMembershipUserFromEntity(usersByEmail(counter))
                        users.Add(u)
                    End If

                    counter += 1
                Loop
            Catch e As Exception
                Throw New ProviderException("Error finding users by email", e)
            Finally
                _adapter.CloseConnection()
            End Try

            Return users
        End Function


    End Class
End Namespace


Next is the Role provider code:


Imports System.Web.Security
Imports System.Configuration.Provider
Imports System.Collections.Specialized
Imports System
Imports System.Data
Imports System.Data.Odbc
Imports System.Configuration
Imports System.Diagnostics
Imports System.Web
Imports System.Globalization
Imports System.Security.Cryptography
Imports System.Text
Imports System.Web.Configuration

Imports SD.LLBLGen.Pro.ORMSupportClasses
Imports YourProject.DAL
Imports YourProject.DAL.DatabaseSpecific
Imports YourProject.DAL.EntityClasses
Imports YourProject.DAL.HelperClasses
Imports YourProject.DAL.FactoryClasses
Imports YourProject.DAL.RelationClasses
Imports YourProject.DAL.ValidatorClasses

Namespace YourProject.Providers

    Public NotInheritable Class MyRoleProvider
        Inherits RoleProvider

        Private _adapter As DataAccessAdapter2

        Public Overrides Sub Initialize(ByVal name As String, ByVal config As NameValueCollection)


            '
            ' Initialize values from web.config.
            '

            If config Is Nothing Then _
              Throw New ArgumentNullException("config")

            If name Is Nothing OrElse name.Length = 0 Then _
              name = "MyRoleProvider"

            If String.IsNullOrEmpty(config("description")) Then
                config.Remove("description")
                config.Add("description", "Interacts with custom tables in the Membership database")
            End If

            ' Initialize the abstract base class.
            MyBase.Initialize(name, config)


            If config("applicationName") Is Nothing OrElse config("applicationName").Trim() = "" Then
                pApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath
            Else
                pApplicationName = config("applicationName")
            End If


            _adapter = New DataAccessAdapter2()

        End Sub



        '
        ' System.Web.Security.RoleProvider properties.
        '   

        Private pApplicationName As String

        Public Overrides Property ApplicationName() As String
            Get
                Return pApplicationName
            End Get
            Set(ByVal value As String)
                pApplicationName = value
            End Set
        End Property


        '
        ' System.Web.Security.RoleProvider methods.
        '

        '
        ' RoleProvider.AddUsersToRoles
        '

        Public Overrides Sub AddUsersToRoles(ByVal userNames As String(), ByVal roleNames As String())

            For Each rolename As String In roleNames
                If Not RoleExists(rolename) Then
                    Throw New ProviderException("Role name not found.")
                End If
            Next

            For Each username As String In userNames
                If username.IndexOf(",") > 0 Then
                    Throw New ArgumentException("User names cannot contain commas.")
                End If

                For Each rolename As String In roleNames
                    If IsUserInRole(username, rolename) Then
                        Throw New ProviderException("User is already in role.")
                    End If
                Next
            Next


            ' Get all users specified
            Dim users As New EntityCollection(New UserEntityFactory())
            Dim usersBucket As New RelationPredicateBucket()
            usersBucket.PredicateExpression.Add(PredicateFactory.CompareRange(UserFieldIndex.UserName, userNames))
            usersBucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))


            ' get all roles specified
            Dim roles As New EntityCollection(New RoleEntityFactory())
            Dim rolesBucket As New RelationPredicateBucket()
            rolesBucket.PredicateExpression.Add(PredicateFactory.CompareRange(RoleFieldIndex.Name, roleNames))
            rolesBucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(RoleFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            ' Create a collection of userRoles to push out to the database when filled. 
            Dim userRoles As New EntityCollection(New UserRoleEntityFactory())

            Try
                _adapter.OpenConnection()
                _adapter.FetchEntityCollection(users, usersBucket)
                _adapter.FetchEntityCollection(roles, rolesBucket)

                For Each user As UserEntity In users
                    For Each role As RoleEntity In roles
                        Dim userRole As New UserRoleEntity()
                        userRole.RoleId = role.RoleId
                        userRole.UserId = user.UserId
                        userRole.ApplicationName = Me.ApplicationName

                        YourProject.DAL.DatabaseSpecific.DataAccessAdapter2.UpdateDetails(userRole)

                        userRoles.Add(userRole)
                    Next
                Next

                _adapter.SaveEntityCollection(userRoles)

            Catch e As Exception
                Throw New ProviderException("Error adding users to roles", e)
            Finally
                _adapter.CloseConnection()
            End Try
        End Sub


        '
        ' RoleProvider.CreateRole
        '

        Public Overrides Sub CreateRole(ByVal rolename As String)

            If rolename.IndexOf(",") > 0 Then
                Throw New ArgumentException("Role names cannot contain commas.")
            End If

            If RoleExists(rolename) Then
                Throw New ProviderException("Role name already exists.")
            End If

            Dim role As New RoleEntity()
            role.Name = rolename
            role.ApplicationName = Me.ApplicationName
            role.Active = True

            Try
                _adapter.OpenConnection()
                _adapter.SaveEntity(role)
            Catch e As Exception
                Throw New ProviderException("Error creating role", e)
            Finally
                _adapter.CloseConnection()
            End Try
        End Sub


        '
        ' RoleProvider.DeleteRole
        '

        Public Overrides Function DeleteRole(ByVal rolename As String, ByVal throwOnPopulatedRole As Boolean) As Boolean

            If Not RoleExists(rolename) Then
                Throw New ProviderException("Role does not exist.")
            End If

            If throwOnPopulatedRole AndAlso GetUsersInRole(rolename).Length > 0 Then
                Throw New ProviderException("Cannot delete a populated role.")
            End If

            ' Delete user roles first
            Dim userRolesBucket As New RelationPredicateBucket()
            userRolesBucket.Relations.Add(UserRoleEntity.Relations.RoleEntityUsingRoleId)
            userRolesBucket.PredicateExpression.Add(PredicateFactory.CompareValue(RoleFieldIndex.Name, ComparisonOperator.Equal, rolename))
            userRolesBucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(RoleFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            ' Delete roles
            Dim roleBucket As New RelationPredicateBucket()
            roleBucket.PredicateExpression.Add(PredicateFactory.CompareValue(RoleFieldIndex.Name, ComparisonOperator.Equal, rolename))
            roleBucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(RoleFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Try
                _adapter.OpenConnection()
                _adapter.DeleteEntitiesDirectly("UserRole", userRolesBucket)
                _adapter.DeleteEntitiesDirectly("Role", roleBucket)
            Catch e As Exception
                Throw New ProviderException("Error deleting role", e)
            Finally
                _adapter.CloseConnection()
            End Try

            Return True
        End Function


        '
        ' RoleProvider.GetAllRoles
        '

        Public Overrides Function GetAllRoles() As String()
            Dim tmpRoleNames As String = ""

            Dim roles As New EntityCollection(New RoleEntityFactory())
            Dim rolesBucket As New RelationPredicateBucket()
            rolesBucket.PredicateExpression.Add(PredicateFactory.CompareValue(RoleFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Try
                _adapter.OpenConnection()

                _adapter.FetchEntityCollection(roles, rolesBucket)

                For Each role As RoleEntity In roles
                    tmpRoleNames &= role.Name & ","
                Next

            Catch e As Exception
                Throw New ProviderException("Error getting all roles.", e)

            Finally
                _adapter.CloseConnection()
            End Try

            If tmpRoleNames.Length > 0 Then
                ' Remove trailing comma.
                tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1)
                Return tmpRoleNames.Split(CChar(","))
            End If

            Return New String() {}
        End Function

        '
        ' RoleProvider.GetRolesForUser
        '

        Public Overrides Function GetRolesForUser(ByVal username As String) As String()

            Dim tmpRoleNames As String = ""

            Dim user As New UserEntity()
            Dim userPath As New PrefetchPath2(EntityType.UserEntity)

            userPath.Add(UserEntity.PrefetchPathRolesCollectionViaUserRole)

            user.UserName = username
            user.ApplicationName = Me.ApplicationName

            Try
                _adapter.OpenConnection()

                If _adapter.FetchEntityUsingUniqueConstraint(user, user.ConstructFilterForUCUserNameApplicationName(), userPath) Then
                    If user.RolesCollectionViaUserRole.Count > 0 Then
                        For Each role As RoleEntity In user.RolesCollectionViaUserRole
                            tmpRoleNames &= role.Name & ","
                        Next

                    End If

                End If

            Catch e As Exception
                Throw New ProviderException("Error getting roles for user.", e)
            Finally
                _adapter.CloseConnection()
            End Try

            If tmpRoleNames.Length > 0 Then
                ' Remove trailing comma.
                tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1)
                Return tmpRoleNames.Split(CChar(","))
            End If

            Return New String() {}
        End Function


        '
        ' RoleProvider.GetUsersInRole
        '

        Public Overrides Function GetUsersInRole(ByVal rolename As String) As String()
            Dim tmpUserNames As String = ""

            Dim role As New RoleEntity()
            role.Name = rolename
            role.ApplicationName = Me.ApplicationName

            Dim rolePath As New PrefetchPath2(EntityType.RoleEntity)
            rolePath.Add(RoleEntity.PrefetchPathUsersCollectionViaUserRole())

            Try
                _adapter.OpenConnection()

                If _adapter.FetchEntityUsingUniqueConstraint(role, role.ConstructFilterForUCNameApplicationName(), rolePath) Then
                    For Each user As UserEntity In role.UsersCollectionViaUserRole
                        tmpUserNames &= user.UserName & ","
                    Next
                End If

            Catch e As Exception
                Throw New ProviderException("Error getting users in role.", e)
            Finally
                _adapter.CloseConnection()
            End Try

            If tmpUserNames.Length > 0 Then
                ' Remove trailing comma.
                tmpUserNames = tmpUserNames.Substring(0, tmpUserNames.Length - 1)
                Return tmpUserNames.Split(CChar(","))
            End If

            Return New String() {}
        End Function


        '
        ' RoleProvider.IsUserInRole
        '

        Public Overrides Function IsUserInRole(ByVal username As String, ByVal rolename As String) As Boolean

            Dim userIsInRole As Boolean = False

            Dim users As New EntityCollection(New UserEntityFactory())

            Dim userBucket As New RelationPredicateBucket()
            userBucket.Relations.Add(UserEntity.Relations.UserRoleEntityUsingUserId)
            userBucket.Relations.Add(UserRoleEntity.Relations.RoleEntityUsingRoleId)

            userBucket.PredicateExpression.Add(PredicateFactory.CompareValue(RoleFieldIndex.Name, ComparisonOperator.Equal, rolename))
            userBucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.UserName, ComparisonOperator.Equal, username))
            userBucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareValue(UserFieldIndex.ApplicationName, ComparisonOperator.Equal, Me.ApplicationName))

            Try
                _adapter.OpenConnection()

                _adapter.FetchEntityCollection(users, userBucket)

                If users.Count > 0 Then
                    userIsInRole = True
                End If

            Catch e As Exception
                Throw New ProviderException("Error determining if user is in role.", e)
            Finally
                _adapter.CloseConnection()
            End Try

            Return userIsInRole
        End Function


        '
        ' RoleProvider.RemoveUsersFromRoles
        '

        Public Overrides Sub RemoveUsersFromRoles(ByVal usernames As String(), ByVal rolenames As String())


            For Each rolename As String In rolenames
                If Not RoleExists(rolename) Then
                    Throw New ProviderException("Role name not found.")
                End If
            Next

            For Each username As String In usernames
                For Each rolename As String In rolenames
                    If Not IsUserInRole(username, rolename) Then
                        Throw New ProviderException("User is not in role.")
                    End If
                Next
            Next

            Dim userRoles As New EntityCollection(New UserRoleEntityFactory())
            Dim userRolesBucket As New RelationPredicateBucket()

            userRolesBucket.Relations.Add(UserRoleEntity.Relations.RoleEntityUsingRoleId)
            userRolesBucket.Relations.Add(UserRoleEntity.Relations.UserEntityUsingUserId)

            userRolesBucket.PredicateExpression.Add(PredicateFactory.CompareRange(UserFieldIndex.UserName, usernames))
            userRolesBucket.PredicateExpression.AddWithAnd(PredicateFactory.CompareRange(RoleFieldIndex.Name, rolenames))

            Try

                _adapter.OpenConnection()

                _adapter.DeleteEntitiesDirectly("UserRoleEntity", userRolesBucket)

            Catch e As Exception
                Throw New ProviderException("Error deleting users from roles.", e)
            Finally
                _adapter.CloseConnection()
            End Try
        End Sub


        '
        ' RoleProvider.RoleExists
        '

        Public Overrides Function RoleExists(ByVal rolename As String) As Boolean
            Dim exists As Boolean = False

            Dim role As New RoleEntity()
            role.Name = rolename
            role.ApplicationName = Me.ApplicationName

            Try

                _adapter.OpenConnection()

                If _adapter.FetchEntityUsingUniqueConstraint(role, role.ConstructFilterForUCNameApplicationName()) Then
                    exists = True
                End If
            Catch e As Exception
                Throw New ProviderException("Error finding role.", e)
            Finally
                _adapter.CloseConnection()
            End Try

            Return exists
        End Function

        '
        ' RoleProvider.FindUsersInRole
        '

        Public Overrides Function FindUsersInRole(ByVal rolename As String, ByVal usernameToMatch As String) As String()

            Dim role As New RoleEntity()
            role.Name = rolename
            role.ApplicationName = Me.ApplicationName

            Dim rolePath As New PrefetchPath2(EntityType.RoleEntity)
            rolePath.Add(RoleEntity.PrefetchPathUsersCollectionViaUserRole)

            Dim tmpUserNames As String = ""

            Try
                _adapter.OpenConnection()

                If _adapter.FetchEntityUsingUniqueConstraint(role, role.ConstructFilterForUCNameApplicationName, rolePath) Then
                    For Each user As UserEntity In role.UsersCollectionViaUserRole
                        tmpUserNames &= user.UserName & ","
                    Next
                End If

            Catch e As Exception
                Throw New ProviderException("Error getting users in role.", e)
            Finally
                _adapter.CloseConnection()
            End Try

            If tmpUserNames.Length > 0 Then
                ' Remove trailing comma.
                tmpUserNames = tmpUserNames.Substring(0, tmpUserNames.Length - 1)
                Return tmpUserNames.Split(CChar(","))
            End If

            Return New String() {}
        End Function

    End Class
End Namespace



Next, you'll notice my code uses an object called DataAccessAdapter2.. This is just a standard DataAccessAdapter that uses the new ConnectionStrings element in .NET 2.0 applications. It also overrides the SaveEntity function to automatically records the CreatedDate, CreatedByUser, ModifiedDate, and ModifiedByUser fields which exist in every table of my application. And speaking of tables, here are the scripts to create the User, UserRole, and Role tables necessary for the membership code above to work.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Role]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Role](
    [RoleId] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](255) NOT NULL,
    [Active] [bit] NOT NULL,
    [Description] [varchar](max) NULL,
    [CreatedByUser] [varchar](50) NOT NULL,
    [CreatedDate] [datetime] NOT NULL,
    [ModifiedByUser] [varchar](50) NOT NULL,
    [ModifiedDate] [datetime] NOT NULL,
    [ApplicationName] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED 
(
    [RoleId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY],
 CONSTRAINT [IX_Role] UNIQUE NONCLUSTERED 
(
    [ApplicationName] ASC,
    [Name] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[UserRole]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[UserRole](
    [UserRoleId] [int] IDENTITY(1,1) NOT NULL,
    [RoleId] [int] NOT NULL,
    [UserId] [int] NOT NULL,
    [CreatedByUser] [varchar](50) NOT NULL,
    [CreatedDate] [datetime] NOT NULL,
    [ModifiedByUser] [varchar](50) NOT NULL,
    [ModifiedDate] [datetime] NOT NULL,
    [ApplicationName] [varchar](50) NOT NULL,
 CONSTRAINT [PK_UserRole] PRIMARY KEY CLUSTERED 
(
    [UserRoleId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[User]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[User](
    [UserId] [int] IDENTITY(1,1) NOT NULL,
    [SchoolId] [int] NOT NULL CONSTRAINT [DF_User_SchoolId]  DEFAULT ((0)),
    [UserName] [varchar](50) NOT NULL,
    [Password] [varchar](50) NOT NULL,
    [FirstName] [varchar](50) NOT NULL CONSTRAINT [DF_User_FirstName]  DEFAULT ('default'),
    [LastName] [varchar](50) NOT NULL CONSTRAINT [DF_User_LastName]  DEFAULT ('default'),
    [Email] [varchar](100) NULL,
    [Description] [varchar](max) NULL,
    [ApplicationName] [varchar](50) NULL,
    [PasswordQuestion] [varchar](255) NULL,
    [PasswordAnswer] [varchar](255) NULL,
    [IsApproved] [bit] NULL,
    [LastActivityDate] [datetime] NULL,
    [LastLoginDate] [datetime] NULL,
    [LastPasswordChangeDate] [datetime] NULL,
    [LastLockedOutDate] [datetime] NULL,
    [IsOnline] [bit] NULL,
    [IsLockedOut] [bit] NULL,
    [FailedPasswordAttemptCount] [int] NULL,
    [FailedPasswordAttemptWindowStart] [datetime] NULL,
    [FailedPasswordAnswerAttemptCount] [int] NULL,
    [FailedPasswordAnswerAttemptWindowStart] [datetime] NULL,
    [ShowAdvancedStandardsOptions] [bit] NULL,
    [AllowClassManagement] [bit] NULL,
    [CreatedByUser] [varchar](50) NOT NULL,
    [CreatedDate] [datetime] NOT NULL,
    [ModifiedByUser] [varchar](50) NOT NULL,
    [ModifiedDate] [datetime] NOT NULL,
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [UserId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY],
 CONSTRAINT [IX_User] UNIQUE NONCLUSTERED 
(
    [UserName] ASC,
    [ApplicationName] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_UserRole_Role]') AND parent_object_id = OBJECT_ID(N'[dbo].[UserRole]'))
ALTER TABLE [dbo].[UserRole]  WITH CHECK ADD  CONSTRAINT [FK_UserRole_Role] FOREIGN KEY([RoleId])
REFERENCES [dbo].[Role] ([RoleId])
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_UserRole_User]') AND parent_object_id = OBJECT_ID(N'[dbo].[UserRole]'))
ALTER TABLE [dbo].[UserRole]  WITH CHECK ADD  CONSTRAINT [FK_UserRole_User] FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([UserId])
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_User_School]') AND parent_object_id = OBJECT_ID(N'[dbo].[User]'))
ALTER TABLE [dbo].[User]  WITH NOCHECK ADD  CONSTRAINT [FK_User_School] FOREIGN KEY([SchoolId])
REFERENCES [dbo].[School] ([SchoolId])
NOT FOR REPLICATION 

Wiring it all up is as simple as changing your web.config to look something like this:


        <roleManager defaultProvider="MyRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName=".ASPROLES" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All">
            <providers>
                <clear/>
                <add name="MyRoleProvider" type="MyProject.Providers.MyRoleProvider" connectionStringName="YourSqlServer" applicationName="YourApplicationName"/>
            </providers>
        </roleManager>

        <membership defaultProvider="MyMembershipProvider (SQL)">
            <providers>
                <add connectionStringName="YourSqlServer" applicationName="YourApplicationName" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Clear" maxInvalidPasswordAttempts="5" passwordAttemptWindow="10" name="MyMembershipProvider (SQL)" type="YourProject.Providers.MyMembershipProvider"/>
            </providers>
        </membership>

    <connectionStrings>
        <remove name="YourSqlServer"/>
        <add name="YourSqlServer" connectionString="Data Source=(local);Initial Catalog=YourDB;Integrated Security=True" providerName="System.Data.SqlClient"/>
    </connectionStrings>

pilotboba
User
Posts: 434
Joined: 05-Aug-2005
# Posted on: 06-Mar-2006 23:03:07   

alexdresko wrote:

Finally got approval to post this code.

What features does your code provide that the default providers don't? If the purpose is to just replace ADO.Net code with LLBLGEN code I don't see the reason for that?

alexdresko wrote:

Finally got approval to post this code. One thing I know that can be enhanced is in the role provider. My app won't ever have more than like 5 roles total so I don't see a problem caching that information in the Application object thus speeding up the Membership.IsInRole functions.

FYI: The default role manager provider can cache a users roles in his cookie, so if you are only assigning a single user role you can go that route.

BOb

erichar11
User
Posts: 268
Joined: 08-Dec-2003
# Posted on: 06-Mar-2006 23:50:30   

Thanks Alex, this is great. I'm going to convert the code to c# and give it a try. One thing I noticed is that you have an Entity called UserEntity. I'm guessing you changed the name of the Aspnet_Users table to User.

Did you do this in the designer, or did you create a new table called user in the db instead of using Aspnet_users (just renamed)?

Also are there other name changes I need to know about (for example, roles, membership, etc)?

Lastly, you mentioned creating a dataaccessadapter2 which I assume modifies the OnSave event. Could you please also provide the code for the dataaccessadapter2 class? This would help me get up and running quickly.

Thanks

alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 07-Mar-2006 16:04:48   

pilotboba wrote:

What features does your code provide that the default providers don't? If the purpose is to just replace ADO.Net code with LLBLGEN code I don't see the reason for that?

The default provider uses tables which must be installed via aspnet_regsql. Those tables are named aspnet_* where * = User, Role, Profile, etc... Those tables used GUIDs for keys and a couple other SQL specific things that I didn't want my application to inherit. I created my own tables because I wanted to be able to modify the structure of those tables without having to worry about MS or some other developer using aspnet_regsql again to overwrite my schema. I also wanted to store user specific information in the User table instead of using the default Profile provider. Nor did I want to create my own Profile provider.

You're right. It doesn't provide any additional functionality otherwise.

For the other person who asked, here's the code for the DataAccessAdapter2 class that I thought I included in my first post but didn't..

Imports System
Imports System.Configuration
Imports System.Web.Security

Namespace YourProject.DAL.DatabaseSpecific
    Public Class DataAccessAdapter2
        Inherits DataAccessAdapter

        Public Sub New()
            MyBase.New(GetConnectionString())
        End Sub

        Public Sub New(ByVal keepConnectionOpen As Boolean)
            MyBase.New(GetConnectionString(), keepConnectionOpen)
        End Sub

        ' Utility function to get the connection string from the web.config
        ' Uses the new ConnectionStrings area. 
        Public Shared Function GetConnectionString() As String
            Dim connectionStringName As String = System.Configuration.ConfigurationManager.AppSettings("ConnectionStringToUse")

            Dim connectionStringSettings As ConnectionStringSettings = ConfigurationManager.ConnectionStrings(connectionStringName)

            If connectionStringSettings Is Nothing OrElse connectionStringSettings.ConnectionString.Trim() = "" Then
                Throw New Provider.ProviderException("Connection string cannot be blank.")
            End If

            Dim connectionString As String = connectionStringSettings.ConnectionString

            Return connectionString

        End Function

        Public Overrides Function SaveEntity(ByVal entityToSave As SD.LLBLGen.Pro.ORMSupportClasses.IEntity2, ByVal refetchAfterSave As Boolean, ByVal updateRestriction As SD.LLBLGen.Pro.ORMSupportClasses.IPredicateExpression, ByVal recurse As Boolean) As Boolean
            UpdateDetails(entityToSave)
            Return MyBase.SaveEntity(entityToSave, refetchAfterSave, updateRestriction, recurse)
        End Function


        Public Shared Sub UpdateDetails(ByRef entity As SD.LLBLGen.Pro.ORMSupportClasses.IEntity2)
            UpdateDetails(entity, True)
        End Sub

        Public Shared Sub UpdateDetails(ByRef entity As SD.LLBLGen.Pro.ORMSupportClasses.IEntity2, ByVal updateCreated As Boolean)
            Dim userName As String = ""
            If ((System.Web.HttpContext.Current Is Nothing) _
                        OrElse ((System.Web.HttpContext.Current.User Is Nothing) _
                        OrElse (System.Web.HttpContext.Current.User.Identity.Name = ""))) Then
            Else
                userName = System.Web.HttpContext.Current.User.Identity.Name

            End If

            If (String.IsNullOrEmpty(userName)) Then
                userName = "default"
            End If

            If (updateCreated AndAlso entity.Fields.State = SD.LLBLGen.Pro.ORMSupportClasses.EntityState.New) Then
                SetFieldValue(entity, "CreatedByUser", userName)
                SetFieldValue(entity, "CreatedDate", DateTime.Now)
                SetFieldValue(entity, "ModifiedByUser", userName)
                SetFieldValue(entity, "ModifiedDate", DateTime.Now)
            Else
                SetFieldValue(entity, "ModifiedByUser", userName.ToString)
                SetFieldValue(entity, "ModifiedDate", DateTime.Now)
            End If
        End Sub

        Private Shared Sub SetFieldValue(ByVal entity As SD.LLBLGen.Pro.ORMSupportClasses.IEntity2, ByVal fieldName As String, ByVal fieldValue As Object)
            If (Not entity.Fields(fieldName) Is Nothing) Then
                entity.Fields(fieldName).CurrentValue = fieldValue
            End If

        End Sub


    End Class
End Namespace

If you get the code to work, it should work no differently than the built in providers. Note that I didn't create my own Profile provider, so you'll need to create your own if you plan on using that feature.

pilotboba
User
Posts: 434
Joined: 05-Aug-2005
# Posted on: 08-Mar-2006 23:20:14   

alexdresko wrote:

The default provider uses tables which must be installed via aspnet_regsql. Those tables are named aspnet_* where * = User, Role, Profile, etc... Those tables used GUIDs for keys and a couple other SQL specific things that I didn't want my application to inherit. I created my own tables because I wanted to be able to modify the structure of those tables without having to worry about MS or some other developer using aspnet_regsql again to overwrite my schema. I also wanted to store user specific information in the User table instead of using the default Profile provider. Nor did I want to create my own Profile provider.

Those are perfectly good reasons! I was just curious. We actually need to create our own because we provide "roles" as asp.net calls it for every task in the system. So, since there are so many "roles" we call them permissions in our app, we create a way for them to aggregate the permissions with what we call roles in our app.

you said you added some additional attribures to the membership table. Does this get exposed by default in the Membership object or do you have to provide a custom one of those also. Like you I need to add some things, but I was planning to just put it into the profile. What is the reason you didn't just use the profile?

Thanks, BOb

pilotboba
User
Posts: 434
Joined: 05-Aug-2005
# Posted on: 08-Mar-2006 23:21:00   

omar wrote:

I am considering utilizing the CAZE engine to implement authorization security in a future application. Hoped to check if any LLBL'ers have used it in their own applications? http://lamarvin.com/caze_default.asp

I looked at CAZE and it sounds interesting... But, I think Enterprise Library 2.x gives you pretty much all those features for free.

BOb

erichar11
User
Posts: 268
Joined: 08-Dec-2003
# Posted on: 09-Mar-2006 00:30:37   

You said you added some additional attribures to the membership table. Does this get exposed by default in the Membership object or do you have to provide a custom one of those also. Like you I need to add some things, but I was planning to just put it into the profile. What is the reason you didn't just use the profile?

I can't speak for Alex, but storing data in the profile is stored basically as a blob. In other words there is really no way filter, sort, etc on profile data. However, there is a ProfileTableProvider (http://www.asp.net/sandbox/samp_profiles.aspx?tabindex=0&tabid=1) which I'm looking to implement which allows you to store the profile data in a table. This way, using llblenPro you have full access to the profile data for filtering. This was a big problem for me in not using the profile data.

Eric

alexdresko
User
Posts: 336
Joined: 08-Jun-2004
# Posted on: 09-Mar-2006 15:05:44   

erichar11 wrote:

You said you added some additional attribures to the membership table. Does this get exposed by default in the Membership object or do you have to provide a custom one of those also. Like you I need to add some things, but I was planning to just put it into the profile. What is the reason you didn't just use the profile?

I can't speak for Alex, but storing data in the profile is stored basically as a blob. In other words there is really no way filter, sort, etc on profile data. However, there is a ProfileTableProvider (http://www.asp.net/sandbox/samp_profiles.aspx?tabindex=0&tabid=1) which I'm looking to implement which allows you to store the profile data in a table. This way, using llblenPro you have full access to the profile data for filtering. This was a big problem for me in not using the profile data.

Eric

Now we're talkin meat and potatoes here. These were all concerns I had when I started out on this project. It would appear that MS wants us to use the Profile provider for storing extra information, but as Eric said, there isn't a way to filter users on that profile data. At least, I'm pretty sure there isn't. If you want all users in SC, for excample, You have to loop through every user, get their profile data, check to see if it exists, and add that user to some external collection. Had the ProfileTableProvider existed when I started my project, I might have used that. For now, I have a manager class that works with users to handle the extra fields.