Description

Completing this tutorial you will add to your Nextpost installation new following functions:

  • Manage Login Activity (approve/unapprove/logout)
  • Change Account Password directly from Nextpost (fast and easy)
  • Update Account Password for Nextpost (when you updated password in app)

Instruction

Suggestion: use Microsoft Visual Studio Code for code editing and profiling. All your syntax error will be highlighted.

Before we start making changes to the code, I strongly recommend you to backup the source files so that you do not have any problems if something goes wrong. 

The list of files that we will change:

/assets/js/core.js
/assets/css/core.css
/app/views/fragments/accounts.fragment.php
/app/controllers/ProfileController.php
/app/inc/js-locale.inc.php

Well, let’s get started. 

Step 1.1

Open file /assets/js/core.js and add this code to the top section.

Check the screenshot below.

NextPost.LoginActivity();
NextPost.ChangeAccountPassword();
New functions in core.js file.

Step 1.2

Open again file /assets/js/core.js and add this code to the bottom of the file.

Check the screenshot below.

New functions in core.js file.
/**
 * Account Login Activity
 */
NextPost.LoginActivity = function() {
    $("body").off("click", "a.js-login-activity").on("click", "a.js-login-activity", function() {
        var id = $(this).data("id"); 
        var url = $(this).data("url");
        var account_box = $(".box-list-item[data-id='" + id + "']");

        account_box.addClass("onprogress");

        // Alert notice
        specialAlertResponse = function(resp = null) {
            $.alert({
                title: resp ? ( resp.title ? resp.title: __("Oops!") )  : __("Oops!"),
                content: resp ? ( resp.msg ? resp.msg: __("An error occured. Please try again later!") )  : __("An error occured. Please try again later!"),
                theme: 'modern',
                buttons: {
                    confirm: {
                        text: __("Close"), 
                        btnClass: "small button btn-red",
                        keys: ['enter']
                    }
                },
                draggable: false,
                closeIcon: true,
                icon: 'sli sli-close',
                type: 'red'
            });
        }

        loginActivityContent = function(resp) {
            var content = '';
            if (resp.suspicious_logins) {
                if (resp.suspicious_logins.length > 0) {
                    content += '<div class="la-login-title">' + __("Was This You?") + "</div>";
                    var current_id = '';
                    resp.sessions.forEach(function(item, index) {
                        if (item.is_current) {
                            current_id = item.id;
                        }
                    });
                    resp.suspicious_logins.forEach(function(item, index) {
                        if (item.id == current_id) {
                            content += 
                            '<div class="la-login-session mt-10" data-login-id="' + item.id + '" data-login-timestamp="' + item.timestamp + '">' +
                                '<div class="la-login-icon mr-10"><span class="mdi mdi-map-marker"></span></div>' +
                                '<div class="la-login-desc">' +
                                    '<div class="la-login-location">' + item.location + '</div>' +
                                    '<div class="la-login-time"><span class="la-color-green">' + __("Active now") + '</span>' + " · " + __(item.device) + '</div>' + 
                                '</div>' +
                                '<div class="la-login-checkpoint mt-5">' +
                                    '<a class="la-login-checkpoint-confirm la-checkpoint-btn-green mr-5 js-la-checkpoint-confirm" href="javascript:void(0)" data-login-id="' + item.id + '" data-login-timestamp="' + item.timestamp + '" data-id="' + id + '" data-url="' + url + '">' + __("This Was Me") + '</a>' +
                                    '<a class="la-login-checkpoint-decline la-checkpoint-btn-red js-la-checkpoint-decline none" href="javascript:void(0)" data-login-id="' + item.id + '" data-login-timestamp="' + item.timestamp + '" data-id="' + id + '" data-url="' + url + '">' + __("This Wasn’t Me") + '</a>' +
                                '</div>' +
                            '</div>';
                        } else {
                            var d = moment.unix(item.timestamp).fromNow();
                            content += 
                            '<div class="la-login-session mt-10" data-login-id="' + item.id + '" data-login-timestamp="' + item.timestamp + '">' +
                                '<div class="la-login-icon mr-10"><span class="mdi mdi-map-marker"></span></div>' +
                                '<div class="la-login-desc">' +
                                    '<div class="la-login-location">' + item.location + '</div>' +
                                    '<div class="la-login-time">' + d + " · " + item.device + '</div>' +
                                '</div>' +
                                '<div class="la-login-checkpoint mt-5">' +
                                    '<a class="la-login-checkpoint-confirm la-checkpoint-btn-green mr-5 js-la-checkpoint-confirm" href="javascript:void(0)" data-login-id="' + item.id + '" data-login-timestamp="' + item.timestamp + '" data-id="' + id + '" data-url="' + url + '">' + __("This Was Me") + '</a>' +
                                    '<a class="la-login-checkpoint-decline la-checkpoint-btn-red js-la-checkpoint-decline none" href="javascript:void(0)" data-login-id="' + item.id + '" data-login-timestamp="' + item.timestamp + '" data-id="' + id + '" data-url="' + url + '">' + __("This Wasn’t Me") + '</a>' +
                                '</div>' +
                            '</div>';
                        }
                    });
                }
            }
            if (resp.sessions) {
                if (resp.sessions.length > 0) {
                    content += '<div class="la-login-title mt-10">' + __("Where You're Logged in") + "</div>";
                    resp.sessions.forEach(function(item, index) {
                        if (item.is_current) {
                            content += 
                            '<div class="la-login-session mt-10" data-login-id="' + item.id + '" data-login-timestamp="' + item.timestamp + '">' +
                                '<div class="la-login-icon mr-10"><span class="mdi mdi-map-marker"></span></div>' +
                                '<div class="la-login-desc">' +
                                    '<div class="la-login-location">' + item.location + '</div>' +
                                    '<div class="la-login-time"><span class="la-color-green">' + __("Active now") + '</span>' + " · " + __(item.device) + '</div>' + 
                                '</div>' +
                            '</div>';
                        } else {
                            var d = moment.unix(item.timestamp).fromNow();
                            content += 
                            '<div class="la-login-session mt-10" data-login-id="' + item.id + '" data-login-timestamp="' + item.timestamp + '">' +
                                '<div class="la-login-icon mr-10"><span class="mdi mdi-map-marker"></span></div>' +
                                '<div class="la-login-desc">' +
                                    '<div class="la-login-location">' + item.location + '</div>' +
                                    '<div class="la-login-time">' + d + " · " + item.device + '</div>' +
                                '</div>' +
                                '<div class="la-login-logout-block">' + 
                                    '<a class="la-login-logout js-la-logout" href="javascript:void(0)" data-login-id="' + item.id + '" data-login-timestamp="' + item.timestamp + '" data-s-login-id="' + item.login_id + '" data-id="' + id + '" data-url="' + url + '">' + __("Log Out") + '</a>' +
                                '</div>' +
                            '</div>';
                        }
                    });
                }
            }
            return content;
        }

        // Popup with login activity
        loginActivityPopUp = function(resp) {
            $content = loginActivityContent(resp);
            $.confirm({
                title: __("Login Activity"),
                content: $content,
                theme: 'material',
                buttons: {
                    confirm: {
                        isHidden: true,
                    },
                    cancel: {
                        isHidden: true,
                    }
                },
                draggable: false,
                backgroundDismiss: false,
                columnClass: 'login-activity-popup',
                closeIcon: true
            });
        }

        $.ajax({
            url: url,
            type: 'POST',
            dataType: 'jsonp',
            data: {
                action: "login-activity", 
                action_type: "get",
                id: id 
            },
            error: function() {
                account_box.removeClass("onprogress");
                specialAlertResponse();
            },
            success: function(resp) {
                account_box.removeClass("onprogress");
                if (resp) {
                    if (resp.result == 0) {
                        specialAlertResponse(resp);
                    } else {
                        if (resp.login_activity) {
                            loginActivityPopUp(resp.login_activity);
                        }
                    }
                }
            }
        });

        $("body").off("click", "a.js-la-checkpoint-confirm").on("click", "a.js-la-checkpoint-confirm", function() {
            var login_id = $(this).data("login-id");
            var login_timestamp = $(this).data("login-timestamp");
            $.ajax({
                url: url,
                type: 'POST',
                dataType: 'jsonp',
                data: {
                    action: "login-activity", 
                    action_type: "approve",
                    id: id,
                    login_id: login_id,
                    login_timestamp: login_timestamp
                },
                error: function() {
                    specialAlertResponse();
                },
                success: function(resp) {
                    if (resp) {
                        if (resp.result == 0) {
                            specialAlertResponse(resp);
                        } else {
                            if (resp.approve.status == "ok") {
                                $("body").find(".la-login-session[data-login-id='" + login_id + "']").find(".la-login-checkpoint-confirm").addClass("none");
                                $("body").find(".la-login-session[data-login-id='" + login_id + "']").find(".la-login-checkpoint-decline").removeClass("none");
                            }
                        }
                    }
                }
            });
        });

        $("body").off("click", "a.js-la-checkpoint-decline").on("click", "a.js-la-checkpoint-decline", function() {
            var login_id = $(this).data("login-id");
            var login_timestamp = $(this).data("login-timestamp");
            $.ajax({
                url: url,
                type: 'POST',
                dataType: 'jsonp',
                data: {
                    action: "login-activity", 
                    action_type: "unapprove",
                    id: id,
                    login_id: login_id,
                    login_timestamp: login_timestamp
                },
                error: function() {
                    specialAlertResponse();
                },
                success: function(resp) {
                    if (resp) {
                        if (resp.result == 0) {
                            specialAlertResponse(resp);
                        } else {
                            if (resp.unapprove.status == "ok") {
                                $("body").find(".la-login-session[data-login-id='" + login_id + "']").find(".la-login-checkpoint-decline").addClass("none");
                                $("body").find(".la-login-session[data-login-id='" + login_id + "']").find(".la-login-checkpoint-confirm").removeClass("none");
                            }
                        }
                    }
                }
            });
        });

        $("body").off("click", "a.js-la-logout").on("click", "a.js-la-logout", function() { 
            var login_id = $(this).data("login-id");
            var s_login_id = $(this).data("s-login-id");
            $.ajax({
                url: url,
                type: 'POST',
                dataType: 'jsonp',
                data: {
                    action: "login-activity", 
                    action_type: "logout",
                    id: id,
                    login_id: login_id
                },
                error: function() {
                    specialAlertResponse();
                },
                success: function(resp) {
                    if (resp) {
                        if (resp.result == 0) {
                            specialAlertResponse(resp);
                        } else {
                            if (resp.logout_session.status == "ok") {
                                $("body").find(".la-login-session[data-login-id='" + login_id + "']").remove();
                                $("body").find(".la-login-session[data-login-id='" + s_login_id + "']").remove();
                            }
                        }
                    }
                }
            });
        });
    });
}

/**
 * Change & Update Account Password 
 */
NextPost.ChangeAccountPassword = function() {
    // Alert notice
    specialAlertResponse = function(resp = null) {
        $.alert({
            title: resp ? ( resp.title ? resp.title: __("Oops!") )  : __("Oops!"),
            content: resp ? ( resp.msg ? resp.msg: __("An error occured. Please try again later!") )  : __("An error occured. Please try again later!"),
            theme: 'modern',
            buttons: {
                confirm: {
                    text: __("Close"), 
                    btnClass: "small button btn-red",
                    keys: ['enter']
                }
            },
            draggable: false,
            closeIcon: true,
            icon: 'sli sli-close',
            type: 'red'
        });
    }

    // Popup with login activity
    changePasswordPopUp = function(id, url, action_type, title) {
        $content = '<div class="mt-5 mb-5">' +
            '<input class="input la-change-password" name="la-change-password" data-id="' + id + '" type="password" maxlength="100" value="" placeholder="' + __("New Password") + '">'
        '</div>';
        
        $.confirm({
            title: title,
            content: $content,
            theme: 'material',
            buttons: {
                save: {
                    text: __("Save"), 
                    btnClass: "col s6 m6 l6 small button button--dark",
                    keys: ['enter'],
                    action: function() {
                        var chp_popup = $("body").find(".la-change-password-popup .jconfirm-box");
                        chp_popup.addClass("onprogress");
                        var new_password = $("body").find(":input[name='la-change-password'][data-id='" + id + "']").val();
                        $.ajax({
                            url: url,
                            type: 'POST',
                            dataType: 'jsonp',
                            data: {
                                action: "login-activity", 
                                action_type: action_type,
                                id: id,
                                new_password: new_password
                            },
                            error: function() {
                                chp_popup.removeClass("onprogress");
                                specialAlertResponse();
                            },
                            success: function(resp) {
                                chp_popup.removeClass("onprogress");
                                if (resp) {
                                    if (resp.result == 0) {
                                        specialAlertResponse(resp);
                                    } else {
                                        if (resp.change_password) {
                                            if (resp.change_password.status == "ok") {
                                                chp_popup.find(".jconfirm-closeIcon").click();
                                            }
                                        } else {
                                            if (resp.password_saved) {
                                                chp_popup.find(".jconfirm-closeIcon").click();
                                            }
                                        }
                                    }
                                }
                            }
                        });
                        return false;
                    }
                },
                cancel: {
                    text: __("Close"), 
                    btnClass: "col s6 s-last m6 m-last l6 l-last small button button--dark--outline button-la-light-outline-last",
                    keys: ['enter']
                }
            },
            draggable: false,
            backgroundDismiss: false,
            columnClass: 'la-change-password-popup',
            closeIcon: true
        });
    }

    $("body").off("click", "a.js-la-change-password").on("click", "a.js-la-change-password", function() {
        var id = $(this).data("id"); 
        var url = $(this).data("url");

        changePasswordPopUp(id, url, "change-password", __("Change Password"));
    });

    $("body").off("click", "a.js-la-update-password").on("click", "a.js-la-update-password", function() {
        var id = $(this).data("id"); 
        var url = $(this).data("url");

        changePasswordPopUp(id, url, "update-password", __("Update Password"));
    });
}

Step 2

Open file /assets/css/core.css and add this code to the bottom of the file.

Check the screenshot below.

New CSS styles in core.css file.
/**
* Account Change Password
*/

@media (min-width: 440px) {
  .la-change-password-popup .jconfirm-box {
    width: 400px;
  }
}

.la-change-password-popup .jconfirm-box {
  padding: 20px !important;
}

.la-change-password-popup .jconfirm-content-pane {
  margin-bottom: 0 !important;
}

.la-change-password-popup .jconfirm-box .jconfirm-buttons {
  padding: 0;
  margin-top: 10px;
}

.la-change-password-popup .jconfirm-box .jconfirm-title-c{
  font-size: 18px !important;
  font-weight: 600 !important;
  padding-bottom: 10px !important;
}

.la-change-password-popup .button-la-light-outline-last {
  margin-right: 0 !important;
}

.la-change-password-popup .jconfirm-box .jconfirm-buttons button {
  text-transform: none !important;
  border-radius: 4px;
  -moz-border-radius: 4px;
  -webkit-border-radius: 4px;
  -o-border-radius: 4px;
  font-size: 13px;
  font-weight: 600 !important;
  padding: 8px 20px;
}

.la-change-password-popup .jconfirm-box .jconfirm-buttons {
  text-align: center;
}

.la-change-password-popup .jconfirm-box {
  padding: 20px !important;
  border-radius: 12px;
  -moz-border-radius: 12px;
  -o-border-radius: 12px;
  -webkit-border-radius: 12px;
}

.la-change-password-popup .jconfirm-box:after {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 50;
  visibility: hidden;
  width: 100%;
  height: 100%;
  content: "";
  opacity: 0;
  background-color: rgba(255, 255, 255, 0.75);
  background-image: url(../img/round-loading.svg);
  background-repeat: no-repeat;
  background-position: center;
  -webkit-transition: all ease 0.2s;
  -moz-transition: all ease 0.2s;
  transition: all ease 0.2s;
}

.la-change-password-popup .jconfirm-box.onprogress:after {
  visibility: visible;
  opacity: 1;
  border-radius: 5px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  -o-border-radius: 5px;
}

/**
* Account Login Activity
*/

@media (min-width: 440px) {
  .login-activity-popup .jconfirm-box {
    width: 400px;
  }
}

.login-activity-popup .jconfirm-box {
  padding: 20px !important;
  border-radius: 12px;
  -moz-border-radius: 12px;
  -o-border-radius: 12px;
  -webkit-border-radius: 12px;
}

.login-activity-popup .jconfirm-content-pane {
  margin-bottom: 0 !important;
}

.la-login-time {
  color: #8e8e8e;
}

.la-login-icon {
  width: 26px;
  color: #c1c1c1;
  border-radius: 50%;
  text-align: center;
  float: left;
}

.la-login-icon .mdi-map-marker {
  font-size: 28px;
  line-height: 36px;
}

.la-login-desc {
  display: inline-block;
  font-size: 14px;
  line-height: 1.4;
}

.la-color-green {
  color: #58c322;
}

.la-checkpoint-btn-green {
  color: #58c322 !important;
  border: 1px solid #58c322 !important;
}

.la-checkpoint-btn-green:hover {
  background-color: rgb(88 195 34 / 15%) !important;
}

.la-checkpoint-btn-red {
  color: #ff3d3d !important;
  border: 1px solid #ff3d3d !important;
}

.la-checkpoint-btn-red:hover {
  background-color: rgb(255 61 61 / 15%) !important;
}

.login-activity-popup .jconfirm-box .jconfirm-buttons {
  padding: 0;
}

.login-activity-popup .jconfirm-box .jconfirm-title-c{
  font-size: 18px !important;
  font-weight: 600 !important;
  padding-bottom: 10px !important;
}

.la-login-logout-block {
  display: inline-block;
  position: absolute;
  right: 0;
  margin-top: 6px;
}

.la-login-logout,
.la-login-checkpoint-confirm,
.la-login-checkpoint-decline {
  font-size: 13px;
  line-height: 13px;
  border: 1px solid #8e8e8e;
  color: #8e8e8e;
  padding: 5px 6px;
  display: block;
  border-radius: 3px;
  -o-border-radius: 3px;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
}

.la-login-checkpoint-confirm,
.la-login-checkpoint-decline {
  display: inline-block;
}

.la-login-logout:hover {
  border: 1px solid #2b69e9;
  background-color: rgb(43 105 233 / 10%);
  color: #2b69e9;
}

.login-activity-popup .jconfirm-box div.jconfirm-content-pane::-webkit-scrollbar {
  width: 0;
}

.darkside .la-login-location,
.darkside .login-activity-popup .jconfirm-box .jconfirm-title-c,
.darkside .jconfirm-box div.jconfirm-closeIcon {
  color: white !important;
}

.la-login-title {
  font-size: 14px;
  font-weight: 500;
  color: #8e8e8e;
  display: inline-block;
}

.mt-3 {
  margin-top: 3px;
}

Step 3

Open file /app/views/fragments/accounts.fragment.php and find this code:

<li>
    <a href="javascript:void(0)" 
        class="js-remove-list-item" 
        data-id="<?= $a->get("id") ?>" 
        data-url="<?= APPURL."/accounts" ?>">
        <?= __("Delete") ?>
    </a>
</li>

Replace this code with new one:

<li>
    <a href="javascript:void(0)" 
        class="js-login-activity"
        data-id="<?= $a->get("id") ?>" 
        data-url="<?= APPURL."/profile" ?>">
        <?= __("Login Activity") ?>
    </a>
</li>

<li>
    <a href="javascript:void(0)" 
        class="js-la-change-password"
        data-id="<?= $a->get("id") ?>" 
        data-url="<?= APPURL."/profile" ?>">
        <?= __("Change Password") ?>
    </a>
</li>

<li>
    <a href="javascript:void(0)" 
        class="js-la-update-password"
        data-id="<?= $a->get("id") ?>" 
        data-url="<?= APPURL."/profile" ?>">
        <?= __("Update Password") ?>
    </a>
</li>

<li>
    <a href="javascript:void(0)" 
        class="js-remove-list-item" 
        data-id="<?= $a->get("id") ?>" 
        data-url="<?= APPURL."/accounts" ?>">
        <?= __("Delete") ?>
    </a>
</li>
New code in accounts.fragment.php file.

Step 4.1

Open file /app/controllers/ProfileController.php and find this code:

if (Input::post("action") == "save") {

Replace this code with new one:

if (Input::post("action") == "login-activity") {
    $this->loginActivity();
}

if (Input::post("action") == "save") {
New code in ProfileController.php file.

Step 4.1

Open again file /app/controllers/ProfileController.php and find this code:

/**
* Save changes
* @return void 
*/
private function save()

Replace this code with new one:

New code in ProfileController.php file.
/**
 * Return login activity of account in Instagram
 * @return void 
 */
private function loginActivity() 
{
    $this->resp->result = 0;
    $this->resp->password_saved = 0;
    $AuthUser = $this->getVariable("AuthUser");

    $Account = Controller::model("Account", Input::post("id"));

    // Check Account ID and Account Status
    if (!$Account->isAvailable() ||
        $Account->get("user_id") != $AuthUser->get("id")) 
    {
        $this->resp->title = __("Error");
        $this->resp->msg = __("Invalid ID");
        $this->jsonecho();
    }


    $action_type = Input::post("action_type") ? Input::post("action_type") : "get";

    // Get self account info 7 times and skip this process, if this 7 retries unsuccessful
    // Mobile proxy connection break adaptation
    $refresh = 0;
    $refresh_count = 0;
    $refresh_status = 0;

    do { 
        $refresh_count += 1;
        if ($refresh_count == 7) {
            $refresh = 1;
            $refresh_status = 0;
        }
        try {
            $last_login_timestamp = strtotime($Account->get("last_login"));
            if ($last_login_timestamp && $last_login_timestamp + 30 * 60 > time()) {
                // Instagram Client Mobile
                \InstagramAPI\Instagram::$allowDangerousWebUsageAtMyOwnRisk = true;
                $storage_config = [
                "storage" => "file",
                "basefolder" => SESSIONS_PATH."/".$Account->get("user_id")."/",
                ];
                // Platform detection
                if (function_exists('is_android_session')) {
                    if (is_android_session($Account->get("user_id"), $Account->get("username"))) {
                    $platform = "android"; 
                    } else {
                    $platform = "ios";
                    }
                    $Instagram = new \InstagramAPI\Instagram(false, false, $storage_config, $platform);
                } else {
                    $Instagram = new \InstagramAPI\Instagram(false, false, $storage_config);
                }
                $Instagram->setVerifySSL(SSL_ENABLED);
                if ($Account->get("proxy")) {
                    $Instagram->setProxy($Account->get("proxy"));
                }
                // Decrypt pass.
                try {
                    $password = \Defuse\Crypto\Crypto::decrypt($Account->get("password"), 
                                \Defuse\Crypto\Key::loadFromAsciiSafeString(CRYPTO_KEY));
                } catch (Exception $e) {
                    echo __("Encryption error");
                    exit;
                }
                $Instagram->changeUser($Account->get("username"), $password);
                if (!$Instagram->isMaybeLoggedIn) {
                   $Instagram = \InstagramController::login($Account);
                }
            } else {
                $Instagram = \InstagramController::login($Account);
            }

            if ($action_type == "get") {
                $this->resp->login_activity = $Instagram->account->getLoginActivity();
            } elseif ($action_type == "logout") {
                $login_id = Input::post("login_id");
                $this->resp->logout_session = $Instagram->request('session/login_activity/logout_session/')
                                                        ->setSignedPost(false)
                                                        ->addPost('session_id', $login_id)
                                                        ->addPost('_csrftoken', $Instagram->client->getToken())
                                                        ->addPost('_uuid',$Instagram->uuid)
                                                        ->getResponse(new \InstagramAPI\Response\GenericResponse());
            } elseif ($action_type == "approve") {
                $login_id = Input::post("login_id");
                $login_timestamp = Input::post("login_timestamp");
                $this->resp->approve = $Instagram->account->approveSuspiciousLogin($login_id, $login_timestamp);
            } elseif ($action_type == "unapprove") {
                $login_id = Input::post("login_id");
                $login_timestamp = Input::post("login_timestamp");
                $this->resp->unapprove = $Instagram->request('session/login_activity/undo_avow_login/')
                    ->setSignedPost(false)
                    ->addPost('login_timestamp', $login_timestamp)
                    ->addPost('login_id', $login_id)
                    ->addPost('_csrftoken', $Instagram->client->getToken())
                    ->addPost('_uuid', $Instagram->uuid)
                    ->getResponse(new \InstagramAPI\Response\GenericResponse());
            } elseif ($action_type == "change-password") {
                // Decrypt pass.
                try {
                    $old_password = \Defuse\Crypto\Crypto::decrypt($Account->get("password"), 
                                    \Defuse\Crypto\Key::loadFromAsciiSafeString(CRYPTO_KEY));
                } catch (\Exception $e) {
                    $this->resp->msg = __("Password decryption error.");
                    $this->jsonecho();
                }

                $new_password = Input::post("new_password");
                $this->resp->change_password = $Instagram->request('accounts/change_password/')
                    ->addPost('_uuid', $Instagram->uuid)
                    ->addPost('_uid', $Instagram->account_id)
                    ->addPost('_csrftoken', $Instagram->client->getToken())
                    ->addPost('enc_old_password', \InstagramAPI\Utils::encryptPassword($old_password, $Instagram->settings->get('public_key_id'), $Instagram->settings->get('public_key')))
                    ->addPost('enc_new_password1', \InstagramAPI\Utils::encryptPassword($new_password, $Instagram->settings->get('public_key_id'), $Instagram->settings->get('public_key')))
                    ->addPost('enc_new_password2', \InstagramAPI\Utils::encryptPassword($new_password, $Instagram->settings->get('public_key_id'), $Instagram->settings->get('public_key')))
                    ->getResponse(new \InstagramAPI\Response\ChangePasswordResponse());

                // Encrypt the password
                try {
                    $passhash = \Defuse\Crypto\Crypto::encrypt($new_password, 
                                \Defuse\Crypto\Key::loadFromAsciiSafeString(CRYPTO_KEY));
                } catch (\Exception $e) {
                    $this->resp->msg = __("Password encryption error.");
                    $this->jsonecho();
                }

                $Account->set("password", $passhash)->save();
                $this->resp->password_saved = 1;
            } elseif ($action_type == "update-password") {
                $new_password = Input::post("new_password");
                // Encrypt the password
                try {
                    $passhash = \Defuse\Crypto\Crypto::encrypt($new_password, 
                                \Defuse\Crypto\Key::loadFromAsciiSafeString(CRYPTO_KEY));
                } catch (\Exception $e) {
                    $this->resp->msg = __("Password encryption error.");
                    $this->jsonecho();
                }
                $Account->set("password", $passhash)->save();
                $this->resp->password_saved = 1;
            }

            $refresh = 1;
            $refresh_status = 1;
        } catch (\InstagramAPI\Exception\NetworkException $e) { 
            // Couldn't connect to Instagram account because of network or connection error
            // Do nothing, just try again
            sleep(7);
        } catch (\InstagramAPI\Exception\EmptyResponseException $e) {
            // Instagram sent us empty response
            $this->resp->title = __("Oops...");
            $this->resp->msg = $e->getMessage() . " " . __("Contact Support.");
            $this->jsonecho();
        } catch (\InstagramAPI\Exception\InstagramException $e) {
            $separated = $e->getMessage();
            $text = explode(" | ", $separated, 2);
            $this->resp->title = $text[0];
            if (isset($text[1])) {
                $this->resp->msg = $text[1];
            } else {
                $this->resp->title = __("Oops...");
                $response = $e->getResponse();
                $response = json_decode($response);
                $this->resp->response = $response;
                $this->resp->msg  = isset($response->message->errors[0]) ? $response->message->errors[0] : $e->getMessage();
            }
            $this->jsonecho();
        } catch (\Exception $e) {
            $separated = $e->getMessage();
            $text = explode(" | ", $separated, 2);
            $this->resp->title = $text[0];
            if (isset($text[1])) {
                $this->resp->msg = $text[1];
            } else {
                $this->resp->title = __("Oops...");
                $this->resp->msg  =  $e->getMessage();
            }
            $this->jsonecho();
        }
    } while (!$refresh);

    if (!$refresh_status) {
        $this->resp->title = __("Couldn't login to Instagram");
        $this->resp->msg= __("Account status not updated. Please try again later or contact to Support.");
        $this->jsonecho();
    }

    $this->resp->result = 1;
    $this->jsonecho();
}

/**
* Save changes
* @return void 
*/
private function save()

Step 5

Open again file /app/inc/js-locale.inc.php and add this code to window.i18n object:

New code in js-locale.inc.php file.
// Account Login Activity
"Login Activity": '<?= js_str_format(__("Login Activity")) ?>',
"Active now": '<?= js_str_format(__("Active now")) ?>',
"Log Out": '<?= js_str_format(__("Log Out")) ?>',
"This Apple iPhone": '<?= js_str_format(__("This Apple iPhone")) ?>',
"Apple iPhone": '<?= js_str_format(__("Apple iPhone")) ?>',
"Where You're Logged in": '<?= js_str_format(__("Where You're Logged in")) ?>',
"Was This You?": '<?= js_str_format(__("Was This You?")) ?>',
"This Was Me": '<?= js_str_format(__("This Was Me")) ?>',
"This Wasn’t Me": '<?= js_str_format(__("This Wasn’t Me")) ?>',

// Account Change Password
"New Password": '<?= js_str_format(__("New Password")) ?>',
"Change Password": '<?= js_str_format(__("Change Password")) ?>',
"Update Password": '<?= js_str_format(__("Update Password")) ?>',

Step 6

You can add translations to all your locale files. Use text from step 5 as translation list.


That’s all.

Clean browser cache and take a look at your changes. For example I attached screenshot from Chrome.

This image has an empty alt attribute; its file name is image-1024x261.png

Now you are able to manage login activity, change or update account password.

Like our dashboard styles?

This is Timeable Skin, our private advanced CSS-styles for Nextpost Dashboard with the integration of San Francisco web font (created by Apple). Tons of CSS improvements, fixes, and customizations inside 3 important Nextpost files.