mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
Add support for package base co-maintainers
This allows for having multiple co-maintainers for AUR packages. Co-maintainers have push access to the package base Git repository but are not allowed to change the package base category, disown the package or modify the list of co-maintainers. The primary maintainer of an AUR package can edit the list of co-maintainers from the Package Actions box. Implements FS#17911. Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de>
This commit is contained in:
parent
b32458cb8a
commit
fc23a9bd50
12 changed files with 156 additions and 9 deletions
|
@ -276,6 +276,17 @@ CREATE TABLE PackageComments (
|
||||||
FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE
|
FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE
|
||||||
) ENGINE = InnoDB;
|
) ENGINE = InnoDB;
|
||||||
|
|
||||||
|
-- Package base co-maintainers
|
||||||
|
--
|
||||||
|
CREATE TABLE PackageComaintainers (
|
||||||
|
UsersID INTEGER UNSIGNED NOT NULL,
|
||||||
|
PackageBaseID INTEGER UNSIGNED NOT NULL,
|
||||||
|
INDEX (UsersID),
|
||||||
|
INDEX (PackageBaseID),
|
||||||
|
FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE
|
||||||
|
) ENGINE = InnoDB;
|
||||||
|
|
||||||
-- Comment addition notifications
|
-- Comment addition notifications
|
||||||
--
|
--
|
||||||
CREATE TABLE CommentNotify (
|
CREATE TABLE CommentNotify (
|
||||||
|
|
|
@ -92,10 +92,13 @@ def check_permissions(pkgbase, user):
|
||||||
unix_socket=aur_db_socket, buffered=True)
|
unix_socket=aur_db_socket, buffered=True)
|
||||||
cur = db.cursor()
|
cur = db.cursor()
|
||||||
|
|
||||||
cur.execute("SELECT COUNT(*) FROM PackageBases INNER JOIN Users " +
|
cur.execute("SELECT COUNT(*) FROM PackageBases " +
|
||||||
"ON Users.ID = PackageBases.MaintainerUID OR " +
|
"LEFT JOIN PackageComaintainers " +
|
||||||
"PackageBases.MaintainerUID IS NULL WHERE " +
|
"ON PackageComaintainers.PackageBaseID = PackageBases.ID " +
|
||||||
"Name = %s AND Username = %s", [pkgbase, user])
|
"INNER JOIN Users ON Users.ID = PackageBases.MaintainerUID " +
|
||||||
|
"OR PackageBases.MaintainerUID IS NULL " +
|
||||||
|
"OR Users.ID = PackageComaintainers.UsersID " +
|
||||||
|
"WHERE Name = %s AND Username = %s", [pkgbase, user])
|
||||||
return cur.fetchone()[0] > 0
|
return cur.fetchone()[0] > 0
|
||||||
|
|
||||||
def die(msg):
|
def die(msg):
|
||||||
|
|
|
@ -47,9 +47,11 @@ def save_srcinfo(srcinfo, db, cur, user):
|
||||||
|
|
||||||
# Update package base details and delete current packages.
|
# Update package base details and delete current packages.
|
||||||
cur.execute("UPDATE PackageBases SET ModifiedTS = UNIX_TIMESTAMP(), " +
|
cur.execute("UPDATE PackageBases SET ModifiedTS = UNIX_TIMESTAMP(), " +
|
||||||
"MaintainerUID = %s, PackagerUID = %s, " +
|
"PackagerUID = %s, OutOfDateTS = NULL WHERE ID = %s",
|
||||||
"OutOfDateTS = NULL WHERE ID = %s",
|
[user_id, pkgbase_id])
|
||||||
[user_id, user_id, pkgbase_id])
|
cur.execute("UPDATE PackageBases SET MaintainerUID = %s " +
|
||||||
|
"WHERE ID = %s AND MaintainerUID IS NULL",
|
||||||
|
[user_id, pkgbase_id])
|
||||||
cur.execute("DELETE FROM Packages WHERE PackageBaseID = %s",
|
cur.execute("DELETE FROM Packages WHERE PackageBaseID = %s",
|
||||||
[pkgbase_id])
|
[pkgbase_id])
|
||||||
|
|
||||||
|
|
|
@ -16,4 +16,17 @@ init-repos.py to initialize them.
|
||||||
UPDATE PackageBases SET PackagerUID = NULL;
|
UPDATE PackageBases SET PackagerUID = NULL;
|
||||||
----
|
----
|
||||||
|
|
||||||
5. (optional) Setup cgit to browse the Git repositories via HTTP.
|
5. Create a new table for package base co-maintainers:
|
||||||
|
|
||||||
|
----
|
||||||
|
CREATE TABLE PackageComaintainers (
|
||||||
|
UsersID INTEGER UNSIGNED NOT NULL,
|
||||||
|
PackageBaseID INTEGER UNSIGNED NOT NULL,
|
||||||
|
INDEX (UsersID),
|
||||||
|
INDEX (PackageBaseID),
|
||||||
|
FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE
|
||||||
|
) ENGINE = InnoDB;
|
||||||
|
----
|
||||||
|
|
||||||
|
6. (optional) Setup cgit to browse the Git repositories via HTTP.
|
||||||
|
|
21
web/html/comaintainers.php
Normal file
21
web/html/comaintainers.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
|
||||||
|
|
||||||
|
include_once("aur.inc.php");
|
||||||
|
include_once("pkgbasefuncs.inc.php");
|
||||||
|
|
||||||
|
set_lang();
|
||||||
|
check_sid();
|
||||||
|
|
||||||
|
if (!isset($base_id) || !has_credential(CRED_PKGBASE_EDIT_COMAINTAINERS, array(pkgbase_maintainer_uid($base_id)))) {
|
||||||
|
header('Location: /');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
html_header(__("Manage Co-maintainers"));
|
||||||
|
$users = pkgbase_get_comaintainers($base_id);
|
||||||
|
include('comaintainers_form.php');
|
||||||
|
html_footer(AUR_VERSION);
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,9 @@ if (!empty($tokens[1]) && '/' . $tokens[1] == get_pkg_route()) {
|
||||||
case "request":
|
case "request":
|
||||||
include('pkgreq.php');
|
include('pkgreq.php');
|
||||||
return;
|
return;
|
||||||
|
case "comaintainers":
|
||||||
|
include('comaintainers.php');
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
header("HTTP/1.0 404 Not Found");
|
header("HTTP/1.0 404 Not Found");
|
||||||
include "./404.php";
|
include "./404.php";
|
||||||
|
|
|
@ -97,6 +97,8 @@ if (check_token()) {
|
||||||
list($ret, $output) = pkgreq_file($ids, $_POST['type'], $_POST['merge_into'], $_POST['comments']);
|
list($ret, $output) = pkgreq_file($ids, $_POST['type'], $_POST['merge_into'], $_POST['comments']);
|
||||||
} elseif (current_action("do_CloseRequest")) {
|
} elseif (current_action("do_CloseRequest")) {
|
||||||
list($ret, $output) = pkgreq_close($_POST['reqid'], $_POST['reason'], $_POST['comments']);
|
list($ret, $output) = pkgreq_close($_POST['reqid'], $_POST['reason'], $_POST['comments']);
|
||||||
|
} elseif (current_action("do_EditComaintainers")) {
|
||||||
|
list($ret, $output) = pkgbase_set_comaintainers($base_id, explode("\n", $_POST['users']));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_REQUEST['comment'])) {
|
if (isset($_REQUEST['comment'])) {
|
||||||
|
@ -124,7 +126,7 @@ if (check_token()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$pkgs = pkgbase_get_pkgnames($base_id);
|
$pkgs = pkgbase_get_pkgnames($base_id);
|
||||||
if (count($pkgs) == 1) {
|
if (!$output && count($pkgs) == 1) {
|
||||||
/* Not a split package. Redirect to the package page. */
|
/* Not a split package. Redirect to the package page. */
|
||||||
if (empty($_SERVER['QUERY_STRING'])) {
|
if (empty($_SERVER['QUERY_STRING'])) {
|
||||||
header('Location: ' . get_pkg_uri($pkgs[0]));
|
header('Location: ' . get_pkg_uri($pkgs[0]));
|
||||||
|
|
|
@ -11,6 +11,7 @@ define("CRED_PKGBASE_ADOPT", 7);
|
||||||
define("CRED_PKGBASE_CHANGE_CATEGORY", 8);
|
define("CRED_PKGBASE_CHANGE_CATEGORY", 8);
|
||||||
define("CRED_PKGBASE_DELETE", 9);
|
define("CRED_PKGBASE_DELETE", 9);
|
||||||
define("CRED_PKGBASE_DISOWN", 10);
|
define("CRED_PKGBASE_DISOWN", 10);
|
||||||
|
define("CRED_PKGBASE_EDIT_COMAINTAINERS", 24);
|
||||||
define("CRED_PKGBASE_FLAG", 11);
|
define("CRED_PKGBASE_FLAG", 11);
|
||||||
define("CRED_PKGBASE_LIST_VOTERS", 12);
|
define("CRED_PKGBASE_LIST_VOTERS", 12);
|
||||||
define("CRED_PKGBASE_NOTIFY", 13);
|
define("CRED_PKGBASE_NOTIFY", 13);
|
||||||
|
@ -61,6 +62,7 @@ function has_credential($credential, $approved_users=array()) {
|
||||||
case CRED_PKGBASE_ADOPT:
|
case CRED_PKGBASE_ADOPT:
|
||||||
case CRED_PKGBASE_CHANGE_CATEGORY:
|
case CRED_PKGBASE_CHANGE_CATEGORY:
|
||||||
case CRED_PKGBASE_DELETE:
|
case CRED_PKGBASE_DELETE:
|
||||||
|
case CRED_PKGBASE_EDIT_COMAINTAINERS:
|
||||||
case CRED_PKGBASE_DISOWN:
|
case CRED_PKGBASE_DISOWN:
|
||||||
case CRED_PKGBASE_LIST_VOTERS:
|
case CRED_PKGBASE_LIST_VOTERS:
|
||||||
case CRED_PKGBASE_SUBMIT_BLACKLISTED:
|
case CRED_PKGBASE_SUBMIT_BLACKLISTED:
|
||||||
|
|
|
@ -928,3 +928,67 @@ function pkgbase_update_category($base_id, $category_id) {
|
||||||
$category_id, $base_id);
|
$category_id, $base_id);
|
||||||
$dbh->exec($q);
|
$dbh->exec($q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of package base co-maintainers
|
||||||
|
*
|
||||||
|
* @param int $base_id The package base ID to retrieve the co-maintainers for
|
||||||
|
*
|
||||||
|
* @return array An array of co-maintainer user names
|
||||||
|
*/
|
||||||
|
function pkgbase_get_comaintainers($base_id) {
|
||||||
|
$dbh = DB::connect();
|
||||||
|
$q = "SELECT UserName FROM PackageComaintainers ";
|
||||||
|
$q .= "INNER JOIN Users ON Users.ID = PackageComaintainers.UsersID ";
|
||||||
|
$q .= "WHERE PackageComaintainers.PackageBaseID = " . intval($base_id);
|
||||||
|
$result = $dbh->query($q);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
return $result->fetchAll(PDO::FETCH_COLUMN, 0);
|
||||||
|
} else {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the list of co-maintainers of a package base
|
||||||
|
*
|
||||||
|
* @param int $base_id The package base ID to update the co-maintainers of
|
||||||
|
* @param array $users Array of co-maintainer user names
|
||||||
|
*
|
||||||
|
* @return array Tuple of success/failure indicator and error message
|
||||||
|
*/
|
||||||
|
function pkgbase_set_comaintainers($base_id, $users) {
|
||||||
|
if (!has_credential(CRED_PKGBASE_EDIT_COMAINTAINERS, array(pkgbase_maintainer_uid($base_id)))) {
|
||||||
|
return array(false, __("You are not allowed to manage co-maintainers of this package base."));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove empty and duplicate user names. */
|
||||||
|
$users = array_unique(array_filter(array_map('trim', $users)));
|
||||||
|
|
||||||
|
$dbh = DB::connect();
|
||||||
|
|
||||||
|
$uids = array();
|
||||||
|
foreach($users as $user) {
|
||||||
|
$q = "SELECT ID FROM Users ";
|
||||||
|
$q .= "WHERE UserName = " . $dbh->quote($user);
|
||||||
|
$result = $dbh->query($q);
|
||||||
|
$uid = $result->fetchColumn(0);
|
||||||
|
|
||||||
|
if (!$uid) {
|
||||||
|
return array(false, __("Invalid user name: %s", $user));
|
||||||
|
}
|
||||||
|
|
||||||
|
$uids[] = $uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
$q = sprintf("DELETE FROM PackageComaintainers WHERE PackageBaseID = %d", $base_id);
|
||||||
|
$dbh->exec($q);
|
||||||
|
|
||||||
|
foreach ($uids as $uid) {
|
||||||
|
$q = sprintf("INSERT INTO PackageComaintainers (PackageBaseID, UsersID) VALUES (%d, %d)", $base_id, $uid);
|
||||||
|
$dbh->exec($q);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(true, __("The package base co-maintainers have been updated."));
|
||||||
|
}
|
||||||
|
|
20
web/template/comaintainers_form.php
Normal file
20
web/template/comaintainers_form.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<div class="box">
|
||||||
|
<h2><?= __('Manage Co-maintainers: %s', htmlspecialchars($pkgbase_name)) ?></h2>
|
||||||
|
<p>
|
||||||
|
<?= __('Use this form to add co-maintainers for %s%s%s (one user name per line):',
|
||||||
|
'<strong>', htmlspecialchars($pkgbase_name), '</strong>'); ?>
|
||||||
|
</p>
|
||||||
|
<form action="<?= get_pkgbase_uri($pkgbase_name); ?>" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" />
|
||||||
|
<p>
|
||||||
|
<label for="id_users"><?= __("Users") ?>:</label>
|
||||||
|
<textarea name="users" id="id_users" rows="5" cols="50"><?= htmlspecialchars(implode("\n", $users)) ?></textarea>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input type="submit" class="button" name="do_EditComaintainers" value="<?= __("Save") ?>" />
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
|
@ -131,6 +131,9 @@ $sources = pkg_sources($row["ID"]);
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php if (has_credential(CRED_PKGBASE_EDIT_COMAINTAINERS, array($row["MaintainerUID"]))): ?>
|
||||||
|
<li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'comaintainers/'; ?>"><?= __('Manage Co-Maintainers'); ?></a></li>
|
||||||
|
<?php endif; ?>
|
||||||
<li><span class="flagged"><?php if ($row["RequestCount"] > 0) { echo _n('%d pending request', '%d pending requests', $row["RequestCount"]); } ?></span></li>
|
<li><span class="flagged"><?php if ($row["RequestCount"] > 0) { echo _n('%d pending request', '%d pending requests', $row["RequestCount"]); } ?></span></li>
|
||||||
<li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'request/'; ?>"><?= __('File Request'); ?></a></li>
|
<li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'request/'; ?>"><?= __('File Request'); ?></a></li>
|
||||||
<?php if (has_credential(CRED_PKGBASE_DELETE)): ?>
|
<?php if (has_credential(CRED_PKGBASE_DELETE)): ?>
|
||||||
|
|
|
@ -82,6 +82,9 @@ $pkgs = pkgbase_get_pkgnames($base_id);
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php if (has_credential(CRED_PKGBASE_EDIT_COMAINTAINERS, array($row["MaintainerUID"]))): ?>
|
||||||
|
<li><a href="<?= get_pkgbase_uri($row['Name']) . 'comaintainers/'; ?>"><?= __('Manage Co-Maintainers'); ?></a></li>
|
||||||
|
<?php endif; ?>
|
||||||
<li><span class="flagged"><?php if ($row["RequestCount"] > 0) { echo _n('%d pending request', '%d pending requests', $row["RequestCount"]); } ?></span></li>
|
<li><span class="flagged"><?php if ($row["RequestCount"] > 0) { echo _n('%d pending request', '%d pending requests', $row["RequestCount"]); } ?></span></li>
|
||||||
<li><a href="<?= get_pkgbase_uri($row['Name']) . 'request/'; ?>"><?= __('File Request'); ?></a></li>
|
<li><a href="<?= get_pkgbase_uri($row['Name']) . 'request/'; ?>"><?= __('File Request'); ?></a></li>
|
||||||
<?php if (has_credential(CRED_PKGBASE_DELETE)): ?>
|
<?php if (has_credential(CRED_PKGBASE_DELETE)): ?>
|
||||||
|
|
Loading…
Add table
Reference in a new issue