[system] / trunk / webwork2 / bin / ww_db_v2_to_v3 Repository:
ViewVC logotype

View of /trunk/webwork2/bin/ww_db_v2_to_v3

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3012 - (download) (annotate)
Thu Nov 25 05:50:51 2004 UTC (8 years, 5 months ago) by sh002i
File size: 8396 byte(s)
the beginnings of an upgrade script. currently deals with converting
permission levels to roles properly! :)

    1 #!/usr/bin/env perl
    2 ################################################################################
    3 # WeBWorK Online Homework Delivery System
    4 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    5 # $CVSHeader: webwork2/bin/wwdb,v 1.12 2004/09/23 16:53:25 sh002i Exp $
    6 # 
    7 # This program is free software; you can redistribute it and/or modify it under
    8 # the terms of either: (a) the GNU General Public License as published by the
    9 # Free Software Foundation; either version 2, or (at your option) any later
   10 # version, or (b) the "Artistic License" which comes with this package.
   11 # 
   12 # This program is distributed in the hope that it will be useful, but WITHOUT
   13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   14 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   15 # Artistic License for more details.
   16 ################################################################################
   17 
   18 =head1 NAME
   19 
   20 ww_db_v2_to_v3 - convert a WWDBv2 database to a WWDBv3 database.
   21 
   22 =head1 SYNOPSIS
   23 
   24  ww_db_v2_to_v3 course ...
   25 
   26 =head1 DESCRIPTION
   27 
   28 Copies course data from legacy WWDBv2 database(s) to a WWDBv3 database. This may
   29 take a long time.
   30 
   31 You must disallow login to the WeBWorK system while the transfer is taking
   32 place. To disable logins for all courses, set the permission level necessary for
   33 C<login> to $nobody in F<global.conf>. (It is usually set to $student.)
   34 
   35 =head1 OPTIONS
   36 
   37 =over
   38 
   39 =item -c
   40 
   41 If an error occurs while copying a course's data, continue copying with the next
   42 course.
   43 
   44 =item -r
   45 
   46 Update role table in WWDBv3 database from permission level information in
   47 F<global.conf>.
   48 
   49 =item -s
   50 
   51 Update status table in WWDBv3 database from the status information in
   52 F<global.conf>.
   53 
   54 =item -u
   55 
   56 When importing a user that already exists in the WWDBv3 database, replace the
   57 existing information (including the password) with the information in the user
   58 record being imported.
   59 
   60 If this option is not specified, existing users are not updated.
   61 
   62 =item -v
   63 
   64 Verbose operation.
   65 
   66 =item course ...
   67 
   68 Data from these courses will be copied.
   69 
   70 =back
   71 
   72 =head1 BEHAVIOR
   73 
   74 =head2 ROLES
   75 
   76 =over
   77 
   78 =item *
   79 
   80 Roles are created by observing the %permissionLevels hash in F<global.conf>, and
   81 collecting the privileges granted at each permission level into sets. Each set
   82 of privileges becomes a WWDBv3 role record.
   83 
   84 =item *
   85 
   86 When a role with the same set of permissions already exists in the WWDBv3
   87 database, a new one is not created.
   88 
   89 =back
   90 
   91 =head2 USERS
   92 
   93 =over
   94 
   95 =item *
   96 
   97 WWDBv2 user IDs are converted to login IDs. WWDBv2 set IDs are converted to set
   98 names. WWDBv2 problem IDs are used to determine the C<problem_order> in the
   99 problem's abstract set.
  100 
  101 =item *
  102 
  103 Users with the same user ID in different courses are assumed to be the same
  104 user.
  105 
  106 =back
  107 
  108 =cut
  109 
  110 use strict;
  111 use warnings;
  112 use Data::Dumper;
  113 use Getopt::Std;
  114 
  115 BEGIN {
  116 	die "WEBWORK_ROOT not found in environment.\n"
  117 		unless exists $ENV{WEBWORK_ROOT};
  118 }
  119 
  120 use lib "$ENV{WEBWORK_ROOT}/lib";
  121 use WeBWorK::CourseEnvironment;
  122 use WeBWorK::DB;
  123 use WeBWorK::DBv3;
  124 
  125 our ($opt_c, $opt_r, $opt_s, $opt_u, $opt_v);
  126 getopts("crsuv");
  127 
  128 sub debug { print STDERR @_ if $opt_v }
  129 sub usage { print STDERR "usage: $0 [-uv] course ...\n"; exit 1 }
  130 
  131 main(@ARGV);
  132 
  133 sub main {
  134 	my (@courseIDs) = @_;
  135 	
  136 	usage() unless @courseIDs;
  137 	
  138 	my $ce = WeBWorK::CourseEnvironment->new({webwork_dir => $ENV{WEBWORK_ROOT}});
  139 	
  140 	WeBWorK::DBv3::init($ce->{wwdbv3_settings});
  141 	
  142 	my %level_to_role_id = set_up_roles($ce->{permissionLevels});
  143 	warn Dumper(\%level_to_role_id);
  144 	
  145 	my %statuses = update_statuses($ce->{siteDefaults}{status});
  146 	
  147 	foreach my $courseID (@courseIDs) {
  148 		eval { copy_course_data($courseID) };
  149 		if ($@) {
  150 			warn "An error occured while copying data from course '$courseID':\n\n$@\n\n";
  151 			if ($opt_c) {
  152 				warn "Continuing with the next course...\n";
  153 			} else {
  154 				warn "Exiting.\n";
  155 				exit 2;
  156 			}
  157 		}
  158 	}
  159 }
  160 
  161 ################################################################################
  162 
  163 sub set_up_roles {
  164 	my ($permissionLevels) = @_;
  165 	my %permissionLevels = %$permissionLevels;
  166 	
  167 	my %level_to_role_id;
  168 	
  169 	# get all the levels mentioned in %permissionLevels, along with which
  170 	# privileges are available at that level
  171 	my %levels;
  172 	foreach my $privilege (keys %permissionLevels) {
  173 		my $level = $permissionLevels{$privilege};
  174 		if (defined $level) {
  175 			push @{ $levels{$level} }, $privilege;
  176 		}
  177 	}
  178 	
  179 	my @level_names = sort { $a <=> $b } keys %levels;
  180 	
  181 	# copy up the privileges at each level to the next-higher level
  182  	# also sort each level
  183 	foreach my $i (0 .. $#level_names-1) {
  184 		my $this_level = $level_names[$i];
  185 		my $next_level = $level_names[$i+1];
  186 		push @{ $levels{$next_level} }, @{ $levels{$this_level} };
  187 	}
  188 	
  189 	# sort the privileges in each level
  190 	debug("I found the following permission levels:\n");
  191 	foreach my $level (keys %levels) {
  192 		my @sorted = sort @{ $levels{$level} };
  193 		$levels{$level} = [ @sorted ];
  194 		debug("\t$level => @sorted\n");
  195 	}
  196 	
  197 	# keep track of role names so we know if we need to rename any of our new ones
  198 	my %role_names;
  199 	
  200 	# look at existing roles to see if we can avoid adding some new ones
  201 	my $i = retrieve_all WeBWorK::DBv3::Role;
  202 	while (my $Role = $i->next) {
  203 		$role_names{$Role->name} = 1;
  204 		my @role_privs = sort $Role->priv_list;
  205 		
  206 		foreach my $level (keys %levels) {
  207 			if (listeq($levels{$level}, \@role_privs)) {
  208 				debug("Permission level '$level' is already represented as role '",
  209 					$Role->name, "' -- skipping.\n");
  210 				delete $levels{$level};
  211 				$level_to_role_id{$level} = $Role->id;
  212 			}
  213 		}
  214 	}
  215 	
  216 	if ($opt_r) {
  217 		debug("Updating role table (as per -r switch).\n");
  218 		foreach my $level (keys %levels) {
  219 			my $name = "Legacy permission level $level";
  220 			if (exists $role_names{$name}) {
  221 				my $i = 2;
  222 				while (1) {
  223 					my $try_name = "$name (#$i)";
  224 					if (not exists $role_names{$try_name}) {
  225 						$name = $try_name;
  226 						last;
  227 					}
  228 				}
  229 			}
  230 			
  231 			my @privs = @{ $levels{$level} };
  232 			
  233 			my $Role = create WeBWorK::DBv3::Role({name => $name });
  234 			$Role->priv_list(@privs);
  235 			$Role->update;
  236 			debug("Added role '", $Role->name, "' with privileges '@privs'.\n");
  237 			$level_to_role_id{$level} = $Role->id;
  238 		}
  239 	} else {
  240 		debug("Not updating role table (as per lack of -r switch).\n");
  241 		debug("I might run into users with permission levels that don't map to roles later.\n");
  242 	}
  243 	
  244 	return %level_to_role_id;
  245 }
  246 
  247 sub set_up_statuses {
  248 	my ($statuses) = @_;
  249 }
  250 
  251 ################################################################################
  252 
  253 sub copy_course_data {
  254 	my ($courseID) = @_;
  255 	
  256 	debug("Processing course '$courseID'...\n");
  257 	
  258 	my $course_ce = WeBWorK::CourseEnvironment->new({
  259 		webwork_dir => $ENV{WEBWORK_ROOT},
  260 		courseName => $courseID,
  261 	});
  262 	
  263 	my $course_db = WeBWorK::DB->new($course_ce->{dbLayout});
  264 	
  265 	# First we see if this course already exists. If it does, there's a problem
  266 	# and we throw an exception.
  267 	if (WeBWorK::DBv3::Course->search(name => $courseID)) {
  268 		die "Course '$courseID' exists";
  269 	} else {
  270 		debug("Course '$courseID' doesn't exist in v3 DB -- adding.\n");
  271 		my $Course = WeBWorK::DBv3::Course->create({name => $courseID});
  272 	}
  273 	
  274 	# Then, deal with users.
  275 	my @userIDs = $course_db->listUsers;
  276 	my %Users; @Users{@userIDs} = $course_db->getUsers(@userIDs);
  277 	
  278 	foreach my $userID (keys %Users) {
  279 		my $User = $Users{$userID};
  280 		unless (defined $User) {
  281 			debug("User record for user ID '$userID' not found -- skipping.\n");
  282 			next;
  283 		}
  284 		
  285 		my $v3User = WeBWorK::DBv3::User->search(login_id => $userID);
  286 		if ($v3User) {
  287 			debug("User with login_id '$userID' exists in v3 database -- ");
  288 			if ($opt_u) {
  289 				debug("updating.\n");
  290 				$v3User->first_name($User->first_name) if $User->first_name ne "";
  291 				$v3User->last_name($User->first_name) if $User->last_name ne "";
  292 				$v3User->email_address($User->email_address) if $User->email_address ne "";
  293 				$v3User->student_id($User->student_id) if $User->student_id ne "";
  294 				$v3User->update;
  295 			} else {
  296 				debug("skipping.\n");
  297 			}
  298 		} else {
  299 			debug("User with login_id '$userID' does not exists in v3 database -- adding.\n");
  300 			WeBWorK::DBv3::User->create({
  301 				
  302 			});
  303 		}
  304 	}
  305 }
  306 
  307 ################################################################################
  308 
  309 sub listeq {
  310 	my ($a, $b) = @_;
  311 	return "" unless @$a == @$b;
  312 	for (my $i = 0; $i < @$a; $i++) {
  313 		return "" unless $a->[$i] eq $b->[$i];
  314 	}
  315 	return 1;
  316 }

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9