diff options
author | Lukas Fleischer <archlinux@cryptocrack.de> | 2015-01-07 12:10:53 +0100 |
---|---|---|
committer | Lukas Fleischer <archlinux@cryptocrack.de> | 2015-01-07 12:21:21 +0100 |
commit | fc23a9bd5012d07cc6ef9d1eba12f320763068d9 (patch) | |
tree | 733f53ac3bcc122afaf6e47a6c3b92cb3da5c66f | |
parent | b32458cb8a043422bfc2962c03a70deaee9eaca9 (diff) | |
download | aur-fc23a9bd5012d07cc6ef9d1eba12f320763068d9.tar.gz aur-fc23a9bd5012d07cc6ef9d1eba12f320763068d9.tar.xz |
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>
-rw-r--r-- | schema/aur-schema.sql | 11 | ||||
-rwxr-xr-x | scripts/git-integration/git-serve.py | 11 | ||||
-rwxr-xr-x | scripts/git-integration/git-update.py | 8 | ||||
-rw-r--r-- | upgrading/4.0.0.txt | 15 | ||||
-rw-r--r-- | web/html/comaintainers.php | 21 | ||||
-rw-r--r-- | web/html/index.php | 3 | ||||
-rw-r--r-- | web/html/pkgbase.php | 4 | ||||
-rw-r--r-- | web/lib/credentials.inc.php | 2 | ||||
-rw-r--r-- | web/lib/pkgbasefuncs.inc.php | 64 | ||||
-rw-r--r-- | web/template/comaintainers_form.php | 20 | ||||
-rw-r--r-- | web/template/pkg_details.php | 3 | ||||
-rw-r--r-- | web/template/pkgbase_details.php | 3 |
12 files changed, 156 insertions, 9 deletions
diff --git a/schema/aur-schema.sql b/schema/aur-schema.sql index dfd158fd..9c647d8b 100644 --- a/schema/aur-schema.sql +++ b/schema/aur-schema.sql @@ -276,6 +276,17 @@ CREATE TABLE PackageComments ( FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE ) 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 -- CREATE TABLE CommentNotify ( diff --git a/scripts/git-integration/git-serve.py b/scripts/git-integration/git-serve.py index a1c6e3a1..d551dba4 100755 --- a/scripts/git-integration/git-serve.py +++ b/scripts/git-integration/git-serve.py @@ -92,10 +92,13 @@ def check_permissions(pkgbase, user): unix_socket=aur_db_socket, buffered=True) cur = db.cursor() - cur.execute("SELECT COUNT(*) FROM PackageBases INNER JOIN Users " + - "ON Users.ID = PackageBases.MaintainerUID OR " + - "PackageBases.MaintainerUID IS NULL WHERE " + - "Name = %s AND Username = %s", [pkgbase, user]) + cur.execute("SELECT COUNT(*) FROM PackageBases " + + "LEFT JOIN PackageComaintainers " + + "ON PackageComaintainers.PackageBaseID = PackageBases.ID " + + "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 def die(msg): diff --git a/scripts/git-integration/git-update.py b/scripts/git-integration/git-update.py index 1ff09b86..b20c0a22 100755 --- a/scripts/git-integration/git-update.py +++ b/scripts/git-integration/git-update.py @@ -47,9 +47,11 @@ def save_srcinfo(srcinfo, db, cur, user): # Update package base details and delete current packages. cur.execute("UPDATE PackageBases SET ModifiedTS = UNIX_TIMESTAMP(), " + - "MaintainerUID = %s, PackagerUID = %s, " + - "OutOfDateTS = NULL WHERE ID = %s", - [user_id, user_id, pkgbase_id]) + "PackagerUID = %s, OutOfDateTS = NULL WHERE ID = %s", + [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", [pkgbase_id]) diff --git a/upgrading/4.0.0.txt b/upgrading/4.0.0.txt index f990c373..b1582f2f 100644 --- a/upgrading/4.0.0.txt +++ b/upgrading/4.0.0.txt @@ -16,4 +16,17 @@ init-repos.py to initialize them. 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. diff --git a/web/html/comaintainers.php b/web/html/comaintainers.php new file mode 100644 index 00000000..591fcad1 --- /dev/null +++ b/web/html/comaintainers.php @@ -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); + + diff --git a/web/html/index.php b/web/html/index.php index 9c321fa4..cfd6598c 100644 --- a/web/html/index.php +++ b/web/html/index.php @@ -78,6 +78,9 @@ if (!empty($tokens[1]) && '/' . $tokens[1] == get_pkg_route()) { case "request": include('pkgreq.php'); return; + case "comaintainers": + include('comaintainers.php'); + return; default: header("HTTP/1.0 404 Not Found"); include "./404.php"; diff --git a/web/html/pkgbase.php b/web/html/pkgbase.php index bdce516b..201749e9 100644 --- a/web/html/pkgbase.php +++ b/web/html/pkgbase.php @@ -97,6 +97,8 @@ if (check_token()) { list($ret, $output) = pkgreq_file($ids, $_POST['type'], $_POST['merge_into'], $_POST['comments']); } elseif (current_action("do_CloseRequest")) { 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'])) { @@ -124,7 +126,7 @@ if (check_token()) { } $pkgs = pkgbase_get_pkgnames($base_id); -if (count($pkgs) == 1) { +if (!$output && count($pkgs) == 1) { /* Not a split package. Redirect to the package page. */ if (empty($_SERVER['QUERY_STRING'])) { header('Location: ' . get_pkg_uri($pkgs[0])); diff --git a/web/lib/credentials.inc.php b/web/lib/credentials.inc.php index 6c70ede1..b813b901 100644 --- a/web/lib/credentials.inc.php +++ b/web/lib/credentials.inc.php @@ -11,6 +11,7 @@ define("CRED_PKGBASE_ADOPT", 7); define("CRED_PKGBASE_CHANGE_CATEGORY", 8); define("CRED_PKGBASE_DELETE", 9); define("CRED_PKGBASE_DISOWN", 10); +define("CRED_PKGBASE_EDIT_COMAINTAINERS", 24); define("CRED_PKGBASE_FLAG", 11); define("CRED_PKGBASE_LIST_VOTERS", 12); define("CRED_PKGBASE_NOTIFY", 13); @@ -61,6 +62,7 @@ function has_credential($credential, $approved_users=array()) { case CRED_PKGBASE_ADOPT: case CRED_PKGBASE_CHANGE_CATEGORY: case CRED_PKGBASE_DELETE: + case CRED_PKGBASE_EDIT_COMAINTAINERS: case CRED_PKGBASE_DISOWN: case CRED_PKGBASE_LIST_VOTERS: case CRED_PKGBASE_SUBMIT_BLACKLISTED: diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index 655856ba..5741b019 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -928,3 +928,67 @@ function pkgbase_update_category($base_id, $category_id) { $category_id, $base_id); $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.")); +} diff --git a/web/template/comaintainers_form.php b/web/template/comaintainers_form.php new file mode 100644 index 00000000..050f2550 --- /dev/null +++ b/web/template/comaintainers_form.php @@ -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> + diff --git a/web/template/pkg_details.php b/web/template/pkg_details.php index ecb081c1..359ea3c7 100644 --- a/web/template/pkg_details.php +++ b/web/template/pkg_details.php @@ -131,6 +131,9 @@ $sources = pkg_sources($row["ID"]); </form> </li> <?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><a href="<?= get_pkgbase_uri($row['BaseName']) . 'request/'; ?>"><?= __('File Request'); ?></a></li> <?php if (has_credential(CRED_PKGBASE_DELETE)): ?> diff --git a/web/template/pkgbase_details.php b/web/template/pkgbase_details.php index e698fb0a..ae363fd3 100644 --- a/web/template/pkgbase_details.php +++ b/web/template/pkgbase_details.php @@ -82,6 +82,9 @@ $pkgs = pkgbase_get_pkgnames($base_id); </form> </li> <?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><a href="<?= get_pkgbase_uri($row['Name']) . 'request/'; ?>"><?= __('File Request'); ?></a></li> <?php if (has_credential(CRED_PKGBASE_DELETE)): ?> |