Commit d2f24859 authored by Leigh Stoller's avatar Leigh Stoller

Implement a project disable, this has come up a few times where we want

to disallow login (and immediately log out) everyone in a project. See
the Admin tab on the Show Project page.
parent 6bdbebfb
...@@ -4575,6 +4575,7 @@ CREATE TABLE `projects` ( ...@@ -4575,6 +4575,7 @@ CREATE TABLE `projects` (
`unix_gid` smallint(5) unsigned NOT NULL auto_increment, `unix_gid` smallint(5) unsigned NOT NULL auto_increment,
`approved` tinyint(4) default '0', `approved` tinyint(4) default '0',
`hidden` tinyint(1) default '0', `hidden` tinyint(1) default '0',
`disabled` tinyint(1) default '0',
`inactive` tinyint(4) default '0', `inactive` tinyint(4) default '0',
`date_inactive` datetime default NULL, `date_inactive` datetime default NULL,
`public` tinyint(4) NOT NULL default '0', `public` tinyint(4) NOT NULL default '0',
......
use strict;
use libdb;
sub DoUpdate($$$)
{
my ($dbhandle, $dbname, $version) = @_;
if (!DBSlotExists("projects", "disabled")) {
DBQueryFatal("alter table projects add " .
" `disabled` tinyint(1) default '0' after `hidden`");
}
return 0;
}
1;
# Local Variables:
# mode:perl
# End:
...@@ -514,6 +514,9 @@ $(function () ...@@ -514,6 +514,9 @@ $(function ()
$(this).html(moment($(this).html()).format("ll")); $(this).html(moment($(this).html()).format("ll"));
} }
}); });
$('#admin_content .toggle').click(function() {
Toggle(this);
});
} }
var xmlthing = sup.CallServerMethod(null, var xmlthing = sup.CallServerMethod(null,
"show-project", "ProjectProfile", "show-project", "ProjectProfile",
...@@ -596,6 +599,24 @@ $(function () ...@@ -596,6 +599,24 @@ $(function ()
{"pid" : window.TARGET_PROJECT}); {"pid" : window.TARGET_PROJECT});
xmlthing.done(callback); xmlthing.done(callback);
} }
//
// Toggle flags.
//
function Toggle(item) {
var name = item.dataset["name"];
var callback = function(json) {
if (json.code) {
sup.SpitOops("oops", json.value);
return;
}
LoadProjectTab();
};
sup.CallServerMethod(null, "show-project", "Toggle",
{"pid" : window.TARGET_PROJECT,
"toggle" : name},
callback);
}
$(document).ready(initialize); $(document).ready(initialize);
}); });
......
...@@ -288,6 +288,23 @@ else { ...@@ -288,6 +288,23 @@ else {
SPITFOOTER(); SPITFOOTER();
return; return;
} }
elseif ($dologin_status == DOLOGIN_STATUS_PROJDISABLED) {
# Short delay.
sleep(1);
SPITHEADER();
echo "<h4>
One of the projects in which you are a member has been
disabled. You are not allowed to log in until this has
been resolved. Please contact $SUPPORT if you have any
further questions. <br> <br>
Please do not attempt to login again; it will not work!
</h4>\n";
echo "<script src='js/lib/jquery-2.0.3.min.js'></script>\n";
SPITNULLREQUIRE();
SPITFOOTER();
return;
}
else if ($dologin_status == DOLOGIN_STATUS_INACTIVE) { else if ($dologin_status == DOLOGIN_STATUS_INACTIVE) {
# Short delay. # Short delay.
sleep(1); sleep(1);
......
...@@ -315,6 +315,8 @@ $routing = array("geni-login" => ...@@ -315,6 +315,8 @@ $routing = array("geni-login" =>
"Do_GroupList", "Do_GroupList",
"UsageSummary" => "UsageSummary" =>
"Do_UsageSummary", "Do_UsageSummary",
"Toggle" =>
"Do_Toggle",
"ProjectProfile" => "ProjectProfile" =>
"Do_ProjectProfile")), "Do_ProjectProfile")),
"groups" => "groups" =>
......
<?php <?php
# #
# Copyright (c) 2000-2017 University of Utah and the Flux Group. # Copyright (c) 2000-2018 University of Utah and the Flux Group.
# #
# {{{EMULAB-LICENSE # {{{EMULAB-LICENSE
# #
...@@ -207,6 +207,7 @@ function Do_ProjectProfile() ...@@ -207,6 +207,7 @@ function Do_ProjectProfile()
$results["portal"] = $target_project->portal(); $results["portal"] = $target_project->portal();
$results["created"] = DateStringGMT($target_project->created()); $results["created"] = DateStringGMT($target_project->created());
$results["approved"] = $target_project->approved() ? true : false; $results["approved"] = $target_project->approved() ? true : false;
$results["disabled"] = $target_project->disabled() ? true : false;
$results["url"] = $target_project->URL(); $results["url"] = $target_project->URL();
$results["description"] = $target_project->name(); $results["description"] = $target_project->name();
$results["why"] = $target_project->why(); $results["why"] = $target_project->why();
...@@ -263,6 +264,47 @@ function Do_UsageSummary() ...@@ -263,6 +264,47 @@ function Do_UsageSummary()
SPITAJAX_RESPONSE($blob); SPITAJAX_RESPONSE($blob);
} }
#
# Toggle flags.
#
function Do_Toggle()
{
global $this_user, $target_project, $ajax_args;
global $TBMAIL_OPS, $TBMAIL_AUDIT, $TBMAIL_WWW;
if (CheckPageArgs()) {
return;
}
if (!ISADMIN()) {
SPITAJAX_ERROR(-1, "Not enough permission");
return;
}
$this_uid = $this_user->uid();
$target_pid = $target_project->pid();
if (!isset($ajax_args["toggle"])) {
SPITAJAX_ERROR(-1, "Missing toggle name");
return -1;
}
$toggle = $ajax_args["toggle"];
if ($toggle == "project_disable") {
$target_project->SetDisabled($target_project->disabled() ? 0 : 1);
$which = $target_project->disabled() ? "disabled" : "enabled";
TBMAIL($TBMAIL_OPS,
"Project '$target_pid' has been $which",
"$this_uid has $which project $target_pid!\n\n",
"From: $TBMAIL_OPS\n".
"Bcc: $TBMAIL_AUDIT\n".
"Errors-To: $TBMAIL_WWW");
}
else {
SPITAJAX_ERROR(-1, "Unknown toggle name: $toggle");
return;
}
SPITAJAX_RESPONSE(1);
}
# Local Variables: # Local Variables:
# mode:php # mode:php
# End: # End:
......
<style>
.toggle {
cursor: pointer;
}
</style>
<div> <div>
<table class='table table-condensed table-bordered' id="admin_table"> <table class='table table-condensed table-bordered' id="admin_table">
<tr> <tr>
...@@ -31,6 +36,12 @@ ...@@ -31,6 +36,12 @@
<td>Approved</td> <td>Approved</td>
<td><% if (fields.approved) { %>Yes<% } else { %>No<% } %></td> <td><% if (fields.approved) { %>Yes<% } else { %>No<% } %></td>
</tr> </tr>
<tr>
<td>Disabled</td>
<td><% if (fields.disabled) { %>Yes<% } else { %>No<% } %>
(<a class="toggle" data-name="project_disable">Toggle</a>)
</td>
</tr>
<tr> <tr>
<td colspan="2"><center>Long Description</center></td> <td colspan="2"><center>Long Description</center></td>
</tr> </tr>
......
...@@ -159,6 +159,7 @@ class Project ...@@ -159,6 +159,7 @@ class Project
function why() { return $this->field("why"); } function why() { return $this->field("why"); }
function control_node() { return $this->field("control_node"); } function control_node() { return $this->field("control_node"); }
function approved() { return $this->field("approved"); } function approved() { return $this->field("approved"); }
function disabled() { return $this->field("disabled"); }
function inactive() { return $this->field("inactive"); } function inactive() { return $this->field("inactive"); }
function date_inactive() { return $this->field("date_inactive"); } function date_inactive() { return $this->field("date_inactive"); }
function ispublic() { return $this->field("public"); } function ispublic() { return $this->field("public"); }
...@@ -710,13 +711,23 @@ class Project ...@@ -710,13 +711,23 @@ class Project
} }
function SetAllowWorkbench($onoff) { function SetAllowWorkbench($onoff) {
$idx = $this->pid_idx(); $idx = $this->pid_idx();
$onofff = ($onoff ? 1 : 0); $onoff = ($onoff ? 1 : 0);
DBQueryFatal("update projects set allow_workbench='$onoff' ". DBQueryFatal("update projects set allow_workbench='$onoff' ".
"where pid_idx='$idx'"); "where pid_idx='$idx'");
return 0; return 0;
} }
function SetDisabled($onoff) {
$idx = $this->pid_idx();
$onoff = ($onoff ? 1 : 0);
DBQueryFatal("update projects set disabled='$onoff' ".
"where pid_idx='$idx'");
$this->project["disabled"] = $onoff;
return 0;
}
function Show() { function Show() {
global $WIKISUPPORT, $CVSSUPPORT, $TBPROJ_DIR, $TBCVSREPO_DIR; global $WIKISUPPORT, $CVSSUPPORT, $TBPROJ_DIR, $TBCVSREPO_DIR;
......
...@@ -71,6 +71,7 @@ define("CHECKLOGIN_ISFOREIGN_ADMIN", 0x0800000); # Admin of another Emulab. ...@@ -71,6 +71,7 @@ define("CHECKLOGIN_ISFOREIGN_ADMIN", 0x0800000); # Admin of another Emulab.
define("CHECKLOGIN_NONLOCAL", 0x1000000); define("CHECKLOGIN_NONLOCAL", 0x1000000);
define("CHECKLOGIN_INACTIVE", 0x2000000); define("CHECKLOGIN_INACTIVE", 0x2000000);
define("CHECKLOGIN_NOPROJECTS", 0x4000000); define("CHECKLOGIN_NOPROJECTS", 0x4000000);
define("CHECKLOGIN_PROJDISABLED", 0x8000000); # Member of disabled proj
# #
# Constants for tracking possible login attacks. # Constants for tracking possible login attacks.
...@@ -86,6 +87,7 @@ define("DOLOGIN_STATUS_IPFREEZE", -2); ...@@ -86,6 +87,7 @@ define("DOLOGIN_STATUS_IPFREEZE", -2);
define("DOLOGIN_STATUS_WEBFREEZE", -3); define("DOLOGIN_STATUS_WEBFREEZE", -3);
define("DOLOGIN_STATUS_INACTIVE", -4); define("DOLOGIN_STATUS_INACTIVE", -4);
define("DOLOGIN_STATUS_FROZEN", -5); define("DOLOGIN_STATUS_FROZEN", -5);
define("DOLOGIN_STATUS_PROJDISABLED", -6);
# So we can redefine this in the APT pages. # So we can redefine this in the APT pages.
$CHANGEPSWD_PAGE = "moduserinfo.php3"; $CHANGEPSWD_PAGE = "moduserinfo.php3";
...@@ -267,7 +269,7 @@ function LoginStatus() { ...@@ -267,7 +269,7 @@ function LoginStatus() {
" user_interface,n.type,u.stud,u.wikiname, ". " user_interface,n.type,u.stud,u.wikiname, ".
" u.wikionly,g.pid,u.foreign_admin,u.uid_idx, " . " u.wikionly,g.pid,u.foreign_admin,u.uid_idx, " .
" p.allow_workbench,u.weblogin_frozen, ". " p.allow_workbench,u.weblogin_frozen, ".
" u.nonlocal_id ". " u.nonlocal_id,p.disabled ".
" from users as u ". " from users as u ".
"left join login as l on l.uid_idx=u.uid_idx ". "left join login as l on l.uid_idx=u.uid_idx ".
"left join group_membership as g on g.uid_idx=u.uid_idx ". "left join group_membership as g on g.uid_idx=u.uid_idx ".
...@@ -294,6 +296,7 @@ function LoginStatus() { ...@@ -294,6 +296,7 @@ function LoginStatus() {
$frozen = 0; $frozen = 0;
$nonlocal = 0; $nonlocal = 0;
$pcount = 0; $pcount = 0;
$pdisabled = 0;
while ($row = mysql_fetch_array($query_result)) { while ($row = mysql_fetch_array($query_result)) {
$expired = $row[0]; $expired = $row[0];
...@@ -336,6 +339,10 @@ function LoginStatus() { ...@@ -336,6 +339,10 @@ function LoginStatus() {
$workbench += $row[17]; $workbench += $row[17];
$frozen = $row[18]; $frozen = $row[18];
$nonlocal = $row[19] ? 1 : 0; $nonlocal = $row[19] ? 1 : 0;
$disable = $row[20];
if ($disable) {
$pdisabled++;
}
$CHECKLOGIN_NODETYPES[$type] = 1; $CHECKLOGIN_NODETYPES[$type] = 1;
} }
...@@ -351,7 +358,7 @@ function LoginStatus() { ...@@ -351,7 +358,7 @@ function LoginStatus() {
# #
# Check for frozen account. Might do something interesting later. # Check for frozen account. Might do something interesting later.
# #
if ($frozen || if ($pdisabled || $frozen ||
$status == TBDB_USERSTATUS_FROZEN) { $status == TBDB_USERSTATUS_FROZEN) {
DBQueryFatal("DELETE FROM login WHERE uid_idx='$uid_idx'"); DBQueryFatal("DELETE FROM login WHERE uid_idx='$uid_idx'");
$CHECKLOGIN_STATUS = CHECKLOGIN_NOTLOGGEDIN; $CHECKLOGIN_STATUS = CHECKLOGIN_NOTLOGGEDIN;
...@@ -873,6 +880,7 @@ function DOLOGIN($token, $password, $adminmode = 0, $nopassword = 0) { ...@@ -873,6 +880,7 @@ function DOLOGIN($token, $password, $adminmode = 0, $nopassword = 0) {
global $TBMAIL_OPS, $TBMAIL_AUDIT, $TBMAIL_WWW; global $TBMAIL_OPS, $TBMAIL_AUDIT, $TBMAIL_WWW;
global $WIKISUPPORT, $WIKICOOKIENAME; global $WIKISUPPORT, $WIKICOOKIENAME;
global $BUGDBSUPPORT, $BUGDBCOOKIENAME, $CHECKLOGIN_USER; global $BUGDBSUPPORT, $BUGDBCOOKIENAME, $CHECKLOGIN_USER;
global $TB_PROJECT_READINFO;
# Caller makes these checks too. # Caller makes these checks too.
if ((!TBvalid_uid($token) && !TBvalid_email($token)) || if ((!TBvalid_uid($token) && !TBvalid_email($token)) ||
...@@ -937,6 +945,11 @@ function DOLOGIN($token, $password, $adminmode = 0, $nopassword = 0) { ...@@ -937,6 +945,11 @@ function DOLOGIN($token, $password, $adminmode = 0, $nopassword = 0) {
$user->UpdateWebLoginFail(); $user->UpdateWebLoginFail();
return DOLOGIN_STATUS_WEBFREEZE; return DOLOGIN_STATUS_WEBFREEZE;
} }
# Check for membership in disabled project.
$plist = $user->DisabledProjects();
if (count($plist)) {
return DOLOGIN_STATUS_PROJDISABLED;
}
if (!$nopassword) { if (!$nopassword) {
$encoding = crypt("$password", $db_encoding); $encoding = crypt("$password", $db_encoding);
if (strcmp($encoding, $db_encoding)) { if (strcmp($encoding, $db_encoding)) {
......
...@@ -57,7 +57,8 @@ $values = array("adminon" => array(0,1), ...@@ -57,7 +57,8 @@ $values = array("adminon" => array(0,1),
"imageglobal" => array(0,1), "imageglobal" => array(0,1),
"imagedoesxen" => array(0,1), "imagedoesxen" => array(0,1),
"adminflag" => array(0,1), "adminflag" => array(0,1),
"hiderun" => array(0,1)); "hiderun" => array(0,1),
"project_disable"=> array(0,1));
# list of valid extra variables for the each toggle, and mandatory flag. # list of valid extra variables for the each toggle, and mandatory flag.
$optargs = array("adminon" => array(), $optargs = array("adminon" => array(),
...@@ -72,7 +73,9 @@ $optargs = array("adminon" => array(), ...@@ -72,7 +73,9 @@ $optargs = array("adminon" => array(),
"imageglobal" => array("imageid" => 1), "imageglobal" => array("imageid" => 1),
"imagedoesxen" => array("imageid" => 1), "imagedoesxen" => array("imageid" => 1),
"adminflag" => array("user" => 1), "adminflag" => array("user" => 1),
"hiderun" => array("instance" => 1, "runidx" => 1)); "hiderun" => array("instance" => 1, "runidx" => 1),
"project_disable"=> array("pid" => 1));
# Mandatory page arguments. # Mandatory page arguments.
$reqargs = RequiredPageArguments("type", PAGEARG_STRING, $reqargs = RequiredPageArguments("type", PAGEARG_STRING,
...@@ -261,6 +264,16 @@ elseif ($type == "workbench") { ...@@ -261,6 +264,16 @@ elseif ($type == "workbench") {
$zapurl = CreateURL("showproject", $project); $zapurl = CreateURL("showproject", $project);
$project->SetAllowWorkbench($value); $project->SetAllowWorkbench($value);
} }
elseif ($type == "project_disable") {
# Must be admin
if (!$isadmin) {
USERERROR("You do not have permission to toggle $type!", 1);
}
if (! ($project = Project::Lookup($pid))) {
PAGEARGERROR("Project $pid is not a valid project!");
}
$project->SetDisabled($value);
}
elseif ($type == "hiderun") { elseif ($type == "hiderun") {
RequiredPageArguments("instance", PAGEARG_INSTANCE, RequiredPageArguments("instance", PAGEARG_INSTANCE,
"runidx", PAGEARG_INTEGER); "runidx", PAGEARG_INTEGER);
......
...@@ -1429,6 +1429,21 @@ class User ...@@ -1429,6 +1429,21 @@ class User
return $result; return $result;
} }
#
# Return a list of disabled projects for user, if any.
#
function DisabledProjects() {
$result = array();
$projlist = $this->ProjectMembershipList();
foreach ($projlist as $project) {
if ($project->disabled()) {
$result[] = $project;
}
}
return $result;
}
# #
# Return list of unapproved membership in projects. This will not # Return list of unapproved membership in projects. This will not
# include projects for which the user is the leader, that is a # include projects for which the user is the leader, that is a
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment