[Rt-commit] rt branch 5.0/dump-initialdata-copy-queues created. rt-5.0.3-64-gf992ffac50
BPS Git Server
git at git.bestpractical.com
Mon Aug 1 19:52:16 UTC 2022
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt".
The branch, 5.0/dump-initialdata-copy-queues has been created
at f992ffac50e17de166dc3186463263b999960083 (commit)
- Log -----------------------------------------------------------------
commit f992ffac50e17de166dc3186463263b999960083
Author: sunnavy <sunnavy at bestpractical.com>
Date: Fri Jul 29 04:19:49 2022 +0800
Test copying queue config via rt-dump-initialdata
It covers queue itself, ACL, watchers, scrips, templates, custom fields,
custom roles and also article classes.
diff --git a/t/api/initialdata_copy_queue.t b/t/api/initialdata_copy_queue.t
new file mode 100644
index 0000000000..694a4c82c5
--- /dev/null
+++ b/t/api/initialdata_copy_queue.t
@@ -0,0 +1,261 @@
+use warnings;
+use strict;
+
+use RT::Test tests => undef;
+RT->Config->Set( 'InitialdataFormatHandlers' => [ 'perl', 'RT::Initialdata::JSON' ] );
+
+my $general = RT::Test->load_or_create_queue( Name => 'General' );
+my $queue = RT::Test->load_or_create_queue( Name => 'Test' );
+
+my $user = RT::Test->load_or_create_user( Name => 'alice' );
+my $group = RT::Test->load_or_create_group('Duty');
+my $engineer = RT::CustomRole->new( RT->SystemUser );
+ok(
+ $engineer->Create(
+ Name => 'Engineer',
+ MaxValues => 0,
+ )
+);
+ok( $engineer->AddToObject( $_->id ) ) for $general, $queue;
+my $class = RT::Class->new( RT->SystemUser );
+ok( $class->Create( Name => 'FAQ' ) );
+ok( $class->AddToObject($_) ) for $general, $queue;
+
+ok( $queue->AddWatcher(Type => 'AdminCc', PrincipalId => $user->Id ) );
+ok( $queue->AddWatcher(Type => 'Cc', PrincipalId => $group->Id ) );
+
+my $scrip = RT::Scrip->new( RT->SystemUser );
+ok(
+ $scrip->Create(
+ Description => 'On Comment Notify Owner',
+ ScripCondition => 'On Comment',
+ ScripAction => 'Notify Owner',
+ Template => 'Blank',
+ )
+);
+
+ok( $scrip->AddToObject( $_->id ) ) for $general, $queue;
+
+my $template = RT::Template->new( RT->SystemUser );
+ok( $template->Create( Name => 'Foo', Description => 'Foo Description', Queue => $queue->Id, Content => q{Foo} ) );
+
+my $custom_field = RT::Test->load_or_create_custom_field(
+ Name => 'Action',
+ Type => 'FreeformSingle',
+ Queue => $queue->Id,
+);
+ok( $custom_field->SetDefaultValues( Object => $queue, Values => 'review, merge' ) );
+
+
+RT::Test->add_rights(
+ { Principal => 'Everyone', Right => 'SeeQueue', Object => RT->System },
+ { Principal => 'Requestor', Right => 'ShowTicket', Object => $general },
+ { Principal => $group, Right => 'TakeTicket', Object => RT->System },
+ { Principal => $user, Right => 'StealTicket', Object => $general },
+ { Principal => $engineer->GroupType, Right => 'CreateTicket', Object => RT->System },
+
+ { Principal => 'Privileged', Right => 'ReplyToTicket', Object => $queue },
+ { Principal => 'AdminCc', Right => 'CommentOnTicket', Object => $queue },
+ { Principal => $user, Right => 'SeeCustomField', Object => $queue },
+ { Principal => $group, Right => 'ModifyTicket', Object => $queue },
+ { Principal => $engineer->GroupType, Right => 'OwnTicket', Object => $queue },
+);
+
+my $parent_dir = RT->Config->Get('LogDir');
+my $global_dir = File::Spec->catdir( $parent_dir, 'global' );
+my $queue_dir = File::Spec->catdir( $parent_dir, 'queue' );
+
+diag "Export queue Test";
+
+ok(
+ RT::Test->run_singleton_command(
+ 'sbin/rt-dump-initialdata', '--quiet', '--dir', $global_dir, '--sync', '--no-queues',
+ ),
+ 'Dump global initialdata'
+);
+
+ok(
+ RT::Test->run_singleton_command(
+ 'sbin/rt-dump-initialdata', '--quiet', '--dir', $queue_dir, '--sync', '--limit-queues', 'Test', '--base',
+ File::Spec->catfile( $global_dir, 'initialdata.json' ),
+ ),
+ 'Dump Test queue changes'
+);
+
+my $changes;
+{
+ open my $fh, "<" . File::Spec->catfile( $queue_dir, 'changes.json' ) or die "Can't load changes.json";
+ local $/;
+ $changes = <$fh>;
+}
+
+my $expected_changes = JSON::decode_json(<<'EOF');
+{
+ "ACL" : [
+ {
+ "GroupDomain" : "SystemInternal",
+ "GroupType" : "Privileged",
+ "ObjectId" : "Test",
+ "ObjectType" : "RT::Queue",
+ "RightName" : "ReplyToTicket"
+ },
+ {
+ "GroupDomain" : "RT::Queue-Role",
+ "GroupType" : "AdminCc",
+ "ObjectId" : "Test",
+ "ObjectType" : "RT::Queue",
+ "RightName" : "CommentOnTicket"
+ },
+ {
+ "ObjectId" : "Test",
+ "ObjectType" : "RT::Queue",
+ "RightName" : "SeeCustomField",
+ "UserId" : "alice"
+ },
+ {
+ "GroupDomain" : "UserDefined",
+ "GroupId" : "Duty",
+ "ObjectId" : "Test",
+ "ObjectType" : "RT::Queue",
+ "RightName" : "ModifyTicket"
+ },
+ {
+ "GroupDomain" : "RT::Queue-Role",
+ "GroupType" : "RT::CustomRole-Engineer",
+ "ObjectId" : "Test",
+ "ObjectType" : "RT::Queue",
+ "RightName" : "OwnTicket"
+ }
+ ],
+ "Attributes" : [
+ {
+ "Content" : {
+ "Action" : "review, merge"
+ },
+ "ContentType" : "storable",
+ "Name" : "CustomFieldDefaultValues",
+ "Object" : "Test",
+ "ObjectType" : "RT::Queue"
+ }
+ ],
+ "Classes" : [
+ {
+ "ApplyTo" : [
+ "Test"
+ ],
+ "_Original" : {
+ "ApplyTo" : [],
+ "Description" : "",
+ "Name" : "FAQ",
+ "SortOrder" : 0
+ },
+ "_Updated" : 1
+ }
+ ],
+ "CustomFields" : [
+ {
+ "ApplyTo" : [
+ "Test"
+ ],
+ "_Original" : {
+ "ApplyTo" : [],
+ "Description" : "",
+ "EntryHint" : "Enter one value",
+ "LookupType" : "RT::Queue-RT::Ticket",
+ "MaxValues" : 1,
+ "Name" : "Action",
+ "SortOrder" : 0,
+ "Type" : "Freeform"
+ },
+ "_Updated" : 1
+ }
+ ],
+ "CustomRoles" : [
+ {
+ "ApplyTo" : [
+ "Test"
+ ],
+ "_Original" : {
+ "Description" : "",
+ "EntryHint" : "",
+ "MaxValues" : 0,
+ "Name" : "Engineer"
+ },
+ "_Updated" : 1
+ }
+ ],
+ "Members" : [
+ {
+ "Class" : "RT::User",
+ "Group" : "AdminCc",
+ "GroupDomain" : "RT::Queue-Role",
+ "GroupInstance" : "Test",
+ "Name" : "alice"
+ },
+ {
+ "Class" : "RT::Group",
+ "Group" : "Cc",
+ "GroupDomain" : "RT::Queue-Role",
+ "GroupInstance" : "Test",
+ "Name" : "Duty"
+ }
+ ],
+ "Queues" : [
+ {
+ "CommentAddress" : "",
+ "CorrespondAddress" : "",
+ "Description" : "",
+ "Lifecycle" : "default",
+ "Name" : "Test",
+ "SLADisabled" : 1,
+ "SortOrder" : 0
+ }
+ ],
+ "Templates" : [
+ {
+ "Content" : "Foo",
+ "Description" : "Foo Description",
+ "Name" : "Foo",
+ "Queue" : "Test",
+ "Type" : "Perl"
+ }
+ ]
+}
+EOF
+
+is_deeply( JSON::decode_json($changes), $expected_changes, 'Generated changes look good' );
+
+diag "Import queue Test with a new name";
+$changes =~ s/"Test"/"Test2"/g;
+
+open my $fh, '>', File::Spec->catdir( $parent_dir, 'queue_changes.json' );
+print $fh $changes;
+close $fh;
+
+ok(
+ RT->DatabaseHandle->InsertData(
+ File::Spec->catdir( $parent_dir, 'queue_changes.json' ),
+ undef, disconnect_after => 0
+ )
+);
+
+$queue_dir = File::Spec->catdir( $parent_dir, 'queue2' );
+
+ok(
+ RT::Test->run_singleton_command(
+ 'sbin/rt-dump-initialdata', '--quiet', '--dir', $queue_dir, '--sync', '--limit-queues', 'Test2', '--base',
+ File::Spec->catfile( $global_dir, 'initialdata.json' ),
+ ),
+ 'Dump Test2 queue changes'
+);
+
+my $new_changes;
+{
+ open my $fh, "<" . File::Spec->catfile( $queue_dir, 'changes.json' ) or die "Can't load changes.json";
+ local $/;
+ $new_changes = <$fh>;
+}
+
+is_deeply( JSON::decode_json($new_changes), JSON::decode_json($changes), 'Generated changes look good' );
+
+done_testing;
commit 4b51ce1f04947e15f17c9fd9d9c72b77a4d857cf
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Jul 28 22:35:40 2022 +0800
Support to dump and import CustomFieldDefaultValues attributes with cf name
The content in db is like:
{ 2 => 'value1', 3 => 'value2' }
This commit tweaks it to:
{ foo => 'value1', bar => 'value2' }
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index e7f27404a1..549eb6ea75 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -3172,6 +3172,23 @@ sub _CanonilizeAttributeContent {
}
}
}
+ elsif ( $item->{Name} eq 'CustomFieldDefaultValues' ) {
+ my %value;
+ for my $name ( keys %{ $item->{Content} || {} } ) {
+ my $custom_field = RT::CustomField->new( RT->SystemUser );
+ $custom_field->LoadByName(
+ Name => $name,
+ IncludeGlobal => 1,
+ ObjectType => $item->{ObjectType},
+ ObjectId => $item->{ObjectId},
+ );
+
+ if ( $custom_field->Id ) {
+ $value{ $custom_field->Id } = $item->{Content}{$name};
+ }
+ }
+ $item->{Content} = \%value;
+ }
}
sub _CanonilizeObjectCustomFieldValue {
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index dabd595003..3f03a70f2f 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -541,6 +541,17 @@ sub CanonicalizeAttributes {
}
}
}
+ elsif ( $record->{Name} eq 'CustomFieldDefaultValues' ) {
+ my %value;
+ for my $id ( keys %{ $record->{Content} || {} } ) {
+ my $custom_field = RT::CustomField->new( RT->SystemUser );
+ $custom_field->Load($id);
+ if ( $custom_field->Id ) {
+ $value{ $custom_field->Name } = $record->{Content}{$id};
+ }
+ }
+ $record->{Content} = \%value;
+ }
}
}
elsif ( $record->{Name} =~ /DefaultDashboard$/ ) {
commit b9aadccac3e137e47a4e14932859436b4c74f28b
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Jul 28 22:04:07 2022 +0800
Support to dump and import custom role ACL with custom role name
This is for custom role groups like "RT::CustomRole-1", this commit
tweaks it to something like "RT::CustomRole-Enginner".
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 15b16a7735..e7f27404a1 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -1554,10 +1554,31 @@ sub InsertData {
$princ->LoadUserDefinedGroup( $item->{'GroupId'} );
} elsif ( $item->{'GroupDomain'} eq 'SystemInternal' ) {
$princ->LoadSystemInternalGroup( $item->{'GroupType'} );
- } elsif ( $item->{'GroupDomain'} eq 'RT::System-Role' ) {
- $princ->LoadRoleGroup( Object => RT->System, Name => $item->{'GroupType'} );
} elsif ( $item->{'GroupDomain'} =~ /-Role$/ ) {
- $princ->LoadRoleGroup( Object => $object, Name => $item->{'GroupType'} );
+ my $obj;
+ if ( $item->{'GroupDomain'} eq 'RT::System-Role' ) {
+ $obj = RT->System;
+ }
+ else {
+ $obj = $object;
+ }
+
+ if ( $item->{GroupType} =~ /^RT::CustomRole-(.+)$/ ) {
+ my $id = $1;
+
+ # $id could be Name
+ if ( $id =~ /\D/ ) {
+ my $custom_role = RT::CustomRole->new( RT->SystemUser );
+ $custom_role->Load($id);
+ if ( $custom_role->Id ) {
+ $item->{GroupType} = $custom_role->GroupType;
+ }
+ else {
+ RT->Logger->error("Unable to load custom role $id");
+ }
+ }
+ }
+ $princ->LoadRoleGroup( Object => $obj, Name => $item->{'GroupType'} );
} else {
$princ->Load( $item->{'GroupId'} );
}
@@ -2950,12 +2971,13 @@ sub _LoadObject {
if ( $values->{_Original}{'GroupDomain'} eq 'SystemInternal' ) {
$group->LoadSystemInternalGroup( $values->{_Original}{GroupType} );
}
- elsif ( $values->{_Original}{'GroupDomain'} eq 'RT::System-Role' ) {
- $group->LoadRoleGroup( Object => RT->System, Name => $values->{_Original}{GroupType} );
- }
elsif ( $values->{_Original}{'GroupDomain'} =~ /-Role$/ ) {
my $object;
- if ( $values->{_Original}{ObjectType} and $values->{_Original}{ObjectId} ) {
+
+ if ( $values->{_Original}{'GroupDomain'} eq 'RT::System-Role' ) {
+ $object = RT->System;
+ }
+ elsif ( $values->{_Original}{ObjectType} and $values->{_Original}{ObjectId} ) {
$object = $values->{_Original}{ObjectType}->new( RT->SystemUser );
my ( $ok, $msg ) = $object->Load( $values->{_Original}{ObjectId} );
unless ($ok) {
@@ -2969,6 +2991,20 @@ sub _LoadObject {
else {
$object = RT->System;
}
+ if ( $values->{_Original}{GroupType} =~ /^RT::CustomRole-(.+)$/ ) {
+ my $id = $1;
+ # $id could be Name
+ if ( $id =~ /\D/ ) {
+ my $custom_role = RT::CustomRole->new(RT->SystemUser);
+ $custom_role->Load($id);
+ if ( $custom_role->Id ) {
+ $values->{_Original}{GroupType} = $custom_role->GroupType;
+ }
+ else {
+ RT->Logger->error("Unable to load custom role $id");
+ }
+ }
+ }
$group->LoadRoleGroup( Object => $object, Name => $values->{_Original}{GroupType} );
}
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index 78c008c665..dabd595003 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -318,7 +318,12 @@ sub CanonicalizeACLs {
$ace->{GroupId} = $group->Name;
}
if ($domain eq 'SystemInternal' || $domain =~ /-Role$/) {
- $ace->{GroupType} = $group->Name;
+ if ( $group->Name =~ /^RT::CustomRole-\d+$/ ) {
+ $ace->{GroupType} = 'RT::CustomRole-' . $group->_CustomRoleObj->Name;
+ }
+ else {
+ $ace->{GroupType} = $group->Name;
+ }
}
}
}
commit a9e7101c3792153be31014e11473a76bc4847211
Author: sunnavy <sunnavy at bestpractical.com>
Date: Sat Jul 23 02:59:51 2022 +0800
Add --limit-queues and --no-queues support for rt-dump-initialdata
--limit-queues is simply a clone from rt-serializer, --no-queues is to
export configs without any queue specific ones.
diff --git a/lib/RT/Migrate/Serializer.pm b/lib/RT/Migrate/Serializer.pm
index bce8530f22..1b740717f5 100644
--- a/lib/RT/Migrate/Serializer.pm
+++ b/lib/RT/Migrate/Serializer.pm
@@ -317,9 +317,12 @@ sub PushBasics {
}
if ($self->{Queues}) {
- my $queues = RT::Queues->new(RT->SystemUser);
- $queues->Limit(FIELD => 'id', OPERATOR => 'IN', VALUE => $self->{Queues});
- $self->PushObj($queues);
+ # MariaDB doesn't like empty list
+ if ( @{ $self->{Queues} } ) {
+ my $queues = RT::Queues->new(RT->SystemUser);
+ $queues->Limit(FIELD => 'id', OPERATOR => 'IN', VALUE => $self->{Queues});
+ $self->PushObj($queues);
+ }
}
else {
$self->PushCollections(qw(Queues));
diff --git a/sbin/rt-dump-initialdata.in b/sbin/rt-dump-initialdata.in
index 98a30648b2..e443d7c76d 100644
--- a/sbin/rt-dump-initialdata.in
+++ b/sbin/rt-dump-initialdata.in
@@ -105,6 +105,8 @@ GetOptions(
"scrips!",
"acls!",
"assets!",
+ 'queues!',
+ "limit-queues=s@",
"sync",
@@ -136,6 +138,26 @@ $args{Sync} = 1 if $OPT{sync} || $OPT{base};
$args{GC} = defined $OPT{gc} ? $OPT{gc} : 5000;
$args{Page} = defined $OPT{page} ? $OPT{page} : 100;
+if ( defined $OPT{'queues'} ) {
+ $args{Queues} = [] unless $OPT{'queues'};
+}
+elsif ( $OPT{'limit-queues'} ) {
+ my @queue_ids;
+
+ for my $name ( split ',', join ',', @{ $OPT{'limit-queues'} } ) {
+ $name =~ s/^\s+//;
+ $name =~ s/\s+$//;
+ my $queue = RT::Queue->new( RT->SystemUser );
+ $queue->Load($name);
+ if ( !$queue->Id ) {
+ die "Unable to load queue '$name'";
+ }
+ push @queue_ids, $queue->Id;
+ }
+
+ $args{Queues} = \@queue_ids;
+}
+
my $walker;
my $gnuplot = `which gnuplot`;
@@ -467,6 +489,15 @@ skips them.
By default, all ACLs are dumped; passing C<--no-acls> skips them.
+=item B<--no-queues>
+
+By default, all queues are dumped; passing C<--no-queues> skips them.
+
+=item B<--limit-queues>
+
+Takes a list of queue IDs or names separated by commas. When provided, only
+that set of queues will be dumped.
+
=item B<--sync>
By default, record ids are ordinarily excluded. Pass C<--sync> to
commit 8fa64ea1e1b974daa36b2bae6542f9fdec35ec1f
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Jul 28 02:28:31 2022 +0800
Handle ObjectClass updates for article classes in initialdata
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 177b9e5ce1..15b16a7735 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2660,7 +2660,7 @@ sub _UpdateObject {
next;
}
}
- if ( $class eq 'RT::CustomRole' ) {
+ elsif ( $class eq 'RT::CustomRole' ) {
if ( $field eq 'ApplyTo' ) {
my %current;
my %new;
@@ -2711,6 +2711,61 @@ sub _UpdateObject {
next;
}
}
+ elsif ( $class eq 'RT::Class' ) {
+ if ( $field eq 'ApplyTo' ) {
+ my %current;
+ my %new;
+
+ # Calculate changes based on $original if possible
+ if ( defined $original->{ApplyTo} ) {
+ for my $item ( @{ $original->{ApplyTo} } ) {
+ my $queue = RT::Queue->new( RT->SystemUser );
+ $queue->Load($item);
+ if ( $queue->Id ) {
+ $current{ $queue->Id } = 1;
+ }
+ }
+ }
+ else {
+ my $ocs = RT::ObjectClasses->new( RT->SystemUser );
+ $ocs->LimitToClass( $object->id );
+
+ while ( my $oc = $ocs->Next ) {
+ $current{ $oc->ObjectId } = 1;
+ }
+ }
+
+
+ for my $item ( @{ $value || [] } ) {
+ my $queue = RT::Queue->new( RT->SystemUser );
+ $queue->Load($item);
+ if ( $queue->Id ) {
+ $new{ $queue->Id } = 1;
+ }
+ }
+
+ for my $id ( keys %current ) {
+ next if $new{$id};
+ my $queue = RT::Queue->new( RT->SystemUser );
+ $queue->Load($id);
+ my ( $ret, $msg ) = $object->RemoveFromObject( $queue );
+ if ( !$ret ) {
+ RT->Logger->error( "Couldn't remove Class #" . $object->Id . " from Queue #$id: $msg" );
+ }
+ }
+
+ for my $id ( keys %new ) {
+ next if $current{$id};
+ my $queue = RT::Queue->new( RT->SystemUser );
+ $queue->Load($id);
+ my ( $ret, $msg ) = $object->AddToObject($queue);
+ if ( !$ret ) {
+ RT->Logger->error( "Couldn't add Class #" . $object->Id . " to Queue #$id: $msg" );
+ }
+ }
+ next;
+ }
+ }
elsif ( $class eq 'RT::Scrip' ) {
if ( $field eq 'Queue' ) {
my %current;
commit 1ce0d06608eedf28e0e406fb72328fb95be88e48
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Jul 28 02:17:10 2022 +0800
Handle ObjectCustomRole updates for custom roles in initialdata
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 954ceb010c..177b9e5ce1 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2660,6 +2660,57 @@ sub _UpdateObject {
next;
}
}
+ if ( $class eq 'RT::CustomRole' ) {
+ if ( $field eq 'ApplyTo' ) {
+ my %current;
+ my %new;
+
+ # Calculate changes based on $original if possible
+ if ( defined $original->{ApplyTo} ) {
+ for my $item ( @{ $original->{ApplyTo} } ) {
+ my $queue = RT::Queue->new( RT->SystemUser );
+ $queue->Load($item);
+ if ( $queue->Id ) {
+ $current{ $queue->Id } = 1;
+ }
+ }
+ }
+ else {
+ my $ocrs = RT::ObjectCustomRoles->new( RT->SystemUser );
+ $ocrs->LimitToCustomRole( $object->id );
+
+ while ( my $ocr = $ocrs->Next ) {
+ $current{ $ocr->ObjectId } = 1;
+ }
+ }
+
+
+ for my $item ( @{ $value || [] } ) {
+ my $queue = RT::Queue->new( RT->SystemUser );
+ $queue->Load($item);
+ if ( $queue->Id ) {
+ $new{ $queue->Id } = 1;
+ }
+ }
+
+ for my $id ( keys %current ) {
+ next if $new{$id};
+ my ($ret, $msg) = $object->RemoveFromObject($id);
+ if ( !$ret ) {
+ RT->Logger->error( "Couldn't remove CustomRole #" . $object->Id . " from Queue #$id: $msg" );
+ }
+ }
+
+ for my $id ( keys %new ) {
+ next if $current{$id};
+ my ($ret, $msg) = $object->AddToObject($id);
+ if ( !$ret ) {
+ RT->Logger->error( "Couldn't add CustomRole #" . $object->id . " to Queue #$id: $msg" );
+ }
+ }
+ next;
+ }
+ }
elsif ( $class eq 'RT::Scrip' ) {
if ( $field eq 'Queue' ) {
my %current;
commit 9fe1355ba955b645ebb5aaab3ee04900a369db9a
Author: sunnavy <sunnavy at bestpractical.com>
Date: Wed Sep 22 03:07:57 2021 +0800
Handle ObjectScrip updates for scrips in initialdata
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 2a7977c46b..954ceb010c 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2517,8 +2517,12 @@ sub _UpdateObject {
}
}
- for my $field ( sort { $a eq 'ApplyTo' || $b eq 'ApplyTo' ? 1 : 0 } keys %$values ) {
+ my %order = (
+ 'Queue' => 1,
+ 'ApplyTo' => 1,
+ );
+ for my $field ( sort { ( $order{$a} || 0 ) <=> ( $order{b} || 0 ) } keys %$values ) {
if ( $class eq 'RT::Attribute' ) {
if ( $field eq 'Content' ) {
$self->_CanonilizeAttributeContent( $values );
@@ -2656,6 +2660,98 @@ sub _UpdateObject {
next;
}
}
+ elsif ( $class eq 'RT::Scrip' ) {
+ if ( $field eq 'Queue' ) {
+ my %current;
+ my %new;
+
+ # Calculate changes based on $original if possible
+ if ( defined $original->{Queue} ) {
+ for my $item ( @{$original->{Queue}} ) {
+ # Globally applied
+ if ( $item->{ObjectId} eq 0 ) {
+ $current{ $item->{Stage} }{0} = $item->{SortOrder};
+ }
+ else {
+ my $queue = RT::Queue->new( RT->SystemUser );
+ $queue->Load( $item->{ObjectId} );
+ if ( $queue->id ) {
+ $current{ $item->{Stage} }{ $queue->id } = $item->{SortOrder};
+ }
+ }
+ }
+ }
+ else {
+ my $object_scrips = RT::ObjectScrips->new(RT->SystemUser);
+ $object_scrips->LimitToScrip($object->id);
+
+ while ( my $object_scrip = $object_scrips->Next ) {
+ $current{$object_scrip->Stage}{$object_scrip->ObjectId} = $object_scrip->SortOrder;
+ }
+ }
+
+ for my $item ( @{ $value || [] } ) {
+ if ( $item->{ObjectId} eq 0 ) {
+ $new{ $item->{Stage} }{0} = $item->{SortOrder};
+ }
+ else {
+ my $queue = RT::Queue->new( RT->SystemUser );
+ $queue->Load( $item->{ObjectId} );
+ if ( $queue->id ) {
+ $new{ $item->{Stage} }{ $queue->id } = $item->{SortOrder};
+ }
+ }
+ }
+
+ for my $stage ( sort keys %current ) {
+ for my $id ( sort { $current{$stage}{$a} <=> $current{$stage}{$b} } keys %{ $current{$stage} } ) {
+ my $object_scrip = RT::ObjectScrip->new( RT->SystemUser );
+ $object_scrip->LoadByCols( Scrip => $object->id, ObjectId => $id, Stage => $stage );
+ if ( $object_scrip->id ) {
+ if ( defined $new{$stage}{$id} ) {
+ if ( $new{$stage}{$id} != $current{$stage}{$id} ) {
+ my ( $ret, $msg ) = $object_scrip->SetSortOrder( $new{$stage}{$id} );
+ if ( !$ret ) {
+ RT->Logger->error( "Couldn't update SortOrder of ObjectScrip #"
+ . $object_scrip->id
+ . ": $msg" );
+ }
+ }
+ }
+ else {
+ my ( $ret, $msg ) = $object_scrip->Delete;
+ if ( !$ret ) {
+ RT->Logger->error( "Couldn't delete ObjectScrip #" . $object_scrip->id . ": $msg" );
+ }
+ }
+ }
+ }
+ }
+
+ for my $stage ( sort keys %new ) {
+ for my $id ( sort { $new{$stage}{$a} <=> $new{$stage}{$b} } keys %{ $new{$stage} } ) {
+ next if defined $current{$stage}{$id};
+
+ my $object_scrip = RT::ObjectScrip->new( RT->SystemUser );
+ $object_scrip->LoadByCols( Scrip => $object->id, ObjectId => $id, Stage => $stage );
+ if ( !$object_scrip->id ) {
+ my ( $ret, $msg ) = $object_scrip->Create(
+ Scrip => $object->id,
+ ObjectId => $id,
+ Stage => $stage,
+ SortOrder => $new{$stage}{SortOrder},
+ );
+ if ( !$ret ) {
+ RT->Logger->error( "Couldn't create ObjectScrip for Scrip #"
+ . $object->id
+ . " and Queue #$id: $msg" );
+ }
+ }
+ }
+ }
+ next;
+ }
+ }
next unless $object->can( $field ) || $object->_Accessible( $field, 'read' );
my $old_value = $object->can( $field ) ? $object->$field : $object->_Value( $field );
commit e963da9bb05797a70d53cb12da50a5fc186645eb
Author: sunnavy <sunnavy at bestpractical.com>
Date: Thu Jul 28 01:32:29 2022 +0800
Calculate ObjectCustomField changes based on source RT if possible
Previously we always calculated changes based on target RT, which could
involve unexpected changes. E.g. if a custom field is applied to a new
Queue in source RT and we want to sync this change to target RT,
previously if target RT had some extra queues applied(i.e. ones not
applied in source RT), these queues would be revoked after sync.
This is initially to sync changes of specific queues, just like the
example above.
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 4be4295d89..2a7977c46b 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2532,18 +2532,36 @@ sub _UpdateObject {
my %current;
my %new;
- my $ocfs = RT::ObjectCustomFields->new(RT->SystemUser);
- $ocfs->LimitToCustomField($object->id);
-
- while ( my $ocf = $ocfs->Next ) {
- if ( $ocf->ObjectId == 0 ) {
- $current{0} = 1;
- }
- else {
- my $added = $object->RecordClassFromLookupType->new( RT->SystemUser );
- $current{$ocf->ObjectId} = 1;
+ # Calculate changes based on $original if possible
+ if ( defined $original->{ApplyTo} ) {
+ for my $item ( @{$original->{ApplyTo}} ) {
+ # Globally applied
+ if ( $item eq 0 ) {
+ $current{0} = 1;
+ }
+ else {
+ my $added = $object->RecordClassFromLookupType->new( RT->SystemUser );
+ $added->Load($item);
+ if ( $added->id ) {
+ $current{ $added->id } = 1;
+ }
+ }
}
}
+ else {
+ my $ocfs = RT::ObjectCustomFields->new(RT->SystemUser);
+ $ocfs->LimitToCustomField($object->id);
+
+ while ( my $ocf = $ocfs->Next ) {
+ if ( $ocf->ObjectId == 0 ) {
+ $current{0} = 1;
+ }
+ else {
+ $current{$ocf->ObjectId} = 1;
+ }
+ }
+ }
+
for my $item ( @{ $value || [] } ) {
if ( $item eq 0 ) {
commit 74f0e2387a71112ac83681e84c872d08e5f2c89b
Author: sunnavy <sunnavy at bestpractical.com>
Date: Fri Oct 1 17:52:58 2021 +0800
Do not keep track of ObjectScrips ids when calculating changes
This is like how we deleted ids of CustomFieldValues and
ObjectCustomFieldValues, which are allowed to be different.
diff --git a/sbin/rt-dump-initialdata.in b/sbin/rt-dump-initialdata.in
index 8e5064ed9b..98a30648b2 100644
--- a/sbin/rt-dump-initialdata.in
+++ b/sbin/rt-dump-initialdata.in
@@ -285,6 +285,10 @@ sub find_differences {
if ( $record->{Topics} ) {
delete $_->{id} for @{$record->{Topics}};
}
+
+ if ( $type eq 'Scrips' && $record->{Queue} ) {
+ delete $_->{id} for @{$record->{Queue}};
+ }
}
my @changes;
commit 629ca7518ed7cc7f1b42522dd0495237388f5a0e
Author: sunnavy <sunnavy at bestpractical.com>
Date: Tue Sep 21 21:55:32 2021 +0800
ACL in initialdata is applied globally by default
When ObjectType/ObjectId are absent in ACL records, it means global.
This is to get rid of errors from RT::ACE::_ParseObjectArg:
Method called with wrong args
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index b51058233b..4be4295d89 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2769,6 +2769,8 @@ sub _LoadObject {
$object->LoadByValues(
PrincipalId => $principal_id,
PrincipalType => $principal_type,
+ ObjectType => 'RT::System',
+ ObjectId => RT->System->Id,
map { $_ => $values->{_Original}{$_} } grep { $values->{_Original}{$_} } qw/ObjectType ObjectId RightName/,
);
}
commit 9fd1a70caf14fc3f6ddc4e955fdcc47a56210301
Author: sunnavy <sunnavy at bestpractical.com>
Date: Tue Sep 21 21:47:18 2021 +0800
Handle system internal and role groups for ACL updates in initialdata
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 709c4df143..b51058233b 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2724,6 +2724,43 @@ sub _LoadObject {
return;
}
}
+ elsif ( $values->{_Original}{GroupType} ) {
+
+ my $group = RT::Group->new(RT->SystemUser);
+ if ( $values->{_Original}{'GroupDomain'} eq 'SystemInternal' ) {
+ $group->LoadSystemInternalGroup( $values->{_Original}{GroupType} );
+ }
+ elsif ( $values->{_Original}{'GroupDomain'} eq 'RT::System-Role' ) {
+ $group->LoadRoleGroup( Object => RT->System, Name => $values->{_Original}{GroupType} );
+ }
+ elsif ( $values->{_Original}{'GroupDomain'} =~ /-Role$/ ) {
+ my $object;
+ if ( $values->{_Original}{ObjectType} and $values->{_Original}{ObjectId} ) {
+ $object = $values->{_Original}{ObjectType}->new( RT->SystemUser );
+ my ( $ok, $msg ) = $object->Load( $values->{_Original}{ObjectId} );
+ unless ($ok) {
+ RT->Logger->error( "Unable to load "
+ . $values->{_Original}{ObjectType} . " "
+ . $values->{_Original}{ObjectId}
+ . ": $msg" );
+ return;
+ }
+ }
+ else {
+ $object = RT->System;
+ }
+ $group->LoadRoleGroup( Object => $object, Name => $values->{_Original}{GroupType} );
+ }
+
+ if ( $group->id ) {
+ $principal_id = $group->PrincipalId;
+ $principal_type = 'Group';
+ }
+ else {
+ RT->Logger->error("Couldn't load group $values->{_Original}{GroupType}");
+ return;
+ }
+ }
else {
RT->Logger->error( "Invalid principal type in $class" );
return;
commit c4ce6b83a55dae8a6cd9f7436c754de2891a27ab
Author: sunnavy <sunnavy at bestpractical.com>
Date: Tue Sep 21 21:44:26 2021 +0800
Fix typo, this block is to check GroupId
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index f557832669..709c4df143 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2720,7 +2720,7 @@ sub _LoadObject {
$principal_type = 'Group';
}
else {
- RT->Logger->error( "Couldn't load group $values->{_Original}{UserId}" );
+ RT->Logger->error( "Couldn't load group $values->{_Original}{GroupId}" );
return;
}
}
-----------------------------------------------------------------------
hooks/post-receive
--
rt
More information about the rt-commit
mailing list