rt 4.0.23
[freeside.git] / rt / lib / RT / SharedSetting.pm
index 63deb98..43df379 100644 (file)
@@ -1,40 +1,40 @@
 # 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
@@ -43,7 +43,7 @@
 # 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
@@ -64,7 +64,9 @@ It consists of an ID, a name, and some arbitrary data.
 package RT::SharedSetting;
 use strict;
 use warnings;
+
 use RT::Attribute;
+use Scalar::Util 'blessed';
 use base qw/RT::Base/;
 
 =head1 METHODS
@@ -110,6 +112,9 @@ sub Load {
             return (0, $self->loc("Permission denied"))
                 unless $self->CurrentUserCanSee;
 
+            my ($ok, $msg) = $self->PostLoadValidate;
+            return ($ok, $msg) if !$ok;
+
             return (1, $self->loc("Loaded [_1] [_2]", $self->ObjectName, $self->Name));
         } else {
             $RT::Logger->error("Could not load attribute " . $id
@@ -150,12 +155,24 @@ sub LoadById {
 
 =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.
@@ -193,11 +210,11 @@ sub Save {
         $self->{'Attribute'} = $object->Attributes->WithId($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 ) ) );
     }
 }
 
@@ -257,11 +274,11 @@ where status is true upon success.
 
 sub Delete {
     my $self = shift;
-
     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 {
@@ -294,6 +311,9 @@ sub Id {
     return $self->{'Id'};
 }
 
+*id = \&Id;
+
+
 =head2 Privacy
 
 Returns the principal object to whom this shared setting belongs, in a string
@@ -329,7 +349,7 @@ This does not deal with ACLs, this only looks at membership.
 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.
@@ -372,6 +392,11 @@ sub _GetObject {
     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) {
@@ -395,7 +420,9 @@ sub _GetObject {
         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;
@@ -450,9 +477,42 @@ sub _build_privacy {
          : 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;