From c8d99bac8ef96ac94bccdf3c754e7d43b3f1703c Mon Sep 17 00:00:00 2001
From: Eli Schwartz
Date: Sun, 8 Jul 2018 14:41:12 -0400
Subject: [PATCH 0001/1451] Fix regression in translating anything at all
In commit 840ee20 (Rename translation resources from aur to aurweb,
2018-07-07) the translations file was renamed but we never actually
switched to using the renamed translations.
As a result, every single push to the AUR contains the following
traceback:
remote: Traceback (most recent call last):
remote: File "/usr/bin/aurweb-notify", line 11, in
remote: load_entry_point('aurweb==4.7.0', 'console_scripts', 'aurweb-notify')()
remote: File "/usr/lib/python3.6/site-packages/aurweb-4.7.0-py3.6.egg/aurweb/scripts/notify.py", line 541, in main
remote: File "/usr/lib/python3.6/site-packages/aurweb-4.7.0-py3.6.egg/aurweb/scripts/notify.py", line 69, in send
remote: File "/usr/lib/python3.6/site-packages/aurweb-4.7.0-py3.6.egg/aurweb/scripts/notify.py", line 56, in get_body_fmt
remote: File "/usr/lib/python3.6/site-packages/aurweb-4.7.0-py3.6.egg/aurweb/scripts/notify.py", line 192, in get_body
remote: File "/usr/lib/python3.6/site-packages/aurweb-4.7.0-py3.6.egg/aurweb/l10n.py", line 14, in translate
remote: File "/usr/lib/python3.6/gettext.py", line 514, in translation
remote: raise OSError(ENOENT, 'No translation file found for domain', domain)
remote: FileNotFoundError: [Errno 2] No translation file found for domain: 'aur'
Signed-off-by: Eli Schwartz
Signed-off-by: Lukas Fleischer
---
aurweb/l10n.py | 2 +-
web/lib/translator.inc.php | 3 +--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/aurweb/l10n.py b/aurweb/l10n.py
index e58e3fe2..66e0f1c0 100644
--- a/aurweb/l10n.py
+++ b/aurweb/l10n.py
@@ -9,7 +9,7 @@ class Translator:
if lang == 'en':
return s
if lang not in self._translator:
- self._translator[lang] = gettext.translation("aur",
+ self._translator[lang] = gettext.translation("aurweb",
"../../web/locale",
languages=[lang])
self._translator[lang].install()
diff --git a/web/lib/translator.inc.php b/web/lib/translator.inc.php
index d10f8e90..cd944c56 100644
--- a/web/lib/translator.inc.php
+++ b/web/lib/translator.inc.php
@@ -131,9 +131,8 @@ function set_lang() {
}
$streamer = new FileReader('../locale/' . $LANG .
- '/LC_MESSAGES/aur.mo');
+ '/LC_MESSAGES/aurweb.mo');
$l10n = new gettext_reader($streamer, true);
return;
}
-
From a7865ef5aa0309976b5dd2642210632babe106d9 Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Sun, 22 Jul 2018 10:41:57 +0200
Subject: [PATCH 0002/1451] Make the locale directory configurable
Add a new configuration option to specify the locale directory to use.
This allows the Python scripts to find the translations, even when not
being run from the source code checkout. At the same time, multiple
parallel aurweb setups can still use different sets of translations.
Fixes FS#59278.
Signed-off-by: Lukas Fleischer
---
aurweb/l10n.py | 5 ++++-
conf/config.defaults | 1 +
web/lib/translator.inc.php | 3 ++-
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/aurweb/l10n.py b/aurweb/l10n.py
index 66e0f1c0..a7c0103e 100644
--- a/aurweb/l10n.py
+++ b/aurweb/l10n.py
@@ -1,8 +1,11 @@
import gettext
+import aurweb.config
+
class Translator:
def __init__(self):
+ self._localedir = aurweb.config.get('options', 'localedir')
self._translator = {}
def translate(self, s, lang):
@@ -10,7 +13,7 @@ class Translator:
return s
if lang not in self._translator:
self._translator[lang] = gettext.translation("aurweb",
- "../../web/locale",
+ self._localedir,
languages=[lang])
self._translator[lang].install()
return _(s)
diff --git a/conf/config.defaults b/conf/config.defaults
index be37f430..c8bc3a7e 100644
--- a/conf/config.defaults
+++ b/conf/config.defaults
@@ -35,6 +35,7 @@ snapshot_uri = /cgit/aur.git/snapshot/%s.tar.gz
enable-maintenance = 1
maintenance-exceptions = 127.0.0.1
render-comment-cmd = /usr/local/bin/aurweb-rendercomment
+localedir = /srv/http/aurweb/aur.git/web/locale/
# memcache or apc
cache = none
memcache_servers = 127.0.0.1:11211
diff --git a/web/lib/translator.inc.php b/web/lib/translator.inc.php
index cd944c56..334d0e76 100644
--- a/web/lib/translator.inc.php
+++ b/web/lib/translator.inc.php
@@ -130,7 +130,8 @@ function set_lang() {
setcookie("AURLANG", $LANG, $cookie_time, "/");
}
- $streamer = new FileReader('../locale/' . $LANG .
+ $localedir = config_get('options', 'localedir');
+ $streamer = new FileReader($localedir . '/' . $LANG .
'/LC_MESSAGES/aurweb.mo');
$l10n = new gettext_reader($streamer, true);
From 3578e77ad4e9258495eed7e786b7dc3aebcf1b63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Johannes=20L=C3=B6thberg?=
Date: Mon, 6 Aug 2018 02:02:57 +0200
Subject: [PATCH 0003/1451] Allow listing all comments from a user
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Johannes Löthberg
Signed-off-by: Lukas Fleischer
---
web/html/account.php | 20 +++++-
web/html/css/aurweb.css | 42 +++++++++++++
web/html/index.php | 2 +
web/html/pkgbase.php | 10 ++-
web/lib/acctfuncs.inc.php | 42 +++++++++++++
web/lib/aur.inc.php | 53 ++++++++++++++++
web/lib/credentials.inc.php | 2 +
web/lib/pkgbasefuncs.inc.php | 10 ++-
web/lib/pkgfuncs.inc.php | 4 ++
web/template/account_details.php | 3 +
web/template/account_edit_form.php | 1 +
web/template/pkg_comments.php | 99 ++++++++++++++++++++++--------
12 files changed, 258 insertions(+), 30 deletions(-)
diff --git a/web/html/account.php b/web/html/account.php
index c30a89aa..9695c9b7 100644
--- a/web/html/account.php
+++ b/web/html/account.php
@@ -8,7 +8,7 @@ include_once('acctfuncs.inc.php'); # access Account specific functions
$action = in_request("Action");
$need_userinfo = array(
- "DisplayAccount", "DeleteAccount", "AccountInfo", "UpdateAccount"
+ "DisplayAccount", "DeleteAccount", "AccountInfo", "UpdateAccount", "ListComments"
);
if (in_array($action, $need_userinfo)) {
@@ -166,6 +166,24 @@ if (isset($_COOKIE["AURSID"])) {
$row["Username"]);
}
+ } elseif ($action == "ListComments") {
+ if (has_credential(CRED_ACCOUNT_LIST_COMMENTS)) {
+ # display the comment list if they're a TU/dev
+
+ $total_comment_count = account_comments_count($row["ID"]);
+ list($pagination_templs, $per_page, $offset) = calculate_pagination($total_comment_count);
+
+ $username = $row["Username"];
+ $uid = $row["ID"];
+ $comments = account_comments($uid, $per_page, $offset);
+
+ $comment_section = "account";
+ include('pkg_comments.php');
+
+ } else {
+ print __("You are not allowed to access this area.");
+ }
+
} else {
if (has_credential(CRED_ACCOUNT_SEARCH)) {
# display the search page if they're a TU/dev
diff --git a/web/html/css/aurweb.css b/web/html/css/aurweb.css
index f5e10371..593c9ae8 100644
--- a/web/html/css/aurweb.css
+++ b/web/html/css/aurweb.css
@@ -148,3 +148,45 @@ label.confirmation,
color: red;
font-weight: bold;
}
+
+.package-comments {
+ margin-top: 1.5em;
+}
+
+.comments-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+}
+
+/* arrowed headings */
+.comments-header h3 span.text {
+ display: block;
+ background: #1794D1;
+ font-size: 15px;
+ padding: 2px 10px;
+ color: white;
+}
+
+.comments-header .comments-header-nav {
+ align-self: flex-end;
+}
+
+.comment-header {
+ clear: both;
+ font-size: 1em;
+ margin-top: 1.5em;
+ border-bottom: 1px dotted #bbb;
+}
+
+.comments div {
+ margin-bottom: 1em;
+}
+
+.comments div p {
+ margin-bottom: 0.5em;
+}
+
+.comments .more {
+ font-weight: normal;
+}
diff --git a/web/html/index.php b/web/html/index.php
index 2c53cddd..b2cd840e 100644
--- a/web/html/index.php
+++ b/web/html/index.php
@@ -142,6 +142,8 @@ if (!empty($tokens[1]) && '/' . $tokens[1] == get_pkg_route()) {
$_REQUEST['Action'] = "UpdateAccount";
} elseif ($tokens[3] == 'delete') {
$_REQUEST['Action'] = "DeleteAccount";
+ } elseif ($tokens[3] == 'comments') {
+ $_REQUEST['Action'] = "ListComments";
} else {
header("HTTP/1.0 404 Not Found");
include "./404.php";
diff --git a/web/html/pkgbase.php b/web/html/pkgbase.php
index cf9a6c60..46ad77e6 100644
--- a/web/html/pkgbase.php
+++ b/web/html/pkgbase.php
@@ -43,6 +43,7 @@ if (isset($_POST['IDs'])) {
/* Perform package base actions. */
$via = isset($_POST['via']) ? $_POST['via'] : NULL;
+$return_to = isset($_POST['return_to']) ? $_POST['return_to'] : NULL;
$ret = false;
$output = "";
$fragment = "";
@@ -133,7 +134,14 @@ if (check_token()) {
/* Redirect back to package request page on success. */
header('Location: ' . get_pkgreq_route());
exit();
- } if (isset($base_id)) {
+ } elseif ((current_action("do_DeleteComment") ||
+ current_action("do_UndeleteComment")) && $return_to) {
+ header('Location: ' . $return_to);
+ exit();
+ } elseif (current_action("do_PinComment") && $return_to) {
+ header('Location: ' . $return_to);
+ exit();
+ } elseif (isset($base_id)) {
/* Redirect back to package base page on success. */
header('Location: ' . get_pkgbase_uri($pkgbase_name) . $fragment);
exit();
diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php
index df573755..dc444842 100644
--- a/web/lib/acctfuncs.inc.php
+++ b/web/lib/acctfuncs.inc.php
@@ -1403,3 +1403,45 @@ function accept_terms($uid, $termrev) {
$dbh->exec($q);
}
}
+
+function account_comments($uid, $limit, $offset=0) {
+ $dbh = DB::connect();
+ $q = "SELECT PackageComments.ID, Comments, UsersID, ";
+ $q.= "PackageBaseId, CommentTS, DelTS, EditedTS, B.UserName AS EditUserName, ";
+ $q.= "PinnedTS, ";
+ $q.= "C.UserName as DelUserName, RenderedComment, ";
+ $q.= "PB.ID as PackageBaseID, PB.Name as PackageBaseName ";
+ $q.= "FROM PackageComments ";
+ $q.= "LEFT JOIN PackageBases PB ON PackageComments.PackageBaseID = PB.ID ";
+ $q.= "LEFT JOIN Users A ON PackageComments.UsersID = A.ID ";
+ $q.= "LEFT JOIN Users B ON PackageComments.EditedUsersID = B.ID ";
+ $q.= "LEFT JOIN Users C ON PackageComments.DelUsersID = C.ID ";
+ $q.= "WHERE A.ID = " . $dbh->quote($uid) . " ";
+ $q.= "ORDER BY CommentTS DESC";
+
+ if ($limit > 0) {
+ $q.=" LIMIT " . intval($limit);
+ }
+
+ if ($offset > 0) {
+ $q.=" OFFSET " . intval($offset);
+ }
+
+ $result = $dbh->query($q);
+ if (!$result) {
+ return null;
+ }
+
+ return $result->fetchAll();
+}
+
+function account_comments_count($uid) {
+ $dbh = DB::connect();
+ $q = "SELECT COUNT(*) ";
+ $q.= "FROM PackageComments ";
+ $q.= "LEFT JOIN Users A ON PackageComments.UsersID = A.ID ";
+ $q.= "WHERE A.ID = " . $dbh->quote($uid);
+
+ $result = $dbh->query($q);
+ return $result->fetchColumn();
+}
diff --git a/web/lib/aur.inc.php b/web/lib/aur.inc.php
index feb4006b..e9530fc0 100644
--- a/web/lib/aur.inc.php
+++ b/web/lib/aur.inc.php
@@ -705,3 +705,56 @@ function aur_location() {
}
return $location;
}
+
+/**
+ * Calculate pagination templates
+ *
+ * @return array The array of pagination templates, per page, and offset values
+ */
+function calculate_pagination($total_comment_count) {
+ /* Sanitize paging variables. */
+ if (isset($_GET["O"])) {
+ $_GET["O"] = max(intval($_GET["O"]), 0);
+ } else {
+ $_GET["O"] = 0;
+ }
+ $offset = $_GET["O"];
+
+ if (isset($_GET["PP"])) {
+ $_GET["PP"] = bound(intval($_GET["PP"]), 1, 250);
+ } else {
+ $_GET["PP"] = 10;
+ }
+ $per_page = $_GET["PP"];
+
+ // Page offsets start at zero, so page 2 has offset 1, which means that we
+ // need to add 1 to the offset to get the current page.
+ $current_page = ceil($offset / $per_page) + 1;
+ $num_pages = ceil($total_comment_count / $per_page);
+ $pagination_templs = array();
+
+ if ($current_page > 1) {
+ $previous_page = $current_page - 1;
+ $previous_offset = ($previous_page - 1) * $per_page;
+ $pagination_templs['« ' . __('First')] = 0;
+ $pagination_templs['‹ ' . __('Previous')] = $previous_offset;
+ }
+
+ if ($current_page - 5 > 1) {
+ $pagination_templs["..."] = false;
+ }
+
+ for ($i = max($current_page - 5, 1); $i <= min($num_pages, $current_page + 5); $i++) {
+ $pagination_templs[$i] = ($i - 1) * $per_page;
+ }
+
+ if ($current_page + 5 < $num_pages)
+ $pagination_templs["... "] = false;
+
+ if ($current_page < $num_pages) {
+ $pagination_templs[__('Next') . ' ›'] = $current_page * $per_page;
+ $pagination_templs[__('Last') . ' »'] = ($num_pages - 1) * $per_page;
+ }
+
+ return array($pagination_templs, $per_page, $offset);
+}
diff --git a/web/lib/credentials.inc.php b/web/lib/credentials.inc.php
index d8698a87..c1251197 100644
--- a/web/lib/credentials.inc.php
+++ b/web/lib/credentials.inc.php
@@ -5,6 +5,7 @@ define("CRED_ACCOUNT_EDIT", 2);
define("CRED_ACCOUNT_EDIT_DEV", 3);
define("CRED_ACCOUNT_LAST_LOGIN", 4);
define("CRED_ACCOUNT_SEARCH", 5);
+define("CRED_ACCOUNT_LIST_COMMENTS", 28);
define("CRED_COMMENT_DELETE", 6);
define("CRED_COMMENT_UNDELETE", 27);
define("CRED_COMMENT_VIEW_DELETED", 22);
@@ -48,6 +49,7 @@ function has_credential($credential, $approved_users=array()) {
$atype = account_from_sid($_COOKIE['AURSID']);
switch ($credential) {
+ case CRED_ACCOUNT_LIST_COMMENTS:
case CRED_PKGBASE_FLAG:
case CRED_PKGBASE_NOTIFY:
case CRED_PKGBASE_VOTE:
diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php
index 72c33b6d..953a5817 100644
--- a/web/lib/pkgbasefuncs.inc.php
+++ b/web/lib/pkgbasefuncs.inc.php
@@ -44,7 +44,7 @@ function pkgbase_comments_count($base_id, $include_deleted, $only_pinned=false)
*
* @return array All package comment information for a specific package base
*/
-function pkgbase_comments($base_id, $limit, $include_deleted, $only_pinned=false) {
+function pkgbase_comments($base_id, $limit, $include_deleted, $only_pinned=false, $offset=0) {
$base_id = intval($base_id);
$limit = intval($limit);
if (!$base_id) {
@@ -71,6 +71,9 @@ function pkgbase_comments($base_id, $limit, $include_deleted, $only_pinned=false
if ($limit > 0) {
$q.=" LIMIT " . $limit;
}
+ if ($offset > 0) {
+ $q.=" OFFSET " . $offset;
+ }
$result = $dbh->query($q);
if (!$result) {
return null;
@@ -273,6 +276,7 @@ function pkgbase_display_details($base_id, $row, $SID="") {
include('pkgbase_details.php');
if ($SID) {
+ $comment_section = "package";
include('pkg_comment_box.php');
}
@@ -281,13 +285,17 @@ function pkgbase_display_details($base_id, $row, $SID="") {
$limit_pinned = isset($_GET['pinned']) ? 0 : 5;
$pinned = pkgbase_comments($base_id, $limit_pinned, false, true);
if (!empty($pinned)) {
+ $comment_section = "package";
include('pkg_comments.php');
}
unset($pinned);
+
$limit = isset($_GET['comments']) ? 0 : 10;
$comments = pkgbase_comments($base_id, $limit, $include_deleted);
+
if (!empty($comments)) {
+ $comment_section = "package";
include('pkg_comments.php');
}
}
diff --git a/web/lib/pkgfuncs.inc.php b/web/lib/pkgfuncs.inc.php
index ad254746..140b8fc2 100644
--- a/web/lib/pkgfuncs.inc.php
+++ b/web/lib/pkgfuncs.inc.php
@@ -624,13 +624,17 @@ function pkg_display_details($id=0, $row, $SID="") {
$limit_pinned = isset($_GET['pinned']) ? 0 : 5;
$pinned = pkgbase_comments($base_id, $limit_pinned, false, true);
if (!empty($pinned)) {
+ $comment_section = "package";
include('pkg_comments.php');
}
unset($pinned);
+
$limit = isset($_GET['comments']) ? 0 : 10;
$comments = pkgbase_comments($base_id, $limit, $include_deleted);
+
if (!empty($comments)) {
+ $comment_section = "package";
include('pkg_comments.php');
}
}
diff --git a/web/template/account_details.php b/web/template/account_details.php
index 024bd9c3..fa6b528c 100644
--- a/web/template/account_details.php
+++ b/web/template/account_details.php
@@ -82,6 +82,9 @@
= __("Edit this user's account") ?>
+
+ = __("List this user's comments") ?>
+
diff --git a/web/template/account_edit_form.php b/web/template/account_edit_form.php
index 6eff81bd..38d5274c 100644
--- a/web/template/account_edit_form.php
+++ b/web/template/account_edit_form.php
@@ -2,6 +2,7 @@
= __('Click %shere%s if you want to permanently delete this account.', '', ' ') ?>
= __('Click %shere%s for user details.', '', ' ') ?>
+ = __('Click %shere%s to list the comments made by this account.', '', ' ') ?>
-
-
= __("The following information is only required if you want to submit packages to the Arch User Repository.") ?>
From 4ececd6041133ea9745261b7a2ac0da1e8976e21 Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Thu, 30 Jan 2020 13:19:16 +0100
Subject: [PATCH 0046/1451] Keep signature delimiters intact in notifications
Since commit eeaa1c3 (Separate text from footer in notification emails,
2020-01-04), information about unsubscribing from notifications is added
in a signature block. However, the code to format the email body trimmed
the RFC 3676 signature delimiter, replacing "-- " by "--". Fix this by
adding a special case for signature delimiters.
Signed-off-by: Lukas Fleischer
---
aurweb/scripts/notify.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/aurweb/scripts/notify.py b/aurweb/scripts/notify.py
index 6c3be222..f2767fd8 100755
--- a/aurweb/scripts/notify.py
+++ b/aurweb/scripts/notify.py
@@ -54,6 +54,9 @@ class Notification:
def get_body_fmt(self, lang):
body = ''
for line in self.get_body(lang).splitlines():
+ if line == '-- ':
+ body += '-- \n'
+ continue
body += textwrap.fill(line, break_long_words=False) + '\n'
for i, ref in enumerate(self.get_refs()):
body += '\n' + '[%d] %s' % (i + 1, ref)
From d0e5c3db693296ed7e909c3a0a4457d1328d87de Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Thu, 30 Jan 2020 13:23:51 +0100
Subject: [PATCH 0047/1451] t2500: fix test cases
Since commit eeaa1c3 (Separate text from footer in notification emails,
2020-01-04), information about unsubscribing from notifications is added
in a signature block. Fix the test cases accordingly.
Signed-off-by: Lukas Fleischer
---
test/t2500-notify.sh | 3 +++
1 file changed, 3 insertions(+)
diff --git a/test/t2500-notify.sh b/test/t2500-notify.sh
index 3080dc24..380e65b8 100755
--- a/test/t2500-notify.sh
+++ b/test/t2500-notify.sh
@@ -101,6 +101,7 @@ test_expect_success 'Test subject and body of comment notifications.' '
This is a test comment.
+ --
If you no longer wish to receive notifications about this package,
please go to the package page [2] and select "Disable notifications".
@@ -126,6 +127,7 @@ test_expect_success 'Test subject and body of update notifications.' '
cat <<-EOD >expected &&
user [1] pushed a new commit to foobar [2].
+ --
If you no longer wish to receive notifications about this package,
please go to the package page [2] and select "Disable notifications".
@@ -264,6 +266,7 @@ test_expect_success 'Test subject and body of merge notifications.' '
cat <<-EOD >expected &&
user [1] merged foobar [2] into foobar2 [3].
+ --
If you no longer wish receive notifications about the new package,
please go to [3] and click "Disable notifications".
From f090896fa1e9570715cfcdec7b23ecf95d25e936 Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Thu, 30 Jan 2020 11:58:16 +0100
Subject: [PATCH 0048/1451] Undo accidental code addition
Rollback an accidental change that sneaked into commit daee20c (Require
current password when setting a new one, 2020-01-30).
Signed-off-by: Lukas Fleischer
---
web/lib/acctfuncs.inc.php | 1 -
1 file changed, 1 deletion(-)
diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php
index 1de49b01..601d4ce0 100644
--- a/web/lib/acctfuncs.inc.php
+++ b/web/lib/acctfuncs.inc.php
@@ -135,7 +135,6 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$PO="",$P="
if(isset($_COOKIE['AURSID'])) {
$editor_user = uid_from_sid($_COOKIE['AURSID']);
- $row = account_details(in_request("ID"), in_request("U"));
}
else {
$editor_user = null;
From 7aa420d24da7e8c2c214ab421d44b4684d42e73e Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Thu, 30 Jan 2020 12:39:52 +0100
Subject: [PATCH 0049/1451] Verify current password against logged in user
When changing the password of an account, instead of asking for the old
password of the account, ask for the password of the currently logged in
user. This allows privileged users to edit other accounts without
knowing their passwords.
Signed-off-by: Lukas Fleischer
---
web/lib/acctfuncs.inc.php | 9 ++++-----
web/template/account_edit_form.php | 4 ++--
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php
index 601d4ce0..d2144c2a 100644
--- a/web/lib/acctfuncs.inc.php
+++ b/web/lib/acctfuncs.inc.php
@@ -134,10 +134,9 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$PO="",$P="
$dbh = DB::connect();
if(isset($_COOKIE['AURSID'])) {
- $editor_user = uid_from_sid($_COOKIE['AURSID']);
- }
- else {
- $editor_user = null;
+ $uid_session = uid_from_sid($_COOKIE['AURSID']);
+ } else {
+ $uid_session = null;
}
if (empty($E) || empty($U)) {
@@ -169,7 +168,7 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$PO="",$P="
if (!$error && $P && $P != $C) {
$error = __("Password fields do not match.");
}
- if (!$error && $P && check_passwd($UID, $PO) != 1) {
+ if (!$error && $P && check_passwd($uid_session, $PO) != 1) {
$error = __("The old password is invalid.");
}
if (!$error && $P != '' && !good_passwd($P)) {
diff --git a/web/template/account_edit_form.php b/web/template/account_edit_form.php
index 25e91853..7bd233a8 100644
--- a/web/template/account_edit_form.php
+++ b/web/template/account_edit_form.php
@@ -140,9 +140,9 @@
- = __("If you want to change your password, enter your current passport, your new password and confirm the new password by entering it again.") ?>
+ = __("If you want to change the password, enter your current passport, the new password and confirm the new password by entering it again.") ?>
- = __("Old password") ?>:
+ = __("Your current password") ?>:
From 8fc8898fef39af20a24c9928464fd8420481d819 Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Thu, 30 Jan 2020 11:52:32 +0100
Subject: [PATCH 0050/1451] Require password when deleting an account
Further reduce the attack surface in case of a stolen session ID.
Signed-off-by: Lukas Fleischer
---
web/html/account.php | 17 +++++++++++++----
web/template/account_delete.php | 11 +++++++++--
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/web/html/account.php b/web/html/account.php
index 7c6c424a..03af8d43 100644
--- a/web/html/account.php
+++ b/web/html/account.php
@@ -120,12 +120,21 @@ if (isset($_COOKIE["AURSID"])) {
} elseif ($action == "DeleteAccount") {
/* Details for account being deleted. */
if (can_edit_account($row)) {
- $UID = $row['ID'];
+ $uid_removal = $row['ID'];
+ $uid_session = uid_from_sid($_COOKIE['AURSID']);
+ $username = $row['Username'];
+
if (in_request('confirm') && check_token()) {
- user_delete($UID);
- header('Location: /');
+ if (check_passwd($uid_session, $_REQUEST['passwd']) == 1) {
+ user_delete($uid_removal);
+ header('Location: /');
+ } else {
+ echo "";
+ echo __("Invalid password.");
+ echo " ";
+ include("account_delete.php");
+ }
} else {
- $username = $row['Username'];
include("account_delete.php");
}
} else {
diff --git a/web/template/account_delete.php b/web/template/account_delete.php
index 718b172f..d0c6e74d 100644
--- a/web/template/account_delete.php
+++ b/web/template/account_delete.php
@@ -12,8 +12,15 @@
-
- = __("Confirm deletion") ?>
+
+ = __("Password") ?>:
+
+
+
+
+
+ = __("Confirm deletion") ?>
+
" />
From def2787b45275de2b8dfab0ece87f35ea280567b Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Thu, 30 Jan 2020 14:00:07 +0100
Subject: [PATCH 0051/1451] Require password when changing account information
Since commits daee20c (Require current password when setting a new one,
2020-01-30) and 8fc8898 (Require password when deleting an account,
2020-01-30), changing a password and deleting an account require the
current password. Extend this to all other profile changes.
Signed-off-by: Lukas Fleischer
---
web/html/account.php | 5 +++--
web/html/register.php | 4 ++--
web/lib/acctfuncs.inc.php | 19 +++++++------------
web/template/account_edit_form.php | 17 +++++++++--------
4 files changed, 21 insertions(+), 24 deletions(-)
diff --git a/web/html/account.php b/web/html/account.php
index 03af8d43..ff9aba5b 100644
--- a/web/html/account.php
+++ b/web/html/account.php
@@ -34,7 +34,6 @@ if ($action == "UpdateAccount") {
in_request("S"),
in_request("E"),
in_request("H"),
- in_request("PO"),
in_request("P"),
in_request("C"),
in_request("R"),
@@ -49,7 +48,9 @@ if ($action == "UpdateAccount") {
in_request("UN"),
in_request("ON"),
in_request("ID"),
- $row["Username"]);
+ $row["Username"],
+ in_request("passwd")
+ );
}
}
diff --git a/web/html/register.php b/web/html/register.php
index 8174e342..610befc4 100644
--- a/web/html/register.php
+++ b/web/html/register.php
@@ -26,7 +26,6 @@ if (in_request("Action") == "NewAccount") {
in_request("H"),
'',
'',
- '',
in_request("R"),
in_request("L"),
in_request("TZ"),
@@ -40,6 +39,7 @@ if (in_request("Action") == "NewAccount") {
in_request("ON"),
0,
"",
+ '',
in_request("captcha_salt"),
in_request("captcha"),
);
@@ -55,7 +55,6 @@ if (in_request("Action") == "NewAccount") {
in_request("H"),
'',
'',
- '',
in_request("R"),
in_request("L"),
in_request("TZ"),
@@ -69,6 +68,7 @@ if (in_request("Action") == "NewAccount") {
in_request("ON"),
0,
"",
+ '',
in_request("captcha_salt"),
in_request("captcha")
);
diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php
index d2144c2a..345d27af 100644
--- a/web/lib/acctfuncs.inc.php
+++ b/web/lib/acctfuncs.inc.php
@@ -96,7 +96,6 @@ function display_account_form($A,$U="",$T="",$S="",$E="",$H="",$P="",$C="",$R=""
* @param string $S Whether or not the account is suspended
* @param string $E The e-mail address for the user
* @param string $H Whether or not the e-mail address should be hidden
- * @param string $PO The old password of the user
* @param string $P The password for the user
* @param string $C The confirmed password for the user
* @param string $R The real name of the user
@@ -112,13 +111,14 @@ function display_account_form($A,$U="",$T="",$S="",$E="",$H="",$P="",$C="",$R=""
* @param string $ON Whether to notify of ownership changes
* @param string $UID The user ID of the modified account
* @param string $N The username as present in the database
+ * @param string $passwd The password of the logged in user.
* @param string $captcha_salt The salt used for the CAPTCHA.
* @param string $captcha The CAPTCHA answer.
*
* @return array Boolean indicating success and message to be printed
*/
-function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$PO="",$P="",$C="",
- $R="",$L="",$TZ="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="",$captcha_salt="",$captcha="") {
+function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$P="",$C="",
+ $R="",$L="",$TZ="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="",$passwd="",$captcha_salt="",$captcha="") {
global $SUPPORTED_LANGS;
$error = '';
@@ -133,10 +133,11 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$PO="",$P="
$dbh = DB::connect();
- if(isset($_COOKIE['AURSID'])) {
+ if (isset($_COOKIE['AURSID'])) {
$uid_session = uid_from_sid($_COOKIE['AURSID']);
- } else {
- $uid_session = null;
+ if (!$error && check_passwd($uid_session, $passwd) != 1) {
+ $error = __("Invalid password.");
+ }
}
if (empty($E) || empty($U)) {
@@ -162,15 +163,9 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$PO="",$P="
if (!$error && $P && !$C) {
$error = __("Please confirm your new password.");
}
- if (!$error && $P && !$PO) {
- $error = __("Please enter your old password in order to set a new one.");
- }
if (!$error && $P && $P != $C) {
$error = __("Password fields do not match.");
}
- if (!$error && $P && check_passwd($uid_session, $PO) != 1) {
- $error = __("The old password is invalid.");
- }
if (!$error && $P != '' && !good_passwd($P)) {
$length_min = config_get_int('options', 'passwd_min_len');
$error = __("Your password must be at least %s characters.",
diff --git a/web/template/account_edit_form.php b/web/template/account_edit_form.php
index 7bd233a8..09d65c0f 100644
--- a/web/template/account_edit_form.php
+++ b/web/template/account_edit_form.php
@@ -140,12 +140,7 @@
- = __("If you want to change the password, enter your current passport, the new password and confirm the new password by entering it again.") ?>
-
- = __("Your current password") ?>:
-
-
-
+ = __("If you want to change the password, enter a new password and confirm the new password by entering it again.") ?>
= __("Password") ?>:
@@ -182,16 +177,22 @@
-
+
+ = __("To confirm the profile changes, please enter your current password:") ?>
+
+ = __("Your current password") ?>:
+
+
+
= __("To protect the AUR against automated account creation, we kindly ask you to provide the output of the following command:") ?> = htmlspecialchars($captcha_challenge) ?>
= __("Answer") ?>:
(= __("required") ?>)
-
+
From 23c0c9c372a7443e96115441571ea57bb24881c7 Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Thu, 30 Jan 2020 13:09:05 +0100
Subject: [PATCH 0052/1451] Update copyright range in the cgit footer
---
web/template/cgit/footer.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/template/cgit/footer.html b/web/template/cgit/footer.html
index 1c0bf6f6..14c358f1 100644
--- a/web/template/cgit/footer.html
+++ b/web/template/cgit/footer.html
@@ -1,6 +1,6 @@
From e5a839bf0b9884e2a015b3f0b3fdbf23d1a1654c Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Thu, 30 Jan 2020 16:57:22 +0100
Subject: [PATCH 0053/1451] Add option to send reset key for a given user name
In addition to supporting email addresses in the reset key form, also
support user names. The reset key is then sent to the email address in
the user's profile.
Signed-off-by: Lukas Fleischer
---
web/html/passreset.php | 25 ++++++++++++-------------
web/lib/acctfuncs.inc.php | 13 +++++++------
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/web/html/passreset.php b/web/html/passreset.php
index 9e7cee88..b3c8bd29 100644
--- a/web/html/passreset.php
+++ b/web/html/passreset.php
@@ -11,14 +11,14 @@ if (isset($_COOKIE["AURSID"])) {
$error = '';
-if (isset($_GET['resetkey'], $_POST['email'], $_POST['password'], $_POST['confirm'])) {
+if (isset($_GET['resetkey'], $_POST['user'], $_POST['password'], $_POST['confirm'])) {
$resetkey = $_GET['resetkey'];
- $email = $_POST['email'];
+ $user = $_POST['user'];
$password = $_POST['password'];
$confirm = $_POST['confirm'];
- $uid = uid_from_email($email);
+ $uid = uid_from_loginname($user);
- if (empty($email) || empty($password)) {
+ if (empty($user) || empty($password)) {
$error = __('Missing a required field.');
} elseif ($password != $confirm) {
$error = __('Password fields do not match.');
@@ -31,16 +31,15 @@ if (isset($_GET['resetkey'], $_POST['email'], $_POST['password'], $_POST['confir
}
if (empty($error)) {
- $error = password_reset($password, $resetkey, $email);
+ $error = password_reset($password, $resetkey, $user);
}
-} elseif (isset($_POST['email'])) {
- $email = $_POST['email'];
- $username = username_from_id(uid_from_email($email));
+} elseif (isset($_POST['user'])) {
+ $user = $_POST['user'];
- if (empty($email)) {
+ if (empty($user)) {
$error = __('Missing a required field.');
} else {
- send_resetkey($email);
+ send_resetkey($user);
header('Location: ' . get_uri('/passreset/') . '?step=confirm');
exit();
}
@@ -67,7 +66,7 @@ html_header(__("Password Reset"));
= __("Confirm your e-mail address:"); ?>
-
+
= __("Enter your new password:"); ?>
@@ -89,8 +88,8 @@ html_header(__("Password Reset"));
diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php
index 345d27af..f6cda69c 100644
--- a/web/lib/acctfuncs.inc.php
+++ b/web/lib/acctfuncs.inc.php
@@ -755,13 +755,13 @@ function create_resetkey($resetkey, $uid) {
/**
* Send a reset key to a specific e-mail address
*
- * @param string $email E-mail address of the user resetting their password
+ * @param string $user User name or email address of the user
* @param bool $welcome Whether to use the welcome message
*
* @return void
*/
-function send_resetkey($email, $welcome=false) {
- $uid = uid_from_email($email);
+function send_resetkey($user, $welcome=false) {
+ $uid = uid_from_loginname($user);
if ($uid == null) {
return;
}
@@ -779,11 +779,11 @@ function send_resetkey($email, $welcome=false) {
*
* @param string $password The new password
* @param string $resetkey Code e-mailed to a user to reset a password
- * @param string $email E-mail address of the user resetting their password
+ * @param string $user User name or email address of the user
*
* @return string|void Redirect page if successful, otherwise return error message
*/
-function password_reset($password, $resetkey, $email) {
+function password_reset($password, $resetkey, $user) {
$hash = password_hash($password, PASSWORD_DEFAULT);
$dbh = DB::connect();
@@ -792,7 +792,8 @@ function password_reset($password, $resetkey, $email) {
$q.= "ResetKey = '' ";
$q.= "WHERE ResetKey != '' ";
$q.= "AND ResetKey = " . $dbh->quote($resetkey) . " ";
- $q.= "AND Email = " . $dbh->quote($email);
+ $q.= "AND (Email = " . $dbh->quote($user) . " OR ";
+ $q.= "UserName = " . $dbh->quote($user) . ")";
$result = $dbh->exec($q);
if (!$result) {
From ee2aa9755fa3c94e8c8a697c3f7a9627027994d5 Mon Sep 17 00:00:00 2001
From: Lukas Fleischer
Date: Thu, 30 Jan 2020 17:15:33 +0100
Subject: [PATCH 0054/1451] Add support for backup email addresses
Support secondary email addresses that can be used to recover an account
in case access to the primary email address is lost. Reset keys for an
account are always sent to both the primary and the backup email
address.
Signed-off-by: Lukas Fleischer
---
aurweb/scripts/notify.py | 12 ++++++++----
schema/aur-schema.sql | 1 +
upgrading/4.9.0.txt | 6 ++++++
web/html/account.php | 3 +++
web/html/login.php | 2 +-
web/html/passreset.php | 6 +++---
web/html/register.php | 4 +++-
web/lib/acctfuncs.inc.php | 15 +++++++++++----
web/template/account_edit_form.php | 12 +++++++++++-
9 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/aurweb/scripts/notify.py b/aurweb/scripts/notify.py
index f2767fd8..b0f218b5 100755
--- a/aurweb/scripts/notify.py
+++ b/aurweb/scripts/notify.py
@@ -90,13 +90,17 @@ class Notification:
class ResetKeyNotification(Notification):
def __init__(self, conn, uid):
- cur = conn.execute('SELECT UserName, Email, LangPreference, ' +
- 'ResetKey FROM Users WHERE ID = ?', [uid])
- self._username, self._to, self._lang, self._resetkey = cur.fetchone()
+ cur = conn.execute('SELECT UserName, Email, BackupEmail, ' +
+ 'LangPreference, ResetKey ' +
+ 'FROM Users WHERE ID = ?', [uid])
+ self._username, self._to, self._backup, self._lang, self._resetkey = cur.fetchone()
super().__init__()
def get_recipients(self):
- return [(self._to, self._lang)]
+ if self._backup:
+ return [(self._to, self._lang), (self._backup, self._lang)]
+ else:
+ return [(self._to, self._lang)]
def get_subject(self, lang):
return self._l10n.translate('AUR Password Reset', lang)
diff --git a/schema/aur-schema.sql b/schema/aur-schema.sql
index fa991ba6..1f86df20 100644
--- a/schema/aur-schema.sql
+++ b/schema/aur-schema.sql
@@ -23,6 +23,7 @@ CREATE TABLE Users (
Suspended TINYINT UNSIGNED NOT NULL DEFAULT 0,
Username VARCHAR(32) NOT NULL,
Email VARCHAR(254) NOT NULL,
+ BackupEmail VARCHAR(254) NULL DEFAULT NULL,
HideEmail TINYINT UNSIGNED NOT NULL DEFAULT 0,
Passwd VARCHAR(255) NOT NULL,
Salt CHAR(32) NOT NULL DEFAULT '',
diff --git a/upgrading/4.9.0.txt b/upgrading/4.9.0.txt
index 4c79283e..241f24af 100644
--- a/upgrading/4.9.0.txt
+++ b/upgrading/4.9.0.txt
@@ -4,3 +4,9 @@
ALTER TABLE PackageRequests ADD COLUMN ClosedTS BIGINT UNSIGNED NULL DEFAULT NULL;
ALTER TABLE PackageRequests ADD COLUMN ClosedUID INTEGER UNSIGNED NULL DEFAULT NULL;
----
+
+2. Add a new column to store backup email addresses:
+
+----
+ALTER TABLE Users ADD COLUMN BackupEmail VARCHAR(254) NULL DEFAULT NULL;
+----
diff --git a/web/html/account.php b/web/html/account.php
index ff9aba5b..c05d136d 100644
--- a/web/html/account.php
+++ b/web/html/account.php
@@ -33,6 +33,7 @@ if ($action == "UpdateAccount") {
in_request("T"),
in_request("S"),
in_request("E"),
+ in_request("BE"),
in_request("H"),
in_request("P"),
in_request("C"),
@@ -97,6 +98,7 @@ if (isset($_COOKIE["AURSID"])) {
$row["AccountTypeID"],
$row["Suspended"],
$row["Email"],
+ $row["BackupEmail"],
$row["HideEmail"],
"",
"",
@@ -159,6 +161,7 @@ if (isset($_COOKIE["AURSID"])) {
in_request("T"),
in_request("S"),
in_request("E"),
+ in_request("BE"),
in_request("H"),
in_request("P"),
in_request("C"),
diff --git a/web/html/login.php b/web/html/login.php
index df517055..01454414 100644
--- a/web/html/login.php
+++ b/web/html/login.php
@@ -26,7 +26,7 @@ html_header('AUR ' . __("Login"));
- = __('User name or email address') . ':'; ?>
+ = __('User name or primary email address') . ':'; ?>
diff --git a/web/html/passreset.php b/web/html/passreset.php
index b3c8bd29..26b9bbbb 100644
--- a/web/html/passreset.php
+++ b/web/html/passreset.php
@@ -65,7 +65,7 @@ html_header(__("Password Reset"));