]> git.wh0rd.org - tt-rss.git/blobdiff - classes/pref/prefs.php
implement one time passwords using TOTP
[tt-rss.git] / classes / pref / prefs.php
index ff8a17cdb9614e0cc30a58fcc90332e78add49b8..c6b109877eb8c4095ac0672ad25b3708018541b7 100644 (file)
@@ -2,7 +2,7 @@
 class Pref_Prefs extends Handler_Protected {
 
        function csrf_ignore($method) {
-               $csrf_ignored = array("index");
+               $csrf_ignored = array("index", "updateself");
 
                return array_search($method, $csrf_ignored) !== false;
        }
@@ -154,12 +154,15 @@ class Pref_Prefs extends Handler_Protected {
 
                print "<table width=\"100%\" class=\"prefPrefsList\">";
 
-               $result = db_query($this->link, "SELECT email,full_name,
+               print "<h2>" . __("Personal data") . "</h2>";
+
+               $result = db_query($this->link, "SELECT email,full_name,otp_enabled,
                        access_level FROM ttrss_users
                        WHERE id = ".$_SESSION["uid"]);
 
                $email = htmlspecialchars(db_fetch_result($result, 0, "email"));
                $full_name = htmlspecialchars(db_fetch_result($result, 0, "full_name"));
+               $otp_enabled = sql_bool_to_bool(db_fetch_result($result, 0, "otp_enabled"));
 
                print "<tr><td width=\"40%\">".__('Full name')."</td>";
                print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" name=\"full_name\" required=\"1\"
@@ -194,6 +197,8 @@ class Pref_Prefs extends Handler_Protected {
 
                if ($authenticator && method_exists($authenticator, "change_password")) {
 
+                       print "<h2>" . __("Password") . "</h2>";
+
                        $result = db_query($this->link, "SELECT id FROM ttrss_users
                                WHERE id = ".$_SESSION["uid"]." AND pwd_hash
                                = 'SHA1:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'");
@@ -249,6 +254,55 @@ class Pref_Prefs extends Handler_Protected {
 
                        print "</form>";
 
+                       if ($_SESSION["auth_module"] == "internal") {
+
+                               print "<h2>" . __("One time passwords / Authenticator") . "</h2>";
+
+                               if ($otp_enabled) {
+
+                                       print "<p>".__("One time passwords are currently enabled. Change your current password and refresh this page to reconfigure.") . "</p>";
+
+                               } else {
+
+                                       print "<p>".__("You will need a compatible Authenticator to use this. Changing your password would automatically disable OTP.") . "</p>";
+
+                                       print "<p>".__("Scan the following code by the Authenticator application:")."</p>";
+
+                                       $csrf_token = $_SESSION["csrf_token"];
+
+                                       print "<img src=\"backend.php?op=pref-prefs&method=otpqrcode&csrf_token=$csrf_token\">";
+
+                                       print "<form dojoType=\"dijit.form.Form\" id=\"changeOtpForm\">";
+
+                                       print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-prefs\">";
+                                       print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"changeotp\">";
+
+                                       print "<script type=\"dojo/method\" event=\"onSubmit\" args=\"evt\">
+                                       evt.preventDefault();
+                                       if (this.validate()) {
+                                               notify_progress('Saving data...', true);
+
+                                               new Ajax.Request('backend.php', {
+                                                       parameters: dojo.objectToQuery(this.getValues()),
+                                                       onComplete: function(transport) {
+                                                               window.location.reload();
+                                               } });
+
+                                       }
+                                       </script>";
+
+                                       print "<input dojoType=\"dijit.form.CheckBox\" required=\"1\"
+                                               type=\"checkbox\" id=\"enable_otp\" name=\"enable_otp\"/> ";
+                                       print "<label for=\"enable_otp\">".__("I have scanned the code and would like to enable OTP")."</label>";
+
+                                       print "<p><button dojoType=\"dijit.form.Button\" type=\"submit\">".
+                                               __("Save OTP setting")."</button>";
+
+                                       print "</form>";
+
+                               }
+
+                       }
                }
 
                print "</div>"; #pane
@@ -291,17 +345,24 @@ class Pref_Prefs extends Handler_Protected {
                        $profile_qpart = "profile IS NULL";
                }
 
+               if ($_SESSION["prefs_show_advanced"])
+                       $access_query = "true";
+               else
+                       $access_query = "(access_level = 0 AND section_id != 3)";
+
                $result = db_query($this->link, "SELECT DISTINCT
                        ttrss_user_prefs.pref_name,short_desc,help_text,value,type_name,
+                       ttrss_prefs_sections.order_id,
                        section_name,def_value,section_id
                        FROM ttrss_prefs,ttrss_prefs_types,ttrss_prefs_sections,ttrss_user_prefs
                        WHERE type_id = ttrss_prefs_types.id AND
                                $profile_qpart AND
                                section_id = ttrss_prefs_sections.id AND
                                ttrss_user_prefs.pref_name = ttrss_prefs.pref_name AND
+                               $access_query AND
                                short_desc != '' AND
                                owner_uid = ".$_SESSION["uid"]."
-                       ORDER BY section_id,short_desc");
+                       ORDER BY ttrss_prefs_sections.order_id,short_desc");
 
                $lnum = 0;
 
@@ -487,13 +548,111 @@ class Pref_Prefs extends Handler_Protected {
                print "<button dojoType=\"dijit.form.Button\" onclick=\"return validatePrefsReset()\">".
                        __('Reset to defaults')."</button>";
 
+               print "&nbsp;";
+
+               $checked = $_SESSION["prefs_show_advanced"] ? "checked='1'" : "";
+
+               print "<input onclick='toggleAdvancedPrefs()'
+                               id='prefs_show_advanced'
+                               dojoType=\"dijit.form.CheckBox\"
+                               $checked
+                               type=\"checkbox\"></input>
+                               <label for='prefs_show_advanced'>" .
+                               __("Show additional preferences") . "</label>";
+
                print '</div>'; # inner pane
                print '</div>'; # border container
-
                print "</form>";
 
                print "</div>"; #pane
+
+
+               if (($_SESSION["access_level"] >= 10 || SINGLE_USER_MODE) && CHECK_FOR_NEW_VERSION) {
+                       print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Update Tiny Tiny RSS')."\">";
+
+                       if ($_SESSION["pref_last_version_check"] + 86400 + rand(-1000, 1000) < time()) {
+                               $_SESSION["version_data"] = @check_for_update($this->link);
+                               $_SESSION["pref_last_version_check"] = time();
+                       }
+
+                       if (is_array($_SESSION["version_data"])) {
+                               $version = $_SESSION["version_data"]["version"];
+                               print_notice(T_sprintf("New version of Tiny Tiny RSS is available (%s).", "<b>$version</b>"));
+
+                               print "<p><button dojoType=\"dijit.form.Button\" onclick=\"return updateSelf()\">".
+                                       __('Update Tiny Tiny RSS')."</button></p>";
+
+                       } else {
+                               print_notice(__("Your Tiny Tiny RSS installation is up to date."));
+                       }
+
+                       print "</div>"; #pane
+               }
+
                print "</div>"; #container
        }
+
+       function updateSelf() {
+               print "<form style='display : block' name='self_update_form' id='self_update_form'>";
+
+               print "<div class='error'>".__("Do not close this dialog until updating is finished. Backup your tt-rss directory before continuing.")."</div>";
+
+               print "<ul class='selfUpdateList' id='self_update_log'>";
+               print "<li>" . __("Ready to update.") . "</li>";
+               print "</ul>";
+
+               print "<div class='dlgButtons'>";
+               print "<button id=\"self_update_start_btn\" dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('updateSelfDlg').start()\" >".
+                       __("Start update")."</button>";
+               print "<button id=\"self_update_stop_btn\" onclick=\"return dijit.byId('updateSelfDlg').close()\" dojoType=\"dijit.form.Button\">".
+                       __("Close this window")."</button>";
+               print "</div>";
+               print "</form>";
+       }
+
+       function performUpdate() {
+               $step = (int) $_REQUEST["step"];
+               $params = json_decode($_REQUEST["params"], true);
+               $force = (bool) $_REQUEST["force"];
+
+               if (($_SESSION["access_level"] >= 10 || SINGLE_USER_MODE) && CHECK_FOR_NEW_VERSION) {
+                       include "update_self.php";
+
+                       print   json_encode(update_self_step($this->link, $step, $params, $force));
+               }
+       }
+
+       function toggleAdvanced() {
+               $_SESSION["prefs_show_advanced"] = !$_SESSION["prefs_show_advanced"];
+       }
+
+       function otpqrcode() {
+               require_once "lib/otphp/vendor/base32.php";
+               require_once "lib/otphp/lib/otp.php";
+               require_once "lib/otphp/lib/totp.php";
+               require_once "lib/phpqrcode/phpqrcode.php";
+
+               $result = db_query($this->link, "SELECT login,salt
+                       FROM ttrss_users
+                       WHERE id = ".$_SESSION["uid"]);
+
+               $base32 = new Base32();
+
+               $login = db_fetch_result($result, 0, "login");
+               $secret = $base32->encode(sha1(db_fetch_result($result, 0, "salt")));
+
+               $topt = new \OTPHP\TOTP($secret);
+
+               print QRcode::png($topt->provisioning_uri($login));
+       }
+
+       function changeotp() {
+               $enable_otp = $_REQUEST["enable_otp"];
+
+               if ($enable_otp == "on") {
+                       db_query($this->link, "UPDATE ttrss_users SET otp_enabled = true WHERE
+                               id = " . $_SESSION["uid"]);
+               }
+       }
 }
 ?>