Join-Website.ps1

function Join-Website
{
    param(        
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [Hashtable]$RequiredInfo,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [Hashtable]$OptionalInfo,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$StorageAccountSetting = "AzureStorageAccountName",
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$StorageKeySetting = "AzureStorageAccountKey",
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$SmtpServer,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [Switch]$UseSsl,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$FromEmail,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$FromUser,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$EmailPasswordSetting,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$TermsOfService,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$ExchangeServer,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$UserTable,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$IntroMessage,

    [Parameter(ValueFromPipelineByPropertyName=$true)]    
    [string]$ConfirmationMailSentMessage,
        
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$userPartition = "Users",
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$FacebookAppId,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [Double]$InitialBalance = 0,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [Double]$LockoutBalance = -10,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$BlacklistParition,
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [string]$WhitelistPartition,
    
    # The URL for the website
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
    [string]$WebsiteUrl
    )
    
    process {
        if (-not ($Request -and $Response -and $Session)) {
            throw "Must run within a web site"
        }
        
        $finalUrl = if ($WebSiteUrl -like "*Module.ashx") {
            $WebSiteUrl 
        } else {
            "$WebSiteUrl".TrimEnd("/") += "/Module.ashx"
        }
    
        $siteName = if ($module.Name) {
            $module.Name
        } else {
            "Website"
        }
        $DisplayForm = $false
        $FormErrors = ""
                                    
        if (-not $request["Join-${siteName}_EmailAddress"]) {
            #$missingFields
            $displayForm = $true
        }
        
        $newUserData =@{}
        
        $missingFields = @()
        $paramBlock = @()
        if ($session['ProfileEditMode'] -eq $true) {
            $editMode = $true
        }
        $defaultValue = if ($editMode -and $session['User'].UserEmail) {
            "|Default $($session['User'].UserEmail)"
        } else {
            ""
        }
        
        if ($Request['ReferredBy']) {
            $session['ReferredBy'] = $Request['ReferredBy']
        }
        
        $paramBlock += "
        #$defaultValue
        [Parameter(Mandatory=`$true,Position=0)]
        [string]
        `$EmailAddress
        "

        
        if ($RequiredInfo) {
        
            $Position = 1
        
            foreach ($k in $RequiredInfo.Keys) {
                $newUserData[$k] = $request["Join-${siteName}_${k}"] -as $RequiredInfo[$k]
                $defaultValue = if ($session['User'].$k) {
                    "|Default $($session['User'].$k)"
                } else {
                    ""
                }
                
                $paramBlock += "
        #$defaultValue
        [Parameter(Mandatory=`$true,Position=$position)]
        [$($RequiredInfo[$k].Fullname)]
        `$$k
        "

                $Position++
                if (-not $newUserData[$k]) { 
                    $missingFields += $k
                }
            }
        
        }
        
        
        if ($OptionalInfo) {
        
            foreach ($k in $OptionalInfo.Keys) {
                $newUserData[$k] = $request["Join-${siteName}_${k}"] -as $OptionalInfo[$k]
                $defaultValue = if ($session['User'].$k) {
                    "|Default $($session['User'].$k)"
                } else {
                    ""
                }
                $paramBlock += "
        #${defaultValue}
        [Parameter(Position=$position)]
        [$($OptionalInfo[$k].Fullname)]
        `$$k
        "

            }
        
        }
        
        
        if ($TermsOfService) {
        
        }
        
        .([ScriptBlock]::Create(
            "function Join-$Sitename {
                <#
                .Synopsis
                    Joins $Sitename or edits a profile
                .Description
                        
                #>
                param(
                $($paramBlock -join ",$([Environment]::NewLine)")
                )
            }
            "
))
        
        $cmdInput = Get-WebInput -CommandMetaData (Get-Command "Join-$Sitename" -CommandType Function)
        if ($cmdInput.Count -gt 0) {
            $DisplayForm = $false
        }
        
        
        if ($missingFields) {
            $email = $request["Join-${siteName}_EmailAddress"]
            $emailFound = [ScriptBlock]::Create("`$_.UserEmail -eq '$email'")
            $storageAccount = (Get-WebConfigurationSetting -Setting $StorageAccountSetting)
            $storageKey = (Get-WebConfigurationSetting -Setting $StorageKeySetting)

            $mailAlreadyExists = 
                Search-AzureTable -TableName $UserTable -StorageAccount $storageAccount -StorageKey $storageKey  -Where $emailFound

            if (-not $mailAlreadyExists) {
                # Get required fields
                $DisplayForm = $true
            } elseif ($editMode -and $session['User']) {
                # Get required fields
                $DisplayForm = $true
            } else {
                # Reconfirm
                $DisplayForm = $false
            }
            
        }

                
        $sendMailParams = @{
            BodyAsHtml = $true
            To = $request["Join-${siteName}_EmailAddress"]
            
        }
        
        $sendMailCommand = if ($SmtpServer -and $FromEmail -and $FromUser -and $EmailPasswordSetting) {
            $($ExecutionContext.InvokeCommand.GetCommand("Send-MailMessage", "All"))
            $un  = $FromUser
            $pass = Get-WebConfigurationSetting -Setting $EmailPasswordSetting
            $pass = ConvertTo-SecureString $pass  -AsPlainText -Force 
            $cred = 
                New-Object Management.Automation.PSCredential ".\$un", $pass 
                    
            $sendMailParams += @{
                SmtpServer = $SmtpServer 
                From = $FromEmail
                Credential = $cred
                UseSsl = $useSsl
            }

        } else {
            $($ExecutionContext.InvokeCommand.GetCommand("Send-Email", "All"))
            $sendMailParams += @{
                UseWebConfiguration = $true
                AsJob = $true
            }
        }
        
        
        if ($displayForm) {
            $formErrors = if ($missingFields -and ($cmdInput.Count -ne 0)) {
                "Missing $missingFields"
            } else {
            
            }                                
            
            $buttonText = if ($mailAlreadyExists -or $session['User']) {
                "Edit Profile"                    
            } else {
                "Join / Login"
            }

            
            "
            $FormErrors
            $(Request-CommandInput -ButtonText $buttonText -Action "${WebsiteUrl}?join=true" -CommandMetaData (Get-Command "Join-${siteName}" -CommandType Function))
            "

            
        } else {
            $session['UserEmail'] = $request["Join-${siteName}_EmailAddress"]
            $session['UserData'] = $newUserData
            $session['EditMode'] = $editMode
            
            
            $storageAccount = (Get-WebConfigurationSetting -Setting $StorageAccountSetting)
            $storageKey = (Get-WebConfigurationSetting -Setting $StorageKeySetting)

            $email = $Session['UserEmail']
            $editMode = $session['EditMode']
            $session['EditMode'] = $null
            $emailFound = [ScriptBlock]::Create("`$_.UserEmail -eq '$email'")

            $userProfilePartition = $userPartition                

            
            $mailAlreadyExists = 
                Search-AzureTable -TableName $UserTable -StorageAccount $storageAccount -StorageKey $storageKey  -Where $emailFound |
                Where-Object {
                    $_.PartitionKey -eq $userProfilePartition
                }
            
            
            $newUserObject = New-Object PSObject -Property @{
                UserEmail = $Session['UserEmail']
                UserID = [GUID]::NewGuid()
                Confirmed = $false
                Created = Get-Date                
            }
            
            
            $ConfirmCode = [Guid]::NewGuid()
            $newUserObject.pstypenames.clear()
            $newUserObject.pstypenames.add("${siteName}_UserInfo")
            
            $extraPropCommonParameters = @{
                InputObject = $newUserObject
                MemberType = 'NoteProperty'
            }
                    
            Add-Member @extraPropCommonParameters -Name ConfirmCode -Value "$confirmCode"
            if ($session['UserData']) {
                foreach ($kvp in $session['UserData'].GetEnumerator()) {
                    Add-Member @extraPropCommonParameters -Name $kvp.Key -Value $kvp.Value
                }
            }
            
            $commonAzureParameters = @{
                TableName = $UserTable
                PartitionKey = $userProfilePartition
            }
            
            
            
            if ($mailAlreadyExists) {
                                                
                if ((-not $editMode) -or (-not $session['User'])) {
                
                    # Creating a brand new item via the email system. Email the confirmation code out.
                    $rootLocation= "$finalUrl".Substring(0, $finalUrl.LAstIndexOf("/"))
                    $introMessage = if ($IntroMessage) {
                        $IntroMessage + "<br/> <a href='${finalUrl}?confirmUser=$confirmCode'>Confirm Email Address</a>"
                    } else {
                        "<br/> <a href='${finalUrl}?confirmUser=$confirmCode'>Re-confirm Email Address to login</a>"
                    }
                    
                    $sendMailParams += @{
                        Subject= "Please re-confirm your email for ${siteName}"
                        Body = $introMessage
                    }                    
                    
                    
                    & $sendMailcommand @sendMailParams 
                    
                    "Account already exists. A request to login has been sent to $($mailAlreadyExists.UserEmail)." |
                        New-WebPage -Title "Email address is already registered, sending reconfirmation mail" -RedirectTo $rootLocation -RedirectIn "0:0:5"  |
                        Out-HTML -WriteResponse                                                           #
                        
                    <# Send-Email -To $newUserObject.UserEmail -UseWebConfiguration - -Body $introMessage -BodyAsHtml -AsJob
                    "Account already exists. A request to login has been sent to $($mailAlreadyExists.UserEmail)." |
                        New-WebPage -Title "Email address is already registered, sending reconfirmation mail" -RedirectTo $rootLocation -RedirectIn "0:0:5" |
                        Out-HTML -WriteResponse #>

                    
                    $mailAlreadyExists |
                        Add-Member NoteProperty ConfirmCode "$confirmCode" -Force -PassThru | 
                        Update-AzureTable @commonAzureParameters -RowKey $mailAlreadyExists.RowKey -Value { $_}
                } else {
                    
                    # Reconfirmation of Changes. If the user is logged in via facebook, then simply make the change. Otherwise, make the changes pending.
                    if (-not $FacebookAppId) {
                    
                        $introMessage = 
                        "<br/> <a href='${finalUrl}?confirmUser=$confirmCode'>Please confirm changes to your ${siteName} account</a>"                   
                        
                        $introMessage += "<br/><br/>"
                        $introMessage += New-Object PSObject -Property $session['UserData'] |
                            Out-HTML
                     
                        $sendMailParams += @{
                            Subject= "Please confirm changes to your ${siteName} account"
                            Body = $introMessage
                        }   
                        
                        & $sendMailcommand @sendMailParams
                        
                        "An email has been sent to $($mailAlreadyExists.UserEmail) to confirm the changes to your acccount" |
                            New-WebPage -Title "Confirming Changes" -RedirectTo $rootLocation -RedirectIn "0:0:5" |
                            Out-HTML -WriteResponse
                        
                        $mailAlreadyExists |
                            Add-Member NoteProperty ConfirmCode "$confirmCode" -Force -PassThru | 
                            Update-AzureTable @commonAzureParameters -RowKey $mailAlreadyExists.RowKey -Value { $_}
                        $changeToMake = @{} + $commonAzureParameters
                        
                        $changeToMake.PartitionKey = "${userProfilePartition}_PendingChanges"
                                            
                        # Create a row in the pending change table
                        $newUserObject.psobject.properties.Remove('ConfirmCode')
                        $newUserObject |
                            Set-AzureTable @changeToMake -RowKey {[GUID]::NewGuid() } 
                    } else {
                        # Make the profile change
                        $newUserObject |
                            Update-AzureTable @commonAzureParameters -RowKey $mailAlreadyExists.RowKey
                    }
                    
                        
                        
                }
                
                
            } else {
                # Check for a whitelist or blacklist within the user table
                if ($BlacklistPartition) {
                    $blackList = 
                        Search-AzureTable -TableName $pipeworks.UserTable.Name -Filter "PartitionKey eq '$($BlacklistPartition)'"                        
                        
                    if ($blacklist) {
                        foreach ($uInfo in $Blacklist) {
                            if ($newUserObject.UserEmail -like "*$uInfo*") {
                                Write-Error "$($newUserObject.UserEmai) is blacklisted from ${siteName}"
                                return
                            }
                        }
                    }
                }
                
                if ($WhitelistPartition) {
                    $whiteList = 
                        Search-AzureTable -TableName $pipeworks.UserTable.Name -Filter "PartitionKey eq '$($WhitelistParition)'"                        
                        
                    if ($whiteList) {
                        $inWhiteList = $false
                        foreach ($uInfo in $whiteList) {
                            if ($newUserObject.UserEmail -like "*$uInfo*") {
                                $inWhiteList = $true
                                break
                            }
                        }
                        if (-not $inWhiteList) {
                            Write-Error "$($newUserObject.UserEmai) is not on the whitelist for ${siteName}"
                        }
                    }

                }
                
                if ($InitialBalance) {
                    $newUserObject | 
                        Add-Member NoteProperty Balance (0- ([Double]$pipeworksManifest.UserTable.InitialBalance))
                }
            
                if ($session['RefferedBy']) {
                    $newUserObject |
                        Add-Member NoteProperty RefferedBy $session['RefferedBy'] -PassThru |
                        Add-Member NoteProperty RefferalCreditApplied $false 
                }
            
                $newUserObject |
                    Set-AzureTable @commonAzureParameters -RowKey $newUserObject.UserId
                    
                    
                $introMessage = if ($IntroMessage) {
                    $IntroMessage + "<br/> <a href='${finalUrl}?confirmUser=$confirmCode'>Confirm Email Address</a>"
                } else {
                    "<br/> <a href='${finalUrl}?confirmUser=$confirmCode'>Confirm Email Address</a>"
                }
                
                $sendMailParams += @{
                    Subject= "Please confirm your email for ${siteName}"
                    Body = $introMessage
                }
                & $sendMailcommand @sendMailParams
                                
                if ($passThru) {
                    $newUserObject
                }
                
                $almostWelcomeScreen  = if ($ConfirmationMailSentMessage) {
                    $ConfirmationMailSentMessage
                } else {
                    "A confirmation mail has been sent to $($newUserObject.UserEmail)"
                }
                                
                $html = New-Region -Content $almostWelcomeScreen -AsWidget -Style @{
                    'margin-left' = $MarginPercentLeftString
                    'margin-right' = $MarginPercentRightString
                    'margin-top' = '10px'   
                    'border' = '0px' 
                } |
                New-WebPage -Title "Welcome to ${siteName} | Confirmation Mail Sent" 
                
                $html
                
                
            }
            
        }    
    
    }    
}