Parent Directory
|
Revision Log
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 |