[Rt-commit] r18719 - rt/3.999/trunk/lib/RT

ruz at bestpractical.com ruz at bestpractical.com
Thu Mar 5 20:11:32 EST 2009


Author: ruz
Date: Thu Mar  5 20:11:32 2009
New Revision: 18719

Added:
   rt/3.999/trunk/lib/RT/HasRoleGroups.pm

Log:
* add an OO role for objects that may have roles (watchers)

Added: rt/3.999/trunk/lib/RT/HasRoleGroups.pm
==============================================================================
--- (empty file)
+++ rt/3.999/trunk/lib/RT/HasRoleGroups.pm	Thu Mar  5 20:11:32 2009
@@ -0,0 +1,330 @@
+package RT::HasRoleGroups;
+
+use strict;
+use warnings;
+
+sub current_user_can_modify_watchers {
+    die "current_user_can_modify_watchers method must be implemented in the role user";
+}
+
+=head2 is_watcher { type => TYPE, principal_id => PRINCIPAL_ID, email => EMAIL }
+
+Takes a param hash with the attributes type and either principal_id or email:
+
+=over 4
+
+=item type is one of defined by L</roles> of this object.
+
+=item principal_id is an id of L<RT::Model::Principal>
+
+=item email can be provided instead of the principal
+
+=back
+
+Returns true if the specified principal (or the one corresponding to the
+specified address) is a member of the role group for this object.
+
+XX TODO: This should be Memoized. 
+
+=cut
+
+sub is_watcher {
+    my $self = shift;
+    my %args = (
+        type         => 'requestor',
+        principal_id => undef,
+        email        => undef,
+        recursively  => 1,
+        @_
+    );
+
+    # Load the relevant group.
+    my $group = RT::Model::Group->new;
+    $group->load_role_group(
+        object => $self,
+        type   => $args{'type'},
+    );
+    return 0 unless $group->id;
+
+    # Find the relevant principal.
+    if ( !$args{'principal_id'} ) {
+        return 0 unless $args{'email'};
+
+        # Look up the specified user.
+        my $user = RT::Model::User->new;
+        $user->load_by_email( $args{'email'} );
+        if ( $user->id ) {
+            $args{'principal_id'} = $user->principal_id;
+        } else {
+            # A non-existent user can't be a group member.
+            return 0;
+        }
+    }
+
+    # Ask if it has the member in question
+    return $group->has_member( $args{'principal_id'}, recursively => $args{'recursively'} );
+}
+
+=head2 add_watcher
+
+add_watcher takes a parameter hash. The keys are as follows:
+
+Type        One of requestor, cc, admin_cc
+
+prinicpal_id The RT::Model::Principal id of the user or group that's being added as a watcher
+
+email       The email address of the new watcher. If a user with this 
+            email address can't be found, a new nonprivileged user will be created.
+
+If the watcher you\'re trying to set has an RT account, set the principal_id paremeter to their User Id. Otherwise, set the email parameter to their email address.
+
+=cut
+
+sub add_watcher {
+    my $self = shift;
+    my %args = (
+        type         => undef,
+        principal_id => undef,
+        email        => undef,
+        @_
+    );
+
+#XXX: check if role is valid
+
+    if ( $args{'email'} ) {
+        my $user = RT::Model::User->new;
+        $user->load_by_email( $args{'email'} );
+        if ( $user->id ) {
+            $args{'principal_id'} = $user->id;
+            delete $args{'email'};
+        } else {
+            delete $args{'principal_id'};
+        }
+    }
+
+    my ($status, $msg) = $self->current_user_can_modify_watchers(
+        %args,
+        action => 'add',
+    );
+    return ( $status, $msg || _("Permission Denied") )
+        unless $status;
+
+    return $self->_add_watcher(%args);
+}
+
+sub _add_watcher {
+    my $self = shift;
+    my %args = (
+        type         => undef,
+        silent       => undef,
+        principal_id => undef,
+        email        => undef,
+        @_
+    );
+
+    # load_or_create
+    if ( $args{'email'} ) {
+        my $user = RT::Model::User->new( current_user => RT->system_user );
+        my ( $pid, $msg ) = $user->load_or_create_by_email( $args{'email'} );
+        if ( $pid ) {
+            $args{'principal_id'} = $pid;
+        } else {
+            return ( 0, _("Could not find or create user with email %1", $args{'email'}) );
+        }
+    }
+
+    unless ( $args{'principal_id'} ) {
+        Jifty->log->error("Invalid arguments for add_watcher");
+        return ( 0, _("System internal error. Contact system administrator.") );
+    }
+
+    my $principal = RT::Model::Principal->new;
+    $principal->load( $args{'principal_id'} );
+    unless ( $principal->id ) {
+        return ( 0, _("Could not find principal #%1", $args{'principal_id'}) );
+    }
+
+    my $group = RT::Model::Group->new;
+    $group->create_role_group(
+        object => $self,
+        type   => $args{'type'},
+    );
+
+    if ( $group->has_member($principal) ) {
+        return ( 0, _( 'That principal is already a %1', _( $args{'type'} ) ) );
+    }
+
+    my ( $m_id, $m_msg ) = $group->_add_member(
+        principal_id => $principal->id,
+    );
+    unless ($m_id) {
+        Jifty->log->error(
+            "Failed to add principal #". $principal->id
+            ." as a member of group #". $group->id .": ". $m_msg
+        );
+        return ( 0, _( 'Could not make that principal a %1', _( $args{'type'} ) ) );
+    }
+
+    unless ( $args{'silent'} ) {
+        $self->_new_transaction(
+            type      => 'AddWatcher',
+            new_value => $principal->id,
+            field     => $args{'type'},
+        );
+    }
+
+    return ( 1, _( 'Added principal as a %1', _( $args{'type'} ) ) );
+}
+
+
+
+=head2 delete_watcher { type => TYPE, principal_id => PRINCIPAL_ID, email => EMAIL_ADDRESS }
+
+
+Deletes a ticket watcher.  Takes two arguments:
+
+Type  (one of requestor,cc,admin_cc)
+
+and one of
+
+principal_id (an RT::Model::Principal id of the watcher you want to remove)
+    OR
+email (the email address of an existing wathcer)
+
+
+=cut
+
+sub delete_watcher {
+    my $self = shift;
+    my %args = (
+        type         => undef,
+        principal_id => undef,
+        email        => undef,
+        @_
+    );
+
+    if ( $args{'email'} ) {
+        my $user = RT::Model::User->new;
+        $user->load_by_email( $args{'email'} );
+        return ( 0, _("Could not find user with email %1", $args{'email'}) )
+            unless $user->id;
+
+        $args{'principal_id'} = $user->id;
+        delete $args{'email'};
+    }
+
+    my ($status, $msg) = $self->current_user_can_modify_watchers(
+        %args,
+        action => 'delete',
+    );
+    return ( $status, $msg || _("Permission Denied") )
+        unless $status;
+
+    return $self->_delete_watcher( %args );
+}
+
+sub _delete_watcher {
+    my $self = shift;
+    my %args = (
+        type         => undef,
+        principal_id => undef,
+        email        => undef,
+        @_
+    );
+
+    if ( $args{'email'} ) {
+        my $user = RT::Model::User->new;
+        $user->load_by_email( $args{'email'} );
+        return ( 0, _("Could not find user with email %1", $args{'email'}) )
+            unless $user->id;
+
+        $args{'principal_id'} = $user->id;
+        delete $args{'email'};
+    }
+
+    unless ( $args{'principal_id'} ) {
+        Jifty->log->error("Invalid arguments for delete_watcher");
+        return ( 0, _("System internal error. Contact system administrator.") );
+    }
+
+    my $principal = RT::Model::Principal->new;
+    $principal->load( $args{'principal_id'} );
+    unless ( $principal->id ) {
+        return ( 0, _("Could not find principal #%1", $args{'principal_id'}) );
+    }
+
+    # see if this user is already a watcher.
+
+    my $group = RT::Model::Group->new;
+    $group->load_role_group(
+        object => $self,
+        type   => $args{'type'},
+    );
+    if ( !$group->id && !$group->has_member($principal) ) {
+        return ( 0, _( 'That principal is not a %1', $args{'type'} ) );
+    }
+
+    my ( $m_id, $m_msg ) = $group->_delete_member( $principal->id );
+    unless ($m_id) {
+        Jifty->log->error(
+            "Failed to delete principal #". $principal->id
+            ." form group ". $group->id .": ". $m_msg
+        );
+
+        return ( 0, _( 'Could not remove that principal as a %1', $args{'type'} ) );
+    }
+
+    unless ( $args{'silent'} ) {
+        $self->_new_transaction(
+            type      => 'del_watcher',
+            old_value => $principal->id,
+            field     => $args{'type'}
+        );
+    }
+
+    return ( 1, _( "%1 is no longer a %2.", $principal->object->name, $args{'type'} ) );
+}
+
+=head2 role_group
+
+Returns an L<RT::Model::Group> role object by its name, for example:
+
+    my $group = $ticket->role_group("requestor");
+
+=cut
+
+sub role_group {
+    my $self = shift;
+    my $role = shift;
+
+    my $obj = RT::Model::Group->new;
+    $obj->load_role_group( object => $self, type => $role );
+    return $obj;
+}
+
+=head2 create_role_group
+
+Create role group for this object.
+
+It will return a tuple ($group, $msg), on error group is undefined.
+
+=cut
+
+sub create_role_group {
+    my $self = shift;
+    my $type = shift;
+
+    my $group = RT::Model::Group->new;
+    my ($id, $msg) = $group->create_role_group(
+        object => $self,
+        type   => $type,
+    );
+    unless ($id) {
+        Jifty->log->error( "Couldn't create '$type' role group for ". ref($self) ." #" . $self->id . ": ". $msg );
+        return (undef, $msg);
+    }
+
+    return ($group, $msg);
+}
+
+1;


More information about the Rt-commit mailing list