Commit 88a9f435 authored by Leigh Stoller's avatar Leigh Stoller

Commit the rest of the collaboration tools and changes. This will be

described elsewhere ...

Note that until Jay approves the new menu config, mere users will *not*
see the new collaboration menu. Only STUDLY() users will see the new
menu, although everyone will see the rest of the front page menu changes
since they are fairly minor.
parent 88926d1c
......@@ -12,8 +12,9 @@ SUBDIR = collab/mailman
include $(OBJDIR)/Makeconf
SBIN_SCRIPTS = addmmlist delmmlist setmmlistmembers mmsetup \
setmmpasswd
LIBEXEC_SCRIPTS = webaddmmlist webdelmmlist websetmmpasswd mmxlogin
setmmpasswd mmlistmembership
LIBEXEC_SCRIPTS = webaddmmlist webdelmmlist websetmmpasswd mmxlogin \
webmmlistmembership
CTRL_LIBEXEC_SCRIPTS = genaliases
CTRL_LIB_FILES = mmscript.py
......@@ -45,6 +46,8 @@ post-install:
chmod u+s $(INSTALL_SBINDIR)/setmmlistmembers
chown root $(INSTALL_SBINDIR)/setmmpasswd
chmod u+s $(INSTALL_SBINDIR)/setmmpasswd
chown root $(INSTALL_SBINDIR)/mmlistmembership
chmod u+s $(INSTALL_SBINDIR)/mmlistmembership
chown root $(INSTALL_LIBEXECDIR)/mmxlogin
chmod u+s $(INSTALL_LIBEXECDIR)/mmxlogin
......
......@@ -6,6 +6,7 @@
#
use English;
use Getopt::Std;
use Errno qw(EEXIST);
#
# Add a mailman list, say for a project or other reason. If for a project
......@@ -159,7 +160,7 @@ if ($listtype eq "admin") {
$listowner_email = $TBOPS;
if (! TBGetSiteVar("general/mailman/password", \$listpasswd)) {
fatal("Could not mailman admin password from sitevars!");
fatal("Could not get mailman admin password from sitevars!");
}
}
else {
......@@ -179,23 +180,20 @@ if ($CONTROL ne $BOSSNODE) {
my $optarg = ($debug ? "-d" : "");
print "Adding mailman list $listname ($listtype) on $CONTROL.\n";
if (system("echo '$listowner_email $listpasswd' | ".
"$SSH -host $CONTROL $MMPROXY addlist $listname $listtype")) {
system("echo '$listowner_email $listpasswd' | ".
"$SSH -host $CONTROL $MMPROXY addlist $listname $listtype");
if ($?) {
if ($? >> 8 == EEXIST()) {
# Not an error.
exit(0);
}
fatal("$MMPROXY failed on $CONTROL!");
}
SENDMAIL($TBAUDIT, "Mailman list created",
"Mailman list '$listname' has been created by '$dbuid'",
$TBOPS);
#
# Generate an initial message to the list so that the archive is not
# empty.
#
SENDMAIL("${listname}\@${OURDOMAIN}", "Mailman list created",
"Mailman list '$listname' has been created by '$dbuid'",
$TBOPS);
}
exit(0);
......
......@@ -6,7 +6,7 @@
#
use English;
use Getopt::Std;
use Errno;
use Errno qw(EEXIST);
#
# A wrapper for messing with Mailman from boss.
......@@ -125,6 +125,9 @@ elsif ($action eq "setadminpassword") {
elsif ($action eq "xlogin") {
exit(xLogin(@ARGV));
}
elsif ($action eq "membership") {
exit(ListMembership(@ARGV));
}
else {
die("*** $0:\n".
" Do not know what to do with '$action'!\n");
......@@ -167,6 +170,10 @@ sub AddList(@)
"$MMBINDIR/newlist $optarg $name $owneremail $password") == 0 or
fatal("AddList: Could not create mailing list!");
}
else {
print "List '$name' and already exists; exiting ...\n";
return EEXIST();
}
# Step 2: Config the list. We just need to alter a few of the defaults.
my $tempfile = "/tmp/config.$$";
......@@ -222,6 +229,24 @@ sub AddList(@)
system("$GENALIASES") == 0 or
fatal("AddList: Could not generate a new aliases file!");
# Step 4: Inject an intro message so that the archive is non-empty.
$tempfile = "/tmp/intro.$$";
open(INTRO, "> $tempfile") or
fatal("Could not open $tempfile for writing!");
print INTRO "From: $TBOPS\n";
print INTRO "To: " . lc($name) . "\@" . "$OURDOMAIN\n";
print INTRO "Subject: Welcome!\n";
print INTRO "\n";
print INTRO "This is the Emulab Mailman archive for $name\n";
print INTRO "\n";
close(INTRO);
# Run the injection.
system("$MMBINDIR/inject -l ". lc($name) . " $tempfile") == 0 or
fatal("AddList: Could not inject initial message to $name!");
unlink($tempfile);
return 0;
}
......@@ -551,6 +576,33 @@ sub DeleteList(@)
return 0;
}
#
# Get the list membership for a person.
#
sub ListMembership(@)
{
usage()
if (@_ != 1);
my ($email) = @_;
#
# Very convenient script provided by mailman ...
#
open(NAMES, "$MMBINDIR/find_member $email |") or
fatal("ListMembership: Could not start up find_member!");
while (<NAMES>) {
if ($_ =~ /^\s*([^\s]*)$/) {
print "$1\n";
}
}
close(NAMES) or
fatal("ListMembership: Error running find_member script!");
return 0;
}
#
# Backdoor Login
#
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2005 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
#
# Ask the mailman server for the list of lists a user belongs to.
#
sub usage()
{
print STDOUT "Usage: mmlistmembership <uid>\n";
exit(-1);
}
my $optlist = "d";
my $debug = 0;
my $user_uid;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $TBAUDIT = "@TBAUDITEMAIL@";
my $CONTROL = "@USERNODE@";
my $BOSSNODE = "@BOSSNODE@";
my $OURDOMAIN = "@OURDOMAIN@";
my $MAILMANSUPPORT= @MAILMANSUPPORT@;
my $SSH = "$TB/bin/sshtb";
my $MMPROXY = "$TB/sbin/mailmanproxy";
# Protos
sub fatal($);
#
# Untaint the path
#
$ENV{'PATH'} = "/bin:/usr/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
#
# Load the Testbed support stuff.
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
#
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("*** $0:\n".
" Must be setuid! Maybe its a development version?\n");
}
#
# This script is setuid, so please do not run it as root. Hard to track
# what has happened.
#
if ($UID == 0) {
die("*** $0:\n".
" Please do not run this as root! Its already setuid!\n");
}
#
# If no mailman support, just exit.
#
if (! $MAILMANSUPPORT) {
print "MailMan support is not enabled. Exit ...\n";
exit(0);
}
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
usage()
if (@ARGV != 1);
$user_uid = $ARGV[0];
#
# Untaint args.
#
if ($user_uid =~ /^([-\w]+)$/) {
$user_uid = $1;
}
else {
die("Bad data in uid: $user_uid");
}
my $email = "${user_uid}\@${OURDOMAIN}";
#
# For ssh.
#
$UID = $EUID;
if ($CONTROL ne $BOSSNODE) {
open(LISTS, "$SSH -host $CONTROL $MMPROXY ".
"membership $email |") or
fatal("$MMPROXY failed on $CONTROL!");
while (<LISTS>) {
# Send back to PHP.
print $_;
}
close(LISTS) or
fatal("$MMPROXY failed on $CONTROL!");
}
exit(0);
sub fatal($)
{
my($mesg) = $_[0];
die("*** $0:\n".
" $mesg\n");
}
......@@ -58,11 +58,13 @@ def findmember(mlist, addr):
def getcookie(mlist, addr, cookietype):
# If we want the admin interface, we do not care if the addr is
# a member of the list.
# a member of the list, since the caller (boss) already verified
# the operation was allowed.
if cookietype == "admin":
print mlist.MakeCookie(mm_cfg.AuthListAdmin, addr)
return
# But for a user cookie, must be a member.
if mlist.isMember(addr):
print mlist.MakeCookie(mm_cfg.AuthUser, addr)
pass
......
......@@ -114,9 +114,11 @@ system("$ADDMMLIST $optarg -a emulab-users") == 0
my @projects = ();
$query_result =
DBQueryFatal("select pid,gid from groups where 1 ".
# "and (pid='testbed' or pid='emulab-ops' or pid='tbres' or ".
# " pid='utahstud')" .
DBQueryFatal("select g.pid,g.gid from groups as g ".
"left join projects as p on p.pid=g.pid ".
"where p.approved=1 ".
# "and (p.pid='testbed' or p.pid='emulab-ops' or ".
# " p.pid='tbres' or p.pid='utahstud') ".
"");
while (my ($pid,$gid) = $query_result->fetchrow_array()) {
......@@ -132,8 +134,8 @@ while (my ($pid,$gid) = $query_result->fetchrow_array()) {
$listname = "$pid" . "-users";
}
system("$ADDMMLIST $optarg -a $listname") == 0
or fatal("Could not create $listname list");
# system("$ADDMMLIST $optarg -a $listname") == 0
# or fatal("Could not create $listname list");
push(@projects, $pid);
}
......@@ -142,7 +144,7 @@ while (my ($pid,$gid) = $query_result->fetchrow_array()) {
# And populate all the lists!
#
foreach my $pid (@projects) {
system("$GENELISTS $optarg -p $pid") == 0
system("$GENELISTS $optarg -d -p $pid") == 0
or fatal("Could not populate lists for project $pid!");
}
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2005 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
#
# This gets invoked from the Web interface. Simply a wrapper ...
#
#
# Configure variables
#
my $TB = "@prefix@";
#
# Run the real thing, and never return.
#
exec "$TB/sbin/mmlistmembership", @ARGV;
die("webmmlistmembership: Could not exec mmlistmembership: $!");
......@@ -36,6 +36,7 @@ PLABSUPPORT=1
PLAB_ROOTBALL="plabroot-10.tar.bz2"
WIKISUPPORT=1
BUGDBSUPPORT=1
MAILMANSUPPORT=1
WINSUPPORT=1
SFSSUPPORT=0
CVSSUPPORT=1
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004 University of Utah and the Flux Group.
# Copyright (c) 2004, 2005 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
......@@ -25,6 +25,7 @@ my $debug = 0;
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $CVSSUPPORT = @CVSSUPPORT@;
# Locals
my $lockfile = "/var/tmp/testbed_opsreboot_lockfile";
......@@ -103,6 +104,10 @@ SENDMAIL($TBOPS, "OPS has rebooted",
#
system("$TB/sbin/eventsys_start");
if ($CVSSUPPORT) {
system("$TB/sbin/cvsrepo_ctrl -b");
}
SENDMAIL($TBOPS, "OPS has rebooted",
"OPS has rebooted. Services have been restarted.",
undef, undef, (defined($logfile) ? ($logfile) : ()));
......
......@@ -13,6 +13,7 @@ SUBDIR = www
#
MAINSITE = emulab.net
OURDOMAIN = @OURDOMAIN@
CVSSUPPORT = @CVSSUPPORT@
include $(OBJDIR)/Makeconf
......@@ -122,6 +123,17 @@ ifeq ($(OURDOMAIN),$(MAINSITE))
INSTALL_CVSWEBCGI = $(INSTALL_PROGRAM) $(CVSWEBCGI) $(INSTALL_WWWDIR)/cvsweb
endif
ifeq ($(CVSSUPPORT),1)
OPSCVSWEBFILES = $(wildcard $(SRCDIR)/cvsweb/*.gif)
OPSCVSWEBCONF = $(wildcard $(SRCDIR)/cvsweb/cvsweb-ops.conf)
OPSCVSWEBCGI = $(wildcard $(SRCDIR)/cvsweb/*.cgi)
INSTALL_OPSCVSWEBCGI = $(INSTALL_PROGRAM) $(OPSCVSWEBCGI) \
$(INSTALL_DIR)/opsdir/www/cvsweb
INSTALL_OPSCVSWEBCONF = $(INSTALL_DATA) $(OPSCVSWEBCONF) \
$(INSTALL_DIR)/opsdir/www/cvsweb/cvsweb.conf
endif
#
# Kill the directory part of the names. The vpath rule will do the rest.
#
......@@ -134,6 +146,7 @@ ALLICONS = $(notdir $(AUTOICONS))
ALLWEBDB = $(notdir $(WEBDBFILES))
ALLDOWNLOADS = $(notdir $(DOWNLOADFILES))
ALLCVSWEB = $(notdir $(CVSWEBFILES))
ALLOPSCVSWEB = $(notdir $(OPSCVSWEBFILES))
ALLBUI = $(notdir $(BUIFILES))
ALLNL = $(notdir $(NLFILES))
ALLHY = $(notdir $(HYFILES))
......@@ -155,6 +168,7 @@ install: $(addprefix $(INSTALL_WWWDIR)/, $(ALLFILES)) \
$(addprefix $(INSTALL_WWWDIR)/autostatus-icons/, $(ALLICONS)) \
$(addprefix $(INSTALL_LIBEXECDIR)/, websearch) \
$(addprefix $(INSTALL_WWWDIR)/cvsweb/, $(ALLCVSWEB)) \
$(addprefix $(INSTALL_DIR)/opsdir/www/cvsweb/, $(ALLOPSCVSWEB)) \
$(INSTALL_WWWDIR)/doc/LICENSE.txt \
$(addprefix $(INSTALL_ETCDIR)/, swish.conf)
(swish-e -c ./swish.conf)
......@@ -163,7 +177,9 @@ install: $(addprefix $(INSTALL_WWWDIR)/, $(ALLFILES)) \
ln -s index.html tbdb.html; \
rm -f icons; \
ln -s /usr/local/www/icons icons;
$(INSTALL_CVSWEBCGI)
$(INSTALL_CVSWEBCGI)
$(INSTALL_OPSCVSWEBCONF)
$(INSTALL_OPSCVSWEBCGI)
post-install:
......@@ -179,6 +195,11 @@ $(INSTALL_WWWDIR)/%: %
-mkdir -p $(patsubst %/,%,$(dir $@))
$(INSTALL_DATA) $(subst $$,\$$,$<) $(subst $$,\$$,$@)
$(INSTALL_DIR)/opsdir/www/%: %
@echo "Installing $<"
-mkdir -p $(patsubst %/,%,$(dir $@))
$(INSTALL_DATA) $(subst $$,\$$,$<) $(subst $$,\$$,$@)
# How to recursively descend into subdirectories to make general
# targets such as `all'.
%.MAKE:
......
www/arrow4.ico

766 Bytes

......@@ -25,6 +25,7 @@ $WIKICOOKIENAME = "WikiCookie";
$BUGDBURL = "https://${USERNODE}/flyspray";
$BUGDBCOOKIENAME= "FlysprayCookie";
$MAILMANURL = "http://${USERNODE}/mailman";
$OPSCVSURL = "http://${USERNODE}/cvsweb/cvsweb.cgi";
$TBMAILADDR_OPS = "@TBOPSEMAIL_NOSLASH@";
$TBMAILADDR_WWW = "@TBWWWEMAIL_NOSLASH@";
......@@ -57,6 +58,7 @@ if ($WWWHOST != "www.emulab.net") {
$TBPROJ_DIR = "/proj";
$TBUSER_DIR = "/users";
$TBGROUP_DIR = "/groups";
$TBCVSREPO_DIR = "$TBPROJ_DIR/cvsrepos";
$TBNSSUBDIR = "nsdir";
$TBAUTHCOOKIE = "HashCookie" . $TBCOOKIESUFFIX;
......
......@@ -92,30 +92,41 @@ elseif (isset($listname) && $listname != "") {
PAGEARGERROR("Invalid characters in $listname!");
}
$optargs = "";
#
# Make sure the user is allowed! We must do a permission check since
# we are asking mailman to generate a cookie without a password.
#
if (!$isadmin) {
$mm_result = DBQueryFatal("select * from mailman_listnames ".
"where listname='$listname'");
if (!mysql_num_rows($mm_result)) {
USERERROR("No such list $listname!", 1);
}
$row = mysql_fetch_array($mm_result);
$owner_uid = $row['owner_uid'];
#
# Verify permission.
#
if ($uid != $owner_uid) {
USERERROR("You do not have permission to admin $listname!", 1);
if (isset($wantadmin)) {
if (!$isadmin) {
$mm_result = DBQueryFatal("select * from mailman_listnames ".
"where listname='$listname'");
if (!mysql_num_rows($mm_result)) {
USERERROR("No such list $listname!", 1);
}
$row = mysql_fetch_array($mm_result);
$owner_uid = $row['owner_uid'];
#
# Verify permission.
#
if ($uid != $owner_uid) {
USERERROR("You do not have permission to admin $listname!", 1);
}
}
$cookietype = "admin";
$listiface = "admin";
}
elseif (isset($wantconfig)) {
$cookietype = "user";
$listiface = "options";
$optargs = "?email=${uid}@${OURDOMAIN}";
}
else {
$cookietype = "user";
$listiface = "private";
}
$cookietype = "admin";
$listiface = "admin";
SUEXEC($uid, "nobody", "mmxlogin $uid $listname $cookietype",
SUEXEC_ACTION_DIE);
......@@ -132,7 +143,7 @@ elseif (isset($listname) && $listname != "") {
}
setcookie($matches[1], $matches[2], 0, $matches[3], $TBAUTHDOMAIN, 0);
$url = "${MAILMANURL}/$listiface/$listname/";
$url = "${MAILMANURL}/$listiface/$listname/$optargs";
if (isset($link)) {
$url .= $link;
......
<?php
#
# EMULAB-COPYRIGHT
# Copyright (c) 2005 University of Utah and the Flux Group.
# All rights reserved.
#
include("defs.php3");
if (!$CVSSUPPORT) {
header("Location: index.php3");
return;
}
#
# Standard Testbed Header is below.
#
#
# Only known and logged in users.
#
$uid = GETLOGIN();
LOGGEDINORDIE($uid);
$isadmin = ISADMIN($uid);
#
# Verify form arguments.
#
if (!isset($target_uid) ||
strcmp($target_uid, "") == 0) {
PAGEARGERROR("You must provide a User ID!");
}
else {
if (! TBvalid_uid($target_uid)) {
PAGEARGERROR("Invalid characters in $target_uid!");
}
}
#
# Standard Testbed Header, now that we know what we want to say.
#
if (strcmp($uid, $target_uid)) {
PAGEHEADER("CVS Repositories for: $target_uid");
}
else {
PAGEHEADER("My CVS Repositories");
}
#
# Check to make sure thats this is a valid UID. Getting the status works,
# and we need that later.
#
if (! ($userstatus = TBUserStatus($target_uid))) {
USERERROR("The user $target_uid is not a valid user", 1);
}
#
# Verify Permission.
#
if (!$isadmin &&
strcmp($uid, $target_uid)) {
if (! TBUserInfoAccessCheck($uid, $target_uid, $TB_USERINFO_READINFO)) {
USERERROR("You do not have permission to view this user's ".
"information!", 1);
}
}
#
# See what projects the uid is a member of, and print some repo pointers
#
$projlist = TBProjList($target_uid, $TB_PROJECT_READINFO);
if (! count($projlist)) {
USERERROR("$target_uid is not a member of any Projects!", 1);
}
echo "<br>
<center><font size=+1>
CVS repositories for the projects you are a member of</font><br>
(Click on the CvsWeb link to visit the repository)
</font></center><br>\n";
echo "<table align=center cellpadding=2 border=1>\n";
echo "<tr>
<th>Project</th>
<th>Repository</th>
<th>CvsWeb Link</th>
</tr>\n";
while (list($pid) = each($projlist)) {
$cvsdir = "$TBCVSREPO_DIR/$pid";
$cvsurl = "cvsweb/cvsweb.php3?pid=$pid";
echo "<tr>
<td><A href='showproject.php3?pid=$pid'>$pid</A></td>
<td>$cvsdir</td>
<td align=center><A href='$cvsurl'>
<img src=\"arrow4.ico\"
border=0 alt='cvsrepo'></A></td>
</tr>\n";
}
echo "</table>\n";
if (TBCvswebAllowed($uid)) {
echo "<br><center>
You also have CVSweb access to the
<a href=cvsweb/cvsweb.php3>Emulab Source Repository</a>.
</center><br>\n";
}
echo "<blockquote><blockquote>
Emulab gives each project its own CVS repository in $TBCVSREPO_DIR.
The repository is available both via FreeBSD's
<a hrep=http://www.freebsd.org/projects/cvsweb.html>CVSweb</a>
interface, and via
<a href=http://www.freebsd.org/cgi/man.cgi?query=cvs&sektion=1>CVS</a>
over
<a href=http://www.freebsd.org/cgi/man.cgi?query=ssh&sektion=1>SSH</a>
to <tt>$USERNODE</tt>.<br>
<br>
Project CVS repositories are initially <b>private</b>; only members
of the project may access the repository. Repositories may also be
set to <b>public</b> via a toggle on the project home page. When a
repository is set to public, anyone on the Internet may access the
repository (read-only), either with the CVSWeb interface, or with
anonymous CVS using CVS's pserver, both hosted on <tt>$USERNODE</tt>.
<br><br>
When a project repository <b>is</b> public, the CVSweb address is:
<blockquote>
<tt>http://$USERNODE/cvsweb/cvsweb.cgi/?cvsroot=yourprojectname</tt>
</blockquote>
or you can use CVS pserver with:
<blockquote>
<tt>cvs -R -d :pserver:anoncvs@$USERNODE:/cvsrepos/yourprojectname ...
</tt>
</blockquote>
just hit carriage return for the password.
</blockquote></blockquote>\n";
#
# Standard Testbed Footer
#
PAGEFOOTER();
?>
This diff is collapsed.
......@@ -17,12 +17,22 @@ $uid = GETLOGIN();
LOGGEDINORDIE($uid);
$isadmin = ISADMIN($uid);
#
# See what projects the uid can do this in.
#
$projlist = TBProjList($uid, $TB_PROJECT_READINFO);
if (! count($projlist)) {
USERERROR("You do not appear to be a member of any Projects in which ".
"you have permission to create new mailing lists", 1);
}
#
# Spit the form out using the array of data.
#
function SPITFORM($formfields, $errors)
{
global $TBDB_MMLENGTH;
global $TBDB_MMLENGTH, $projlist, $OURDOMAIN;
PAGEHEADER("Create a new MailMan list");
......@@ -47,6 +57,43 @@ function SPITFORM($formfields, $errors)
}
echo "</table><br>\n";
}
else {
echo "<blockquote><blockquote>
<center>
<font size=+1>
Host your own project related mailing lists at $OURDOMAIN
</font>
</center><br>
Use the form below to create a new mailing list. You will
become the administrator for the new list, and are responsible
for the list configuration and management, including user
subscriptions, approval, etc. <b>Note that mailing lists
should be related to your project in some manner; please,
no lists discussing the latest episode of your favorite TV
show.</b>
</blockquote></blockquote>\n";
}
echo "<SCRIPT LANGUAGE=JavaScript>
function Changed(theform)
{
var pidx = theform['formfields[pid]'].selectedIndex;
var pid = theform['formfields[pid]'].options[pidx].value;
var list = theform['formfields[listname]'].value;
if (pid == '') {
theform['formfields[fullname]'].value = '';
}