");
+
+ $paths = array();
+ $xml = "".$result->xml_doc_out."";
+ $r = simplexml_load_string($xml);
+ if (!$r) return $paths;
+ foreach ($r->file_info as $fi) {
+ $path = dir_hier_path((string)($fi->name), $upload_dir, $fanout);
+ $paths[] = $path;
+ }
+ return $paths;
+}
+
+function abort_workunit($wu) {
+ BoincResult::update_aux(
+ "server_state=5, outcome=5 where server_state=2 and workunitid=$wu->id"
+ );
+ $wu->update("error_mask=error_mask|16");
+}
+
+function abort_batch($batch) {
+ $wus = BoincWorkunit::enum("batch=$batch->id");
+ foreach ($wus as $wu) {
+ abort_workunit($wu);
+ }
+ $batch->update("state=".BATCH_STATE_ABORTED);
+ return 0;
+}
+
+function retire_batch($batch) {
+ $wus = BoincWorkunit::enum("batch=$batch_id");
+ $now = time();
+ foreach ($wus as $wu) {
+ $wu->update("assimilate_state=2, transition_time=$now");
+ }
+ $batch->update("state=".BATCH_STATE_RETIRED);
+}
+
+function batch_state_string($state) {
+ switch ($state) {
+ case BATCH_STATE_INIT: return "new";
+ case BATCH_STATE_IN_PROGRESS: return "in progress";
+ case BATCH_STATE_COMPLETE: return "completed";
+ case BATCH_STATE_ABORTED: return "aborted";
+ case BATCH_STATE_RETIRED: return "retired";
+ }
+ return "unknown state $state";
+}
+
+?>
diff --git a/html/ops/db_update.php b/html/ops/db_update.php
index 9e3f73d4e2..22c77880c1 100755
--- a/html/ops/db_update.php
+++ b/html/ops/db_update.php
@@ -781,6 +781,21 @@ function update_9_15_2011() {
");
}
+function update_9_20_2011() {
+ do_query("
+ alter table user_submit
+ drop column all_apps,
+ drop column create_apps,
+ drop column create_app_versions,
+ add submit_all tinyint not null,
+ add manage_all tinyint not null
+ ");
+
+ do_query("
+ alter table user_submit_app
+ add manage tinyint not null
+ ");
+}
// Updates are done automatically if you use "upgrade".
//
// If you need to do updates manually,
@@ -803,6 +818,9 @@ $db_updates = array (
array(23881, "update_7_26_2011"),
array(24137, "update_9_6_2011"),
array(24225, "update_9_15_2011"),
+ array(24248, "update_9_20_2011"),
);
+
+
?>
diff --git a/html/user/manage.php b/html/user/manage.php
new file mode 100644
index 0000000000..e52da6badb
--- /dev/null
+++ b/html/user/manage.php
@@ -0,0 +1,70 @@
+.
+
+// top-level management page;
+// shows links to the various functions available to the user.
+// If the only option is managing a particular app,
+// redirect to that page
+
+require_once("../inc/submit_db.inc");
+require_once("../inc/util.inc");
+
+$user = get_logged_in_user();
+
+$bus = BoincUserSubmit::lookup_userid($user->id);
+if (!$bus) die("no access");
+
+if ($bus->manage_all) {
+ page_head("Management functions");
+ echo "
+ Project-wide management
+ ";
+ $apps = BoincApp::enum(null);
+ echo "
+ Application-specific management:
+
+ ";
+ foreach ($apps as $app) {
+ echo "
+ - id>$app->name
+ ";
+ }
+ echo "
\n";
+ page_tail();
+ exit;
+}
+
+$apps = BoincUserSubmit::enum("user_id=$user->id and manage<>1");
+switch (count($apps)) {
+case 0:
+ error_page("Nothing to manage");
+case 1:
+ $app = $apps[0];
+ Header("Location: manage_app.php?app_id=$app->id");
+ exit;
+default:
+ page_head("Management functions");
+ foreach ($apps as $app) {
+ echo "
+ id>Manage $app->name
+ ";
+ }
+ page_tail();
+}
+
+?>
diff --git a/html/user/manage_app.php b/html/user/manage_app.php
new file mode 100644
index 0000000000..715f3673bb
--- /dev/null
+++ b/html/user/manage_app.php
@@ -0,0 +1,231 @@
+.
+
+// app-specific management interface
+
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+ini_set('display_startup_errors', true);
+
+require_once("../inc/submit_util.inc");
+require_once("../inc/util.inc");
+
+function main_page($app) {
+ page_head("Management functions for $app->name");
+ echo "
+ id&action=app_version_form>Manage app versions
+
+ id&action=permissions_form>Manage user permissions
+
+ id&action=batches_form>Manage jobs
+ ";
+ page_tail();
+}
+
+function app_version_form($app) {
+ page_head("Manage app versions");
+ echo "
+
+
+ Return to project-wide management functions
";
- admin_page_tail();
+ page_tail();
}
function handle_edit_action() {
$user_id = get_int('user_id');
$us = BoincUserSubmit::lookup_userid($user_id);
- if (!$us) admin_error_page("user not found");
+ if (!$us) error_page("user not found");
BoincUserSubmitApp::delete_user($user_id);
- $all_apps = get_str('all_apps');
- if ($all_apps) {
- $us->update("all_apps=1");
+ $submit_all = get_str('submit_all');
+ if ($submit_all) {
+ $us->update("submit_all=1");
} else {
- $us->update("all_apps=0");
+ $us->update("submit_all=0");
$apps = BoincApp::enum("deprecated=0");
foreach ($apps as $app) {
$x = "app_$app->id";
@@ -128,39 +137,41 @@ function handle_edit_action() {
if ($quota != $us->quota) {
$us->update("quota=$quota");
}
- $x = get_str('create_apps', true)?1:0;
- $us->update("create_apps=$x");
- $x = get_str('create_app_versions', true)?1:0;
- $us->update("create_app_versions=$x");
-
- admin_page_head("User permissions updated");
- admin_page_tail();
+ page_head("Update successful");
+ echo "Return to project-wide management functions";
+ page_tail();
}
function handle_add_form() {
- admin_page_head("Add user");
+ page_head("Add user");
echo "
-
";
- admin_page_tail();
+ page_tail();
}
function handle_add_action() {
$user_id = get_int('user_id');
$user = BoincUser::lookup_id($user_id);
- if (!$user) admin_error_page("no such user");
+ if (!$user) error_page("no such user");
$us = BoincUserSubmit::lookup_userid($user_id);
if (!$us) {
if (!BoincUserSubmit::insert("(user_id) values ($user_id)")) {
- admin_error_page("Insert failed");
+ error_page("Insert failed");
}
}
- header("Location: submit_permissions.php?action=edit_form&user_id=$user_id");
+ header("Location: manage_project.php?action=edit_form&user_id=$user_id");
+}
+
+$user = get_logged_in_user();
+$bus = BoincUserSubmit::lookup_userid($user->id);
+if (!$bus) {
+ die("no access");
}
$action = get_str('action', true);
@@ -177,7 +188,7 @@ case 'edit_form':
case 'edit_action':
handle_edit_action(); break;
default:
- admin_error_page("unknown action: $action");
+ error_page("unknown action: $action");
}
?>
diff --git a/html/user/submit.php b/html/user/submit.php
index 6f7808bafa..6d6af80c36 100644
--- a/html/user/submit.php
+++ b/html/user/submit.php
@@ -24,6 +24,7 @@ require_once("../inc/submit_db.inc");
require_once("../inc/xml.inc");
require_once("../inc/dir_hier.inc");
require_once("../inc/result.inc");
+require_once("../inc/submit_util.inc");
error_reporting(E_ALL);
ini_set('display_errors', true);
@@ -41,7 +42,7 @@ function authenticate_user($r, $app) {
if (!$user) error("bad authenticator");
$user_submit = BoincUserSubmit::lookup_userid($user->id);
if (!$user_submit) error("no submit access");
- if ($app && !$user_submit->all_apps) {
+ if ($app && !$user_submit->submit_all) {
$usa = BoincUserSubmitApp::lookup("user_id=$user->id and app_id=$app->id");
if (!$usa) {
error("no submit access");
@@ -326,34 +327,25 @@ function query_job($r) {
echo "\n";
}
-function abort_batch($r) {
+function handle_abort_batch($r) {
list($user, $user_submit) = authenticate_user($r, null);
$batch_id = (int)($r->batch_id);
$batch = BoincBatch::lookup_id($batch_id);
if ($batch->user_id != $user->id) {
error("not owner");
}
- $wus = BoincWorkunit::enum("batch=$batch_id");
- foreach ($wus as $wu) {
- abort_workunit($wu);
- }
- $batch->update("state=".BATCH_STATE_ABORTED);
+ abort_batch($batch);
echo "1";
}
-function retire_batch($r) {
+function handle_retire_batch($r) {
list($user, $user_submit) = authenticate_user($r, null);
$batch_id = (int)($r->batch_id);
$batch = BoincBatch::lookup_id($batch_id);
if ($batch->user_id != $user->id) {
error("not owner");
}
- $wus = BoincWorkunit::enum("batch=$batch_id");
- $now = time();
- foreach ($wus as $wu) {
- $wu->update("assimilate_state=2, transition_time=$now");
- }
- $batch->update("state=".BATCH_STATE_RETIRED);
+ retire_batch($batch);
echo "1";
}
@@ -413,8 +405,8 @@ switch ($r->getName()) {
case 'query_batches': query_batches($r); break;
case 'query_batch': query_batch($r); break;
case 'query_job': query_job($r); break;
- case 'abort_batch': abort_batch($r); break;
- case 'retire_batch': retire_batch($r); break;
+ case 'abort_batch': handle_abort_batch($r); break;
+ case 'retire_batch': handle_retire_batch($r); break;
default: error("bad command");
}
diff --git a/html/user/submit_example.php b/html/user/submit_example.php
index f9c62ff9aa..39749e7586 100644
--- a/html/user/submit_example.php
+++ b/html/user/submit_example.php
@@ -149,7 +149,7 @@ function eligible_apps() {
if (!$user_submit) return null;
$a = array();
foreach($apps as $app) {
- if ($user_submit->all_apps) {
+ if ($user_submit->submit_all) {
$a[] = $app;
} else {
if (BoincUserSubmitApp::lookup("user_id=$user->id and app_id=$app->id")) {
diff --git a/py/Boinc/setup_project.py b/py/Boinc/setup_project.py
index 9170136c08..c85bc54004 100644
--- a/py/Boinc/setup_project.py
+++ b/py/Boinc/setup_project.py
@@ -384,6 +384,7 @@ sys.path.insert(0, os.path.join('%s', 'py'))
[ 'appmgr', 'create_work', 'xadd', 'dbcheck_files_exist', 'run_in_ops',
'update_versions', 'parse_config', 'grep_logs', 'db_query',
'watch_tcp', 'sign_executable', 'dir_hier_move',
+ 'manage_privileges',
'dir_hier_path', 'boinc_submit', 'demo_submit', 'demo_query' ])
map(lambda (s): install(srcdir('lib',s), dir('bin',s)),
[ 'crypt_prog' ])
diff --git a/tools/manage_privileges b/tools/manage_privileges
new file mode 100755
index 0000000000..427b94adac
--- /dev/null
+++ b/tools/manage_privileges
@@ -0,0 +1,162 @@
+#!/usr/bin/env php
+
+.
+
+// script for controlling "manage" privileges.
+// See http://boinc.berkeley.edu/trac/wiki/MultiUser
+// Run this from the project directory.
+
+// usage:
+//
+// manage_privileges grant userid {appname|all}
+// manage_privileges revoke userid {appname|all}
+// manage_privileges list
+//
+// grant/revoke the "manage" privileges for the given app (or all apps).
+
+error_reporting(E_ALL);
+ini_set('display_errors', true);
+ini_set('display_startup_errors', true);
+
+function usage() {
+ die("usage:
+manage_privileges grant userid {appname|all}
+manage_privileges revoke userid {appname|all}
+manage_privileges list
+");
+}
+
+function show_user($user) {
+ echo "$user->name (ID $user->id)\n";
+}
+
+function show_managers() {
+ echo "Users with global manager privileges: \n";
+ $buss = BoincUserSubmit::enum("manage_all<>0");
+ if (!count($buss)) {
+ echo "none\n";
+ } else {
+ foreach ($buss as $bus) {
+ $user = BoincUser::lookup_id($bus->user_id);
+ show_user($user);
+ }
+ }
+
+ $apps = BoincApp::enum(null);
+ foreach ($apps as $app) {
+ echo "\nUsers with manager privileges for $app->name:\n";
+ $busas = BoincUserSubmitApp::enum("app_id=$app->id and manage<>0");
+ if (!count($busas)) {
+ echo "none\n";
+ } else {
+ foreach ($busas as $busa) {
+ $user = BoincUser::lookup_id($busa->user_id);
+ show_user($user);
+ }
+ }
+ }
+}
+
+if (!file_exists("config.xml")) {
+ die("run this script from the project directory\n");
+}
+
+chdir("html/inc");
+
+require_once("boinc_db.inc");
+require_once("submit_db.inc");
+
+if ($argc < 2) usage();
+
+if ($argv[1] == "list") {
+ show_managers();
+ exit;
+}
+
+if ($argc < 4) usage();
+
+$user = BoincUser::lookup_id($argv[2]);
+if (!$user) {
+ die("no such user: ".$argv[1]."\n");
+}
+
+if ($argv[1] === "grant") {
+ $grant = true;
+} else if ($argv[1] === "revoke") {
+ $grant = false;
+} else {
+ usage();
+}
+
+if ($argv[3] === "all") {
+ $bus = BoincUserSubmit::lookup_userid($user->id);
+ if ($bus) {
+ if ($grant) {
+ if ($bus->manage_all) {
+ die("User $user->id already has global manage access\n");
+ } else {
+ $bus->update("manage_all=1");
+ }
+ } else {
+ if ($bus->manage_all) {
+ $bus->update("manage_all=0");
+ } else {
+ die("User $user->id does not have global manage access\n");
+ }
+ }
+ } else {
+ if ($grant) {
+ BoincUserSubmit::insert("user_id=$user->id and manage_all=1");
+ } else {
+ die("User $user->id does not have global manage access\n");
+ }
+ }
+} else {
+ $app = BoincApp::lookup_name($argv[3]);
+ if (!$app) die("no such app: ".$argv[2]."\n");
+ $busa = BoincUserSubmitApp::lookup("user_id=$user->id and app_id=$app->id");
+ if ($busa) {
+ if ($grant) {
+ if ($busa->manage) {
+ die("User $user->id already has manage access for $app->name\n");
+ } else {
+ $busa->update("manage=1");
+ }
+ } else {
+ if ($busa->manage) {
+ $busa->update("manage=0");
+ } else {
+ die("User $user->id does not have manage access for $app->name\n");
+ }
+ }
+ } else {
+ if ($grant) {
+ $bus = BoincUserSubmit::lookup(userid($user->id);
+ if (!$bus) {
+ BoincUserSubmit::insert("user_id=$user->id=1");
+ }
+ BoincUserSubmitApp::insert("user_id=$user->id and app_id=$app->id and manage=1");
+ } else {
+ die("User $user->id does not have manage access for $app->name\n");
+ }
+ }
+}
+echo "Done.\n";
+
+?>