prefs: remove some more stuff from global context (user management, etc)

master
Andrew Dolgov 6 years ago
parent 58e54282d3
commit b9869dbc01

@ -166,7 +166,9 @@ class Dlg extends Handler_Protected {
$url_path = htmlspecialchars($this->params[2]) . "&key=" . $key; $url_path = htmlspecialchars($this->params[2]) . "&key=" . $key;
print "<h2>".__("You can view this feed as RSS using the following URL:")."</h2>"; $feed_title = Feeds::getFeedTitle($feed_id, $is_cat);
print "<div>".T_sprintf("%s can be accessed via the following secret URL:", $feed_title)."</div>";
print "<div class=\"tagCloudContainer\">"; print "<div class=\"tagCloudContainer\">";
print "<a id='gen_feed_url' href='$url_path' target='_blank'>$url_path</a>"; print "<a id='gen_feed_url' href='$url_path' target='_blank'>$url_path</a>";

@ -1174,7 +1174,7 @@ class Pref_Feeds extends Handler_Protected {
print "<div style='float : right; padding-right : 4px;'> print "<div style='float : right; padding-right : 4px;'>
<input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\" <input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"
value=\"$feed_search\"> value=\"$feed_search\">
<button dojoType=\"dijit.form.Button\" onclick=\"Feeds.reload()\">". <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedTree').reload()\">".
__('Search')."</button> __('Search')."</button>
</div>"; </div>";
@ -1326,7 +1326,7 @@ class Pref_Feeds extends Handler_Protected {
print "<button dojoType=\"dijit.form.Button\" onclick=\"return Utils.displayDlg('".__("Show as feed")."','generatedFeed', '$rss_url')\">". print "<button dojoType=\"dijit.form.Button\" onclick=\"return Utils.displayDlg('".__("Show as feed")."','generatedFeed', '$rss_url')\">".
__('Display URL')."</button> "; __('Display URL')."</button> ";
print "<button class=\"warning\" dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">". print "<button class=\"btn-danger\" dojoType=\"dijit.form.Button\" onclick=\"return Prefs.clearFeedAccessKeys()\">".
__('Clear all generated URLs')."</button> "; __('Clear all generated URLs')."</button> ";
print "</p>"; print "</p>";

@ -218,12 +218,13 @@ class Pref_Users extends Handler_Protected {
} }
function add() { function add() {
$login = trim(clean($_REQUEST["login"])); $login = trim(clean($_REQUEST["login"]));
$tmp_user_pwd = make_password(8); $tmp_user_pwd = make_password(8);
$salt = substr(bin2hex(get_random_bytes(125)), 0, 250); $salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
$pwd_hash = encrypt_password($tmp_user_pwd, $salt, true); $pwd_hash = encrypt_password($tmp_user_pwd, $salt, true);
if (!$login) return; // no blank usernames
$sth = $this->pdo->prepare("SELECT id FROM ttrss_users WHERE $sth = $this->pdo->prepare("SELECT id FROM ttrss_users WHERE
login = ?"); login = ?");
$sth->execute([$login]); $sth->execute([$login]);
@ -243,18 +244,18 @@ class Pref_Users extends Handler_Protected {
$new_uid = $row['id']; $new_uid = $row['id'];
print format_notice(T_sprintf("Added user <b>%s</b> with password <b>%s</b>", print T_sprintf("Added user %s with password %s",
$login, $tmp_user_pwd)); $login, $tmp_user_pwd);
initialize_user($new_uid); initialize_user($new_uid);
} else { } else {
print format_warning(T_sprintf("Could not create user <b>%s</b>", $login)); print T_sprintf("Could not create user %s", $login);
} }
} else { } else {
print format_warning(T_sprintf("User <b>%s</b> already exists.", $login)); print T_sprintf("User %s already exists.", $login);
} }
} }
@ -282,9 +283,9 @@ class Pref_Users extends Handler_Protected {
$sth->execute([$pwd_hash, $new_salt, $uid]); $sth->execute([$pwd_hash, $new_salt, $uid]);
if ($show_password) { if ($show_password) {
print T_sprintf("Changed password of user <b>%s</b> to <b>%s</b>", $login, $tmp_user_pwd); print T_sprintf("Changed password of user %s to %s", $login, $tmp_user_pwd);
} else { } else {
print_notice(T_sprintf("Sending new password of user <b>%s</b> to <b>%s</b>", $login, $email)); print_notice(T_sprintf("Sending new password of user %s to %s", $login, $email));
} }
if ($email) { if ($email) {
@ -341,7 +342,7 @@ class Pref_Users extends Handler_Protected {
print "<div style='float : right; padding-right : 4px;'> print "<div style='float : right; padding-right : 4px;'>
<input dojoType=\"dijit.form.TextBox\" id=\"user_search\" size=\"20\" type=\"search\" <input dojoType=\"dijit.form.TextBox\" id=\"user_search\" size=\"20\" type=\"search\"
value=\"$user_search\"> value=\"$user_search\">
<button dojoType=\"dijit.form.Button\" onclick=\"updateUsersList()\">". <button dojoType=\"dijit.form.Button\" oncl1ick=\"Users.reload()\">".
__('Search')."</button> __('Search')."</button>
</div>"; </div>";
@ -360,14 +361,14 @@ class Pref_Users extends Handler_Protected {
dojoType=\"dijit.MenuItem\">".__('None')."</div>"; dojoType=\"dijit.MenuItem\">".__('None')."</div>";
print "</div></div>"; print "</div></div>";
print "<button dojoType=\"dijit.form.Button\" onclick=\"addUser()\">".__('Create user')."</button>"; print "<button dojoType=\"dijit.form.Button\" onclick=\"Users.add()\">".__('Create user')."</button>";
print " print "
<button dojoType=\"dijit.form.Button\" onclick=\"editSelectedUser()\">". <button dojoType=\"dijit.form.Button\" onclick=\"Users.editSelected()\">".
__('Edit')."</button dojoType=\"dijit.form.Button\"> __('Edit')."</button dojoType=\"dijit.form.Button\">
<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedUsers()\">". <button dojoType=\"dijit.form.Button\" onclick=\"Users.removeSelected()\">".
__('Remove')."</button dojoType=\"dijit.form.Button\"> __('Remove')."</button dojoType=\"dijit.form.Button\">
<button dojoType=\"dijit.form.Button\" onclick=\"resetSelectedUserPass()\">". <button dojoType=\"dijit.form.Button\" onclick=\"Users.resetSelected()\">".
__('Reset password')."</button dojoType=\"dijit.form.Button\">"; __('Reset password')."</button dojoType=\"dijit.form.Button\">";
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION,
@ -400,11 +401,11 @@ class Pref_Users extends Handler_Protected {
print "<tr class=\"title\"> print "<tr class=\"title\">
<td align='center' width=\"5%\">&nbsp;</td> <td align='center' width=\"5%\">&nbsp;</td>
<td width='20%'><a href=\"#\" onclick=\"updateUsersList('login')\">".__('Login')."</a></td> <td width='20%'><a href=\"#\" onclick=\"Users.reload('login')\">".__('Login')."</a></td>
<td width='20%'><a href=\"#\" onclick=\"updateUsersList('access_level')\">".__('Access Level')."</a></td> <td width='20%'><a href=\"#\" onclick=\"Users.reload('access_level')\">".__('Access Level')."</a></td>
<td width='10%'><a href=\"#\" onclick=\"updateUsersList('num_feeds')\">".__('Subscribed feeds')."</a></td> <td width='10%'><a href=\"#\" onclick=\"Users.reload('num_feeds')\">".__('Subscribed feeds')."</a></td>
<td width='20%'><a href=\"#\" onclick=\"updateUsersList('created')\">".__('Registered')."</a></td> <td width='20%'><a href=\"#\" onclick=\"Users.reload('created')\">".__('Registered')."</a></td>
<td width='20%'><a href=\"#\" onclick=\"updateUsersList('last_login')\">".__('Last login')."</a></td></tr>"; <td width='20%'><a href=\"#\" onclick=\"Users.reload('last_login')\">".__('Last login')."</a></td></tr>";
$lnum = 0; $lnum = 0;
@ -412,26 +413,21 @@ class Pref_Users extends Handler_Protected {
$uid = $line["id"]; $uid = $line["id"];
print "<tr data-row-id=\"$uid\">"; print "<tr data-row-id=\"$uid\" onclick='Users.edit($uid)'>";
$line["login"] = htmlspecialchars($line["login"]); $line["login"] = htmlspecialchars($line["login"]);
$line["created"] = make_local_datetime($line["created"], false); $line["created"] = make_local_datetime($line["created"], false);
$line["last_login"] = make_local_datetime($line["last_login"], false); $line["last_login"] = make_local_datetime($line["last_login"], false);
print "<td align='center'><input onclick='Tables.onRowChecked(this);' print "<td align='center'><input onclick='Tables.onRowChecked(this); event.stopPropagation();'
dojoType=\"dijit.form.CheckBox\" type=\"checkbox\"></td>"; dojoType=\"dijit.form.CheckBox\" type=\"checkbox\"></td>";
$onclick = "onclick='editUser($uid, event)' title='".__('Click to edit')."'"; print "<td title='".__('Click to edit')."'><img src='images/user.png' class='marked-pic' alt=''> " . $line["login"] . "</td>";
print "<td $onclick><img src='images/user.png' class='marked-pic' alt=''> " . $line["login"] . "</td>";
if (!$line["email"]) $line["email"] = "&nbsp;";
print "<td $onclick>" . $access_level_names[$line["access_level"]] . "</td>"; print "<td>" . $access_level_names[$line["access_level"]] . "</td>";
print "<td $onclick>" . $line["num_feeds"] . "</td>"; print "<td>" . $line["num_feeds"] . "</td>";
print "<td $onclick>" . $line["created"] . "</td>"; print "<td>" . $line["created"] . "</td>";
print "<td $onclick>" . $line["last_login"] . "</td>"; print "<td>" . $line["last_login"] . "</td>";
print "</tr>"; print "</tr>";

@ -82,6 +82,15 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
getIconClass: function (item, opened) { getIconClass: function (item, opened) {
return (!item || this.model.store.getValue(item, 'type') == 'category') ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "feedIcon"; return (!item || this.model.store.getValue(item, 'type') == 'category') ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "feedIcon";
}, },
reload: function() {
const searchElem = $("feed_search");
let search = (searchElem) ? searchElem.value : "";
xhrPost("backend.php", { op: "pref-feeds", search: search }, (transport) => {
dijit.byId('feedConfigTab').attr('content', transport.responseText);
notify("");
});
},
checkItemAcceptance: function(target, source, position) { checkItemAcceptance: function(target, source, position) {
const item = dijit.getEnclosingWidget(target).item; const item = dijit.getEnclosingWidget(target).item;
@ -113,14 +122,14 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
notify_progress("Loading, please wait..."); notify_progress("Loading, please wait...");
xhrPost("backend.php", {op: "pref-feeds", method: "feedsortreset"}, () => { xhrPost("backend.php", {op: "pref-feeds", method: "feedsortreset"}, () => {
updateFeedList(); this.reload();
}); });
}, },
resetCatOrder: function() { resetCatOrder: function() {
notify_progress("Loading, please wait..."); notify_progress("Loading, please wait...");
xhrPost("backend.php", {op: "pref-feeds", method: "catsortreset"}, () => { xhrPost("backend.php", {op: "pref-feeds", method: "catsortreset"}, () => {
updateFeedList(); this.reload();
}); });
}, },
removeCategory: function(id, item) { removeCategory: function(id, item) {
@ -129,7 +138,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
xhrPost("backend.php", {op: "pref-feeds", method: "removeCat", ids: id}, () => { xhrPost("backend.php", {op: "pref-feeds", method: "removeCat", ids: id}, () => {
notify(''); notify('');
updateFeedList(); this.reload();
}); });
} }
}, },
@ -147,7 +156,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
}; };
xhrPost("backend.php", query, () => { xhrPost("backend.php", query, () => {
updateFeedList(); this.reload();
}); });
} }
@ -189,7 +198,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
}; };
xhrPost("backend.php", query, () => { xhrPost("backend.php", query, () => {
updateFeedList(); this.reload();
}); });
} }
} else { } else {
@ -284,7 +293,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
xhrPost("backend.php", query, () => { xhrPost("backend.php", query, () => {
dialog.hide(); dialog.hide();
updateFeedList(); dijit.byId("feedTree").reload();
}); });
} }
}, },
@ -306,7 +315,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
notify_progress("Loading, please wait..."); notify_progress("Loading, please wait...");
xhrPost("backend.php", { op: 'pref-feeds', method: 'renamecat', id: id, title: new_name }, () => { xhrPost("backend.php", { op: 'pref-feeds', method: 'renamecat', id: id, title: new_name }, () => {
updateFeedList(); this.reload();
}); });
} }
}, },
@ -318,7 +327,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
xhrPost("backend.php", {op: "pref-feeds", method: "addCat", cat: title}, () => { xhrPost("backend.php", {op: "pref-feeds", method: "addCat", cat: title}, () => {
notify(''); notify('');
updateFeedList(); this.reload();
}); });
} }
}, },
@ -339,7 +348,7 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
xhrPost("backend.php", this.attr('value'), () => { xhrPost("backend.php", this.attr('value'), () => {
notify(""); notify("");
updateFeedList(); dijit.byId("feedTree").reload();
dialog.hide(); dialog.hide();
}); });
} }
@ -376,8 +385,8 @@ define(["dojo/_base/declare", "dojo/dom-construct", "lib/CheckBoxTree"], functio
xhrPost("backend.php", query, () => { xhrPost("backend.php", query, () => {
notify(''); notify('');
dijit.byId("feedTree").reload();
dialog.hide(); dialog.hide();
updateFeedList();
}); });
} }

@ -132,6 +132,17 @@ const App = {
}; };
const Prefs = { const Prefs = {
clearFeedAccessKeys: function() {
if (confirm(__("This will invalidate all previously generated feed URLs. Continue?"))) {
notify_progress("Clearing URLs...");
xhrPost("backend.php", {op: "pref-feeds", method: "clearKeys"}, () => {
notify_info("Generated URLs cleared.");
});
}
return false;
},
clearEventLog: function() { clearEventLog: function() {
if (confirm(__("Clear event log?"))) { if (confirm(__("Clear event log?"))) {
@ -264,187 +275,120 @@ const Prefs = {
} }
}; };
function notify_callback2(transport, sticky) { const Users = {
notify_info(transport.responseText, sticky); reload: function(sort) {
} const user_search = $("user_search");
const search = user_search ? user_search.value : "";
function updateFeedList() { xhrPost("backend.php", { op: "pref-users", sort: sort, search: search }, (transport) => {
dijit.byId('userConfigTab').attr('content', transport.responseText);
notify("");
});
},
add: function() {
const login = prompt(__("Please enter username:"), "");
const user_search = $("feed_search"); if (login) {
let search = ""; notify_progress("Adding user...");
if (user_search) { search = user_search.value; }
xhrPost("backend.php", { op: "pref-feeds", search: search }, (transport) => { xhrPost("backend.php", {op: "pref-users", method: "add", login: login}, (transport) => {
dijit.byId('feedConfigTab').attr('content', transport.responseText); alert(transport.responseText);
notify(""); Users.reload();
}); });
}
function updateUsersList(sort_key) { }
const user_search = $("user_search"); },
const search = user_search ? user_search.value : ""; edit: function(id) {
const query = "backend.php?op=pref-users&method=edit&id=" +
param_escape(id);
const query = { op: "pref-users", sort: sort_key, search: search }; if (dijit.byId("userEditDlg"))
dijit.byId("userEditDlg").destroyRecursive();
xhrPost("backend.php", query, (transport) => { const dialog = new dijit.Dialog({
dijit.byId('userConfigTab').attr('content', transport.responseText); id: "userEditDlg",
notify(""); title: __("User Editor"),
}); style: "width: 600px",
} execute: function () {
if (this.validate()) {
notify_progress("Saving data...", true);
function addUser() { xhrPost("backend.php", dojo.formToObject("user_edit_form"), (transport) => {
const login = prompt(__("Please enter login:"), ""); dialog.hide();
Users.reload();
});
}
},
href: query
});
if (login == null) { dialog.show();
return false; },
} resetSelected: function() {
const rows = this.getSelection();
if (login == "") { if (rows.length == 0) {
alert(__("Can't create user: no login specified.")); alert(__("No users are selected."));
return false; return;
} }
notify_progress("Adding user..."); if (rows.length > 1) {
alert(__("Please select one user."));
return;
}
xhrPost("backend.php", { op: "pref-users", method: "add", login: login }, (transport) => { if (confirm(__("Reset password of selected user?"))) {
notify_callback2(transport); notify_progress("Resetting password for selected user...");
updateUsersList();
});
} const id = rows[0];
function editUser(id) { xhrPost("backend.php", {op: "pref-users", method: "resetPass", id: id}, (transport) => {
notify('');
alert(transport.responseText);
});
const query = "backend.php?op=pref-users&method=edit&id=" + }
param_escape(id); },
removeSelected: function() {
const sel_rows = this.getSelection();
if (dijit.byId("userEditDlg")) if (sel_rows.length > 0) {
dijit.byId("userEditDlg").destroyRecursive(); if (confirm(__("Remove selected users? Neither default admin nor your account will be removed."))) {
notify_progress("Removing selected users...");
const dialog = new dijit.Dialog({ const query = {
id: "userEditDlg", op: "pref-users", method: "remove",
title: __("User Editor"), ids: sel_rows.toString()
style: "width: 600px", };
execute: function () {
if (this.validate()) {
notify_progress("Saving data...", true);
xhrPost("backend.php", dojo.formToObject("user_edit_form"), (transport) => { xhrPost("backend.php", query, () => {
dialog.hide(); this.reload();
updateUsersList();
}); });
} }
},
href: query
});
dialog.show();
}
function getSelectedUsers() {
return Tables.getSelected("prefUserList");
}
function removeSelectedUsers() {
const sel_rows = getSelectedUsers();
if (sel_rows.length > 0) {
if (confirm(__("Remove selected users? Neither default admin nor your account will be removed."))) { } else {
notify_progress("Removing selected users..."); alert(__("No users are selected."));
const query = { op: "pref-users", method: "remove",
ids: sel_rows.toString() };
xhrPost("backend.php", query, () => {
updateUsersList();
});
} }
},
editSelected: function() {
const rows = this.getSelection();
} else { if (rows.length == 0) {
alert(__("No users are selected.")); alert(__("No users are selected."));
} return;
}
return false;
}
function editSelectedUser() {
const rows = getSelectedUsers();
if (rows.length == 0) {
alert(__("No users are selected."));
return;
}
if (rows.length > 1) {
alert(__("Please select only one user."));
return;
}
notify("");
editUser(rows[0]);
}
function resetSelectedUserPass() {
const rows = getSelectedUsers();
if (rows.length == 0) {
alert(__("No users are selected."));
return;
}
if (rows.length > 1) {
alert(__("Please select only one user."));
return;
}
if (confirm(__("Reset password of selected user?"))) {
notify_progress("Resetting password for selected user...");
const id = rows[0];
xhrPost("backend.php", { op: "pref-users", method: "resetPass", id: id }, (transport) => {
notify_info(transport.responseText, true);
});
}
}
function selectedUserDetails() {
const rows = getSelectedUsers();
if (rows.length == 0) { if (rows.length > 1) {
alert(__("No users are selected.")); alert(__("Please select one user."));
return; return;
} }
if (rows.length > 1) { this.edit(rows[0]);
alert(__("Please select only one user.")); },
return; getSelection :function() {
return Tables.getSelected("prefUserList");
} }
};
const query = "backend.php?op=pref-users&method=userdetails&id=" + param_escape(rows[0]);
if (dijit.byId("userDetailsDlg"))
dijit.byId("userDetailsDlg").destroyRecursive();
const dialog = new dijit.Dialog({
id: "userDetailsDlg",
title: __("User details"),
style: "width: 600px",
execute: function () {
dialog.hide();
},
href: query
});
dialog.show();
}
function opmlImportComplete(iframe) { function opmlImportComplete(iframe) {
if (!iframe.contentDocument.body.innerHTML) return false; if (!iframe.contentDocument.body.innerHTML) return false;
@ -541,19 +485,6 @@ function opmlRegenKey() {
return false; return false;
} }
function clearFeedAccessKeys() {
if (confirm(__("This will invalidate all previously generated feed URLs. Continue?"))) {
notify_progress("Clearing URLs...");
xhrPost("backend.php", { op: "pref-feeds", method: "clearKeys" }, () => {
notify_info("Generated URLs cleared.");
});
}
return false;
}
function gotoExportOpml(filename, settings) { function gotoExportOpml(filename, settings) {
const tmp = settings ? 1 : 0; const tmp = settings ? 1 : 0;
document.location.href = "backend.php?op=opml&method=export&filename=" + filename + "&settings=" + tmp; document.location.href = "backend.php?op=opml&method=export&filename=" + filename + "&settings=" + tmp;

Loading…
Cancel
Save