@using WebMatrix.WebData

@* Remove this section if you are using bundling *@
@section Scripts {
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
}

@{
    WebSecurity.RequireAuthenticatedUser();

    Layout = "~/_SiteLayout.cshtml";
    Page.Title = "Manage Account";

    var action = Request.Form["action"];

    bool hasLocalAccount = OAuthWebSecurity.HasLocalAccount(WebSecurity.CurrentUserId);

    string successMessage = "";
    var message = Request.QueryString["message"];
    if (message == "ChangedPassword") {
        successMessage = "Your password has been changed.";
    } else if (message == "SetPassword") {
        successMessage = "Your password has been set.";
    } else if (message == "RemovedLogin") {
        successMessage = "The external login was removed.";
    }

    var externalLogins =
        (from account in OAuthWebSecurity.GetAccountsFromUserName(WebSecurity.CurrentUserName)
         let clientData = OAuthWebSecurity.GetOAuthClientData(account.Provider)
         select new { Provider = account.Provider, ProviderDisplayName = clientData.DisplayName, UserId = account.ProviderUserId })
        .ToList();
    bool canRemoveLogin = externalLogins.Count > 1 || hasLocalAccount;

    // Setup validation
    if (hasLocalAccount) {
        Validation.RequireField("currentPassword", "The current password field is required.");
        Validation.Add("currentPassword",
            Validator.StringLength(
                maxLength: Int32.MaxValue,
                minLength: 6,
                errorMessage: "Current password must be at least 6 characters"));
    }
    Validation.RequireField("newPassword", "The new password field is required.");
    Validation.Add("confirmPassword",
        Validator.Required("The confirm new password field is required."),
        Validator.EqualsTo("newPassword", "The new password and confirmation password do not match."));
    Validation.Add("newPassword",
        Validator.StringLength(
            maxLength: Int32.MaxValue,
            minLength: 6,
            errorMessage: "New password must be at least 6 characters"));

    if (IsPost) {
        AntiForgery.Validate();
        if (action == "password") {
            // Handle local account password operations
            var currentPassword = Request.Form["currentPassword"];
            var newPassword = Request.Form["newPassword"];
            var confirmPassword = Request.Form["confirmPassword"];

            if (Validation.IsValid()) {
                if (hasLocalAccount) {
                    if (WebSecurity.ChangePassword(WebSecurity.CurrentUserName, currentPassword, newPassword)) {
                        Response.Redirect("~/Account/Manage?message=ChangedPassword");
                        return;
                    } else {
                        ModelState.AddFormError("An error occurred when attempting to change the password. Please contact the site owner.");
                    }
                } else {
                    bool requireEmailConfirmation = !WebMail.SmtpServer.IsEmpty();
                    try {
                        WebSecurity.CreateAccount(WebSecurity.CurrentUserName, newPassword, requireEmailConfirmation);
                        Response.Redirect("~/Account/Manage?message=SetPassword");
                        return;
                    } catch (System.Web.Security.MembershipCreateUserException e) {
                        ModelState.AddFormError(e.Message);
                    }
                }
            } else {
                ModelState.AddFormError("Password change was unsuccessful. Please correct the errors and try again.");
            }
        } else if (action == "removeLogin") {
            // Remove external login
            var provider = Request.Form["provider"];
            var userId = Request.Form["userId"];

            message = null;
            var ownerAccount = OAuthWebSecurity.GetUserName(provider, userId);
            // Only remove the external login if it is owned by the currently logged in user and it is not the users last login credential
            if (ownerAccount == WebSecurity.CurrentUserName && canRemoveLogin) {
                OAuthWebSecurity.DeleteAccount(provider, userId);
                message = "RemovedLogin";
            }
            Response.Redirect(Href("~/Account/Manage", new { message }));
            return;
        } else {
            // Assume this an external login request
            string provider = Request.Form["provider"];
            if (!provider.IsEmpty()) {
                OAuthWebSecurity.RequestAuthentication(provider, Href("~/Account/RegisterService", new { returnUrl = Href("~/Account/Manage") }));
                return;
            }
        }
    }
}
<hgroup class="title">
    <h1>@Page.Title.</h1>
</hgroup>

@if (!successMessage.IsEmpty()) {
    <p class="message-success">
        @successMessage
    </p>
}

<p>You're logged in as <strong>@WebSecurity.CurrentUserName</strong>.</p>

@if (hasLocalAccount) {
    <h3>Change password</h3>
} else {
    <p>
        You do not have a local password for this site. Add a local password so you can log in without an external login.
    </p>
}

<form method="post">
    @AntiForgery.GetHtml()
    @Html.ValidationSummary(excludeFieldErrors: true)

    <fieldset>
        <legend>
        @if (hasLocalAccount) {
            <text>Change Password Form</text>
        } else {
            <text>Set Password Form</text>
        }
        </legend>
        <ol>
            @if (hasLocalAccount) {
                <li class="current-password">
                    <label for="currentPassword" @if (!ModelState.IsValidField("currentPassword")) {<text>class="error-label"</text>}>Current password</label>
                    <input type="password" id="currentPassword" name="currentPassword" @Validation.For("currentPassword")/>
                    @Html.ValidationMessage("currentPassword")
                </li>
            }
            <li class="new-password">
                <label for="newPassword" @if (!ModelState.IsValidField("newPassword")) {<text>class="error-label"</text>}>New password</label>
                <input type="password" id="newPassword" name="newPassword" @Validation.For("newPassword")/>
                @Html.ValidationMessage("newPassword")
            </li>
            <li class="confirm-password">
                <label for="confirmPassword" @if (!ModelState.IsValidField("confirmPassword")) {<text>class="error-label"</text>}>Confirm new password</label>
                <input type="password" id="confirmPassword" name="confirmPassword" @Validation.For("confirmPassword")/>
                @Html.ValidationMessage("confirmPassword")
            </li>
        </ol>
        @if (hasLocalAccount) {
            <button type="submit" name="action" value="password">Change Password</button>
            <p>
                Click <a href="~/Account/ForgotPassword" title="Forgot password page">here</a> if you've forgotten your password.
            </p>
        } else {
            <button type="submit" name="action" value="password">Set Password</button>
        }
    </fieldset>
</form>

<section id="externalLogins">
    @if (externalLogins.Count > 0) {
        <h3>Registered external logins</h3>
        <table>
            <tbody>
            @foreach (var externalLogin in externalLogins) {
                <tr>
                    <td>@externalLogin.ProviderDisplayName</td>
                    <td>
                        @if (canRemoveLogin) {
                            <form method="post">
                                @AntiForgery.GetHtml()
                                <fieldset>
                                    <legend></legend>
                                    <input type="hidden" name="provider" value="@externalLogin.Provider" />
                                    <input type="hidden" name="userId" value="@externalLogin.UserId" />
                                    <button type="submit" name="action" value="removeLogin" title="Remove this @externalLogin.ProviderDisplayName credential from your account">Remove</button>
                                </fieldset>
                            </form>
                        } else {
                            @: &nbsp;
                        }
                    </td>
                </tr>
            }
            </tbody>
        </table>
    }

    <h3>Add an external login</h3>
    @RenderPage("~/Account/_ExternalLoginsList.cshtml")
</section>
