[Rt-commit] rt branch 5.0/dump-initialdata-copy-queues created. rt-5.0.4-182-g390e9e1d9f
BPS Git Server
git at git.bestpractical.com
Fri Sep 1 20:05:22 UTC 2023
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 390e9e1d9f437f9ee40621a6fe2029800425dcfb (commit)
- Log -----------------------------------------------------------------
commit 390e9e1d9f437f9ee40621a6fe2029800425dcfb
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..fa594f0a5e
--- /dev/null
+++ b/t/api/initialdata_copy_queue.t
@@ -0,0 +1,262 @@
+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,
+ "LookupType" : "RT::Queue-RT::Ticket",
+ "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 9bf7d46770cd33fcdd3395fa7dd08808d85bc7a7
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 f8e34fe4ad..cdfb69b6c0 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -3226,6 +3226,23 @@ sub _CanonilizeAttributeContent {
$item->{Content}{StackedGroupBy} = $stacked_group_by if $stacked_group_by;
}
}
+ 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 978378a675..279671183f 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -569,6 +569,17 @@ sub CanonicalizeAttributes {
$record->{Content}{StackedGroupBy} = $stacked_group_by if $stacked_group_by;
}
}
+ 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 e2365b417e3714490c613fb086d0e8975a51206b
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 c300f7836a..1c6b8e16b0 100644
--- a/lib/RT/Migrate/Serializer.pm
+++ b/lib/RT/Migrate/Serializer.pm
@@ -362,9 +362,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 853a64b524..57f3a57eaf 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 df9e41deae5d2d753cff0c1fa15be7b8253dcbc2
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 7abfb57081..f8e34fe4ad 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2694,7 +2694,7 @@ sub _UpdateObject {
next;
}
}
- if ( $class eq 'RT::CustomRole' ) {
+ elsif ( $class eq 'RT::CustomRole' ) {
if ( $field eq 'ApplyTo' ) {
my %current;
my %new;
@@ -2745,6 +2745,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 dff631b80960f5030fbea243a7f0c80acdc84c1a
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 ea13b79abd..7abfb57081 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2694,6 +2694,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 e0fbb381969ce616eb38d2d5e178808346b6e033
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 0cbd60c3c1..ea13b79abd 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2552,8 +2552,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 );
@@ -2690,6 +2694,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 155f31fc2480362937cbed3d11abb52dbdf2f146
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 a46ab0f93b..0cbd60c3c1 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2567,16 +2567,33 @@ 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;
+ # 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 $added = $object->RecordClassFromLookupType->new( RT->SystemUser );
- $current{$ocf->ObjectId} = 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;
+ }
}
}
commit f687cd52a7119f36062947539c0bb4a36a210c19
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 b45643ce80..853a64b524 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 2992f2773250f23a8e7af87206bcdc7f9973509e
Author: sunnavy <sunnavy at bestpractical.com>
Date: Fri Sep 1 15:21:18 2023 -0400
Handle system internal and role groups for ACL deletion in initialdata
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 5bdd6c4017..a46ab0f93b 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2759,6 +2759,55 @@ 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'} =~ /-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;
+ }
+ 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");
+ }
+ }
+ $principal_type = $values->{_Original}{GroupType};
+ }
+ $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 d68dc82c55b1ef1099de222394a7623ab1a7cede
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 6451581cb3..5bdd6c4017 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2767,6 +2767,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 9219752e35d5092d41f72ad2123d1e910c7430b4
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 74df5b9c14..6451581cb3 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -2755,7 +2755,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