[Rt-commit] rt branch, 4.4/initial-custom-field, created. rt-4.4.0-102-gce92fa2
Dustin Graves
dustin at bestpractical.com
Fri May 6 13:22:59 EDT 2016
The branch, 4.4/initial-custom-field has been created
at ce92fa285c404b7ad8ee65aa20133969a4631853 (commit)
- Log -----------------------------------------------------------------
commit dca5e8bd2aa2cae4e90978f56b36cd526f93e57f
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 e8ea75c..6eb9640 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 c9efb08..b2e75bb 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 1ed8585..c6b457c 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 99faf19..71315ab 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 a6fb1d7..ed8503c 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 7565b1d..b3940b3 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 2d96103..7f04111 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 bd17619..61f0ee0 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 f2905e6..36d21e9 100644
--- a/share/html/Articles/Article/Edit.html
+++ b/share/html/Articles/Article/Edit.html
@@ -67,7 +67,8 @@
CFContent => \%CFContent,
ClassObj => $ClassObj,
%ARGS,
- id =>$id,
+ id => $id,
+ ForCreation => ($id eq 'new'),
&>
</&>
diff --git a/share/html/Asset/Create.html b/share/html/Asset/Create.html
index 1d258ce..d059ec9 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 79174de..4423b0a 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 8357af2..e396857 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 182d10ac59f83b7939e6c77949bf7b6d80f9aae8
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 4423b0a..f09fe6c 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 13016f4b0cfcde0a531385a39d442a1f901f7598
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 ed8503c..21db16f 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 d421ead..6aa6d41 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 7235ed1..ba781f5 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 372deeb..cd15dd3 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 ff67b7533073659d6aea6bb3de97a94ec4301212
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 dd32da7..75b38b1 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 f01337c..23dc84d 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 7f04111..930d044 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 61f0ee0..07e5c57 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 cd15dd3..9fc3211 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 f3cd5f6fd03de149f1c87bc16bc90c60c5b2fb6a
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 ba781f5..fa6623c 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 ce92fa285c404b7ad8ee65aa20133969a4631853
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 21db16f..e317810 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 6aa6d41..7ef55da 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 23dc84d..17a73e6 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 fa6623c..101f9e9 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 930d044..6d24385 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 07e5c57..3fa0557 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 f09fe6c..fbfb5ed 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..2bf81d9
--- /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