[Rt-commit] rt branch, 4.4/serialize-json-initialdata, updated. rt-4.4.1-354-gc6e0169
Shawn Moore
shawn at bestpractical.com
Mon Mar 20 16:57:37 EDT 2017
The branch, 4.4/serialize-json-initialdata has been updated
via c6e016974d8df964d3815271f4ea605e3b63add8 (commit)
via a90d18d3267a0c9361dd06c0bf11fd8ea74e73c0 (commit)
via 7c86a84a029f1ba4431d142a07049326b8638ed0 (commit)
via 3a9545fa25f9d10e504ee26f272382359931bf8b (commit)
via ded0d923b6f8ef6a2cead7fa5990ca54c6351010 (commit)
via 3f6721c135c0a6d0e6703a9e24e39c266daf0680 (commit)
via 3abcb9e007949ae602caaa71f89d5500af0e70e1 (commit)
via 60c3125fd382d45127f49c1118d6e3a0817d6256 (commit)
via ccb982d74e6e859b1e1c285e71864080659d264d (commit)
via 0bbf2d740166bf1f4995afbc31abc6629f219aba (commit)
via 7dfb677fcf6b7771e6dddb7127cd270a76a560e0 (commit)
via 4e281b8d9029d5cd4fe42d92f9b1a035e1ed8e98 (commit)
via cf6b45ab86ca00320ae746b3a8dd2556f433ece9 (commit)
via 256334a7f7440fc2372c172b4e65a3effbcb988c (commit)
via 8037d969bc5507173c30791456b01465d0067e95 (commit)
via 24fea90c0b57991a64e1a1e482e5932a23d4ef1a (commit)
via 96382aeb8c5af06ead18236bb0ead3db31798c94 (commit)
from 2dc725b4dce35d1daa6ca604af5c9d9943809af0 (commit)
Summary of changes:
etc/RT_Config.pm.in | 34 ++++++++
lib/RT/Group.pm | 43 ++++++++--
lib/RT/Handle.pm | 101 +++++++++++++++++++----
lib/RT/Migrate/Serializer/JSON.pm | 99 +++++++++++++++++++++-
t/api/initialdata-roundtrip.t | 167 ++++++++++++++++++++++++++++++++++++++
5 files changed, 416 insertions(+), 28 deletions(-)
create mode 100644 t/api/initialdata-roundtrip.t
- Log -----------------------------------------------------------------
commit 24fea90c0b57991a64e1a1e482e5932a23d4ef1a
Merge: 2dc725b 96382ae
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 17:11:58 2017 +0000
Merge branch '4.4.1/json-initialdata' into 4.4/serialize-json-initialdata
commit 8037d969bc5507173c30791456b01465d0067e95
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 17:37:13 2017 +0000
Only serialize user-defined groups for initialdata
ACLEquivalence, role groups, etc will be created automatically
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index 7e6d73d..2c48e05 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -120,6 +120,23 @@ sub Directory {
return $self->{Directory};
}
+sub Observe {
+ my $self = shift;
+ my %args = @_;
+
+ my $obj = $args{object};
+
+ # avoid serializing ACLEquivalence, etc
+ if ($obj->isa("RT::Group")) {
+ return 0 unless $obj->Domain eq 'UserDefined';
+ }
+ if ($obj->isa("RT::GroupMember")) {
+ return 0 unless $obj->GroupObj->Object->Domain eq 'UserDefined';
+ }
+
+ return $self->SUPER::Observe(%args);
+}
+
sub JSON {
my $self = shift;
return $self->{JSON} ||= JSON->new->pretty->canonical;
commit 256334a7f7440fc2372c172b4e65a3effbcb988c
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 17:57:34 2017 +0000
Avoid serializing attributes (for now)
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index 2c48e05..d800284 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -274,6 +274,8 @@ sub WriteFile {
$self->CanonicalizeObjects;
+ delete $self->{Records}{'RT::Attribute'};
+
for my $intype (keys %{ $self->{Records} }) {
my $outtype = $intype;
$outtype =~ s/^RT:://;
commit cf6b45ab86ca00320ae746b3a8dd2556f433ece9
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:04:54 2017 +0000
Handle explicit ApplyTo => 0 to make a CF which is global
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 0b62526..41aee32 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -1208,22 +1208,25 @@ sub InsertData {
my $class = $new_entry->RecordClassFromLookupType;
if ($class) {
- if ($new_entry->IsOnlyGlobal and $apply_to) {
- $RT::Logger->warn("ApplyTo provided for global custom field ".$new_entry->Name );
- undef $apply_to;
- }
- if ( !$apply_to ) {
- # Apply to all by default
+ $apply_to = [ $apply_to ] unless ref $apply_to;
+ for my $name ( @{ $apply_to } ) {
my $ocf = RT::ObjectCustomField->new(RT->SystemUser);
- ( $return, $msg) = $ocf->Create( CustomField => $new_entry->Id );
- $RT::Logger->error( $msg ) unless $return and $ocf->Id;
- } else {
- $apply_to = [ $apply_to ] unless ref $apply_to;
- for my $name ( @{ $apply_to } ) {
+
+ # global CF
+ if (!$name) {
+ ( $return, $msg ) = $ocf->Create(
+ CustomField => $new_entry->Id,
+ );
+ $RT::Logger->error( $msg ) unless $return and $ocf->Id;
+ }
+ else {
+ if ($new_entry->IsOnlyGlobal) {
+ $RT::Logger->warn("ApplyTo '$name' provided for global custom field ".$new_entry->Name );
+ }
+
my $obj = $class->new(RT->SystemUser);
$obj->Load($name);
if ( $obj->Id ) {
- my $ocf = RT::ObjectCustomField->new(RT->SystemUser);
( $return, $msg ) = $ocf->Create(
CustomField => $new_entry->Id,
ObjectId => $obj->Id,
commit 4e281b8d9029d5cd4fe42d92f9b1a035e1ed8e98
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:23:49 2017 +0000
Have _GetRecordByRef dereference if needed
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index d800284..944c225 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -179,6 +179,7 @@ sub _GetRecordByRef {
my $self = shift;
my $ref = shift;
+ $ref = $$ref if ref($ref) eq 'SCALAR';
my ($class) = $ref =~ /^([\w:]+)-/
or return undef;
return $self->{Records}{$class}{$ref};
@@ -249,7 +250,7 @@ sub CanonicalizeObjects {
primary_class => 'RT::CustomRole',
canonicalize_object => sub {
ref($_->{ObjectId})
- ? $self->_GetRecordByRef(${ $_->{ObjectId} })->{Name}
+ ? $self->_GetRecordByRef($_->{ObjectId})->{Name}
: $_->{ObjectId};
},
);
@@ -261,7 +262,7 @@ sub CanonicalizeObjects {
primary_key => 'Queue',
canonicalize_object => sub {
my $object = ref($_->{ObjectId})
- ? $self->_GetRecordByRef(${ $_->{ObjectId} })->{Name}
+ ? $self->_GetRecordByRef($_->{ObjectId})->{Name}
: $_->{ObjectId};
return { ObjectId => $object, Stage => $_->{Stage} };
},
commit 7dfb677fcf6b7771e6dddb7127cd270a76a560e0
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:26:10 2017 +0000
Try harder to load references
Even if it's not in the serialized output (perhaps due to being
excluded) we can still inspect such objects because we have their class
and id, and the database
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index 944c225..71fa923 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -180,9 +180,17 @@ sub _GetRecordByRef {
my $ref = shift;
$ref = $$ref if ref($ref) eq 'SCALAR';
- my ($class) = $ref =~ /^([\w:]+)-/
+
+ return RT->System if $ref eq 'RT::System';
+
+ my ($class, $id) = $ref =~ /^([\w:]+)-.*-(\d+)$/
or return undef;
- return $self->{Records}{$class}{$ref};
+
+ return $self->{Records}{$class}{$ref} || do {
+ my $obj = $class->new(RT->SystemUser);
+ $obj->Load($id);
+ $obj;
+ };
}
sub CanonicalizeReference {
commit 0bbf2d740166bf1f4995afbc31abc6629f219aba
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:33:16 2017 +0000
Handle RightName in initialdata
This is what RT::ACE calls it
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 41aee32..1390507 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -1346,6 +1346,8 @@ sub InsertData {
}
}
+ $item->{Right} = delete $item->{RightName} if $item->{RightName};
+
# Grant it
my @rights = ref($item->{'Right'}) eq 'ARRAY' ? @{$item->{'Right'}} : $item->{'Right'};
foreach my $right ( @rights ) {
commit ccb982d74e6e859b1e1c285e71864080659d264d
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:33:32 2017 +0000
Canonicalize ACLs the way initialdata needs them
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index 71fa923..5d8a7b2 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -237,6 +237,37 @@ sub _CanonicalizeManyToMany {
}
}
+sub CanonicalizeACLs {
+ my $self = shift;
+
+ for my $ace (values %{ $self->{Records}{'RT::ACE'} }) {
+ my $principal = $self->_GetRecordByRef(delete $ace->{PrincipalId});
+ my $object = $self->_GetRecordByRef(delete $ace->{Object});
+
+ if ($principal->IsGroup) {
+ my $domain = $principal->Object->Domain;
+ if ($domain eq 'ACLEquivalence') {
+ $ace->{UserId} = $principal->Object->InstanceObj->Name;
+ }
+ else {
+ $ace->{GroupDomain} = $domain;
+ if ($domain eq 'SystemInternal') {
+ $ace->{GroupType} = $principal->Object->Name;
+ }
+ elsif ($domain eq 'RT::Queue-Role') {
+ $ace->{Queue} = $principal->Object->Instance;
+ }
+ }
+ }
+ else {
+ $ace->{UserId} = $principal->Object->Name;
+ }
+
+ $ace->{ObjectType} = ref($object);
+ $ace->{ObjectId} = $object->Id;
+ }
+}
+
sub CanonicalizeObjects {
my $self = shift;
@@ -282,6 +313,7 @@ sub WriteFile {
my %output;
$self->CanonicalizeObjects;
+ $self->CanonicalizeACLs;
delete $self->{Records}{'RT::Attribute'};
commit 60c3125fd382d45127f49c1118d6e3a0817d6256
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:42:07 2017 +0000
Disambiguate _GetSerializedByRef from _GetObjectByRef
The consuming API is different (serialized hashref vs live object)
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index 5d8a7b2..11272a3 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -175,7 +175,7 @@ my %initialdataType = (
GroupMember => 'Members',
);
-sub _GetRecordByRef {
+sub _GetObjectByRef {
my $self = shift;
my $ref = shift;
@@ -186,11 +186,21 @@ sub _GetRecordByRef {
my ($class, $id) = $ref =~ /^([\w:]+)-.*-(\d+)$/
or return undef;
- return $self->{Records}{$class}{$ref} || do {
- my $obj = $class->new(RT->SystemUser);
- $obj->Load($id);
- $obj;
- };
+ my $obj = $class->new(RT->SystemUser);
+ $obj->Load($id);
+ return $obj;
+}
+
+sub _GetSerializedByRef {
+ my $self = shift;
+ my $ref = shift;
+
+ $ref = $$ref if ref($ref) eq 'SCALAR';
+
+ my ($class) = $ref =~ /^([\w:]+)-/
+ or return undef;
+
+ return $self->{Records}{$class}{$ref};
}
sub CanonicalizeReference {
@@ -199,7 +209,7 @@ sub CanonicalizeReference {
my $context = shift;
my $for_key = shift;
- my $record = $self->_GetRecordByRef($ref)
+ my $record = $self->_GetSerializedByRef($ref)
or return $ref;
return $record->{Name} || $ref;
@@ -241,8 +251,8 @@ sub CanonicalizeACLs {
my $self = shift;
for my $ace (values %{ $self->{Records}{'RT::ACE'} }) {
- my $principal = $self->_GetRecordByRef(delete $ace->{PrincipalId});
- my $object = $self->_GetRecordByRef(delete $ace->{Object});
+ my $principal = $self->_GetObjectByRef(delete $ace->{PrincipalId});
+ my $object = $self->_GetObjectByRef(delete $ace->{Object});
if ($principal->IsGroup) {
my $domain = $principal->Object->Domain;
@@ -289,7 +299,7 @@ sub CanonicalizeObjects {
primary_class => 'RT::CustomRole',
canonicalize_object => sub {
ref($_->{ObjectId})
- ? $self->_GetRecordByRef($_->{ObjectId})->{Name}
+ ? $self->_GetSerializedByRef($_->{ObjectId})->{Name}
: $_->{ObjectId};
},
);
@@ -301,7 +311,7 @@ sub CanonicalizeObjects {
primary_key => 'Queue',
canonicalize_object => sub {
my $object = ref($_->{ObjectId})
- ? $self->_GetRecordByRef($_->{ObjectId})->{Name}
+ ? $self->_GetSerializedByRef($_->{ObjectId})->{Name}
: $_->{ObjectId};
return { ObjectId => $object, Stage => $_->{Stage} };
},
commit 3abcb9e007949ae602caaa71f89d5500af0e70e1
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:47:28 2017 +0000
Handle systemuser
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index 11272a3..d8efbec 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -182,9 +182,10 @@ sub _GetObjectByRef {
$ref = $$ref if ref($ref) eq 'SCALAR';
return RT->System if $ref eq 'RT::System';
+ return RT->SystemUser if $ref eq 'RT::User-RT_System';
my ($class, $id) = $ref =~ /^([\w:]+)-.*-(\d+)$/
- or return undef;
+ or do { warn "Unable to canonicalize ref '$ref'"; return undef };
my $obj = $class->new(RT->SystemUser);
$obj->Load($id);
commit 3f6721c135c0a6d0e6703a9e24e39c266daf0680
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:47:34 2017 +0000
Creator and LastUpdatedBy are always user ids
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index d8efbec..22dd12f 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -210,6 +210,10 @@ sub CanonicalizeReference {
my $context = shift;
my $for_key = shift;
+ if ($for_key eq 'Creator' || $for_key eq 'LastUpdatedBy') {
+ return $self->_GetObjectByRef($ref)->Id;
+ }
+
my $record = $self->_GetSerializedByRef($ref)
or return $ref;
commit ded0d923b6f8ef6a2cead7fa5990ca54c6351010
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:47:53 2017 +0000
Avoid uniqueness violations (for now) by skipping id from initialdata output
This will likely be added in to handle updating existing records
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index 22dd12f..1f63c9c 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -344,6 +344,7 @@ sub WriteFile {
$record->{$key} = $self->CanonicalizeReference($record->{$key}, $record, $key);
}
}
+ delete $record->{id};
push @{ $output{$outtype} }, $record;
}
}
commit 3a9545fa25f9d10e504ee26f272382359931bf8b
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 18:53:01 2017 +0000
Handle passing a hash with Stage as first param to Queue
diff --git a/lib/RT/Handle.pm b/lib/RT/Handle.pm
index 1390507..2011ebd 100644
--- a/lib/RT/Handle.pm
+++ b/lib/RT/Handle.pm
@@ -1424,7 +1424,18 @@ sub InsertData {
my @queues = ref $item->{'Queue'} eq 'ARRAY'? @{ $item->{'Queue'} }: $item->{'Queue'} || 0;
push @queues, 0 unless @queues; # add global queue at least
- my ( $return, $msg ) = $new_entry->Create( %$item, Queue => shift @queues );
+ my %args = %$item;
+ $args{Queue} = shift @queues;
+ if (ref($args{Queue})) {
+ # transform ScripObject->Create API into Scrip->Create API
+ $args{Queue}{Queue} = delete $args{Queue}{ObjectId};
+ %args = (
+ %args,
+ %{ $args{Queue} },
+ );
+ }
+
+ my ( $return, $msg ) = $new_entry->Create(%args);
unless ( $return ) {
$RT::Logger->error( $msg );
next;
commit 7c86a84a029f1ba4431d142a07049326b8638ed0
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 19:01:41 2017 +0000
CanonicalizeUsers
Skip principal fields, add Privileged
diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
index 1f63c9c..dd35607 100644
--- a/lib/RT/Migrate/Serializer/JSON.pm
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -283,6 +283,20 @@ sub CanonicalizeACLs {
}
}
+sub CanonicalizeUsers {
+ my $self = shift;
+
+ for my $user (values %{ $self->{Records}{'RT::User'} }) {
+ delete $user->{Principal};
+ delete $user->{PrincipalId};
+
+ my $object = RT::User->new(RT->SystemUser);
+ $object->Load($user->{id});
+
+ $user->{Privileged} = $object->Privileged ? JSON::true : JSON::false;
+ }
+}
+
sub CanonicalizeObjects {
my $self = shift;
@@ -329,6 +343,7 @@ sub WriteFile {
$self->CanonicalizeObjects;
$self->CanonicalizeACLs;
+ $self->CanonicalizeUsers;
delete $self->{Records}{'RT::Attribute'};
commit a90d18d3267a0c9361dd06c0bf11fd8ea74e73c0
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 19:26:43 2017 +0000
Avoid creating duplicate SystemInternal and RT::Role-System groups
We've seen copies of the SystemInternal groups in the wild, which causes
symptoms such as privileged users being forced into self-service
initialdata is one avenue by which this could happen, as there was no
validation previously
diff --git a/lib/RT/Group.pm b/lib/RT/Group.pm
index e6fe7dd..1593700 100644
--- a/lib/RT/Group.pm
+++ b/lib/RT/Group.pm
@@ -305,10 +305,18 @@ sub _Create {
@_
);
- # Enforce uniqueness on user defined group names
- if ($args{'Domain'} and $args{'Domain'} eq 'UserDefined') {
- my ($ok, $msg) = $self->_ValidateUserDefinedName($args{'Name'});
- return ($ok, $msg) if not $ok;
+ if ($args{'Domain'}) {
+ # Enforce uniqueness on user defined group names
+ if ($args{'Domain'} eq 'UserDefined') {
+ my ($ok, $msg) = $self->_ValidateUserDefinedName($args{'Name'});
+ return ($ok, $msg) if not $ok;
+ }
+
+ # Enforce uniqueness on SystemInternal and system role groups
+ if ($args{'Domain'} eq 'SystemInternal' || $args{'Domain'} eq 'RT::System-Role') {
+ my ($ok, $msg) = $self->_ValidateNameForDomain($args{'Name'}, $args{'Domain'});
+ return ($ok, $msg) if not $ok;
+ }
}
$RT::Handle->BeginTransaction() unless ($args{'InsideTransaction'});
@@ -398,25 +406,42 @@ sub ValidateName {
return $self->SUPER::ValidateName($value);
}
-=head2 _ValidateUserDefinedName VALUE
+=head2 _ValidateNameForDomain VALUE DOMAIN
-Returns true if the user defined group name isn't in use, false otherwise.
+Returns true if the group name isn't in use in the same domain, false otherwise.
=cut
-sub _ValidateUserDefinedName {
- my ($self, $value) = @_;
+sub _ValidateNameForDomain {
+ my ($self, $value, $domain) = @_;
return (0, 'Name is required') unless length $value;
my $dupcheck = RT::Group->new(RT->SystemUser);
- $dupcheck->LoadUserDefinedGroup($value);
+ if ($domain eq 'UserDefined') {
+ $dupcheck->LoadUserDefinedGroup($value);
+ }
+ else {
+ $dupcheck->LoadByCols(Domain => $domain, Name => $value);
+ }
if ( $dupcheck->id && ( !$self->id || $self->id != $dupcheck->id ) ) {
return ( 0, $self->loc( "Group name '[_1]' is already in use", $value ) );
}
return 1;
}
+=head2 _ValidateUserDefinedName VALUE
+
+Returns true if the user defined group name isn't in use, false otherwise.
+
+=cut
+
+sub _ValidateUserDefinedName {
+ my ($self, $value) = @_;
+
+ return $self->_ValidateNameForDomain($value, 'UserDefined');
+}
+
=head2 _CreateACLEquivalenceGroup { Principal }
A helper subroutine which creates a group containing only
commit c6e016974d8df964d3815271f4ea605e3b63add8
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Mar 20 20:56:10 2017 +0000
First cut of initialdata roundtrip tests
This relies on an extension inside RT, which is obviously unsuitable.
But during development it's the best place for tests
diff --git a/t/api/initialdata-roundtrip.t b/t/api/initialdata-roundtrip.t
new file mode 100644
index 0000000..83e387c
--- /dev/null
+++ b/t/api/initialdata-roundtrip.t
@@ -0,0 +1,167 @@
+use strict;
+use warnings;
+
+use RT::Test tests => undef, config => << 'CONFIG';
+Plugin('RT::Extension::Initialdata::JSON');
+Set($InitialdataFormatHandlers, [ 'perl', 'RT::Extension::Initialdata::JSON' ]);
+CONFIG
+
+my @tests = (
+ {
+ name => 'Simple user-defined group',
+ create => sub {
+ my $group = RT::Group->new(RT->SystemUser);
+ my ($ok, $msg) = $group->CreateUserDefinedGroup(Name => 'Staff');
+ ok($ok, $msg);
+ },
+ absent => sub {
+ my $group = RT::Group->new(RT->SystemUser);
+ $group->LoadUserDefinedGroup('Staff');
+ ok(!$group->Id, 'No such group');
+ },
+ present => sub {
+ my $group = RT::Group->new(RT->SystemUser);
+ $group->LoadUserDefinedGroup('Staff');
+ ok($group->Id, 'Loaded group');
+ is($group->Name, 'Staff', 'Group name');
+ is($group->Domain, 'UserDefined', 'Domain');
+ },
+ },
+
+ {
+ name => 'Custom field on two queues',
+ create => sub {
+ my $bugs = RT::Queue->new(RT->SystemUser);
+ my ($ok, $msg) = $bugs->Create(Name => 'Bugs');
+ ok($ok, $msg);
+
+ my $features = RT::Queue->new(RT->SystemUser);
+ ($ok, $msg) = $features->Create(Name => 'Features');
+ ok($ok, $msg);
+
+ my $cf = RT::CustomField->new(RT->SystemUser);
+ ($ok, $msg) = $cf->Create(
+ Name => 'Fixed In',
+ Type => 'SelectSingle',
+ LookupType => RT::Queue->CustomFieldLookupType,
+ );
+ ok($ok, $msg);
+
+ ($ok, $msg) = $cf->AddToObject($bugs);
+ ok($ok, $msg);
+
+ ($ok, $msg) = $cf->AddToObject($features);
+ ok($ok, $msg);
+ },
+ present => sub {
+ my $bugs = RT::Queue->new(RT->SystemUser);
+ $bugs->Load('Bugs');
+ ok($bugs->Id, 'Bugs queue loaded');
+ is($bugs->Name, 'Bugs');
+
+ my $features = RT::Queue->new(RT->SystemUser);
+ $features->Load('Features');
+ ok($features->Id, 'Features queue loaded');
+ is($features->Name, 'Features');
+
+ my $cf = RT::CustomField->new(RT->SystemUser);
+ $cf->Load('Fixed In');
+ ok($cf->Id, 'Features queue loaded');
+ is($cf->Name, 'Fixed In');
+ is($cf->Type, 'Select', 'Type');
+ is($cf->MaxValues, 1, 'MaxValues');
+ is($cf->LookupType, RT::Queue->CustomFieldLookupType, 'LookupType');
+ },
+ },
+);
+
+my $id = 0;
+for my $test (@tests) {
+ $id++;
+ my $directory = File::Spec->catdir(RT::Test->temp_directory, "export-$id");
+
+ # we get a lot of warnings about already-existing objects; suppress them
+ # for now until we clean it up
+ my $warn = $SIG{__WARN__};
+ local $SIG{__WARN__} = sub {
+ return if $_[0] =~ join '|', (
+ qr/^Name in use$/,
+ qr/^Group name '.*' is already in use$/,
+ qr/^A Template with that name already exists$/,
+ qr/^.* already has the right .* on .*$/,
+ qr/^Invalid value for Name$/,
+ qr/^Queue already exists$/,
+ qr/^Use of uninitialized value in/,
+ );
+
+ # Avoid reporting this anonymous call frame as the source of the warning
+ goto &$warn;
+ };
+
+ subtest "$test->{name} (ordinary creation)" => sub {
+ autorollback(sub {
+ $test->{absent}->() if $test->{absent};
+ $test->{create}->();
+ $test->{present}->() if $test->{present};
+ export_initialdata($directory);
+ });
+ };
+
+ subtest "$test->{name} (from initialdata)" => sub {
+ autorollback(sub {
+ $test->{absent}->() if $test->{absent};
+ import_initialdata($directory);
+ $test->{present}->() if $test->{present};
+ });
+ };
+}
+
+done_testing();
+
+# vvvv here be dragons vvvv
+
+sub autorollback {
+ my $code = shift;
+
+ $RT::Handle->BeginTransaction;
+ {
+ # avoid "Rollback and commit are mixed while escaping nested transaction" warnings
+ # due to (begin; (begin; commit); rollback)
+ no warnings 'redefine';
+ local *DBIx::SearchBuilder::Handle::BeginTransaction = sub {};
+ local *DBIx::SearchBuilder::Handle::Commit = sub {};
+ local *DBIx::SearchBuilder::Handle::Rollback = sub {};
+
+ $code->();
+ }
+ $RT::Handle->Rollback;
+}
+
+sub export_initialdata {
+ my $directory = shift;
+ local @RT::Record::ISA = qw( DBIx::SearchBuilder::Record RT::Base );
+
+ use RT::Migrate::Serializer::JSON;
+ my $migrator = RT::Migrate::Serializer::JSON->new(
+ Directory => $directory,
+ Verbose => 0,
+ AllUsers => 0,
+ FollowACL => 1,
+ FollowScrips => 1,
+ FollowTransactions => 0,
+ );
+
+ $migrator->Export;
+}
+
+sub import_initialdata {
+ my $directory = shift;
+ my $initialdata = File::Spec->catfile($directory, "initialdata.json");
+
+ ok(-e $initialdata, "File $initialdata exists");
+
+ my ($rv, $msg) = RT->DatabaseHandle->InsertData( $initialdata, undef, disconnect_after => 0 );
+ ok($rv, "Inserted test data from $initialdata")
+ or diag "Error: $msg";
+}
+
-----------------------------------------------------------------------
More information about the rt-commit
mailing list