[Rt-commit] rt branch, 4.4/initial-custom-field, created. rt-4.4.0rc2-27-g2928131
Shawn Moore
shawn at bestpractical.com
Wed Apr 20 17:21:53 EDT 2016
The branch, 4.4/initial-custom-field has been created
at 2928131f083ca86b334a8c89c31043cd6ac2d82e (commit)
- Log -----------------------------------------------------------------
commit 60c12a84b12151f16e4454a26ca9ccb11ad7cd38
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Mon Dec 28 02:12:21 2015 +0000
Add a new SetInitialCustomField right
This lets you set custom field values on records (tickets, assets,
articles) that you're creating. But it does not permit modifying the
custom field values of existing records.
Fixes: I#14974
diff --git a/lib/RT/Article.pm b/lib/RT/Article.pm
index 66c3b4c..88b01b5 100644
--- a/lib/RT/Article.pm
+++ b/lib/RT/Article.pm
@@ -147,7 +147,8 @@ sub Create {
: (Value => $value)
),
Field => $cf,
- RecordTransaction => 0
+ RecordTransaction => 0,
+ ForCreation => 1,
);
unless ($cfid) {
diff --git a/lib/RT/Asset.pm b/lib/RT/Asset.pm
index 2ebc56b..4effee1 100644
--- a/lib/RT/Asset.pm
+++ b/lib/RT/Asset.pm
@@ -293,7 +293,8 @@ sub Create {
? %$value
: (Value => $value)),
Field => $cf,
- RecordTransaction => 0
+ RecordTransaction => 0,
+ ForCreation => 1,
);
unless ($cfid) {
RT->DatabaseHandle->Rollback();
diff --git a/lib/RT/Catalog.pm b/lib/RT/Catalog.pm
index 66f613a..59cd0ea 100644
--- a/lib/RT/Catalog.pm
+++ b/lib/RT/Catalog.pm
@@ -83,8 +83,9 @@ __PACKAGE__->AddRight( General => ShowAsset => 'See assets' ); #loc
__PACKAGE__->AddRight( Staff => CreateAsset => 'Create assets' ); #loc
__PACKAGE__->AddRight( Staff => ModifyAsset => 'Modify assets' ); #loc
-__PACKAGE__->AddRight( General => SeeCustomField => 'View custom field values' ); # loc
-__PACKAGE__->AddRight( Staff => ModifyCustomField => 'Modify custom field values' ); # loc
+__PACKAGE__->AddRight( General => SeeCustomField => 'View custom field values' ); # loc
+__PACKAGE__->AddRight( Staff => ModifyCustomField => 'Modify custom field values' ); # loc
+__PACKAGE__->AddRight( Staff => SetInitialCustomField => 'Add custom field values only at object creation time'); # loc
RT::ACE->RegisterCacheHandler(sub {
my %args = (
diff --git a/lib/RT/Class.pm b/lib/RT/Class.pm
index 04bd5a8..66f59c4 100644
--- a/lib/RT/Class.pm
+++ b/lib/RT/Class.pm
@@ -84,19 +84,20 @@ sub Load {
}
}
-__PACKAGE__->AddRight( Staff => SeeClass => 'See that this class exists'); # loc
-__PACKAGE__->AddRight( Staff => CreateArticle => 'Create articles in this class'); # loc
-__PACKAGE__->AddRight( General => ShowArticle => 'See articles in this class'); # loc
-__PACKAGE__->AddRight( Staff => ShowArticleHistory => 'See changes to articles in this class'); # loc
-__PACKAGE__->AddRight( General => SeeCustomField => 'View custom field values' ); # loc
-__PACKAGE__->AddRight( Staff => ModifyArticle => 'Modify articles in this class'); # loc
-__PACKAGE__->AddRight( Staff => ModifyArticleTopics => 'Modify topics for articles in this class'); # loc
-__PACKAGE__->AddRight( Staff => ModifyCustomField => 'Modify custom field values' ); # loc
-__PACKAGE__->AddRight( Admin => AdminClass => 'Modify metadata and custom fields for this class'); # loc
-__PACKAGE__->AddRight( Admin => AdminTopics => 'Modify topic hierarchy associated with this class'); # loc
-__PACKAGE__->AddRight( Admin => ShowACL => 'Display Access Control List'); # loc
-__PACKAGE__->AddRight( Admin => ModifyACL => 'Create, modify and delete Access Control List entries'); # loc
-__PACKAGE__->AddRight( Staff => DisableArticle => 'Disable articles in this class'); # loc
+__PACKAGE__->AddRight( Staff => SeeClass => 'See that this class exists'); # loc
+__PACKAGE__->AddRight( Staff => CreateArticle => 'Create articles in this class'); # loc
+__PACKAGE__->AddRight( General => ShowArticle => 'See articles in this class'); # loc
+__PACKAGE__->AddRight( Staff => ShowArticleHistory => 'See changes to articles in this class'); # loc
+__PACKAGE__->AddRight( General => SeeCustomField => 'View custom field values' ); # loc
+__PACKAGE__->AddRight( Staff => ModifyArticle => 'Modify articles in this class'); # loc
+__PACKAGE__->AddRight( Staff => ModifyArticleTopics => 'Modify topics for articles in this class'); # loc
+__PACKAGE__->AddRight( Staff => ModifyCustomField => 'Modify custom field values' ); # loc
+__PACKAGE__->AddRight( Staff => SetInitialCustomField => 'Add custom field values only at object creation time'); # loc
+__PACKAGE__->AddRight( Admin => AdminClass => 'Modify metadata and custom fields for this class'); # loc
+__PACKAGE__->AddRight( Admin => AdminTopics => 'Modify topic hierarchy associated with this class'); # loc
+__PACKAGE__->AddRight( Admin => ShowACL => 'Display Access Control List'); # loc
+__PACKAGE__->AddRight( Admin => ModifyACL => 'Create, modify and delete Access Control List entries'); # loc
+__PACKAGE__->AddRight( Staff => DisableArticle => 'Disable articles in this class'); # loc
# {{{ Create
diff --git a/lib/RT/CustomField.pm b/lib/RT/CustomField.pm
index 1149d38..f0b7521 100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@ -214,6 +214,7 @@ __PACKAGE__->AddRight( General => SeeCustomField => 'View custom fields'
__PACKAGE__->AddRight( Admin => AdminCustomField => 'Create, modify and delete custom fields'); # loc
__PACKAGE__->AddRight( Admin => AdminCustomFieldValues => 'Create, modify and delete custom fields values'); # loc
__PACKAGE__->AddRight( Staff => ModifyCustomField => 'Add, modify and delete custom field values for objects'); # loc
+__PACKAGE__->AddRight( Staff => SetInitialCustomField => 'Add custom field values only at object creation time'); # loc
=head1 NAME
@@ -1639,11 +1640,15 @@ sub AddValueForObject {
Content => undef,
LargeContent => undef,
ContentType => undef,
+ ForCreation => 0,
@_
);
my $obj = $args{'Object'} or return ( 0, $self->loc('Invalid object') );
- unless ( $self->CurrentUserHasRight('ModifyCustomField') ) {
+ unless (
+ $self->CurrentUserHasRight('ModifyCustomField') ||
+ ($args{ForCreation} && $self->CurrentUserHasRight('SetInitialCustomField'))
+ ) {
return ( 0, $self->loc('Permission Denied') );
}
diff --git a/lib/RT/Queue.pm b/lib/RT/Queue.pm
index 83e2b3b..44e3dae 100644
--- a/lib/RT/Queue.pm
+++ b/lib/RT/Queue.pm
@@ -100,16 +100,17 @@ use RT::CustomRoles;
use RT::ACL;
use RT::Interface::Email;
-__PACKAGE__->AddRight( General => SeeQueue => 'View queue' ); # loc
-__PACKAGE__->AddRight( Admin => AdminQueue => 'Create, modify and delete queue' ); # loc
-__PACKAGE__->AddRight( Admin => ShowACL => 'Display Access Control List' ); # loc
-__PACKAGE__->AddRight( Admin => ModifyACL => 'Create, modify and delete Access Control List entries' ); # loc
-__PACKAGE__->AddRight( Admin => ModifyQueueWatchers => 'Modify queue watchers' ); # loc
-__PACKAGE__->AddRight( General => SeeCustomField => 'View custom field values' ); # loc
-__PACKAGE__->AddRight( Staff => ModifyCustomField => 'Modify custom field values' ); # loc
-__PACKAGE__->AddRight( Admin => AssignCustomFields => 'Assign and remove queue custom fields' ); # loc
-__PACKAGE__->AddRight( Admin => ModifyTemplate => 'Modify Scrip templates' ); # loc
-__PACKAGE__->AddRight( Admin => ShowTemplate => 'View Scrip templates' ); # loc
+__PACKAGE__->AddRight( General => SeeQueue => 'View queue' ); # loc
+__PACKAGE__->AddRight( Admin => AdminQueue => 'Create, modify and delete queue' ); # loc
+__PACKAGE__->AddRight( Admin => ShowACL => 'Display Access Control List' ); # loc
+__PACKAGE__->AddRight( Admin => ModifyACL => 'Create, modify and delete Access Control List entries' ); # loc
+__PACKAGE__->AddRight( Admin => ModifyQueueWatchers => 'Modify queue watchers' ); # loc
+__PACKAGE__->AddRight( General => SeeCustomField => 'View custom field values' ); # loc
+__PACKAGE__->AddRight( Staff => ModifyCustomField => 'Modify custom field values' ); # loc
+__PACKAGE__->AddRight( Staff => SetInitialCustomField => 'Add custom field values only at object creation time'); # loc
+__PACKAGE__->AddRight( Admin => AssignCustomFields => 'Assign and remove queue custom fields' ); # loc
+__PACKAGE__->AddRight( Admin => ModifyTemplate => 'Modify Scrip templates' ); # loc
+__PACKAGE__->AddRight( Admin => ShowTemplate => 'View Scrip templates' ); # loc
__PACKAGE__->AddRight( Admin => ModifyScrips => 'Modify Scrips' ); # loc
__PACKAGE__->AddRight( Admin => ShowScrips => 'View Scrips' ); # loc
diff --git a/lib/RT/Record.pm b/lib/RT/Record.pm
index ae0262d..de03b30 100644
--- a/lib/RT/Record.pm
+++ b/lib/RT/Record.pm
@@ -1937,6 +1937,7 @@ sub _AddCustomFieldValue {
LargeContent => undef,
ContentType => undef,
RecordTransaction => 1,
+ ForCreation => 0,
@_
);
@@ -2015,6 +2016,7 @@ sub _AddCustomFieldValue {
Content => $args{'Value'},
LargeContent => $args{'LargeContent'},
ContentType => $args{'ContentType'},
+ ForCreation => $args{'ForCreation'},
);
unless ( $new_value_id ) {
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index a786a83..48728a2 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -502,6 +502,7 @@ sub Create {
),
Field => $cfid,
RecordTransaction => 0,
+ ForCreation => 1,
);
push @non_fatal_errors, $msg unless $status;
}
diff --git a/share/html/Articles/Article/Edit.html b/share/html/Articles/Article/Edit.html
index 8f3b923..b67043a 100644
--- a/share/html/Articles/Article/Edit.html
+++ b/share/html/Articles/Article/Edit.html
@@ -72,7 +72,8 @@
CFContent => \%CFContent,
ClassObj => $ClassObj,
%ARGS,
- id =>$id,
+ id => $id,
+ ForCreation => ($id eq 'new'),
&>
<tr>
diff --git a/share/html/Asset/Create.html b/share/html/Asset/Create.html
index 2b97d7c..498dcdf 100644
--- a/share/html/Asset/Create.html
+++ b/share/html/Asset/Create.html
@@ -94,7 +94,9 @@
Object => $asset,
TitleBoxARGS => { title_class => "inverse" },
KeepValue => 1,
- CustomFieldGenerator => sub { $catalog->AssetCustomFields } &>
+ CustomFieldGenerator => sub { $catalog->AssetCustomFields },
+ ForCreation => 1,
+ &>
</div>
<& /Elements/Submit, Label => loc('Create asset') &>
diff --git a/share/html/Elements/EditCustomFields b/share/html/Elements/EditCustomFields
index 3c7ba8c..4e96090 100644
--- a/share/html/Elements/EditCustomFields
+++ b/share/html/Elements/EditCustomFields
@@ -51,7 +51,8 @@
<<% $WRAP %> class="edit-custom-fields">
% }
% while ( my $CustomField = $CustomFields->Next ) {
-% next unless $CustomField->CurrentUserHasRight('ModifyCustomField');
+% next unless $CustomField->CurrentUserHasRight('ModifyCustomField')
+% || ($ForCreation && $CustomField->CurrentUserHasRight('SetInitialCustomField'));
% my $Type = $CustomField->Type || 'Unknown';
<<% $FIELD %> class="edit-custom-field cftype-<% $Type %>">
@@ -116,4 +117,5 @@ $Grouping => undef
$AsTable => 1
$InTable => 0
$ShowHints => 1
+$ForCreation => 0
</%ARGS>
diff --git a/share/html/Ticket/Create.html b/share/html/Ticket/Create.html
index 6881b62..63a8db6 100644
--- a/share/html/Ticket/Create.html
+++ b/share/html/Ticket/Create.html
@@ -121,6 +121,7 @@
CustomFields => $QueueObj->TicketCustomFields,
Grouping => 'Basics',
InTable => 1,
+ ForCreation => 1,
&>
<& /Ticket/Elements/EditTransactionCustomFields, %ARGS, QueueObj => $QueueObj, InTable => 1 &>
</table>
@@ -134,6 +135,7 @@
%ARGS,
Object => $ticket,
CustomFieldGenerator => sub { $QueueObj->TicketCustomFields },
+ ForCreation => 1,
&>
</div>
@@ -210,6 +212,7 @@
CustomFields => $QueueObj->TicketCustomFields,
Grouping => 'People',
InTable => 1,
+ ForCreation => 1,
&>
<tr>
@@ -304,6 +307,7 @@
CustomFields => $QueueObj->TicketCustomFields,
Grouping => 'Dates',
InTable => 1,
+ ForCreation => 1,
&>
</table>
</&>
commit dd4105f6a7b8d20f8ef57fc6489ea574c1501bfd
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Thu Mar 3 23:19:07 2016 +0000
Hide empty "edit custom fields" panels
The titlebox widget hides its chrome when its content contains only
whitespace characters. This commit suppresses all output from
EditCustomFields when there are no editable custom fields. This causes
the titlebox to render nothing, rather than a panel with
chrome but without content.
Beware that the BeforeCustomFields and AfterCustomFields callbacks
_may_ generate output even when there are no editable custom fields.
This commit was carefully written to handle such cases by continuing to
invoke those callbacks unconditionally.
As best I can tell, we have always had this bug surviving through
several refactorings. The only conditions under which we successfully
hid "edit custom field" panels is for users who had no rights to _see_
any custom fields, since that triggers the following long-standing
short-circuit return:
# don't print anything if there is no custom fields
return unless $CustomFields->First;
If you can _see_ any custom fields, they are included in the
$CustomFields collection, causing us to skip right past that
short-circuit return. Then, we begin rendering with a <div> or <table>
container tag. We then iterate over $CustomFields, skipping any custom
fields you have no modify permissions for. Finally we close the
container tag. So in the failure case, even though there was no
_visible_ content, there was still some non-whitespace content (the HTML
of the container tag) being produced, which was enough to cause the
titlebox to render its chrome.
diff --git a/share/html/Elements/EditCustomFields b/share/html/Elements/EditCustomFields
index 4e96090..7e21d31 100644
--- a/share/html/Elements/EditCustomFields
+++ b/share/html/Elements/EditCustomFields
@@ -47,12 +47,18 @@
%# END BPS TAGGED BLOCK }}}
% $m->callback( CallbackName => 'BeforeCustomFields', Object => $Object,
% Grouping => $Grouping, ARGSRef => \%ARGS, CustomFields => $CustomFields);
+
+%# only show the wrapper if there are editable custom fields, so we can
+%# suppress the empty titlebox. we do this in such a way that we still call the
+%# BeforeCustomFields and AfterCustomFields callbacks (rather than returning
+%# from the INIT block) to maintain compatibility with old behavior
+
+% if (@CustomFields) {
+
% if ( $WRAP ) {
<<% $WRAP %> class="edit-custom-fields">
% }
-% while ( my $CustomField = $CustomFields->Next ) {
-% next unless $CustomField->CurrentUserHasRight('ModifyCustomField')
-% || ($ForCreation && $CustomField->CurrentUserHasRight('SetInitialCustomField'));
+% for my $CustomField (@CustomFields) {
% my $Type = $CustomField->Type || 'Unknown';
<<% $FIELD %> class="edit-custom-field cftype-<% $Type %>">
@@ -86,6 +92,9 @@
% if ( $WRAP ) {
</<% $WRAP %>>
% }
+
+% }
+
% $m->callback( CallbackName => 'AfterCustomFields', Object => $Object,
% Grouping => $Grouping, ARGSRef => \%ARGS );
<%INIT>
@@ -95,9 +104,14 @@ $CustomFields->LimitToGrouping( $Object => $Grouping ) if defined $Grouping;
$m->callback( %ARGS, CallbackName => 'MassageCustomFields', CustomFields => $CustomFields );
-# don't print anything if there is no custom fields
-return unless $CustomFields->First;
$CustomFields->GotoFirstItem;
+my @CustomFields;
+while ( my $CustomField = $CustomFields->Next ) {
+ next unless $CustomField->CurrentUserHasRight('ModifyCustomField')
+ || ($ForCreation && $CustomField->CurrentUserHasRight('SetInitialCustomField'));
+
+ push @CustomFields, $CustomField;
+}
$AsTable ||= $InTable;
my $FIELD = $AsTable ? 'tr' : 'div';
commit fe7ca40bf2d5bae87b8473b796643467a4a62f58
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Wed Apr 20 18:51:26 2016 +0000
Add a $CF->CurrentUserCanSee method and switch to it
This is to prepare for allowing users to see custom fields for which they
do not have SeeCustomField, but for those who should still have access
thanks to SetInitialCustomField
diff --git a/lib/RT/CustomField.pm b/lib/RT/CustomField.pm
index f0b7521..29780f6 100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@ -611,7 +611,7 @@ sub Values {
my $cf_values = $class->new( $self->CurrentUser );
$cf_values->SetCustomFieldObject( $self );
# if the user has no rights, return an empty object
- if ( $self->id && $self->CurrentUserHasRight( 'SeeCustomField') ) {
+ if ( $self->id && $self->CurrentUserCanSee ) {
$cf_values->LimitToCustomField( $self->Id );
} else {
$cf_values->Limit( FIELD => 'id', VALUE => 0, SUBCLAUSE => 'acl' );
@@ -1050,7 +1050,7 @@ sub _Value {
return undef unless $self->id;
# we need to do the rights check
- unless ( $self->CurrentUserHasRight('SeeCustomField') ) {
+ unless ( $self->CurrentUserCanSee ) {
$RT::Logger->debug(
"Permission denied. User #". $self->CurrentUser->id
." has no SeeCustomField right on CF #". $self->id
@@ -1870,7 +1870,7 @@ sub ValuesForObject {
my $object = shift;
my $values = RT::ObjectCustomFieldValues->new($self->CurrentUser);
- unless ($self->id and $self->CurrentUserHasRight('SeeCustomField')) {
+ unless ($self->id and $self->CurrentUserCanSee) {
# Return an empty object if they have no rights to see
$values->Limit( FIELD => "id", VALUE => 0, SUBCLAUSE => "ACL" );
return ($values);
@@ -1882,6 +1882,16 @@ sub ValuesForObject {
return ($values);
}
+=head2 CurrentUserCanSee
+
+If the user has SeeCustomField they can see this custom field and its details.
++
+=cut
+
+sub CurrentUserCanSee {
+ my $self = shift;
+ return $self->CurrentUserHasRight('SeeCustomField');
+}
=head2 RegisterLookupType LOOKUPTYPE FRIENDLYNAME
@@ -1971,7 +1981,7 @@ sub _URLTemplate {
}
return ( 1, $self->loc('Updated') );
} else {
- unless ( $self->id && $self->CurrentUserHasRight('SeeCustomField') ) {
+ unless ( $self->id && $self->CurrentUserCanSee ) {
return (undef);
}
@@ -1993,7 +2003,7 @@ sub SetBasedOn {
$cf->Load( ref $value ? $value->id : $value );
return (0, "Permission Denied")
- unless $cf->id && $cf->CurrentUserHasRight('SeeCustomField');
+ unless $cf->id && $cf->CurrentUserCanSee;
# XXX: Remove this restriction once we support lists and cascaded selects
if ( $self->RenderType =~ /List/ ) {
diff --git a/lib/RT/CustomFields.pm b/lib/RT/CustomFields.pm
index e95dc7c..1a8054c 100644
--- a/lib/RT/CustomFields.pm
+++ b/lib/RT/CustomFields.pm
@@ -403,7 +403,8 @@ sub AddRecord {
my ($record) = @_;
$record->SetContextObject( $self->ContextObject );
- return unless $record->CurrentUserHasRight('SeeCustomField');
+ return unless $record->CurrentUserCanSee;
+
return $self->SUPER::AddRecord( $record );
}
diff --git a/lib/RT/ObjectCustomFieldValue.pm b/lib/RT/ObjectCustomFieldValue.pm
index 4579a38..4d0ab34 100644
--- a/lib/RT/ObjectCustomFieldValue.pm
+++ b/lib/RT/ObjectCustomFieldValue.pm
@@ -221,7 +221,7 @@ my $re_ip_serialized = qr/$re_ip_sunit(?:\.$re_ip_sunit){3}/;
sub Content {
my $self = shift;
- return undef unless $self->CustomFieldObj->CurrentUserHasRight('SeeCustomField');
+ return undef unless $self->CustomFieldObj->CurrentUserCanSee;
my $content = $self->_Value('Content');
if ( $self->CustomFieldObj->Type eq 'IPAddress'
diff --git a/lib/RT/Transaction.pm b/lib/RT/Transaction.pm
index b01e976..145ca34 100644
--- a/lib/RT/Transaction.pm
+++ b/lib/RT/Transaction.pm
@@ -1423,7 +1423,7 @@ sub CurrentUserCanSee {
my $cf = RT::CustomField->new( $self->CurrentUser );
$cf->SetContextObject( $self->Object );
$cf->Load( $cf_id );
- return 0 unless $cf->CurrentUserHasRight('SeeCustomField');
+ return 0 unless $cf->CurrentUserCanSee;
}
# Transactions that might have changed the ->Object's visibility to
commit c9c6f3534cf190e24824d1104ca6b934e878fbb0
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Wed Apr 20 19:57:29 2016 +0000
Support passing the CF directly to CustomFieldValueIsEmpty
No reason to reload it if we already have the object
diff --git a/lib/RT/Action/CreateTickets.pm b/lib/RT/Action/CreateTickets.pm
index d19f152..824c1ab 100644
--- a/lib/RT/Action/CreateTickets.pm
+++ b/lib/RT/Action/CreateTickets.pm
@@ -1140,7 +1140,7 @@ sub UpdateCustomFields {
foreach my $value (@values) {
next if $ticket->CustomFieldValueIsEmpty(
- Field => $cf,
+ Field => $CustomFieldObj,
Value => $value,
);
my ( $val, $msg ) = $ticket->AddCustomFieldValue(
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index ab13a43..266ba6e 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -3211,7 +3211,7 @@ sub _ProcessObjectCustomFieldUpdates {
if ( $arg eq 'AddValue' || $arg eq 'Value' ) {
foreach my $value (@values) {
next if $args{'Object'}->CustomFieldValueIsEmpty(
- Field => $cf->id,
+ Field => $cf,
Value => $value,
);
my ( $val, $msg ) = $args{'Object'}->AddCustomFieldValue(
diff --git a/lib/RT/Record.pm b/lib/RT/Record.pm
index de03b30..8947a91 100644
--- a/lib/RT/Record.pm
+++ b/lib/RT/Record.pm
@@ -2124,7 +2124,7 @@ sub AddCustomFieldDefaultValues {
my $values = $cf->DefaultValues( Object => $on || RT->System );
foreach my $value ( UNIVERSAL::isa( $values => 'ARRAY' ) ? @$values : $values ) {
next if $self->CustomFieldValueIsEmpty(
- Field => $cf->id,
+ Field => $cf,
Value => $value,
);
@@ -2161,7 +2161,10 @@ sub CustomFieldValueIsEmpty {
my $value = $args{Value};
return 1 unless defined $value && length $value;
- my $cf = $self->LoadCustomFieldByIdentifier( $args{'Field'} );
+ my $cf = ref($args{'Field'})
+ ? $args{'Field'}
+ : $self->LoadCustomFieldByIdentifier( $args{'Field'} );
+
if ($cf) {
if ( $cf->Type =~ /^Date(?:Time)?$/ ) {
my $DateObj = RT::Date->new( $self->CurrentUser );
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index 48728a2..b65aae4 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -490,7 +490,7 @@ sub Create {
UNIVERSAL::isa( $args{$arg} => 'ARRAY' ) ? @{ $args{$arg} } : ( $args{$arg} ) )
{
next if $self->CustomFieldValueIsEmpty(
- Field => $cfid,
+ Field => $cf,
Value => $value,
);
diff --git a/lib/RT/Transaction.pm b/lib/RT/Transaction.pm
index 145ca34..9d1b009 100644
--- a/lib/RT/Transaction.pm
+++ b/lib/RT/Transaction.pm
@@ -1539,7 +1539,7 @@ sub UpdateCustomFields {
my $value ( UNIVERSAL::isa( $values, 'ARRAY' ) ? @$values : $values )
{
next if $self->CustomFieldValueIsEmpty(
- Field => $cfid,
+ Field => $cf,
Value => $value,
);
$self->_AddCustomFieldValue(
commit 2a66732416de5b9bbc4648c3a6e022b5b7de9b1f
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Wed Apr 20 21:19:56 2016 +0000
Avoid constantly reloading the OCFV CustomFieldObj
This code was written as though OCFV kept its CF object in cache, but
it doesn't.
diff --git a/lib/RT/ObjectCustomFieldValue.pm b/lib/RT/ObjectCustomFieldValue.pm
index 4d0ab34..70a96ac 100644
--- a/lib/RT/ObjectCustomFieldValue.pm
+++ b/lib/RT/ObjectCustomFieldValue.pm
@@ -221,11 +221,13 @@ my $re_ip_serialized = qr/$re_ip_sunit(?:\.$re_ip_sunit){3}/;
sub Content {
my $self = shift;
- return undef unless $self->CustomFieldObj->CurrentUserCanSee;
+ my $cf = $self->CustomFieldObj;
+
+ return undef unless $cf->CurrentUserCanSee;
my $content = $self->_Value('Content');
- if ( $self->CustomFieldObj->Type eq 'IPAddress'
- || $self->CustomFieldObj->Type eq 'IPAddressRange' )
+ if ( $cf->Type eq 'IPAddress'
+ || $cf->Type eq 'IPAddressRange' )
{
require Net::IP;
@@ -236,7 +238,7 @@ sub Content {
$content = Net::IP::ip_compress_address($1, 6);
}
- return $content if $self->CustomFieldObj->Type eq 'IPAddress';
+ return $content if $cf->Type eq 'IPAddress';
my $large_content = $self->__Value('LargeContent');
if ( $large_content =~ /^\s*($re_ip_serialized)\s*$/o ) {
commit 2928131f083ca86b334a8c89c31043cd6ac2d82e
Author: Shawn M Moore <shawn at bestpractical.com>
Date: Wed Apr 20 20:04:02 2016 +0000
Allow SetInitialCustomFieldValue without SeeCustomField
This allows you to set up permissions such that users can set custom
fields on initial ticket create but not see them on ticket display,
nor edit them on ticket modify.
We have to propagate "this is for creation so
SetInitialCustomFieldValue is enough to see the CF" from the web
interface down through to custom field rights checking.
diff --git a/lib/RT/CustomField.pm b/lib/RT/CustomField.pm
index 29780f6..af2da9f 100644
--- a/lib/RT/CustomField.pm
+++ b/lib/RT/CustomField.pm
@@ -1885,12 +1885,22 @@ sub ValuesForObject {
=head2 CurrentUserCanSee
If the user has SeeCustomField they can see this custom field and its details.
-+
+
+Otherwise, if the user has SetInitialCustomField and this is being used in a
+"create" context, then they can see this custom field and its details. This
+allows you to set up custom fields that are only visible on create pages and
+are then inaccessible.
+
=cut
sub CurrentUserCanSee {
my $self = shift;
- return $self->CurrentUserHasRight('SeeCustomField');
+ return 1 if $self->CurrentUserHasRight('SeeCustomField');
+
+ return 1 if $self->{include_set_initial}
+ && $self->CurrentUserHasRight('SetInitialCustomField');
+
+ return 0;
}
=head2 RegisterLookupType LOOKUPTYPE FRIENDLYNAME
diff --git a/lib/RT/CustomFields.pm b/lib/RT/CustomFields.pm
index 1a8054c..4cc5961 100644
--- a/lib/RT/CustomFields.pm
+++ b/lib/RT/CustomFields.pm
@@ -403,6 +403,8 @@ sub AddRecord {
my ($record) = @_;
$record->SetContextObject( $self->ContextObject );
+ $record->{include_set_initial} = $self->{include_set_initial};
+
return unless $record->CurrentUserCanSee;
return $self->SUPER::AddRecord( $record );
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index 266ba6e..563b09e 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -3306,6 +3306,7 @@ sub ProcessObjectCustomFieldUpdatesForCreate {
# we're only interested in new objects, so only look at $id == 0
for my $cfid (keys %{ $custom_fields{$class}{0} || {} }) {
my $cf = RT::CustomField->new( $session{'CurrentUser'} );
+ $cf->{include_set_initial} = 1;
if ($context) {
my $system_cf = RT::CustomField->new( RT->SystemUser );
$system_cf->LoadById($cfid);
diff --git a/lib/RT/ObjectCustomFieldValue.pm b/lib/RT/ObjectCustomFieldValue.pm
index 70a96ac..0909f54 100644
--- a/lib/RT/ObjectCustomFieldValue.pm
+++ b/lib/RT/ObjectCustomFieldValue.pm
@@ -222,6 +222,7 @@ sub Content {
my $self = shift;
my $cf = $self->CustomFieldObj;
+ $cf->{include_set_initial} = $self->{include_set_initial};
return undef unless $cf->CurrentUserCanSee;
diff --git a/lib/RT/Record.pm b/lib/RT/Record.pm
index 8947a91..3018ad8 100644
--- a/lib/RT/Record.pm
+++ b/lib/RT/Record.pm
@@ -1942,6 +1942,8 @@ sub _AddCustomFieldValue {
);
my $cf = $self->LoadCustomFieldByIdentifier($args{'Field'});
+ $cf->{include_set_initial} = 1 if $args{'ForCreation'};
+
unless ( $cf->Id ) {
return ( 0, $self->loc( "Custom field [_1] not found", $args{'Field'} ) );
}
@@ -2024,6 +2026,7 @@ sub _AddCustomFieldValue {
}
my $new_value = RT::ObjectCustomFieldValue->new( $self->CurrentUser );
+ $new_value->{include_set_initial} = 1 if $args{'ForCreation'};
$new_value->Load( $new_value_id );
# now that adding the new value was successful, delete the old one
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index b65aae4..27b186b 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -484,6 +484,7 @@ sub Create {
next unless $arg =~ /^CustomField-(\d+)$/i;
my $cfid = $1;
my $cf = $self->LoadCustomFieldByIdentifier($cfid);
+ $cf->{include_set_initial} = 1;
next unless $cf->ObjectTypeFromLookupType($cf->__Value('LookupType'))->isa(ref $self);
foreach my $value (
diff --git a/share/html/Elements/EditCustomFields b/share/html/Elements/EditCustomFields
index 7e21d31..7349ac2 100644
--- a/share/html/Elements/EditCustomFields
+++ b/share/html/Elements/EditCustomFields
@@ -99,6 +99,7 @@
% Grouping => $Grouping, ARGSRef => \%ARGS );
<%INIT>
$CustomFields ||= $Object->CustomFields;
+$CustomFields->{include_set_initial} = 1 if $ForCreation;
$CustomFields->LimitToGrouping( $Object => $Grouping ) if defined $Grouping;
diff --git a/t/web/cf_set_initial.t b/t/web/cf_set_initial.t
new file mode 100644
index 0000000..061920d
--- /dev/null
+++ b/t/web/cf_set_initial.t
@@ -0,0 +1,89 @@
+use strict;
+use warnings;
+
+use RT::Test tests => undef;
+my ($baseurl, $m) = RT::Test->started_ok;
+
+ok $m->login, 'logged in';
+
+my $cf = RT::CustomField->new( RT->SystemUser );
+my ($cfid, $msg) = $cf->Create(
+ Name => 'Test Set Initial CF',
+ Queue => '0',
+ Type => 'FreeformSingle',
+);
+
+my $tester = RT::Test->load_or_create_user( Name => 'tester', Password => '123456' );
+RT::Test->set_rights(
+ { Principal => $tester->PrincipalObj,
+ Right => [qw(SeeQueue ShowTicket CreateTicket)],
+ },
+);
+ok $m->login( $tester->Name, 123456, logout => 1), 'logged in';
+
+diag "check that we have no CF on the create"
+ ." ticket page when user has no SetInitialCustomField right";
+{
+ $m->submit_form(
+ form_name => "CreateTicketInQueue",
+ fields => { Queue => 'General' },
+ );
+ $m->content_lacks('Test Set Initial CF', 'has no CF input');
+
+ my $form = $m->form_name("TicketCreate");
+ my $edit_field = "Object-RT::Ticket--CustomField-$cfid-Value";
+ ok !$form->find_input( $edit_field ), 'no form field on the page';
+
+ $m->submit_form(
+ form_name => "TicketCreate",
+ fields => { Subject => 'test' },
+ );
+ $m->content_like(qr/Ticket \d+ created/, "a ticket is created succesfully");
+
+ $m->content_lacks('Test Set Initial CF', 'has no CF on the page');
+ $m->follow_link( text => 'Custom Fields');
+ $m->content_lacks('Test Set Initial CF', 'has no CF field');
+}
+
+RT::Test->set_rights(
+ { Principal => $tester->PrincipalObj,
+ Right => [qw(SeeQueue ShowTicket CreateTicket SetInitialCustomField)],
+ },
+);
+
+diag "check that we have the CF on the create"
+ ." ticket page when user has SetInitialCustomField but no SeeCustomField";
+{
+ $m->submit_form(
+ form_name => "CreateTicketInQueue",
+ fields => { Queue => 'General' },
+ );
+ $m->content_contains('Test Set Initial CF', 'has CF input');
+
+ my $form = $m->form_name("TicketCreate");
+ my $edit_field = "Object-RT::Ticket--CustomField-$cfid-Value";
+ ok $form->find_input( $edit_field ), 'has form field on the page';
+
+ $m->submit_form(
+ form_name => "TicketCreate",
+ fields => {
+ $edit_field => 'yatta',
+ Subject => 'test 2',
+ },
+ );
+ $m->content_like(qr/Ticket \d+ created/, "a ticket is created succesfully");
+ if (my ($id) = $m->content =~ /Ticket (\d+) created/) {
+ my $ticket = RT::Ticket->new(RT->SystemUser);
+ my ($ok, $msg) = $ticket->Load($id);
+ ok($ok, "loaded ticket $id");
+ is($ticket->Subject, 'test 2', 'subject is correct');
+ is($ticket->FirstCustomFieldValue('Test Set Initial CF'), 'yatta', 'CF was set correctly');
+ }
+
+ $m->content_lacks('Test Set Initial CF', 'has no CF on the page');
+ $m->follow_link( text => 'Custom Fields');
+ $m->content_lacks('Test Set Initial CF', 'has no CF edit field');
+}
+
+undef $m;
+done_testing;
-----------------------------------------------------------------------
More information about the rt-commit
mailing list