diff options
Diffstat (limited to 'rt/etc/upgrade')
65 files changed, 1527 insertions, 618 deletions
diff --git a/rt/etc/upgrade/3.1.0/acl.Informix b/rt/etc/upgrade/3.1.0/acl.Informix deleted file mode 100644 index 73c16ae03..000000000 --- a/rt/etc/upgrade/3.1.0/acl.Informix +++ /dev/null @@ -1,4 +0,0 @@ -sub acl { - return (); -} -1; diff --git a/rt/etc/upgrade/3.1.0/schema.Informix b/rt/etc/upgrade/3.1.0/schema.Informix deleted file mode 100644 index 722eb70b3..000000000 --- a/rt/etc/upgrade/3.1.0/schema.Informix +++ /dev/null @@ -1,17 +0,0 @@ -CREATE TABLE Attributes ( - id SERIAL, - Name VARCHAR(255) DEFAULT '' NOT NULL, - Description VARCHAR(255) DEFAULT NULL, - Content BYTE, - ContentType VARCHAR(16), - ObjectType VARCHAR(25) NOT NULL, - ObjectId INTEGER DEFAULT 0 NOT NULL, - Creator INTEGER DEFAULT 0 NOT NULL, - Created DATETIME YEAR TO SECOND, - LastUpdatedBy INTEGER DEFAULT 0 NOT NULL, - LastUpdated DATETIME YEAR TO SECOND, - PRIMARY KEY (id) -); - -CREATE INDEX Attributes1 on Attributes(Name); -CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); diff --git a/rt/etc/upgrade/3.1.0/schema.Pg b/rt/etc/upgrade/3.1.0/schema.Pg index 94c3fe70d..08a964c4b 100755 --- a/rt/etc/upgrade/3.1.0/schema.Pg +++ b/rt/etc/upgrade/3.1.0/schema.Pg @@ -1,4 +1,4 @@ --- {{{ Attributes + CREATE SEQUENCE attributes_id_seq; @@ -21,5 +21,5 @@ CREATE TABLE Attributes ( CREATE INDEX Attributes1 on Attributes(Name); CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); --- }}} + diff --git a/rt/etc/upgrade/3.1.0/schema.mysql b/rt/etc/upgrade/3.1.0/schema.mysql index c4a345d3e..e4f02c278 100755 --- a/rt/etc/upgrade/3.1.0/schema.mysql +++ b/rt/etc/upgrade/3.1.0/schema.mysql @@ -1,4 +1,3 @@ -# {{{ Attributes CREATE TABLE Attributes ( id INTEGER NOT NULL AUTO_INCREMENT, @@ -13,9 +12,8 @@ CREATE TABLE Attributes ( LastUpdatedBy integer NOT NULL DEFAULT 0 , LastUpdated DATETIME NULL , PRIMARY KEY (id) -) TYPE=InnoDB; +) ENGINE=InnoDB; CREATE INDEX Attributes1 on Attributes(Name); CREATE INDEX Attributes2 on Attributes(ObjectType, ObjectId); -# }}} diff --git a/rt/etc/upgrade/3.3.0/acl.Informix b/rt/etc/upgrade/3.3.0/acl.Informix deleted file mode 100644 index 73c16ae03..000000000 --- a/rt/etc/upgrade/3.3.0/acl.Informix +++ /dev/null @@ -1,4 +0,0 @@ -sub acl { - return (); -} -1; diff --git a/rt/etc/upgrade/3.3.0/schema.mysql b/rt/etc/upgrade/3.3.0/schema.mysql index 0e33a2819..f6998363e 100644 --- a/rt/etc/upgrade/3.3.0/schema.mysql +++ b/rt/etc/upgrade/3.3.0/schema.mysql @@ -45,7 +45,7 @@ CREATE TABLE ObjectCustomFields ( LastUpdatedBy integer NOT NULL DEFAULT 0 , LastUpdated DATETIME NULL , PRIMARY KEY (id) -) TYPE=InnoDB; +) ENGINE=InnoDB; INSERT into ObjectCustomFields (id, CustomField, ObjectId, SortOrder, Creator, LastUpdatedBy) SELECT null, id, Queue, SortOrder, Creator, LastUpdatedBy from CustomFields; diff --git a/rt/etc/upgrade/3.7.19/content b/rt/etc/upgrade/3.7.19/content index ac34ebeb5..31ab1c84a 100644 --- a/rt/etc/upgrade/3.7.19/content +++ b/rt/etc/upgrade/3.7.19/content @@ -4,7 +4,7 @@ add_description_to_all_scrips(); sub add_description_to_all_scrips { require RT::Scrips; - my $scrips = RT::Scrips->new( $RT::SystemUser ); + my $scrips = RT::Scrips->new( RT->SystemUser ); $scrips->Limit( FIELD => 'Description', OPERATOR => 'IS', VALUE => 'NULL' ); $scrips->Limit( FIELD => 'Description', VALUE => '' ); while ( my $scrip = $scrips->Next ) { diff --git a/rt/etc/upgrade/3.7.86/content b/rt/etc/upgrade/3.7.86/content index da087ed75..94912d626 100644 --- a/rt/etc/upgrade/3.7.86/content +++ b/rt/etc/upgrade/3.7.86/content @@ -1,9 +1,9 @@ @Final = ( sub { $RT::Logger->debug("Adding search for bookmarked tickets to defaults"); - my $sys = RT::System->new($RT::SystemUser); + my $sys = RT::System->new(RT->SystemUser); - my $attrs = RT::Attributes->new( $RT::SystemUser ); + my $attrs = RT::Attributes->new( RT->SystemUser ); $attrs->LimitToObject( $sys ); my ($attr) = $attrs->Named( 'HomepageSettings' ); unless ($attr) { diff --git a/rt/etc/upgrade/3.8-branded-queues-extension b/rt/etc/upgrade/3.8-branded-queues-extension deleted file mode 100755 index b3785342f..000000000 --- a/rt/etc/upgrade/3.8-branded-queues-extension +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/perl -# BEGIN BPS TAGGED BLOCK {{{ -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC -# <sales@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -# -# -# CONTRIBUTION SUBMISSION POLICY: -# -# (The following paragraph is not intended to limit the rights granted -# to you to modify and distribute this software under the terms of -# the GNU General Public License and is only of importance to you if -# you choose to contribute your changes and enhancements to the -# community by submitting them to Best Practical Solutions, LLC.) -# -# By intentionally submitting any modifications, corrections or -# derivatives to this work, or any other work intended for use with -# Request Tracker, to Best Practical Solutions, LLC, you confirm that -# you are the copyright holder for those contributions and you grant -# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -# royalty-free, perpetual, license to use, copy, create derivative -# works based on those contributions, and sublicense and distribute -# those contributions and any derivatives thereof. -# -# END BPS TAGGED BLOCK }}} -use strict; -use warnings; - -use lib "local/lib"; -use lib "lib"; - - -use RT; -RT::LoadConfig(); -RT::Init(); - -use RT::Queues; - -my $queues = RT::Queues->new( $RT::SystemUser ); -$queues->UnLimit(); -while ( my $queue = $queues->Next ) { - print "Processing queue ". ($queue->Name || $queue->id) ."...\n"; - my $old_attr = $queue->FirstAttribute('BrandedSubjectTag'); - unless ( $old_attr ) { - print "\thas no old-style subject tag. skipping\n"; - next; - } - my $old_value = $old_attr->Content; - unless ( $old_value ) { - print "\thas empty old-style subject tag\n"; - } else { - my ($status, $msg) = $queue->SetSubjectTag( $old_value ); - unless ( $status ) { - print STDERR "\tERROR. Couldn't set tag: $msg\n"; - next; - } else { - print "\thave set new-style subject tag to '$old_value'\n"; - } - } - - my ($status, $msg) = $queue->DeleteAttribute('BrandedSubjectTag'); - unless ( $status ) { - print STDERR "\tERROR. Couldn't delete old-style tag: $msg\n"; - next; - } else { - print "\tdeleted old-style tag entry\n"; - } - print "\tDONE\n"; -} - -exit 0; - diff --git a/rt/etc/upgrade/3.8-branded-queues-extension.in b/rt/etc/upgrade/3.8-branded-queues-extension.in index dece470d4..8c9f58ded 100755 --- a/rt/etc/upgrade/3.8-branded-queues-extension.in +++ b/rt/etc/upgrade/3.8-branded-queues-extension.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC # <sales@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -59,7 +59,7 @@ RT::Init(); use RT::Queues; -my $queues = RT::Queues->new( $RT::SystemUser ); +my $queues = RT::Queues->new( RT->SystemUser ); $queues->UnLimit(); while ( my $queue = $queues->Next ) { print "Processing queue ". ($queue->Name || $queue->id) ."...\n"; diff --git a/rt/etc/upgrade/3.8-ical-extension b/rt/etc/upgrade/3.8-ical-extension deleted file mode 100755 index a241ee2a1..000000000 --- a/rt/etc/upgrade/3.8-ical-extension +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/perl -# BEGIN BPS TAGGED BLOCK {{{ -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC -# <sales@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -# -# -# CONTRIBUTION SUBMISSION POLICY: -# -# (The following paragraph is not intended to limit the rights granted -# to you to modify and distribute this software under the terms of -# the GNU General Public License and is only of importance to you if -# you choose to contribute your changes and enhancements to the -# community by submitting them to Best Practical Solutions, LLC.) -# -# By intentionally submitting any modifications, corrections or -# derivatives to this work, or any other work intended for use with -# Request Tracker, to Best Practical Solutions, LLC, you confirm that -# you are the copyright holder for those contributions and you grant -# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -# royalty-free, perpetual, license to use, copy, create derivative -# works based on those contributions, and sublicense and distribute -# those contributions and any derivatives thereof. -# -# END BPS TAGGED BLOCK }}} -use strict; -use warnings; - -use lib "local/lib"; -use lib "lib"; - - -use RT; -RT::LoadConfig(); -RT::Init(); - -use RT::Attributes; -my $attrs = RT::Attributes->new( $RT::SystemUser ); -$attrs->Limit(FIELD => 'ObjectType', OPERATOR=> '=', VALUE => 'RT::User'); -$attrs->Limit(FIELD => 'Name', OPERATOR=> '=', VALUE => 'ical-auth-token'); -while ( my $attr = $attrs->Next ) { - my $uid = $attr->ObjectId; - print "Processing auth token of user #". $uid ."...\n"; - - my $user = RT::User->new( $RT::SystemUser ); - $user->Load( $uid ); - unless ( $user->id ) { - print STDERR "\tERROR. Couldn't load user record\n"; - next; - } - - my ($status, $msg); - - ($status, $msg) = $user->DeleteAttribute('AuthToken') - if $user->FirstAttribute('AuthToken'); - unless ( $status ) { - print STDERR "\tERROR. Couldn't delete duplicated attribute: $msg\n"; - next; - } else { - print "\tdeleted duplicate attribute\n"; - } - - ($status, $msg) = $attr->SetName('AuthToken'); - unless ( $status ) { - print STDERR "\tERROR. Couldn't rename attribute: $msg\n"; - next; - } else { - print "\trenamed attribute\n"; - } - print "\tDONE\n"; -} - -exit 0; diff --git a/rt/etc/upgrade/3.8-ical-extension.in b/rt/etc/upgrade/3.8-ical-extension.in index 45b14a6eb..af95a96d9 100644 --- a/rt/etc/upgrade/3.8-ical-extension.in +++ b/rt/etc/upgrade/3.8-ical-extension.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC # <sales@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -58,14 +58,14 @@ RT::LoadConfig(); RT::Init(); use RT::Attributes; -my $attrs = RT::Attributes->new( $RT::SystemUser ); +my $attrs = RT::Attributes->new( RT->SystemUser ); $attrs->Limit(FIELD => 'ObjectType', OPERATOR=> '=', VALUE => 'RT::User'); $attrs->Limit(FIELD => 'Name', OPERATOR=> '=', VALUE => 'ical-auth-token'); while ( my $attr = $attrs->Next ) { my $uid = $attr->ObjectId; print "Processing auth token of user #". $uid ."...\n"; - my $user = RT::User->new( $RT::SystemUser ); + my $user = RT::User->new( RT->SystemUser ); $user->Load( $uid ); unless ( $user->id ) { print STDERR "\tERROR. Couldn't load user record\n"; diff --git a/rt/etc/upgrade/3.8.0/content b/rt/etc/upgrade/3.8.0/content index f4e389b90..4fa5ac7d8 100644 --- a/rt/etc/upgrade/3.8.0/content +++ b/rt/etc/upgrade/3.8.0/content @@ -3,9 +3,9 @@ # 3.7.82 upgrade script still was creating 'My Bookmarks', try to fix it sub { $RT::Logger->debug("Going to rename 'My Bookmarks' to 'Bookmarked Tickets'"); - my $sys = RT::System->new($RT::SystemUser); + my $sys = RT::System->new(RT->SystemUser); - my $attrs = RT::Attributes->new( $RT::SystemUser ); + my $attrs = RT::Attributes->new( RT->SystemUser ); $attrs->LimitToObject( $sys ); my ($attr) = $attrs->Named( 'Search - My Bookmarks' ); unless ($attr) { diff --git a/rt/etc/upgrade/3.8.1/content b/rt/etc/upgrade/3.8.1/content index 89db596ec..1667efa78 100644 --- a/rt/etc/upgrade/3.8.1/content +++ b/rt/etc/upgrade/3.8.1/content @@ -1,9 +1,9 @@ @Final = ( sub { $RT::Logger->debug("Going to adjust 'Bookmarked Tickets'"); - my $sys = RT::System->new($RT::SystemUser); + my $sys = RT::System->new(RT->SystemUser); - my $attrs = RT::Attributes->new( $RT::SystemUser ); + my $attrs = RT::Attributes->new( RT->SystemUser ); $attrs->LimitToObject( $sys ); my ($attr) = $attrs->Named( 'Search - Bookmarked Tickets' ); unless ($attr) { diff --git a/rt/etc/upgrade/3.8.2/content b/rt/etc/upgrade/3.8.2/content index d8f54e9ba..0eef401b8 100644 --- a/rt/etc/upgrade/3.8.2/content +++ b/rt/etc/upgrade/3.8.2/content @@ -7,14 +7,14 @@ ." you may eventually want to start using approvals." ); - my $approvals_q = RT::Queue->new( $RT::SystemUser ); + my $approvals_q = RT::Queue->new( RT->SystemUser ); $approvals_q->Load('___Approvals'); unless ( $approvals_q->id ) { $RT::Logger->error("You have no approvals queue."); return 1; } - my $templates = RT::Templates->new( $RT::SystemUser ); + my $templates = RT::Templates->new( RT->SystemUser ); $templates->LimitToQueue( $approvals_q->id ); while ( my $tmpl = $templates->Next ) { my ($status, $msg) = $tmpl->SetName( "[OLD] ". $tmpl->Name ); @@ -109,9 +109,9 @@ The ticket has been approved, you may now start to act on it. @Final = ( sub { $RT::Logger->debug("Going to adjust dashboards"); - my $sys = RT::System->new($RT::SystemUser); + my $sys = RT::System->new(RT->SystemUser); - my $attrs = RT::Attributes->new( $RT::SystemUser ); + my $attrs = RT::Attributes->new( RT->SystemUser ); $attrs->UnLimit; my @dashboards = $attrs->Named('Dashboard'); @@ -147,7 +147,7 @@ The ticket has been approved, you may now start to act on it. return 1; }, sub { - my $approvals_q = RT::Queue->new( $RT::SystemUser ); + my $approvals_q = RT::Queue->new( RT->SystemUser ); $approvals_q->Load('___Approvals'); unless ( $approvals_q->id ) { $RT::Logger->error("You have no approvals queue."); @@ -168,7 +168,7 @@ The ticket has been approved, you may now start to act on it. require Data::Dumper; - my $scrips = RT::Scrips->new( $RT::SystemUser ); + my $scrips = RT::Scrips->new( RT->SystemUser ); $scrips->LimitToQueue( $approvals_q->id ); while ( my $scrip = $scrips->Next ) { my %tmp = diff --git a/rt/etc/upgrade/3.8.3/content b/rt/etc/upgrade/3.8.3/content index 8538e4287..b8052acde 100644 --- a/rt/etc/upgrade/3.8.3/content +++ b/rt/etc/upgrade/3.8.3/content @@ -12,7 +12,7 @@ sub { $RT::Logger->debug("Going to correct descriptions of notify actions in the DB"); - my $actions = RT::ScripActions->new( $RT::SystemUser ); + my $actions = RT::ScripActions->new( RT->SystemUser ); $actions->Limit( FIELD => 'ExecModule', VALUE => 'Notify', @@ -31,7 +31,7 @@ unless $status; } - $actions = RT::ScripActions->new( $RT::SystemUser ); + $actions = RT::ScripActions->new( RT->SystemUser ); $actions->Limit( FIELD => 'ExecModule', VALUE => 'NotifyAsComment', @@ -59,7 +59,7 @@ { $RT::Logger->debug("Going to add in Extract Subject Tag actions if they were missed during a previous upgrade"); -$actions = RT::ScripActions->new( $RT::SystemUser ); +$actions = RT::ScripActions->new( RT->SystemUser ); $actions->Limit( FIELD => 'ExecModule', VALUE => 'ExtractSubjectTag', diff --git a/rt/etc/upgrade/3.8.4/content b/rt/etc/upgrade/3.8.4/content index be5a6bf39..38d551450 100644 --- a/rt/etc/upgrade/3.8.4/content +++ b/rt/etc/upgrade/3.8.4/content @@ -4,7 +4,7 @@ $RT::Logger->debug("Going to correct arguments of NotifyGroup actions if you have any"); use strict; - my $actions = RT::ScripActions->new( $RT::SystemUser ); + my $actions = RT::ScripActions->new( RT->SystemUser ); $actions->Limit( FIELD => 'ExecModule', VALUE => 'NotifyGroup', @@ -21,9 +21,9 @@ my $obj; next unless $r->{'Type'}; if( lc $r->{'Type'} eq 'user' ) { - $obj = RT::User->new( $RT::SystemUser ); + $obj = RT::User->new( RT->SystemUser ); } elsif ( lc $r->{'Type'} eq 'group' ) { - $obj = RT::Group->new( $RT::SystemUser ); + $obj = RT::Group->new( RT->SystemUser ); } else { next; } diff --git a/rt/etc/upgrade/3.8.8/content b/rt/etc/upgrade/3.8.8/content index ee1943304..cad77e948 100644 --- a/rt/etc/upgrade/3.8.8/content +++ b/rt/etc/upgrade/3.8.8/content @@ -1,7 +1,7 @@ @Initial = ( sub { # make sure global CFs are not applied to local objects - my $ocfs = RT::ObjectCustomFields->new( $RT::SystemUser ); + my $ocfs = RT::ObjectCustomFields->new( RT->SystemUser ); $ocfs->Limit( FIELD => 'ObjectId', OPERATOR => '!=', VALUE => 0 ); my $alias = $ocfs->Join( FIELD1 => 'CustomField', @@ -26,7 +26,7 @@ my ($i, $prev_type) = (0, ''); while ( my ($lt, $id) = $sth->fetchrow_array ) { $i = 0 if $prev_type ne $lt; - my $ocf = RT::ObjectCustomField->new( $RT::SystemUser ); + my $ocf = RT::ObjectCustomField->new( RT->SystemUser ); $ocf->Load( $id ); my ($status, $msg) = $ocf->SetSortOrder( $i++ ); $RT::Logger->warning("Couldn't set SortOrder: $msg") diff --git a/rt/etc/upgrade/3.8.9/content b/rt/etc/upgrade/3.8.9/content index 8a28f7dce..898c19ebf 100644 --- a/rt/etc/upgrade/3.8.9/content +++ b/rt/etc/upgrade/3.8.9/content @@ -10,7 +10,7 @@ my $found; do { $found = 0; - my $links = RT::Links->new( $RT::SystemUser ); + my $links = RT::Links->new( RT->SystemUser ); $links->Limit( FIELD => $dir, OPERATOR => 'STARTSWITH', VALUE => $prefix ); $links->Limit( FIELD => 'Local'.$dir, VALUE => 0 ); $links->Limit( diff --git a/rt/etc/upgrade/3.9.1/content b/rt/etc/upgrade/3.9.1/content new file mode 100644 index 000000000..acdc0adb7 --- /dev/null +++ b/rt/etc/upgrade/3.9.1/content @@ -0,0 +1,68 @@ +@Initial = ( + sub { + use strict; + $RT::Logger->debug('Make sure templates all have known types'); + + # We update all NULL rows, below. We want to find non-NULL + # rows, which weren't created by the current codebase running + # through earlier initialdatas. Type != 'Perl' enforces the + # non-NULL part, as well + my $templates = RT::Templates->new(RT->SystemUser); + $templates->Limit( + FIELD => 'Type', + OPERATOR => '!=', + VALUE => 'Perl', + ); + + if ($templates->Count) { + die "You have templates with Type already set. This will interfere with your upgrade because RT used to ignore the template Type field, but now uses it."; + } + + $templates = RT::Templates->new(RT->SystemUser); + $templates->Limit( + FIELD => 'Type', + OPERATOR => 'IS', + VALUE => 'NULL', + ); + while (my $template = $templates->Next) { + my ($status, $msg) = $template->SetType('Perl'); + $RT::Logger->warning( "Couldn't change Type of Template #" . $template->Id . ": $msg" ) unless $status; + } + }, + sub { + use strict; + $RT::Logger->debug('Adding ExecuteCode right to principals that currently have ModifyTemplate or ModifyScrips'); + + my $acl = RT::ACL->new(RT->SystemUser); + $acl->Limit( + FIELD => 'RightName', + OPERATOR => '=', + VALUE => 'ModifyTemplate', + ENTRYAGGREGATOR => 'OR', + ); + $acl->Limit( + FIELD => 'RightName', + OPERATOR => '=', + VALUE => 'ModifyScrips', + ENTRYAGGREGATOR => 'OR', + ); + + while (my $ace = $acl->Next) { + my $principal = $ace->PrincipalObj; + next if $principal->HasRight( + Right => 'ExecuteCode', + Object => $RT::System, + ); + + my ($ok, $msg) = $principal->GrantRight( + Right => 'ExecuteCode', + Object => $RT::System, + ); + + if (!$ok) { + $RT::Logger->warn("Unable to grant ExecuteCode on principal " . $principal->id . ": $msg"); + } + } + }, +); + diff --git a/rt/etc/upgrade/3.9.2/content b/rt/etc/upgrade/3.9.2/content new file mode 100644 index 000000000..d0dbbfd0a --- /dev/null +++ b/rt/etc/upgrade/3.9.2/content @@ -0,0 +1,48 @@ +@Initial = ( + sub { + use strict; + $RT::Logger->debug('Removing all delegated rights'); + + my $acl = RT::ACL->new(RT->SystemUser); + $acl->Limit( CLAUSE => 'search', + FIELD => 'DelegatedBy', + OPERATOR => '>', + VALUE => '0' + ); + $acl->Limit( CLAUSE => 'search', + FIELD => 'DelegatedFrom', + OPERATOR => '>', + VALUE => '0', + ENTRYAGGREGATOR => 'OR', + ); + + while ( my $ace = $acl->Next ) { + my ( $ok, $msg ) = $ace->Delete(); + + if ( !$ok ) { + $RT::Logger->warn( + "Unable to delete ACE " . $ace->id . ": " . $msg ); + } + } + + my $groups = RT::Groups->new(RT->SystemUser); + $groups->Limit( FIELD => 'Domain', + OPERATOR => '=', + VALUE => 'Personal' + ); + while ( my $group = $groups->Next ) { + my $members = $group->MembersObj(); + while ( my $member = $members->Next ) { + my ( $ok, $msg ) = $group->DeleteMember( $member->MemberId ); + if ( !$ok ) { + $RT::Logger->warn( "Unable to remove group member " + . $member->id . ": " + . $msg ); + } + } + $group->PrincipalObj->Delete; + $group->RT::Record::Delete(); + } + }, +); + diff --git a/rt/etc/upgrade/3.9.3/schema.Oracle b/rt/etc/upgrade/3.9.3/schema.Oracle new file mode 100644 index 000000000..4ee50c446 --- /dev/null +++ b/rt/etc/upgrade/3.9.3/schema.Oracle @@ -0,0 +1,2 @@ +ALTER TABLE ACL DROP COLUMN DelegatedBy; +ALTER TABLE ACL DROP COLUMN DelegatedFrom; diff --git a/rt/etc/upgrade/3.9.3/schema.Pg b/rt/etc/upgrade/3.9.3/schema.Pg new file mode 100644 index 000000000..4ee50c446 --- /dev/null +++ b/rt/etc/upgrade/3.9.3/schema.Pg @@ -0,0 +1,2 @@ +ALTER TABLE ACL DROP COLUMN DelegatedBy; +ALTER TABLE ACL DROP COLUMN DelegatedFrom; diff --git a/rt/etc/upgrade/3.9.3/schema.mysql b/rt/etc/upgrade/3.9.3/schema.mysql new file mode 100644 index 000000000..4ee50c446 --- /dev/null +++ b/rt/etc/upgrade/3.9.3/schema.mysql @@ -0,0 +1,2 @@ +ALTER TABLE ACL DROP COLUMN DelegatedBy; +ALTER TABLE ACL DROP COLUMN DelegatedFrom; diff --git a/rt/etc/upgrade/3.9.5/backcompat b/rt/etc/upgrade/3.9.5/backcompat new file mode 100644 index 000000000..611ab5186 --- /dev/null +++ b/rt/etc/upgrade/3.9.5/backcompat @@ -0,0 +1 @@ +RT::ACE LastUpdated LastUpdatedBy Creator Created diff --git a/rt/etc/upgrade/3.9.5/schema.Oracle b/rt/etc/upgrade/3.9.5/schema.Oracle new file mode 100644 index 000000000..065776dfb --- /dev/null +++ b/rt/etc/upgrade/3.9.5/schema.Oracle @@ -0,0 +1,20 @@ +alter Table CustomFieldValues ADD Category varchar2(255); + +UPDATE CustomFieldValues SET Category = (SELECT Content FROM Attributes WHERE +Name = 'Category' AND ObjectType = 'RT::CustomFieldValue' +AND CustomFieldValues.id = Attributes.ObjectId); + +DELETE FROM Attributes WHERE Name = 'Category' AND ObjectType = 'RT::CustomFieldValue'; + +ALTER TABLE Groups ADD Creator NUMBER(11,0) DEFAULT 0 NOT NULL; +ALTER TABLE Groups ADD Created DATE; +ALTER TABLE Groups ADD LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL; +ALTER TABLE Groups ADD LastUpdated DATE; +ALTER TABLE GroupMembers ADD Creator NUMBER(11,0) DEFAULT 0 NOT NULL; +ALTER TABLE GroupMembers ADD Created DATE; +ALTER TABLE GroupMembers ADD LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL; +ALTER TABLE GroupMembers ADD LastUpdated DATE; +ALTER TABLE ACL ADD Creator NUMBER(11,0) DEFAULT 0 NOT NULL; +ALTER TABLE ACL ADD Created DATE; +ALTER TABLE ACL ADD LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL; +ALTER TABLE ACL ADD LastUpdated DATE; diff --git a/rt/etc/upgrade/3.9.5/schema.Pg b/rt/etc/upgrade/3.9.5/schema.Pg new file mode 100644 index 000000000..cea2c4410 --- /dev/null +++ b/rt/etc/upgrade/3.9.5/schema.Pg @@ -0,0 +1,20 @@ +alter Table CustomFieldValues ADD Column Category varchar(255); + +UPDATE CustomFieldValues SET Category = (SELECT Content FROM Attributes WHERE +Name = 'Category' AND ObjectType = 'RT::CustomFieldValue' +AND CustomFieldValues.id = Attributes.ObjectId); + +DELETE FROM Attributes WHERE Name = 'Category' AND ObjectType = 'RT::CustomFieldValue'; + +ALTER TABLE Groups ADD COLUMN Creator integer NOT NULL DEFAULT 0; +ALTER TABLE Groups ADD COLUMN Created TIMESTAMP NULL; +ALTER TABLE Groups ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; +ALTER TABLE Groups ADD COLUMN LastUpdated TIMESTAMP NULL; +ALTER TABLE GroupMembers ADD COLUMN Creator integer NOT NULL DEFAULT 0; +ALTER TABLE GroupMembers ADD COLUMN Created TIMESTAMP NULL; +ALTER TABLE GroupMembers ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; +ALTER TABLE GroupMembers ADD COLUMN LastUpdated TIMESTAMP NULL; +ALTER TABLE ACL ADD COLUMN Creator integer NOT NULL DEFAULT 0; +ALTER TABLE ACL ADD COLUMN Created TIMESTAMP NULL; +ALTER TABLE ACL ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; +ALTER TABLE ACL ADD COLUMN LastUpdated TIMESTAMP NULL; diff --git a/rt/etc/upgrade/3.9.5/schema.SQLite b/rt/etc/upgrade/3.9.5/schema.SQLite new file mode 100644 index 000000000..c23f89bc7 --- /dev/null +++ b/rt/etc/upgrade/3.9.5/schema.SQLite @@ -0,0 +1,19 @@ +ALTER TABLE CustomFieldValues ADD Column Category varchar(255); +UPDATE CustomFieldValues SET Category = (SELECT Content FROM Attributes WHERE +Name = 'Category' AND ObjectType = 'RT::CustomFieldValue' +AND CustomFieldValues.id = Attributes.ObjectId); + +DELETE FROM Attributes WHERE Name = 'Category' AND ObjectType = 'RT::CustomFieldValue'; + +ALTER TABLE Groups ADD COLUMN Creator integer NOT NULL DEFAULT 0; +ALTER TABLE Groups ADD COLUMN Created DATETIME NULL; +ALTER TABLE Groups ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; +ALTER TABLE Groups ADD COLUMN LastUpdated DATETIME NULL; +ALTER TABLE GroupMembers ADD COLUMN Creator integer NOT NULL DEFAULT 0; +ALTER TABLE GroupMembers ADD COLUMN Created DATETIME NULL; +ALTER TABLE GroupMembers ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; +ALTER TABLE GroupMembers ADD COLUMN LastUpdated DATETIME NULL; +ALTER TABLE ACL ADD COLUMN Creator integer NOT NULL DEFAULT 0; +ALTER TABLE ACL ADD COLUMN Created DATETIME NULL; +ALTER TABLE ACL ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; +ALTER TABLE ACL ADD COLUMN LastUpdated DATETIME NULL; diff --git a/rt/etc/upgrade/3.9.5/schema.mysql b/rt/etc/upgrade/3.9.5/schema.mysql new file mode 100644 index 000000000..4bd0907c0 --- /dev/null +++ b/rt/etc/upgrade/3.9.5/schema.mysql @@ -0,0 +1,20 @@ +alter Table CustomFieldValues ADD Column Category varchar(255); + +UPDATE CustomFieldValues SET Category = (SELECT Content FROM Attributes WHERE +Name = 'Category' AND ObjectType = 'RT::CustomFieldValue' +AND CustomFieldValues.id = Attributes.ObjectId); + +DELETE FROM Attributes WHERE Name = 'Category' AND ObjectType = 'RT::CustomFieldValue'; + +ALTER TABLE Groups ADD COLUMN Creator integer NOT NULL DEFAULT 0; +ALTER TABLE Groups ADD COLUMN Created DATETIME NULL; +ALTER TABLE Groups ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; +ALTER TABLE Groups ADD COLUMN LastUpdated DATETIME NULL; +ALTER TABLE GroupMembers ADD COLUMN Creator integer NOT NULL DEFAULT 0; +ALTER TABLE GroupMembers ADD COLUMN Created DATETIME NULL; +ALTER TABLE GroupMembers ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; +ALTER TABLE GroupMembers ADD COLUMN LastUpdated DATETIME NULL; +ALTER TABLE ACL ADD COLUMN Creator integer NOT NULL DEFAULT 0; +ALTER TABLE ACL ADD COLUMN Created DATETIME NULL; +ALTER TABLE ACL ADD COLUMN LastUpdatedBy integer NOT NULL DEFAULT 0; +ALTER TABLE ACL ADD COLUMN LastUpdated DATETIME NULL; diff --git a/rt/etc/upgrade/3.9.6/schema.Oracle b/rt/etc/upgrade/3.9.6/schema.Oracle new file mode 100644 index 000000000..ecec972f4 --- /dev/null +++ b/rt/etc/upgrade/3.9.6/schema.Oracle @@ -0,0 +1 @@ +ALTER TABLE Tickets MODIFY Status VARCHAR2(64); diff --git a/rt/etc/upgrade/3.9.6/schema.Pg b/rt/etc/upgrade/3.9.6/schema.Pg new file mode 100644 index 000000000..f4f909edc --- /dev/null +++ b/rt/etc/upgrade/3.9.6/schema.Pg @@ -0,0 +1 @@ +ALTER TABLE Tickets ALTER Status TYPE varchar(64); diff --git a/rt/etc/upgrade/3.9.6/schema.SQLite b/rt/etc/upgrade/3.9.6/schema.SQLite new file mode 100644 index 000000000..2e7b6d307 --- /dev/null +++ b/rt/etc/upgrade/3.9.6/schema.SQLite @@ -0,0 +1,69 @@ +BEGIN TRANSACTION; +CREATE TEMPORARY TABLE Tickets_backup ( + id INTEGER PRIMARY KEY , + EffectiveId integer NULL , + Queue integer NULL , + Type varchar(16) NULL , + IssueStatement integer NULL , + Resolution integer NULL , + Owner integer NULL , + Subject varchar(200) NULL DEFAULT '[no subject]' , + InitialPriority integer NULL , + FinalPriority integer NULL , + Priority integer NULL , + TimeEstimated integer NULL , + TimeWorked integer NULL , + Status varchar(64) NULL , + TimeLeft integer NULL , + Told DATETIME NULL , + Starts DATETIME NULL , + Started DATETIME NULL , + Due DATETIME NULL , + Resolved DATETIME NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL , + Creator integer NULL , + Created DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 +); + +INSERT INTO Tickets_backup SELECT * FROM Tickets; +DROP TABLE Tickets; + +CREATE TABLE Tickets ( + id INTEGER PRIMARY KEY , + EffectiveId integer NULL , + Queue integer NULL , + Type varchar(16) NULL , + IssueStatement integer NULL , + Resolution integer NULL , + Owner integer NULL , + Subject varchar(200) NULL DEFAULT '[no subject]' , + InitialPriority integer NULL , + FinalPriority integer NULL , + Priority integer NULL , + TimeEstimated integer NULL , + TimeWorked integer NULL , + Status varchar(64) NULL , + TimeLeft integer NULL , + Told DATETIME NULL , + Starts DATETIME NULL , + Started DATETIME NULL , + Due DATETIME NULL , + Resolved DATETIME NULL , + LastUpdatedBy integer NULL , + LastUpdated DATETIME NULL , + Creator integer NULL , + Created DATETIME NULL , + Disabled int2 NOT NULL DEFAULT 0 +); + +CREATE INDEX Tickets1 ON Tickets (Queue, Status) ; +CREATE INDEX Tickets2 ON Tickets (Owner) ; +CREATE INDEX Tickets3 ON Tickets (EffectiveId) ; +CREATE INDEX Tickets4 ON Tickets (id, Status) ; +CREATE INDEX Tickets5 ON Tickets (id, EffectiveId) ; + +INSERT INTO Tickets SELECT * FROM Tickets_backup; +DROP TABLE Tickets_backup; +COMMIT; diff --git a/rt/etc/upgrade/3.9.6/schema.mysql b/rt/etc/upgrade/3.9.6/schema.mysql new file mode 100644 index 000000000..b0a9eaf9f --- /dev/null +++ b/rt/etc/upgrade/3.9.6/schema.mysql @@ -0,0 +1 @@ +ALTER TABLE Tickets Modify Status varchar(64); diff --git a/rt/etc/upgrade/3.9.7/content b/rt/etc/upgrade/3.9.7/content new file mode 100644 index 000000000..504ddf18f --- /dev/null +++ b/rt/etc/upgrade/3.9.7/content @@ -0,0 +1,82 @@ +my $move_attributes = sub { + my ($table, $type, $column) = @_; + my $query = "UPDATE $table SET $column = (SELECT Content FROM Attributes WHERE" + ." Name = ? AND ObjectType = ? AND $table.id = Attributes.ObjectId)"; + + my $res = $RT::Handle->SimpleQuery( $query, $column, $type ); + unless ( $res ) { + $RT::Logger->error("Failed to move $column on $type from Attributes into $table table"); + return; + } + + $query = 'DELETE FROM Attributes WHERE Name = ? AND ObjectType = ?'; + $res = $RT::Handle->SimpleQuery( $query, $column, $type ); + unless ( $res ) { + $RT::Logger->error("Failed to delete $column on $type from Attributes"); + return; + } + return 1; +}; + +@Initial = ( + sub { + return $move_attributes->( 'Users', 'RT::User', 'AuthToken'); + }, + sub { + return $move_attributes->( 'CustomFields', 'RT::CustomField', 'RenderType'); + }, + sub { + my $cfs = RT::CustomFields->new($RT::SystemUser); + $cfs->UnLimit; + $cfs->FindAllRows; + while ( my $cf = $cfs->Next ) { + # Explicitly remove 'ORDER BY id asc' to emulate the + # previous functionality, where Pg might return the the + # rows in arbitrary order + $cf->Attributes->OrderByCols(); + + my $attr = $cf->FirstAttribute('BasedOn'); + next unless $attr; + $cf->SetBasedOn($attr->Content); + } + $query = 'DELETE FROM Attributes WHERE Name = ? AND ObjectType = ?'; + $res = $RT::Handle->SimpleQuery( $query, 'BasedOn', 'RT::CustomField' ); + unless ( $res ) { + $RT::Logger->error("Failed to delete BasedOn CustomFields from Attributes"); + return; + } + return 1; + }, + sub { + $move_attributes->( 'CustomFields', 'RT::CustomField', 'ValuesClass') + or return; + + my $query = "UPDATE CustomFields SET ValuesClass = NULL WHERE ValuesClass = ?"; + my $res = $RT::Handle->SimpleQuery( $query, 'RT::CustomFieldValues' ); + unless ( $res ) { + $RT::Logger->error("Failed to replace default with NULLs"); + return; + } + return 1; + }, + sub { + my $attr = RT->System->FirstAttribute('BrandedSubjectTag'); + return 1 unless $attr; + + my $map = $attr->Content || {}; + while ( my ($qid, $tag) = each %$map ) { + my $queue = RT::Queue->new( RT->SystemUser ); + $queue->Load( $qid ); + unless ( $queue->id ) { + $RT::Logger->warning("Couldn't load queue #$qid. Skipping..."); + next; + } + + my ($status, $msg) = $queue->SetSubjectTag($tag); + unless ( $status ) { + $RT::Logger->error("Couldn't set subject tag for queue #$qid: $msg"); + next; + } + } + }, +); diff --git a/rt/etc/upgrade/3.9.7/schema.Oracle b/rt/etc/upgrade/3.9.7/schema.Oracle new file mode 100644 index 000000000..3c75c917d --- /dev/null +++ b/rt/etc/upgrade/3.9.7/schema.Oracle @@ -0,0 +1,6 @@ +ALTER TABLE Users ADD AuthToken VARCHAR2(16) NULL; +ALTER TABLE CustomFields ADD BasedOn NUMBER(11,0) NULL; +ALTER TABLE CustomFields ADD RenderType VARCHAR2(64) NULL; +ALTER TABLE CustomFields ADD ValuesClass VARCHAR2(64) NULL; +ALTER TABLE Queues ADD SubjectTag VARCHAR2(120) NULL; +ALTER TABLE Queues ADD Lifecycle VARCHAR2(32) NULL; diff --git a/rt/etc/upgrade/3.9.7/schema.Pg b/rt/etc/upgrade/3.9.7/schema.Pg new file mode 100644 index 000000000..1704fa673 --- /dev/null +++ b/rt/etc/upgrade/3.9.7/schema.Pg @@ -0,0 +1,6 @@ +ALTER TABLE Users ADD COLUMN AuthToken VARCHAR(16) NULL; +ALTER TABLE CustomFields ADD COLUMN BasedOn INTEGER NULL; +ALTER TABLE CustomFields ADD COLUMN RenderType VARCHAR(64) NULL; +ALTER TABLE CustomFields ADD COLUMN ValuesClass VARCHAR(64) NULL; +ALTER TABLE Queues ADD COLUMN SubjectTag VARCHAR(120) NULL; +ALTER TABLE Queues ADD COLUMN Lifecycle VARCHAR(32) NULL; diff --git a/rt/etc/upgrade/3.9.7/schema.SQLite b/rt/etc/upgrade/3.9.7/schema.SQLite new file mode 100644 index 000000000..1704fa673 --- /dev/null +++ b/rt/etc/upgrade/3.9.7/schema.SQLite @@ -0,0 +1,6 @@ +ALTER TABLE Users ADD COLUMN AuthToken VARCHAR(16) NULL; +ALTER TABLE CustomFields ADD COLUMN BasedOn INTEGER NULL; +ALTER TABLE CustomFields ADD COLUMN RenderType VARCHAR(64) NULL; +ALTER TABLE CustomFields ADD COLUMN ValuesClass VARCHAR(64) NULL; +ALTER TABLE Queues ADD COLUMN SubjectTag VARCHAR(120) NULL; +ALTER TABLE Queues ADD COLUMN Lifecycle VARCHAR(32) NULL; diff --git a/rt/etc/upgrade/3.9.7/schema.mysql b/rt/etc/upgrade/3.9.7/schema.mysql new file mode 100644 index 000000000..1be165647 --- /dev/null +++ b/rt/etc/upgrade/3.9.7/schema.mysql @@ -0,0 +1,6 @@ +ALTER TABLE Users ADD COLUMN AuthToken VARCHAR(16) CHARACTER SET ascii NULL; +ALTER TABLE CustomFields ADD COLUMN BasedOn INTEGER NULL; +ALTER TABLE CustomFields ADD COLUMN RenderType VARCHAR(64) NULL; +ALTER TABLE CustomFields ADD COLUMN ValuesClass VARCHAR(64) CHARACTER SET ascii NULL; +ALTER TABLE Queues ADD COLUMN SubjectTag VARCHAR(120) NULL; +ALTER TABLE Queues ADD COLUMN Lifecycle VARCHAR(32) NULL; diff --git a/rt/etc/upgrade/3.9.8/content b/rt/etc/upgrade/3.9.8/content new file mode 100644 index 000000000..d759db9cd --- /dev/null +++ b/rt/etc/upgrade/3.9.8/content @@ -0,0 +1,24 @@ +@Initial = sub { + my $dbh = $RT::Handle->dbh; + my $sth = $dbh->table_info( '', undef, undef, "'TABLE'"); + my $found_fm_tables = {}; + while ( my $table = $sth->fetchrow_hashref ) { + my $name = $table->{TABLE_NAME} || $table->{table_name}; + next unless $name =~ /^fm_/i; + $found_fm_tables->{lc $name}++; + } + + return unless %$found_fm_tables; + + unless ( $found_fm_tables->{fm_topics} && $found_fm_tables->{fm_objecttopics} ) { + $RT::Logger->error("You appear to be upgrading from RTFM 2.0 - We don't support upgrading this old of an RTFM yet"); + } + + $RT::Logger->error("We found RTFM tables in your database. Checking for content."); + + my $result = $dbh->selectall_arrayref("SELECT count(*) AS articlecount FROM FM_Articles", { Slice => {} } ); + + if ($result->[0]{articlecount} > 0) { + $RT::Logger->error("You appear to have RTFM Articles. You can upgrade using the etc/upgrade/upgrade-articles script. Read more about it in UPGRADING"); + } +}; diff --git a/rt/etc/upgrade/3.9.8/schema.Oracle b/rt/etc/upgrade/3.9.8/schema.Oracle new file mode 100644 index 000000000..4f823731f --- /dev/null +++ b/rt/etc/upgrade/3.9.8/schema.Oracle @@ -0,0 +1,65 @@ +CREATE SEQUENCE Classes_seq; +CREATE TABLE Classes ( +id NUMBER(11,0) + CONSTRAINT Classes_key PRIMARY KEY, +Name varchar2(255) DEFAULT '', +Description varchar2(255) DEFAULT '', +SortOrder NUMBER(11,0) DEFAULT 0 NOT NULL, +Disabled NUMBER(11,0) DEFAULT 0 NOT NULL, +Creator NUMBER(11,0) DEFAULT 0 NOT NULL, +Created DATE, +LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, +LastUpdated DATE, +HotList NUMBER(11,0) DEFAULT 0 NOT NULL +); + +CREATE SEQUENCE Articles_seq; +CREATE TABLE Articles ( +id NUMBER(11,0) + CONSTRAINT Articles_key PRIMARY KEY, +Name varchar2(255) DEFAULT '', +Summary varchar2(255) DEFAULT '', +SortOrder NUMBER(11,0) DEFAULT 0 NOT NULL, +Class NUMBER(11,0) DEFAULT 0 NOT NULL, +Parent NUMBER(11,0) DEFAULT 0 NOT NULL, +URI varchar2(255), +Creator NUMBER(11,0) DEFAULT 0 NOT NULL, +Created DATE, +LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, +LastUpdated DATE +); + + +CREATE SEQUENCE Topics_seq; +CREATE TABLE Topics ( +id NUMBER(11,0) + CONSTRAINT Topics_key PRIMARY KEY, +Parent NUMBER(11,0) DEFAULT 0 NOT NULL, +Name varchar2(255) DEFAULT '', +Description varchar2(255) DEFAULT '', +ObjectType varchar2(64) DEFAULT '' NOT NULL, +ObjectId NUMBER(11,0) NOT NULL +); + + +CREATE SEQUENCE ObjectTopics_seq; +CREATE TABLE ObjectTopics ( +id NUMBER(11,0) + CONSTRAINT ObjectTopics_key PRIMARY KEY, +Topic NUMBER(11,0) NOT NULL, +ObjectType varchar2(64) DEFAULT '' NOT NULL, +ObjectId NUMBER(11,0) NOT NULL +); + +CREATE SEQUENCE ObjectClasses_seq; +CREATE TABLE ObjectClasses ( +id NUMBER(11,0) + CONSTRAINT ObjectClasses_key PRIMARY KEY, +Class NUMBER(11,0) NOT NULL, +ObjectType varchar2(255) DEFAULT '' NOT NULL, +ObjectId NUMBER(11,0) NOT NULL, +Creator NUMBER(11,0) DEFAULT 0 NOT NULL, +Created DATE, +LastUpdatedBy NUMBER(11,0) DEFAULT 0 NOT NULL, +LastUpdated DATE +); diff --git a/rt/etc/upgrade/3.9.8/schema.Pg b/rt/etc/upgrade/3.9.8/schema.Pg new file mode 100644 index 000000000..d12e27a73 --- /dev/null +++ b/rt/etc/upgrade/3.9.8/schema.Pg @@ -0,0 +1,62 @@ +CREATE TABLE Classes ( +id SERIAL, +Name varchar(255) NOT NULL DEFAULT '', +Description varchar(255) NOT NULL DEFAULT '', +SortOrder integer NOT NULL DEFAULT 0, +Disabled smallint NOT NULL DEFAULT 0, +Creator integer NOT NULL DEFAULT 0, +Created TIMESTAMP NULL, +LastUpdatedBy integer NOT NULL DEFAULT 0, +LastUpdated TIMESTAMP NULL, +HotList smallint NOT NULL DEFAULT 0, +PRIMARY KEY (id) +); + +CREATE TABLE Articles ( +id SERIAL, +Name varchar(255) NOT NULL DEFAULT '', +Summary varchar(255) NOT NULL DEFAULT '', +SortOrder integer NOT NULL DEFAULT 0, +Class integer NOT NULL DEFAULT 0, +Parent integer NOT NULL DEFAULT 0, +URI varchar(255), +Creator integer NOT NULL DEFAULT 0, +Created TIMESTAMP NULL, +LastUpdatedBy integer NOT NULL DEFAULT 0, +LastUpdated TIMESTAMP NULL, +PRIMARY KEY (id) +); + + +CREATE TABLE Topics ( +id SERIAL, +Parent integer NOT NULL DEFAULT 0, +Name varchar(255) NOT NULL DEFAULT '', +Description varchar(255) NOT NULL DEFAULT '', +ObjectType varchar(64) NOT NULL DEFAULT '', +ObjectId integer NOT NULL, +PRIMARY KEY (id) +); + + +CREATE TABLE ObjectTopics ( +id SERIAL, +Topic integer NOT NULL, +ObjectType varchar(64) NOT NULL DEFAULT '', +ObjectId integer NOT NULL, +PRIMARY KEY (id) +); + + +CREATE TABLE ObjectClasses ( +id SERIAL, +Class integer NOT NULL, +ObjectType varchar(255) NOT NULL DEFAULT '', +ObjectId integer NOT NULL, +Creator integer NOT NULL DEFAULT 0, +Created TIMESTAMP NULL, +LastUpdatedBy integer NOT NULL DEFAULT 0, +LastUpdated TIMESTAMP NULL, +PRIMARY KEY (id) +); + diff --git a/rt/etc/upgrade/3.9.8/schema.SQLite b/rt/etc/upgrade/3.9.8/schema.SQLite new file mode 100644 index 000000000..29ed7e87a --- /dev/null +++ b/rt/etc/upgrade/3.9.8/schema.SQLite @@ -0,0 +1,55 @@ +CREATE TABLE Classes ( +id INTEGER PRIMARY KEY, +Name varchar(255) NOT NULL DEFAULT '', +Description varchar(255) NOT NULL DEFAULT '', +SortOrder integer NOT NULL DEFAULT 0, +Disabled smallint NOT NULL DEFAULT 0, +Creator integer NOT NULL DEFAULT 0, +Created TIMESTAMP NULL, +LastUpdatedBy integer NOT NULL DEFAULT 0, +LastUpdated TIMESTAMP NULL, +HotList smallint NOT NULL DEFAULT 0 +); + +CREATE TABLE Articles ( +id INTEGER PRIMARY KEY, +Name varchar(255) NOT NULL DEFAULT '', +Summary varchar(255) NOT NULL DEFAULT '', +SortOrder integer NOT NULL DEFAULT 0, +Class integer NOT NULL DEFAULT 0, +Parent integer NOT NULL DEFAULT 0, +URI varchar(255), +Creator integer NOT NULL DEFAULT 0, +Created TIMESTAMP NULL, +LastUpdatedBy integer NOT NULL DEFAULT 0, +LastUpdated TIMESTAMP NULL +); + + +CREATE TABLE Topics ( +id INTEGER PRIMARY KEY, +Parent integer NOT NULL DEFAULT 0, +Name varchar(255) NOT NULL DEFAULT '', +Description varchar(255) NOT NULL DEFAULT '', +ObjectType varchar(64) NOT NULL DEFAULT '', +ObjectId integer NOT NULL +); + + +CREATE TABLE ObjectTopics ( +id INTEGER PRIMARY KEY, +Topic integer NOT NULL, +ObjectType varchar(64) NOT NULL DEFAULT '', +ObjectId integer NOT NULL +); + +CREATE TABLE ObjectClasses ( +id INTEGER PRIMARY KEY, +Class integer NOT NULL, +ObjectType varchar(64) NOT NULL DEFAULT '', +ObjectId integer NOT NULL, +Creator integer NOT NULL DEFAULT 0, +Created TIMESTAMP NULL, +LastUpdatedBy integer NOT NULL DEFAULT 0, +LastUpdated TIMESTAMP NULL +); diff --git a/rt/etc/upgrade/3.9.8/schema.mysql b/rt/etc/upgrade/3.9.8/schema.mysql new file mode 100644 index 000000000..e7ed84de7 --- /dev/null +++ b/rt/etc/upgrade/3.9.8/schema.mysql @@ -0,0 +1,58 @@ +CREATE TABLE Classes ( + id int(11) NOT NULL auto_increment, + Name varchar(255) NOT NULL default '', + Description varchar(255) NOT NULL default '', + SortOrder int(11) NOT NULL default '0', + Disabled int(2) NOT NULL default '0', + Creator int(11) NOT NULL default '0', + Created datetime default NULL, + LastUpdatedBy int(11) NOT NULL default '0', + LastUpdated datetime default NULL, + HotList int(2) NOT NULL default '0', + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE Articles ( + id int(11) NOT NULL auto_increment, + Name varchar(255) NOT NULL default '', + Summary varchar(255) NOT NULL default '', + SortOrder int(11) NOT NULL default '0', + Class int(11) NOT NULL default '0', + Parent int(11) NOT NULL default '0', + URI varchar(255) character set ascii default NULL, + Creator int(11) NOT NULL default '0', + Created datetime default NULL, + LastUpdatedBy int(11) NOT NULL default '0', + LastUpdated datetime default NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE Topics ( + id int(11) NOT NULL auto_increment, + Parent int(11) NOT NULL default '0', + Name varchar(255) NOT NULL default '', + Description varchar(255) NOT NULL default '', + ObjectType varchar(64) character set ascii NOT NULL default '', + ObjectId int(11) NOT NULL default '0', + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE ObjectTopics ( + id int(11) NOT NULL auto_increment, + Topic int(11) NOT NULL default '0', + ObjectType varchar(64) character set ascii NOT NULL default '', + ObjectId int(11) NOT NULL default '0', + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE ObjectClasses ( + id int(11) NOT NULL auto_increment, + Class int(11) NOT NULL default '0', + ObjectType varchar(255) character set ascii NOT NULL default '', + ObjectId int(11) NOT NULL default '0', + Creator int(11) NOT NULL default '0', + Created datetime default NULL, + LastUpdatedBy int(11) NOT NULL default '0', + LastUpdated datetime default NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/rt/etc/upgrade/4.0.0rc2/schema.mysql b/rt/etc/upgrade/4.0.0rc2/schema.mysql new file mode 100644 index 000000000..9431213ec --- /dev/null +++ b/rt/etc/upgrade/4.0.0rc2/schema.mysql @@ -0,0 +1,10 @@ + +DROP TABLE IF EXISTS sessions; + +CREATE TABLE sessions ( + id char(32) NOT NULL, + a_session LONGBLOB, + LastUpdated TIMESTAMP, + PRIMARY KEY (id) +) ENGINE=InnoDB CHARACTER SET ascii; + diff --git a/rt/etc/upgrade/4.0.0rc4/schema.Oracle b/rt/etc/upgrade/4.0.0rc4/schema.Oracle new file mode 100644 index 000000000..0df9d65c2 --- /dev/null +++ b/rt/etc/upgrade/4.0.0rc4/schema.Oracle @@ -0,0 +1 @@ +ALTER TABLE Users MODIFY Password VARCHAR2(256); diff --git a/rt/etc/upgrade/4.0.0rc4/schema.Pg b/rt/etc/upgrade/4.0.0rc4/schema.Pg new file mode 100644 index 000000000..728081041 --- /dev/null +++ b/rt/etc/upgrade/4.0.0rc4/schema.Pg @@ -0,0 +1 @@ +ALTER TABLE Users ALTER Password TYPE varchar(256); diff --git a/rt/etc/upgrade/4.0.0rc4/schema.mysql b/rt/etc/upgrade/4.0.0rc4/schema.mysql new file mode 100644 index 000000000..2f562bd4d --- /dev/null +++ b/rt/etc/upgrade/4.0.0rc4/schema.mysql @@ -0,0 +1 @@ +ALTER TABLE Users MODIFY Password varchar(256); diff --git a/rt/etc/upgrade/4.0.0rc7/content b/rt/etc/upgrade/4.0.0rc7/content new file mode 100644 index 000000000..d0d210b7b --- /dev/null +++ b/rt/etc/upgrade/4.0.0rc7/content @@ -0,0 +1,21 @@ +@Initial = ( + sub { + $RT::Logger->debug("Going to set lifecycle for approvals"); + + my $queue = RT::Queue->new( RT->SystemUser ); + $queue->Load('___Approvals'); + unless ( $queue->id ) { + $RT::Logger->warning("There is no ___Approvals queue in the DB"); + return 1; + } + + return 1 if $queue->Lifecycle->Name eq 'approvals'; + + my ($status, $msg) = $queue->SetLifecycle('approvals'); + unless ( $status ) { + $RT::Logger->error("Couldn't set lifecycle for '___Approvals' queue: $msg"); + return 0; + } + return 1; + }, +); diff --git a/rt/etc/upgrade/4.0.1/acl.Pg b/rt/etc/upgrade/4.0.1/acl.Pg new file mode 100644 index 000000000..6b0e7bb3d --- /dev/null +++ b/rt/etc/upgrade/4.0.1/acl.Pg @@ -0,0 +1,39 @@ + +sub acl { + my $dbh = shift; + + my @acls; + + my @tables = qw ( + classes_id_seq + Classes + articles_id_seq + Articles + topics_id_seq + Topics + objecttopics_id_seq + ObjectTopics + objectclasses_id_seq + ObjectClasses + ); + + my $db_user = RT->Config->Get('DatabaseUser'); + + my $sequence_right + = ( $dbh->{pg_server_version} >= 80200 ) + ? "USAGE, SELECT, UPDATE" + : "SELECT, UPDATE"; + + foreach my $table (@tables) { + # Tables are upper-case, sequences are lowercase + if ( $table =~ /^[a-z]/ ) { + push @acls, "GRANT $sequence_right ON $table TO \"$db_user\";" + } + else { + push @acls, "GRANT SELECT, INSERT, UPDATE, DELETE ON $table TO \"$db_user\";" + } + } + return (@acls); +} + +1; diff --git a/rt/etc/upgrade/4.0.1/content b/rt/etc/upgrade/4.0.1/content new file mode 100644 index 000000000..9b74ff1a8 --- /dev/null +++ b/rt/etc/upgrade/4.0.1/content @@ -0,0 +1,83 @@ +@Initial = ( + sub { + use strict; + $RT::Logger->debug('Removing all delegated rights'); + + my $acl = RT::ACL->new(RT->SystemUser); + my $groupjoin = $acl->NewAlias('Groups'); + $acl->Join( ALIAS1 => 'main', + FIELD1 => 'PrincipalId', + ALIAS2 => $groupjoin, + FIELD2 => 'id' + ); + $acl->Limit( ALIAS => $groupjoin, + FIELD => 'Domain', + OPERATOR => '=', + VALUE => 'Personal', + ); + + while ( my $ace = $acl->Next ) { + my ( $ok, $msg ) = $ace->Delete(); + + if ( !$ok ) { + $RT::Logger->warn( "Unable to delete ACE " . $ace->id . ": " . $msg ); + } + } + + my $groups = RT::Groups->new(RT->SystemUser); + $groups->Limit( FIELD => 'Domain', + OPERATOR => '=', + VALUE => 'Personal' + ); + while ( my $group = $groups->Next ) { + my $members = $group->MembersObj(); + while ( my $member = $members->Next ) { + my ( $ok, $msg ) = $group->DeleteMember( $member->MemberId ); + if ( !$ok ) { + $RT::Logger->warn( "Unable to remove group member " + . $member->id . ": " + . $msg ); + } + } + $group->PrincipalObj->Delete; + $group->RT::Record::Delete(); + } + }, + sub { + use strict; + $RT::Logger->debug('Removing all Delegate and PersonalGroup rights'); + + my $acl = RT::ACL->new(RT->SystemUser); + for my $right (qw/AdminOwnPersonalGroups AdminAllPersonalGroups DelegateRights/) { + $acl->Limit( FIELD => 'RightName', VALUE => $right ); + } + + while ( my $ace = $acl->Next ) { + my ( $ok, $msg ) = $ace->Delete(); + $RT::Logger->debug("Removing ACE ".$ace->id." for right ".$ace->__Value('RightName')); + + if ( !$ok ) { + $RT::Logger->warn( "Unable to delete ACE " . $ace->id . ": " . $msg ); + } + } + }, + sub { + use strict; + $RT::Logger->debug('Removing unimplemented RejectTicket and ModifyTicketStatus rights'); + + my $acl = RT::ACL->new(RT->SystemUser); + for my $right (qw/RejectTicket ModifyTicketStatus/) { + $acl->Limit( FIELD => 'RightName', VALUE => $right ); + } + + while ( my $ace = $acl->Next ) { + my ( $ok, $msg ) = $ace->Delete(); + $RT::Logger->debug("Removing ACE ".$ace->id." for right ".$ace->__Value('RightName')); + + if ( !$ok ) { + $RT::Logger->warn( "Unable to delete ACE " . $ace->id . ": " . $msg ); + } + } + }, +); + diff --git a/rt/etc/upgrade/4.0.3/content b/rt/etc/upgrade/4.0.3/content new file mode 100644 index 000000000..3e06c89d0 --- /dev/null +++ b/rt/etc/upgrade/4.0.3/content @@ -0,0 +1,23 @@ +@ScripConditions = ( + { + + Name => 'On Forward', # loc + Description => 'Whenever a ticket or transaction is forwarded', # loc + ApplicableTransTypes => 'Forward Transaction,Forward Ticket', + ExecModule => 'AnyTransaction', }, + + { + + Name => 'On Forward Ticket', # loc + Description => 'Whenever a ticket is forwarded', # loc + ApplicableTransTypes => 'Forward Ticket', + ExecModule => 'AnyTransaction', }, + + { + + Name => 'On Forward Transaction', # loc + Description => 'Whenever a transaction is forwarded', # loc + ApplicableTransTypes => 'Forward Transaction', + ExecModule => 'AnyTransaction', }, + +); diff --git a/rt/etc/upgrade/4.0.4/content b/rt/etc/upgrade/4.0.4/content new file mode 100644 index 000000000..fdfcb3e27 --- /dev/null +++ b/rt/etc/upgrade/4.0.4/content @@ -0,0 +1,16 @@ +@Initial = ( + sub { + use strict; + my $templates = RT::Templates->new(RT->SystemUser); + $templates->Limit( + FIELD => 'Type', + OPERATOR => 'IS', + VALUE => 'NULL', + ); + while (my $template = $templates->Next) { + my ($status, $msg) = $template->SetType('Perl'); + $RT::Logger->warning( "Couldn't change Type of Template #" . $template->Id . ": $msg" ) unless $status; + } + }, +); + diff --git a/rt/etc/upgrade/4.0.6/content b/rt/etc/upgrade/4.0.6/content new file mode 100644 index 000000000..dc1a00951 --- /dev/null +++ b/rt/etc/upgrade/4.0.6/content @@ -0,0 +1,17 @@ +@Initial = ( + sub { + my $txns = RT::Transactions->new( $RT::SystemUser ); + $txns->Limit( + FIELD => "ObjectType", + VALUE => "RT::User", + ); + $txns->Limit( + FIELD => "Field", + VALUE => "Password", + ); + while (my $txn = $txns->Next) { + $txn->__Set( Field => $_, Value => '********' ) + for qw/OldValue NewValue/; + } + }, +); diff --git a/rt/etc/upgrade/4.0.6/schema.mysql b/rt/etc/upgrade/4.0.6/schema.mysql new file mode 100644 index 000000000..ab32007ae --- /dev/null +++ b/rt/etc/upgrade/4.0.6/schema.mysql @@ -0,0 +1 @@ +ALTER TABLE Attributes MODIFY Content LONGBLOB; diff --git a/rt/etc/upgrade/generate-rtaddressregexp.in b/rt/etc/upgrade/generate-rtaddressregexp.in index a0787ca15..68259ff94 100644 --- a/rt/etc/upgrade/generate-rtaddressregexp.in +++ b/rt/etc/upgrade/generate-rtaddressregexp.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC # <sales@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -65,23 +65,45 @@ if (my $re = RT->Config->Get('RTAddressRegexp')) { } use RT::Queues; -my $queues = RT::Queues->new( $RT::SystemUser ); +my $queues = RT::Queues->new( RT->SystemUser ); $queues->UnLimit; -$queues->RowsPerPage(100); -my @addresses = (RT->Config->Get('CorrespondAddress'), RT->Config->Get('CommentAddress')); +my %merged; +merge(\%merged, RT->Config->Get('CorrespondAddress'), RT->Config->Get('CommentAddress')); while ( my $queue = $queues->Next ) { - push @addresses, $queue->CorrespondAddress, $queue->CommentAddress; + merge(\%merged, $queue->CorrespondAddress, $queue->CommentAddress); } -my %seen; -my $re = join '|', map "\Q$_\E", - grep defined && length && !$seen{ lc $_ }++, - @addresses; +my @domains; +for my $domain (sort keys %merged) { + my @addresses; + for my $base (sort keys %{$merged{$domain}}) { + my @subbits = keys(%{$merged{$domain}{$base}}); + if (@subbits > 1) { + push @addresses, "\Q$base\E(?:".join("|",@subbits).")"; + } else { + push @addresses, "\Q$base\E$subbits[0]"; + } + } + if (@addresses > 1) { + push @domains, "(?:".join("|", @addresses).")\Q\@".$domain."\E"; + } else { + push @domains, "$addresses[0]\Q\@$domain\E"; + } +} +my $re = join "|", @domains; print <<ENDDESCRIPTION; You can add the following to RT_SiteConfig.pm, but may want to collapse it into a more efficient regexp. Keep in mind that this only contains the email addresses that RT knows about, you should also examine your mail system for aliases that reach RT but which RT doesn't know about. ENDDESCRIPTION -print "Set(\$RTAddressRegexp,'^(?:${re})\$');\n"; +print "Set(\$RTAddressRegexp,qr{^(?:${re})\$}i);\n"; + +sub merge { + my $merged = shift; + for my $address (grep {defined and length} @_) { + $address =~ /^\s*(.*?)(-comments?)?\@(.*?)\s*$/; + $merged->{lc $3}{$1}{$2||''}++; + } +} diff --git a/rt/etc/upgrade/generate-rtaddressregexp b/rt/etc/upgrade/sanity-check-stylesheets.pl index adffab9cd..eff469fd6 100755..100644 --- a/rt/etc/upgrade/generate-rtaddressregexp +++ b/rt/etc/upgrade/sanity-check-stylesheets.pl @@ -1,9 +1,8 @@ -#!/usr/bin/perl # BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC # <sales@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -49,9 +48,6 @@ use strict; use warnings; -use lib "local/lib"; -use lib "lib"; - use RT; RT::LoadConfig(); RT->Config->Set('LogToScreen' => 'debug'); @@ -59,29 +55,33 @@ RT::Init(); $| = 1; -if (my $re = RT->Config->Get('RTAddressRegexp')) { - print "No need to use this script, you already have RTAddressRegexp set to $re\n"; - exit; -} +use RT::Users; +my $users = RT::Users->new( $RT::SystemUser ); +$users->UnLimit(); + +my @comp_roots = RT::Interface::Web->ComponentRoots; +my %comp_root_check_cache; +sub stylesheet_exists { + my $stylesheet = shift; -use RT::Queues; -my $queues = RT::Queues->new( $RT::SystemUser ); -$queues->UnLimit; -$queues->RowsPerPage(100); + return $comp_root_check_cache{$stylesheet} + if exists $comp_root_check_cache{$stylesheet}; -my @addresses = (RT->Config->Get('CorrespondAddress'), RT->Config->Get('CommentAddress')); -while ( my $queue = $queues->Next ) { - push @addresses, $queue->CorrespondAddress, $queue->CommentAddress; + for my $comp_root (@comp_roots) { + return ++$comp_root_check_cache{$stylesheet} + if -d "$comp_root/NoAuth/css/$stylesheet"; + } + + return $comp_root_check_cache{$stylesheet} = 0; } -my %seen; -my $re = join '|', map "\Q$_\E", - grep defined && length && !$seen{ lc $_ }++, - @addresses; +my $system_stylesheet = RT->Config->Get('WebDefaultStylesheet'); -print <<ENDDESCRIPTION; -You can add the following to RT_SiteConfig.pm, but may want to collapse it into a more efficient regexp. -Keep in mind that this only contains the email addresses that RT knows about, you should also examine -your mail system for aliases that reach RT but which RT doesn't know about. -ENDDESCRIPTION -print "Set(\$RTAddressRegexp,'^(?:${re})\$');\n"; +while (my $u = $users->Next) { + my $stylesheet = RT->Config->Get('WebDefaultStylesheet', $u); + unless (stylesheet_exists $stylesheet) { + my $prefs = $u->Preferences($RT::System); + $prefs->{WebDefaultStylesheet} = $system_stylesheet; + $u->SetPreferences($RT::System, $prefs); + } +} diff --git a/rt/etc/upgrade/shrink_cgm_table.pl b/rt/etc/upgrade/shrink_cgm_table.pl index 0ce3d287b..cf39d04d7 100644 --- a/rt/etc/upgrade/shrink_cgm_table.pl +++ b/rt/etc/upgrade/shrink_cgm_table.pl @@ -1,9 +1,9 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC # <sales@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -56,7 +56,7 @@ RT->Config->Set('LogToScreen' => 'debug'); RT::Init(); use RT::CachedGroupMembers; -my $cgms = RT::CachedGroupMembers->new( $RT::SystemUser ); +my $cgms = RT::CachedGroupMembers->new( RT->SystemUser ); $cgms->Limit( FIELD => 'id', OPERATOR => '!=', diff --git a/rt/etc/upgrade/shrink_transactions_table.pl b/rt/etc/upgrade/shrink_transactions_table.pl index b4f2e1907..c23d09188 100644 --- a/rt/etc/upgrade/shrink_transactions_table.pl +++ b/rt/etc/upgrade/shrink_transactions_table.pl @@ -1,9 +1,9 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC # <sales@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -56,7 +56,7 @@ RT->Config->Set('LogToScreen' => 'debug'); RT::Init(); use RT::Transactions; -my $txns = RT::Transactions->new( $RT::SystemUser ); +my $txns = RT::Transactions->new( RT->SystemUser ); $txns->Limit( FIELD => 'ObjectType', OPERATOR => '=', diff --git a/rt/etc/upgrade/split-out-cf-categories b/rt/etc/upgrade/split-out-cf-categories deleted file mode 100755 index 23169f43c..000000000 --- a/rt/etc/upgrade/split-out-cf-categories +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/perl -# BEGIN BPS TAGGED BLOCK {{{ -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC -# <sales@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -# -# -# CONTRIBUTION SUBMISSION POLICY: -# -# (The following paragraph is not intended to limit the rights granted -# to you to modify and distribute this software under the terms of -# the GNU General Public License and is only of importance to you if -# you choose to contribute your changes and enhancements to the -# community by submitting them to Best Practical Solutions, LLC.) -# -# By intentionally submitting any modifications, corrections or -# derivatives to this work, or any other work intended for use with -# Request Tracker, to Best Practical Solutions, LLC, you confirm that -# you are the copyright holder for those contributions and you grant -# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -# royalty-free, perpetual, license to use, copy, create derivative -# works based on those contributions, and sublicense and distribute -# those contributions and any derivatives thereof. -# -# END BPS TAGGED BLOCK }}} -use strict; -use warnings; - -use lib "local/lib"; -use lib "lib"; - -use RT; -RT::LoadConfig(); -RT->Config->Set('LogToScreen' => 'debug'); -RT::Init(); - -$| = 1; - -$RT::Handle->BeginTransaction(); - -use RT::CustomFields; -my $CFs = RT::CustomFields->new( $RT::SystemUser ); -$CFs->UnLimit; -$CFs->Limit( FIELD => 'Type', VALUE => 'Select' ); - -my $seen; -while (my $cf = $CFs->Next ) { - next if $cf->BasedOnObj->Id; - my @categories; - my %mapping; - my $values = $cf->Values; - while (my $value = $values->Next) { - next unless defined $value->Category and length $value->Category; - push @categories, $value->Category unless grep {$_ eq $value->Category} @categories; - $mapping{$value->Name} = $value->Category; - } - next unless @categories; - - $seen++; - print "Found CF '@{[$cf->Name]}' with categories:\n"; - print " $_\n" for @categories; - - print "Split this CF's categories into a hierarchical custom field (Y/n)? "; - my $dothis = <>; - next if $dothis =~ /n/i; - - print "Enter name of CF to create as category ('@{[$cf->Name]} category'): "; - my $newname = <>; - chomp $newname; - $newname = $cf->Name . " category" unless length $newname; - - # bump the CF's sort oder up by one - $cf->SetSortOrder( ($cf->SortOrder || 0) + 1 ); - - # ..and add a new CF before it - my $new = RT::CustomField->new( $RT::SystemUser ); - my ($id, $msg) = $new->Create( - Name => $newname, - Type => 'Select', - MaxValues => 1, - LookupType => $cf->LookupType, - SortOrder => $cf->SortOrder - 1, - ); - die "Can't create custom field '$newname': $msg" unless $id; - - # Set the CF to be based on what we just made - $cf->SetBasedOn( $new->Id ); - - # Apply it to all of the same things - { - my $ocfs = RT::ObjectCustomFields->new( $RT::SystemUser ); - $ocfs->LimitToCustomField( $cf->Id ); - while (my $ocf = $ocfs->Next) { - my $newocf = RT::ObjectCustomField->new( $RT::SystemUser ); - ($id, $msg) = $newocf->Create( - SortOrder => $ocf->SortOrder, - CustomField => $new->Id, - ObjectId => $ocf->ObjectId, - ); - die "Can't create ObjectCustomField: $msg" unless $id; - } - } - - # Copy over all of the rights - { - my $acl = RT::ACL->new( $RT::SystemUser ); - $acl->LimitToObject( $cf ); - while (my $ace = $acl->Next) { - my $newace = RT::ACE->new( $RT::SystemUser ); - ($id, $msg) = $newace->Create( - PrincipalId => $ace->PrincipalId, - PrincipalType => $ace->PrincipalType, - RightName => $ace->RightName, - Object => $new, - ); - die "Can't assign rights: $msg" unless $id; - } - } - - # Add values for all of the categories - for my $i (0..$#categories) { - ($id, $msg) = $new->AddValue( - Name => $categories[$i], - SortOrder => $i + 1, - ); - die "Can't create custom field value: $msg" unless $id; - } - - # Grovel through all ObjectCustomFieldValues, and add the - # appropriate category - { - my $ocfvs = RT::ObjectCustomFieldValues->new( $RT::SystemUser ); - $ocfvs->LimitToCustomField( $cf->Id ); - while (my $ocfv = $ocfvs->Next) { - next unless exists $mapping{$ocfv->Content}; - my $newocfv = RT::ObjectCustomFieldValue->new( $RT::SystemUser ); - ($id, $msg) = $newocfv->Create( - CustomField => $new->Id, - ObjectType => $ocfv->ObjectType, - ObjectId => $ocfv->ObjectId, - Content => $mapping{$ocfv->Content}, - ); - } - } -} - -$RT::Handle->Commit; -print "No custom fields with categories found\n" unless $seen; diff --git a/rt/etc/upgrade/split-out-cf-categories.in b/rt/etc/upgrade/split-out-cf-categories.in index 9d157b4f5..28ea309de 100644 --- a/rt/etc/upgrade/split-out-cf-categories.in +++ b/rt/etc/upgrade/split-out-cf-categories.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC # <sales@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -62,7 +62,7 @@ $| = 1; $RT::Handle->BeginTransaction(); use RT::CustomFields; -my $CFs = RT::CustomFields->new( $RT::SystemUser ); +my $CFs = RT::CustomFields->new( RT->SystemUser ); $CFs->UnLimit; $CFs->Limit( FIELD => 'Type', VALUE => 'Select' ); @@ -96,7 +96,7 @@ while (my $cf = $CFs->Next ) { $cf->SetSortOrder( ($cf->SortOrder || 0) + 1 ); # ..and add a new CF before it - my $new = RT::CustomField->new( $RT::SystemUser ); + my $new = RT::CustomField->new( RT->SystemUser ); my ($id, $msg) = $new->Create( Name => $newname, Type => 'Select', @@ -111,10 +111,10 @@ while (my $cf = $CFs->Next ) { # Apply it to all of the same things { - my $ocfs = RT::ObjectCustomFields->new( $RT::SystemUser ); + my $ocfs = RT::ObjectCustomFields->new( RT->SystemUser ); $ocfs->LimitToCustomField( $cf->Id ); while (my $ocf = $ocfs->Next) { - my $newocf = RT::ObjectCustomField->new( $RT::SystemUser ); + my $newocf = RT::ObjectCustomField->new( RT->SystemUser ); ($id, $msg) = $newocf->Create( SortOrder => $ocf->SortOrder, CustomField => $new->Id, @@ -126,10 +126,10 @@ while (my $cf = $CFs->Next ) { # Copy over all of the rights { - my $acl = RT::ACL->new( $RT::SystemUser ); + my $acl = RT::ACL->new( RT->SystemUser ); $acl->LimitToObject( $cf ); while (my $ace = $acl->Next) { - my $newace = RT::ACE->new( $RT::SystemUser ); + my $newace = RT::ACE->new( RT->SystemUser ); ($id, $msg) = $newace->Create( PrincipalId => $ace->PrincipalId, PrincipalType => $ace->PrincipalType, @@ -152,11 +152,11 @@ while (my $cf = $CFs->Next ) { # Grovel through all ObjectCustomFieldValues, and add the # appropriate category { - my $ocfvs = RT::ObjectCustomFieldValues->new( $RT::SystemUser ); + my $ocfvs = RT::ObjectCustomFieldValues->new( RT->SystemUser ); $ocfvs->LimitToCustomField( $cf->Id ); while (my $ocfv = $ocfvs->Next) { next unless exists $mapping{$ocfv->Content}; - my $newocfv = RT::ObjectCustomFieldValue->new( $RT::SystemUser ); + my $newocfv = RT::ObjectCustomFieldValue->new( RT->SystemUser ); ($id, $msg) = $newocfv->Create( CustomField => $new->Id, ObjectType => $ocfv->ObjectType, diff --git a/rt/etc/upgrade/upgrade-articles b/rt/etc/upgrade/upgrade-articles new file mode 100755 index 000000000..eef00aa67 --- /dev/null +++ b/rt/etc/upgrade/upgrade-articles @@ -0,0 +1,264 @@ +#!/usr/bin/perl +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +# <sales@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +use strict; +use warnings; + +use lib "/opt/rt3/local/lib"; +use lib "/opt/rt3/lib"; + +use RT; +RT::LoadConfig(); +RT->Config->Set('LogToScreen' => 'debug'); +RT::Init(); + +$| = 1; + +my $db_name = RT->Config->Get('DatabaseName'); +my $db_type = RT->Config->Get('DatabaseType'); + +my $dbh = $RT::Handle->dbh; + +my $sth = $dbh->table_info( '', undef, undef, "'TABLE'"); +my $found_fm_tables; +while ( my $table = $sth->fetchrow_hashref ) { + my $name = $table->{TABLE_NAME} || $table->{'table_name'}; # Oracle's table_info affected by NAME_lc + next unless $name =~ /^fm_/i; + $found_fm_tables->{lc $name}++; +} + +unless ( $found_fm_tables->{fm_topics} && $found_fm_tables->{fm_objecttopics} ) { + warn "Couldn't find topics tables, it appears you have RTFM 2.0 or earlier."; + warn "This script cannot yet upgrade RTFM versions which are that old"; + exit; +} + +{ # port over Articles + my @columns = qw(id Name Summary SortOrder Class Parent URI Creator Created LastUpdatedBy LastUpdated); + copy_tables('FM_Articles','Articles',\@columns); + +} + + +{ # port over Classes + my @columns = qw(id Name Description SortOrder Disabled Creator Created LastUpdatedBy LastUpdated); + if ( grep lc($_) eq 'hotlist', $RT::Handle->Fields('FM_Classes') ) { + push @columns, 'HotList'; + } + copy_tables('FM_Classes','Classes',\@columns); +} + +{ # port over Topics + my @columns = qw(id Parent Name Description ObjectType ObjectId); + copy_tables('FM_Topics','Topics',\@columns); +} + +{ # port over ObjectTopics + my @columns = qw(id Topic ObjectType ObjectId); + copy_tables('FM_ObjectTopics','ObjectTopics',\@columns); +} + +sub copy_tables { + my ($source, $dest, $columns) = @_; + my $column_list = join(', ',@$columns); + my $sql; + # SQLite: http://www.sqlite.org/lang_insert.html + if ( $db_type eq 'mysql' || $db_type eq 'SQLite' ) { + $sql = "insert into $dest ($column_list) select $column_list from $source"; + } + # Oracle: http://www.adp-gmbh.ch/ora/sql/insert/select_and_subquery.html + elsif ( $db_type eq 'Pg' || $db_type eq 'Oracle' ) { + $sql = "insert into $dest ($column_list) (select $column_list from $source)"; + } + $RT::Logger->debug($sql); + $dbh->do($sql); +} + +{ # create ObjectClasses + # this logic will need updating when folks have an FM_ObjectClasses table + use RT::Classes; + use RT::ObjectClass; + + my $classes = RT::Classes->new(RT->SystemUser); + $classes->UnLimit; + while ( my $class = $classes->Next ) { + my $objectclass = RT::ObjectClass->new(RT->SystemUser); + my ($ret, $msg ) = $objectclass->Create( Class => $class->Id, ObjectType => 'RT::System', ObjectId => 0 ); + if ($ret) { + warn("Applied Class '".$class->Name."' globally"); + } else { + warn("Couldn't create linkage for Class ".$class->Name.": $msg"); + } + } +} + +{ # update ACLs + use RT::ACL; + my $acl = RT::ACL->new(RT->SystemUser); + $acl->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Class' ); + $acl->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::System' ); + while ( my $ace = $acl->Next ) { + if ( $ace->__Value('ObjectType') eq 'RT::FM::Class' ) { + my ($ret, $msg ) = $ace->__Set( Field => 'ObjectType', Value => 'RT::Class'); + warn "Fixing ACL ".$ace->Id." to refer to RT::Class: $msg"; + } elsif ( $ace->__Value('ObjectType') eq 'RT::FM::System' ) { + my ($ret, $msg) = $ace->__Set(Field => 'ObjectType', Value => 'RT::System'); + warn "Fixing ACL ".$ace->Id." to refer to RT::System: $msg"; + } + } + + +} + +{ # update CustomFields + use RT::CustomFields; + my $cfs = RT::CustomFields->new(RT->SystemUser); + $cfs->Limit( FIELD => 'LookupType', VALUE => 'RT::FM::Class-RT::FM::Article' ); + while ( my $cf = $cfs->Next ) { + my ($ret, $msg) = $cf->__Set( Field => 'LookupType', Value => 'RT::Class-RT::Article' ); + warn "Update Custom Field LookupType for CF.".$cf->Id." $msg"; + } +} + +{ # update ObjectCustomFieldValues + use RT::ObjectCustomFieldValues; + my $ocfvs = RT::ObjectCustomFieldValues->new(RT->System); + $ocfvs->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Article' ); + while ( my $ocfv = $ocfvs->Next ) { + my ($ret, $msg) = $ocfv->__Set( Field => 'ObjectType', Value => 'RT::Article' ); + warn "Updated CF ".$ocfv->__Value('CustomField')." Value for Article ".$ocfv->__Value('ObjectId'); + } + +} + +{ # update Topics + use RT::Topics; + my $topics = RT::Topics->new(RT->SystemUser); + $topics->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Class' ); + $topics->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::System' ); + while ( my $topic = $topics->Next ) { + if ( $topic->__Value('ObjectType') eq 'RT::FM::Class' ) { + my ($ret, $msg ) = $topic->__Set( Field => 'ObjectType', Value => 'RT::Class'); + warn "Fixing Topic ".$topic->Id." to refer to RT::Class: $msg"; + } elsif ( $topic->__Value('ObjectType') eq 'RT::FM::System' ) { + my ($ret, $msg) = $topic->__Set(Field => 'ObjectType', Value => 'RT::System'); + warn "Fixing Topic ".$topic->Id." to refer to RT::System: $msg"; + } + } +} + +{ # update ObjectTopics + use RT::ObjectTopics; + my $otopics = RT::ObjectTopics->new(RT->SystemUser); + $otopics->UnLimit; + while ( my $otopic = $otopics->Next ) { + if ( $otopic->ObjectType eq 'RT::FM::Article' ) { + my ($ret, $msg) = $otopic->SetObjectType('RT::Article'); + warn "Fixing Topic ".$otopic->Topic." to apply to article: $msg"; + } + } +} + +{ # update Links + use RT::Links; + my $links = RT::Links->new(RT->SystemUser); + $links->Limit(FIELD => 'Base', VALUE => 'rtfm', OPERATOR => 'LIKE', SUBCLAUSE => 'stopanding', ENTRYAGGREGATOR => 'OR'); + $links->Limit(FIELD => 'Target', VALUE => 'rtfm', OPERATOR => 'LIKE', SUBCLAUSE => 'stopanding', ENTRYAGGREGATOR => 'OR' ); + while ( my $link = $links->Next ) { + my $base = $link->__Value('Base'); + my $target = $link->__Value('Target'); + if ( $base =~ s/rtfm/article/i ) { + my ($ret, $msg) = $link->__Set( Field => 'Base', Value => $base ); + warn "Updating base to $base: $msg for link ".$link->id; + } + if ( $target =~ s/rtfm/article/i ) { + my ($ret, $msg) = $link->__Set( Field => 'Target', Value => $target ); + warn "Updating target to $target: $msg for link ".$link->id; + } + + } +} + +{ # update Transactions + # we only keep article transactions at this point + no warnings 'once'; + use RT::Transactions; + # Next calls Type to check readability and Type calls _Accessible + # which called CurrentUserCanSee which calls Object which tries to instantiate + # an RT::FM::Article. Rather than a shim RT::FM::Article class, I'm just avoiding + # the ACL check since we're running around as the superuser. + local *RT::Transaction::Type = sub { shift->__Value('Type') }; + my $transactions = RT::Transactions->new(RT->SystemUser); + $transactions->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Article' ); + while ( my $t = $transactions->Next ) { + my ($ret, $msg) = $t->__Set( Field => 'ObjectType', Value => 'RT::Article' ); + warn "Updated Transaction ".$t->Id." to point to RT::Article"; + } + + # we also need to change links that point to articles + $transactions = RT::Transactions->new(RT->SystemUser); + $transactions->Limit( FIELD => 'Type', VALUE => 'AddLink' ); + $transactions->Limit( FIELD => 'NewValue', VALUE => 'rtfm', OPERATOR => 'LIKE' ); + while ( my $t = $transactions->Next ) { + my $value = $t->__Value('NewValue'); + $value =~ s/rtfm/article/; + my ($ret, $msg) = $t->__Set( Field => 'NewValue', Value => $value ); + warn "Updated Transaction ".$t->Id." to link to $value"; + } +} + +{ # update Attributes + # these are all things we should make real columns someday + use RT::Attributes; + my $attributes = RT::Attributes->new(RT->SystemUser); + $attributes->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Class' ); + while ( my $a = $attributes->Next ) { + my ($ret,$msg) = $a->__Set( Field => 'ObjectType', Value => 'RT::Class' ); + warn "Updating Attribute ".$a->Name." to point to RT::Class"; + } +} diff --git a/rt/etc/upgrade/upgrade-articles.in b/rt/etc/upgrade/upgrade-articles.in new file mode 100644 index 000000000..b0f13d674 --- /dev/null +++ b/rt/etc/upgrade/upgrade-articles.in @@ -0,0 +1,264 @@ +#!@PERL@ +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +# <sales@bestpractical.com> +# +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: +# +# This work is made available to you under the terms of Version 2 of +# the GNU General Public License. A copy of that license should have +# been provided with this software, but in any event can be snarfed +# from www.gnu.org. +# +# This work is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (The following paragraph is not intended to limit the rights granted +# to you to modify and distribute this software under the terms of +# the GNU General Public License and is only of importance to you if +# you choose to contribute your changes and enhancements to the +# community by submitting them to Best Practical Solutions, LLC.) +# +# By intentionally submitting any modifications, corrections or +# derivatives to this work, or any other work intended for use with +# Request Tracker, to Best Practical Solutions, LLC, you confirm that +# you are the copyright holder for those contributions and you grant +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +# royalty-free, perpetual, license to use, copy, create derivative +# works based on those contributions, and sublicense and distribute +# those contributions and any derivatives thereof. +# +# END BPS TAGGED BLOCK }}} +use strict; +use warnings; + +use lib "@LOCAL_LIB_PATH@"; +use lib "@RT_LIB_PATH@"; + +use RT; +RT::LoadConfig(); +RT->Config->Set('LogToScreen' => 'debug'); +RT::Init(); + +$| = 1; + +my $db_name = RT->Config->Get('DatabaseName'); +my $db_type = RT->Config->Get('DatabaseType'); + +my $dbh = $RT::Handle->dbh; + +my $sth = $dbh->table_info( '', undef, undef, "'TABLE'"); +my $found_fm_tables; +while ( my $table = $sth->fetchrow_hashref ) { + my $name = $table->{TABLE_NAME} || $table->{'table_name'}; # Oracle's table_info affected by NAME_lc + next unless $name =~ /^fm_/i; + $found_fm_tables->{lc $name}++; +} + +unless ( $found_fm_tables->{fm_topics} && $found_fm_tables->{fm_objecttopics} ) { + warn "Couldn't find topics tables, it appears you have RTFM 2.0 or earlier."; + warn "This script cannot yet upgrade RTFM versions which are that old"; + exit; +} + +{ # port over Articles + my @columns = qw(id Name Summary SortOrder Class Parent URI Creator Created LastUpdatedBy LastUpdated); + copy_tables('FM_Articles','Articles',\@columns); + +} + + +{ # port over Classes + my @columns = qw(id Name Description SortOrder Disabled Creator Created LastUpdatedBy LastUpdated); + if ( grep lc($_) eq 'hotlist', $RT::Handle->Fields('FM_Classes') ) { + push @columns, 'HotList'; + } + copy_tables('FM_Classes','Classes',\@columns); +} + +{ # port over Topics + my @columns = qw(id Parent Name Description ObjectType ObjectId); + copy_tables('FM_Topics','Topics',\@columns); +} + +{ # port over ObjectTopics + my @columns = qw(id Topic ObjectType ObjectId); + copy_tables('FM_ObjectTopics','ObjectTopics',\@columns); +} + +sub copy_tables { + my ($source, $dest, $columns) = @_; + my $column_list = join(', ',@$columns); + my $sql; + # SQLite: http://www.sqlite.org/lang_insert.html + if ( $db_type eq 'mysql' || $db_type eq 'SQLite' ) { + $sql = "insert into $dest ($column_list) select $column_list from $source"; + } + # Oracle: http://www.adp-gmbh.ch/ora/sql/insert/select_and_subquery.html + elsif ( $db_type eq 'Pg' || $db_type eq 'Oracle' ) { + $sql = "insert into $dest ($column_list) (select $column_list from $source)"; + } + $RT::Logger->debug($sql); + $dbh->do($sql); +} + +{ # create ObjectClasses + # this logic will need updating when folks have an FM_ObjectClasses table + use RT::Classes; + use RT::ObjectClass; + + my $classes = RT::Classes->new(RT->SystemUser); + $classes->UnLimit; + while ( my $class = $classes->Next ) { + my $objectclass = RT::ObjectClass->new(RT->SystemUser); + my ($ret, $msg ) = $objectclass->Create( Class => $class->Id, ObjectType => 'RT::System', ObjectId => 0 ); + if ($ret) { + warn("Applied Class '".$class->Name."' globally"); + } else { + warn("Couldn't create linkage for Class ".$class->Name.": $msg"); + } + } +} + +{ # update ACLs + use RT::ACL; + my $acl = RT::ACL->new(RT->SystemUser); + $acl->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Class' ); + $acl->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::System' ); + while ( my $ace = $acl->Next ) { + if ( $ace->__Value('ObjectType') eq 'RT::FM::Class' ) { + my ($ret, $msg ) = $ace->__Set( Field => 'ObjectType', Value => 'RT::Class'); + warn "Fixing ACL ".$ace->Id." to refer to RT::Class: $msg"; + } elsif ( $ace->__Value('ObjectType') eq 'RT::FM::System' ) { + my ($ret, $msg) = $ace->__Set(Field => 'ObjectType', Value => 'RT::System'); + warn "Fixing ACL ".$ace->Id." to refer to RT::System: $msg"; + } + } + + +} + +{ # update CustomFields + use RT::CustomFields; + my $cfs = RT::CustomFields->new(RT->SystemUser); + $cfs->Limit( FIELD => 'LookupType', VALUE => 'RT::FM::Class-RT::FM::Article' ); + while ( my $cf = $cfs->Next ) { + my ($ret, $msg) = $cf->__Set( Field => 'LookupType', Value => 'RT::Class-RT::Article' ); + warn "Update Custom Field LookupType for CF.".$cf->Id." $msg"; + } +} + +{ # update ObjectCustomFieldValues + use RT::ObjectCustomFieldValues; + my $ocfvs = RT::ObjectCustomFieldValues->new(RT->System); + $ocfvs->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Article' ); + while ( my $ocfv = $ocfvs->Next ) { + my ($ret, $msg) = $ocfv->__Set( Field => 'ObjectType', Value => 'RT::Article' ); + warn "Updated CF ".$ocfv->__Value('CustomField')." Value for Article ".$ocfv->__Value('ObjectId'); + } + +} + +{ # update Topics + use RT::Topics; + my $topics = RT::Topics->new(RT->SystemUser); + $topics->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Class' ); + $topics->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::System' ); + while ( my $topic = $topics->Next ) { + if ( $topic->__Value('ObjectType') eq 'RT::FM::Class' ) { + my ($ret, $msg ) = $topic->__Set( Field => 'ObjectType', Value => 'RT::Class'); + warn "Fixing Topic ".$topic->Id." to refer to RT::Class: $msg"; + } elsif ( $topic->__Value('ObjectType') eq 'RT::FM::System' ) { + my ($ret, $msg) = $topic->__Set(Field => 'ObjectType', Value => 'RT::System'); + warn "Fixing Topic ".$topic->Id." to refer to RT::System: $msg"; + } + } +} + +{ # update ObjectTopics + use RT::ObjectTopics; + my $otopics = RT::ObjectTopics->new(RT->SystemUser); + $otopics->UnLimit; + while ( my $otopic = $otopics->Next ) { + if ( $otopic->ObjectType eq 'RT::FM::Article' ) { + my ($ret, $msg) = $otopic->SetObjectType('RT::Article'); + warn "Fixing Topic ".$otopic->Topic." to apply to article: $msg"; + } + } +} + +{ # update Links + use RT::Links; + my $links = RT::Links->new(RT->SystemUser); + $links->Limit(FIELD => 'Base', VALUE => 'rtfm', OPERATOR => 'LIKE', SUBCLAUSE => 'stopanding', ENTRYAGGREGATOR => 'OR'); + $links->Limit(FIELD => 'Target', VALUE => 'rtfm', OPERATOR => 'LIKE', SUBCLAUSE => 'stopanding', ENTRYAGGREGATOR => 'OR' ); + while ( my $link = $links->Next ) { + my $base = $link->__Value('Base'); + my $target = $link->__Value('Target'); + if ( $base =~ s/rtfm/article/i ) { + my ($ret, $msg) = $link->__Set( Field => 'Base', Value => $base ); + warn "Updating base to $base: $msg for link ".$link->id; + } + if ( $target =~ s/rtfm/article/i ) { + my ($ret, $msg) = $link->__Set( Field => 'Target', Value => $target ); + warn "Updating target to $target: $msg for link ".$link->id; + } + + } +} + +{ # update Transactions + # we only keep article transactions at this point + no warnings 'once'; + use RT::Transactions; + # Next calls Type to check readability and Type calls _Accessible + # which called CurrentUserCanSee which calls Object which tries to instantiate + # an RT::FM::Article. Rather than a shim RT::FM::Article class, I'm just avoiding + # the ACL check since we're running around as the superuser. + local *RT::Transaction::Type = sub { shift->__Value('Type') }; + my $transactions = RT::Transactions->new(RT->SystemUser); + $transactions->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Article' ); + while ( my $t = $transactions->Next ) { + my ($ret, $msg) = $t->__Set( Field => 'ObjectType', Value => 'RT::Article' ); + warn "Updated Transaction ".$t->Id." to point to RT::Article"; + } + + # we also need to change links that point to articles + $transactions = RT::Transactions->new(RT->SystemUser); + $transactions->Limit( FIELD => 'Type', VALUE => 'AddLink' ); + $transactions->Limit( FIELD => 'NewValue', VALUE => 'rtfm', OPERATOR => 'LIKE' ); + while ( my $t = $transactions->Next ) { + my $value = $t->__Value('NewValue'); + $value =~ s/rtfm/article/; + my ($ret, $msg) = $t->__Set( Field => 'NewValue', Value => $value ); + warn "Updated Transaction ".$t->Id." to link to $value"; + } +} + +{ # update Attributes + # these are all things we should make real columns someday + use RT::Attributes; + my $attributes = RT::Attributes->new(RT->SystemUser); + $attributes->Limit( FIELD => 'ObjectType', VALUE => 'RT::FM::Class' ); + while ( my $a = $attributes->Next ) { + my ($ret,$msg) = $a->__Set( Field => 'ObjectType', Value => 'RT::Class' ); + warn "Updating Attribute ".$a->Name." to point to RT::Class"; + } +} diff --git a/rt/etc/upgrade/upgrade-mysql-schema.pl b/rt/etc/upgrade/upgrade-mysql-schema.pl index 4a104b60f..310a6a826 100755 --- a/rt/etc/upgrade/upgrade-mysql-schema.pl +++ b/rt/etc/upgrade/upgrade-mysql-schema.pl @@ -1,9 +1,9 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # BEGIN BPS TAGGED BLOCK {{{ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC # <sales@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -104,6 +104,10 @@ my @tables = qw( Tickets Transactions Users + FM_Articles + FM_Classes + FM_ObjectTopics + FM_Topics ); my %charset = ( @@ -139,6 +143,23 @@ my %charset = ( Name => 'utf8', Description => 'utf8', }, + FM_Articles => { + Name => 'utf8', + Summary => 'utf8', + URI => 'ascii', + }, + FM_Classes => { + Name => 'utf8', + Description => 'utf8', + }, + FM_ObjectTopics => { + ObjectType => 'ascii', + }, + FM_Topics => { + Name => 'utf8', + Description => 'utf8', + ObjectType => 'ascii', + }, Groups => { Name => 'utf8', Description => 'utf8', @@ -265,7 +286,7 @@ $db_name =~ s/:.*$//; my $version = ($dbh->selectrow_array("show variables like 'version'"))[1]; ($version) = $version =~ /^(\d+\.\d+)/; -push @sql_commands, qq{ALTER DATABASE $db_name DEFAULT CHARACTER SET utf8}; +push @sql_commands, qq{ALTER DATABASE `$db_name` DEFAULT CHARACTER SET utf8}; convert_table($_) foreach @tables; print join "\n", map(/;$/? $_ : "$_;", @sql_commands), ""; @@ -285,7 +306,9 @@ sub convert_table { my $sth = $dbh->column_info( undef, $db_name, $table, undef ); $sth->execute; - while ( my $info = $sth->fetchrow_hashref ) { + my $columns = $sth->fetchall_arrayref({}); + return unless @$columns; + foreach my $info (@$columns) { convert_column(%$info); } for my $conversiontype (qw(char_to_binary binary_to_char)) { @@ -416,11 +439,15 @@ sub build_column_definition { sub column_byte_length { my ($table, $column) = @_; if ( $version >= 5.0 ) { + # information_schema searches can be case sensitive + # and users may use lower_case_table_names, use LOWER + # for everything just in case + # http://dev.mysql.com/doc/refman/5.1/en/charset-collation-information-schema.html my ($char, $octet) = @{ $dbh->selectrow_arrayref( "SELECT CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH FROM information_schema.COLUMNS WHERE" - ." TABLE_SCHEMA = ". $dbh->quote($db_name) - ." AND TABLE_NAME = ". $dbh->quote($table) - ." AND COLUMN_NAME = ". $dbh->quote($column) + ." LOWER(TABLE_SCHEMA) = ". lc( $dbh->quote($db_name) ) + ." AND LOWER(TABLE_NAME) = ". lc( $dbh->quote($table) ) + ." AND LOWER(COLUMN_NAME) = ". lc( $dbh->quote($column) ) ) }; return $octet if $octet == $char; } diff --git a/rt/etc/upgrade/vulnerable-passwords b/rt/etc/upgrade/vulnerable-passwords deleted file mode 100755 index f0fed0cfe..000000000 --- a/rt/etc/upgrade/vulnerable-passwords +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/perl -# BEGIN BPS TAGGED BLOCK {{{ -# -# COPYRIGHT: -# -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC -# <sales@bestpractical.com> -# -# (Except where explicitly superseded by other copyright notices) -# -# -# LICENSE: -# -# This work is made available to you under the terms of Version 2 of -# the GNU General Public License. A copy of that license should have -# been provided with this software, but in any event can be snarfed -# from www.gnu.org. -# -# This work is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 or visit their web page on the internet at -# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. -# -# -# CONTRIBUTION SUBMISSION POLICY: -# -# (The following paragraph is not intended to limit the rights granted -# to you to modify and distribute this software under the terms of -# the GNU General Public License and is only of importance to you if -# you choose to contribute your changes and enhancements to the -# community by submitting them to Best Practical Solutions, LLC.) -# -# By intentionally submitting any modifications, corrections or -# derivatives to this work, or any other work intended for use with -# Request Tracker, to Best Practical Solutions, LLC, you confirm that -# you are the copyright holder for those contributions and you grant -# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, -# royalty-free, perpetual, license to use, copy, create derivative -# works based on those contributions, and sublicense and distribute -# those contributions and any derivatives thereof. -# -# END BPS TAGGED BLOCK }}} -use strict; -use warnings; - -use lib "local/lib"; -use lib "lib"; - -use RT; -RT::LoadConfig; -RT::Init; - -$| = 1; - -use Getopt::Long; -use Digest::SHA; -my $fix; -GetOptions("fix!" => \$fix); - -use RT::Users; -my $users = RT::Users->new( $RT::SystemUser ); -$users->Limit( - FIELD => 'Password', - OPERATOR => 'IS NOT', - VALUE => 'NULL', - ENTRYAGGREGATOR => 'AND', -); -$users->Limit( - FIELD => 'Password', - OPERATOR => '!=', - VALUE => '*NO-PASSWORD*', - ENTRYAGGREGATOR => 'AND', -); -$users->Limit( - FIELD => 'Password', - OPERATOR => 'NOT STARTSWITH', - VALUE => '!', - ENTRYAGGREGATOR => 'AND', -); -push @{$users->{'restrictions'}{ "main.Password" }}, "AND", { - field => 'LENGTH(main.Password)', - op => '<', - value => '40', -}; - -my $count = $users->Count; -if ($count == 0) { - print "No users with unsalted or weak cryptography found.\n"; - exit 0; -} - -if ($fix) { - print "Upgrading $count users...\n"; - while (my $u = $users->Next) { - my $stored = $u->__Value("Password"); - my $raw; - if (length $stored == 32) { - $raw = pack("H*",$stored); - } elsif (length $stored == 22) { - $raw = MIME::Base64::decode_base64($stored); - } elsif (length $stored == 13) { - printf "%20s => Old crypt() format, cannot upgrade\n", $u->Name; - } else { - printf "%20s => Unknown password format!\n", $u->Name; - } - next unless $raw; - - my $salt = pack("C4",map{int rand(256)} 1..4); - my $sha = Digest::SHA::sha256( - $salt . $raw - ); - $u->_Set( - Field => "Password", - Value => MIME::Base64::encode_base64( - $salt . substr($sha,0,26), ""), - ); - } - print "Done.\n"; - exit 0; -} else { - if ($count < 20) { - print "$count users found with unsalted or weak-cryptography passwords:\n"; - print " Id | Name\n", "-"x9, "+", "-"x9, "\n"; - while (my $u = $users->Next) { - printf "%8d | %s\n", $u->Id, $u->Name; - } - } else { - print "$count users found with unsalted or weak-cryptography passwords\n"; - } - - print "\n", "Run again with --fix to upgrade.\n"; - exit 1; -} diff --git a/rt/etc/upgrade/vulnerable-passwords.in b/rt/etc/upgrade/vulnerable-passwords.in index 0af2b6423..a3d719c31 100755 --- a/rt/etc/upgrade/vulnerable-passwords.in +++ b/rt/etc/upgrade/vulnerable-passwords.in @@ -3,7 +3,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC # <sales@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -89,6 +89,9 @@ push @{$users->{'restrictions'}{ "main.Password" }}, "AND", { value => '40', }; +# we want to update passwords on disabled users +$users->{'find_disabled_rows'} = 1; + my $count = $users->Count; if ($count == 0) { print "No users with unsalted or weak cryptography found.\n"; |
