# BEGIN BPS TAGGED BLOCK {{{
-#
+#
# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC
-# <jesse@bestpractical.com>
-#
+#
+# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+# <sales@bestpractical.com>
+#
# (Except where explicitly superseded by other copyright notices)
-#
-#
+#
+#
# LICENSE:
-#
+#
# This work is made available to you under the terms of Version 2 of
# the GNU General Public License. A copy of that license should have
# been provided with this software, but in any event can be snarfed
# from www.gnu.org.
-#
+#
# This work is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 or visit their web page on the internet at
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
-#
-#
+#
+#
# CONTRIBUTION SUBMISSION POLICY:
-#
+#
# (The following paragraph is not intended to limit the rights granted
# to you to modify and distribute this software under the terms of
# the GNU General Public License and is only of importance to you if
# you choose to contribute your changes and enhancements to the
# community by submitting them to Best Practical Solutions, LLC.)
-#
+#
# By intentionally submitting any modifications, corrections or
# derivatives to this work, or any other work intended for use with
# Request Tracker, to Best Practical Solutions, LLC, you confirm that
# royalty-free, perpetual, license to use, copy, create derivative
# works based on those contributions, and sublicense and distribute
# those contributions and any derivatives thereof.
-#
+#
# END BPS TAGGED BLOCK }}}
=head1 NAME
package RT::SharedSetting;
use strict;
use warnings;
-use RT::Attribute;
use base qw/RT::Base/;
+use RT::Attribute;
+use Scalar::Util 'blessed';
+
=head1 METHODS
=head2 new
my $object = $self->_GetObject($privacy);
if ($object) {
- $self->{'Attribute'} = $object->Attributes->WithId($id);
+ $self->{'Attribute'} = RT::Attribute->new($self->CurrentUser);
+ $self->{'Attribute'}->Load( $id );
if ($self->{'Attribute'}->Id) {
$self->{'Id'} = $self->{'Attribute'}->Id;
$self->{'Privacy'} = $privacy;
$self->PostLoad();
- return (0, $self->loc("Permission denied"))
+ return wantarray ? (0, $self->loc("Permission Denied")) : 0
unless $self->CurrentUserCanSee;
- return (1, $self->loc("Loaded [_1] [_2]", $self->ObjectName, $self->Name));
+ my ($ok, $msg) = $self->PostLoadValidate;
+ return wantarray ? ($ok, $msg) : $ok if !$ok;
+
+ return wantarray ? (1, $self->loc("Loaded [_1] [_2]", $self->ObjectName, $self->Name)) : 1;
} else {
$RT::Logger->error("Could not load attribute " . $id
. " for object " . $privacy);
- return (0, $self->loc("Failed to load [_1] [_2]", $self->ObjectName, $id))
+ return wantarray ? (0, $self->loc("Failed to load [_1] [_2]", $self->ObjectName, $id)) : 0;
}
} else {
$RT::Logger->warning("Could not load object $privacy when loading " . $self->ObjectName);
- return (0, $self->loc("Could not load object for [_1]", $privacy));
+ return wantarray ? (0, $self->loc("Could not load object for [_1]", $privacy)) : 0;
}
}
my ($ok, $msg) = $attr->LoadById($id);
if (!$ok) {
- return (0, $self->loc("Failed to load [_1] [_2]: [_3]", $self->ObjectName, $id, $msg))
+ return wantarray ? (0, $self->loc("Failed to load [_1] [_2]: [_3]", $self->ObjectName, $id, $msg)) : 0;
}
my $privacy = $self->_build_privacy($attr->ObjectType, $attr->ObjectId);
- return (0, $self->loc("Bad privacy for attribute [_1]", $id))
+ return wantarray ? (0, $self->loc("Bad privacy for attribute [_1]", $id)) : 0
if !$privacy;
return $self->Load($privacy, $id);
=head2 PostLoad
-Called after after successful L</Load>.
+Called after a successful L</Load>.
=cut
sub PostLoad { }
+=head2 PostLoadValidate
+
+Called just before returning success from L</Load>; may be used to validate
+that the record is correct. This method is expected to return a (ok, msg)
+pair.
+
+=cut
+
+sub PostLoadValidate {
+ return 1;
+}
+
=head2 Save
Creates a new shared setting. Takes a privacy, a name, and any other arguments.
my %args = (
'Privacy' => 'RT::User-' . $self->CurrentUser->Id,
'Name' => "new " . $self->ObjectName,
- @_,
+ @_,
);
my $privacy = $args{'Privacy'};
return (0, $self->loc("Failed to load object for [_1]", $privacy))
unless $object;
- return (0, $self->loc("Permission denied"))
+ return (0, $self->loc("Permission Denied"))
unless $self->CurrentUserCanCreate($privacy);
my ($att_id, $att_msg) = $self->SaveAttribute($object, \%args);
if ($att_id) {
- $self->{'Attribute'} = $object->Attributes->WithId($att_id);
+ $self->{'Attribute'} = RT::Attribute->new($self->CurrentUser);
+ $self->{'Attribute'}->Load( $att_id );
$self->{'Id'} = $att_id;
$self->{'Privacy'} = $privacy;
- return ( 1, $self->loc( "Saved [_1] [_2]", $self->ObjectName, $name ) );
+ return ( 1, $self->loc( "Saved [_1] [_2]", $self->loc( $self->ObjectName ), $name ) );
}
else {
$RT::Logger->error($self->ObjectName . " save failure: $att_msg");
- return ( 0, $self->loc("Failed to create [_1] attribute", $self->ObjectName) );
+ return ( 0, $self->loc("Failed to create [_1] attribute", $self->loc( $self->ObjectName ) ) );
}
}
return(0, $self->loc("Could not load [_1] attribute", $self->ObjectName))
unless $self->{'Attribute'}->Id;
- return (0, $self->loc("Permission denied"))
+ return (0, $self->loc("Permission Denied"))
unless $self->CurrentUserCanModify;
my ($status, $msg) = $self->UpdateAttribute(\%args);
sub Delete {
my $self = shift;
-
- return (0, $self->loc("Permission denied"))
+ return (0, $self->loc("Permission Denied"))
unless $self->CurrentUserCanDelete;
my ($status, $msg) = $self->{'Attribute'}->Delete;
+ $self->CurrentUser->ClearAttributes; # force the current user's attribute cache to be cleaned up
if ($status) {
return (1, $self->loc("Deleted [_1]", $self->ObjectName));
} else {
return $self->{'Id'};
}
+*id = \&Id;
+
+
=head2 Privacy
Returns the principal object to whom this shared setting belongs, in a string
sub IsVisibleTo {
my $self = shift;
my $to = shift;
- my $privacy = $self->Privacy;
+ my $privacy = $self->Privacy || '';
# if the privacies are the same, then they can be seen. this handles
# a personal setting being visible to that user.
my $self = shift;
my $privacy = shift;
+ # short circuit: if they pass the object we want anyway, just return it
+ if (blessed($privacy) && $privacy->isa('RT::Record')) {
+ return $privacy;
+ }
+
my ($obj_type, $obj_id) = split(/\-/, ($privacy || ''));
unless ($obj_type && $obj_id) {
return undef;
}
- if ($obj_type eq 'RT::Group' && !$object->HasMemberRecursively($self->CurrentUser->PrincipalObj)) {
+ if ( $obj_type eq 'RT::Group'
+ && !$object->HasMemberRecursively($self->CurrentUser->PrincipalObj)
+ && !$self->CurrentUser->HasRight( Object => $RT::System, Right => 'SuperUser' ) ) {
$RT::Logger->debug("Permission denied, ".$self->CurrentUser->Name.
" is not a member of group");
return undef;
: undef;
}
-eval "require RT::SharedSetting_Vendor";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/SharedSetting_Vendor.pm});
-eval "require RT::SharedSetting_Local";
-die $@ if ($@ && $@ !~ qr{^Can't locate RT/SharedSetting_Local.pm});
+=head2 ObjectsForLoading
+
+Returns a list of objects that can be used to load this shared setting. It
+is ACL checked.
+
+=cut
+
+sub ObjectsForLoading {
+ my $self = shift;
+ return grep { $self->CurrentUserCanSee($_) } $self->_PrivacyObjects;
+}
+
+=head2 ObjectsForCreating
+
+Returns a list of objects that can be used to create this shared setting. It
+is ACL checked.
+
+=cut
+
+sub ObjectsForCreating {
+ my $self = shift;
+ return grep { $self->CurrentUserCanCreate($_) } $self->_PrivacyObjects;
+}
+
+=head2 ObjectsForModifying
+
+Returns a list of objects that can be used to modify this shared setting. It
+is ACL checked.
+
+=cut
+
+sub ObjectsForModifying {
+ my $self = shift;
+ return grep { $self->CurrentUserCanModify($_) } $self->_PrivacyObjects;
+}
+
+RT::Base->_ImportOverlays();
1;