summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Fleischer <lfleischer@archlinux.org>2017-04-27 09:24:11 +0200
committerLukas Fleischer <lfleischer@archlinux.org>2017-04-30 16:47:13 +0200
commita8ac2004d3f25877d9e7b4fa58f10009c39f8acf (patch)
tree968cb95c2e7617608f15ccece4823ea4006c59cf
parent6892ec7791bf04361ac2973b38d0025b50fa4727 (diff)
downloadaur-a8ac2004d3f25877d9e7b4fa58f10009c39f8acf.tar.gz
aur-a8ac2004d3f25877d9e7b4fa58f10009c39f8acf.tar.xz
Add support for Terms of Service documents
This allows for adding Terms of Service documents to the database that registered users need to accept before using the AUR. A revision field can be used to indicate whether a document was updated. If it is increased, all users are again asked to accept the new terms. Signed-off-by: Lukas Fleischer <lfleischer@archlinux.org>
-rw-r--r--schema/aur-schema.sql20
-rw-r--r--upgrading/4.6.0.txt20
-rw-r--r--web/html/tos.php50
-rw-r--r--web/lib/acctfuncs.inc.php74
-rw-r--r--web/lib/aur.inc.php23
-rw-r--r--web/lib/routing.inc.php1
6 files changed, 188 insertions, 0 deletions
diff --git a/schema/aur-schema.sql b/schema/aur-schema.sql
index e5841652..45272bbe 100644
--- a/schema/aur-schema.sql
+++ b/schema/aur-schema.sql
@@ -379,3 +379,23 @@ CREATE TABLE Bans (
BanTS TIMESTAMP NOT NULL,
PRIMARY KEY (IPAddress)
) ENGINE = InnoDB;
+
+-- Terms and Conditions
+--
+CREATE TABLE Terms (
+ ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ Description VARCHAR(255) NOT NULL,
+ URL VARCHAR(8000) NOT NULL,
+ Revision INTEGER UNSIGNED NOT NULL DEFAULT 1,
+ PRIMARY KEY (ID)
+) ENGINE = InnoDB;
+
+-- Terms and Conditions accepted by users
+--
+CREATE TABLE AcceptedTerms (
+ UsersID INTEGER UNSIGNED NOT NULL,
+ TermsID INTEGER UNSIGNED NOT NULL,
+ Revision INTEGER UNSIGNED NOT NULL DEFAULT 0,
+ FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE,
+ FOREIGN KEY (TermsID) REFERENCES Terms(ID) ON DELETE CASCADE
+) ENGINE = InnoDB;
diff --git a/upgrading/4.6.0.txt b/upgrading/4.6.0.txt
index b051baca..816409d5 100644
--- a/upgrading/4.6.0.txt
+++ b/upgrading/4.6.0.txt
@@ -15,3 +15,23 @@ UPDATE PackageDepends
---
ALTER TABLE PackageComments ADD COLUMN RenderedComment TEXT NOT NULL;
---
+
+3. Add Terms and AcceptedTerms tables:
+
+---
+CREATE TABLE Terms (
+ ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ Description VARCHAR(255) NOT NULL,
+ URL VARCHAR(8000) NOT NULL,
+ Revision INTEGER UNSIGNED NOT NULL DEFAULT 1,
+ PRIMARY KEY (ID)
+) ENGINE = InnoDB;
+
+CREATE TABLE AcceptedTerms (
+ UsersID INTEGER UNSIGNED NOT NULL,
+ TermsID INTEGER UNSIGNED NOT NULL,
+ Revision INTEGER UNSIGNED NOT NULL DEFAULT 0,
+ FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE,
+ FOREIGN KEY (TermsID) REFERENCES Terms(ID) ON DELETE CASCADE
+) ENGINE = InnoDB;
+---
diff --git a/web/html/tos.php b/web/html/tos.php
new file mode 100644
index 00000000..fc5d8765
--- /dev/null
+++ b/web/html/tos.php
@@ -0,0 +1,50 @@
+<?php
+set_include_path(get_include_path() . PATH_SEPARATOR . '../lib');
+
+include_once("aur.inc.php");
+
+$uid = uid_from_sid($_COOKIE["AURSID"]);
+
+if (isset($_POST["accept"]) && $_POST["accept"]) {
+ accept_terms($uid, $_POST["rev"]);
+ header("Location: " . get_uri('/'));
+}
+
+$terms = fetch_updated_terms($uid);
+if (!$terms) {
+ header("Location: " . get_uri('/'));
+}
+
+html_header('AUR ' . __("Terms of Service"));
+?>
+<div id="dev-login" class="box">
+ <h2>AUR <?= __('Terms of Service') ?></h2>
+ <?php if (isset($_COOKIE["AURSID"])): ?>
+ <form method="post" action="<?= get_uri('/tos') ?>">
+ <fieldset>
+ <p>
+ <?= __("Logged-in as: %s", '<strong>' . username_from_sid($_COOKIE["AURSID"]) . '</strong>'); ?>
+ </p>
+ <p>
+ <?= __("The following documents have been updated. Please review them carefully:"); ?>
+ </p>
+ <ul>
+ <?php foreach($terms as $row): ?>
+ <li><a href="<?= htmlspecialchars(sprintf($row["URL"], $row["Revision"]), ENT_QUOTES) ?>"><?= htmlspecialchars($row["Description"]) ?></a> (<?= __('revision %d', $row["Revision"]) ?>)</li>
+ <?php endforeach; ?>
+ </ul>
+ <p>
+ <?php foreach($terms as $row): ?>
+ <input type="hidden" name="rev[<?= $row["ID"] ?>]" value="<?= $row["Revision"] ?>" />
+ <?php endforeach; ?>
+ <input type="checkbox" name="accept" /> <?= __("I accept the terms and conditions above."); ?>
+ </p>
+ <p>
+ <input type="submit" name="submit" value="<?= __("Continue") ?>" />
+ </p>
+ </fieldset>
+ </form>
+ <?php endif; ?>
+</div>
+<?php
+html_footer(AURWEB_VERSION);
diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php
index 22b3ca8d..e45d735b 100644
--- a/web/lib/acctfuncs.inc.php
+++ b/web/lib/acctfuncs.inc.php
@@ -1325,3 +1325,77 @@ function notify($params) {
return proc_close($p);
}
+
+/*
+ * Obtain a list of terms a given user has not yet accepted.
+ *
+ * @param int $uid The ID of the user to obtain terms for.
+ *
+ * @return array A list of terms the user has not yet accepted.
+ */
+function fetch_updated_terms($uid) {
+ $dbh = DB::connect();
+
+ $q = "SELECT ID, Terms.Revision, Description, URL ";
+ $q .= "FROM Terms LEFT JOIN AcceptedTerms ";
+ $q .= "ON AcceptedTerms.TermsID = Terms.ID ";
+ $q .= "AND AcceptedTerms.UsersID = " . intval($uid) . " ";
+ $q .= "WHERE AcceptedTerms.Revision IS NULL OR ";
+ $q .= "AcceptedTerms.Revision < Terms.Revision";
+
+ $result = $dbh->query($q);
+
+ if ($result) {
+ return $result->fetchAll();
+ } else {
+ return array();
+ }
+}
+
+/*
+ * Accept a list of given terms.
+ *
+ * @param int $uid The ID of the user to accept the terms.
+ * @param array $termrev An array mapping each term to the accepted revision.
+ *
+ * @return void
+ */
+function accept_terms($uid, $termrev) {
+ $dbh = DB::connect();
+
+ $q = "SELECT TermsID, Revision FROM AcceptedTerms ";
+ $q .= "WHERE UsersID = " . intval($uid);
+
+ $result = $dbh->query($q);
+
+ if (!$result) {
+ return;
+ }
+
+ $termrev_update = array();
+ while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
+ $id = $row['TermsID'];
+ if (!array_key_exists($id, $termrev)) {
+ continue;
+ }
+ if ($row['Revision'] < $termrev[$id]) {
+ $termrev_update[$id] = $termrev[$id];
+ }
+ }
+ $termrev_add = array_diff_key($termrev, $termrev_update);
+
+ foreach ($termrev_add as $id => $rev) {
+ $q = "INSERT INTO AcceptedTerms (TermsID, UsersID, Revision) ";
+ $q .= "VALUES (" . intval($id) . ", " . intval($uid) . ", ";
+ $q .= intval($rev) . ")";
+ $dbh->exec($q);
+ }
+
+ foreach ($termrev_update as $id => $rev) {
+ $q = "UPDATE AcceptedTerms ";
+ $q .= "SET Revision = " . intval($rev) . " ";
+ $q .= "WHERE TermsID = " . intval($id) . " AND ";
+ $q .= "UsersID = " . intval($uid);
+ $dbh->exec($q);
+ }
+}
diff --git a/web/lib/aur.inc.php b/web/lib/aur.inc.php
index 063de8fc..ce569ea7 100644
--- a/web/lib/aur.inc.php
+++ b/web/lib/aur.inc.php
@@ -22,6 +22,7 @@ include_once('timezone.inc.php');
set_tz();
check_sid();
+check_tos();
/**
* Check if a visitor is logged in
@@ -92,6 +93,28 @@ function check_sid() {
}
/**
+ * Redirect user to the Terms of Service agreement if there are updated terms.
+ *
+ * @return void
+ */
+function check_tos() {
+ if (!isset($_COOKIE["AURSID"])) {
+ return;
+ }
+
+ $path = $_SERVER['PATH_INFO'];
+ $route = get_route($path);
+ if (!$route || $route == "tos.php") {
+ return;
+ }
+
+ if (count(fetch_updated_terms(uid_from_sid($_COOKIE["AURSID"]))) > 0) {
+ header('Location: ' . get_uri('/tos'));
+ exit();
+ }
+}
+
+/**
* Verify the supplied CSRF token matches expected token
*
* @return bool True if the CSRF token is the same as the cookie SID, otherwise false
diff --git a/web/lib/routing.inc.php b/web/lib/routing.inc.php
index 8c45c626..7d9750a0 100644
--- a/web/lib/routing.inc.php
+++ b/web/lib/routing.inc.php
@@ -16,6 +16,7 @@ $ROUTES = array(
'/passreset' => 'passreset.php',
'/rpc' => 'rpc.php',
'/rss' => 'rss.php',
+ '/tos' => 'tos.php',
'/tu' => 'tu.php',
'/addvote' => 'addvote.php',
);