File Coverage

File:/home/mik/work/module/Tivoli/AccessManager/Admin/Action.pm
Coverage:99.6%

linestmtbrancondsubpodtimecode
1package Tivoli::AccessManager::Admin::Action;
2
15
15
15
157
54
319
use Carp;
3
15
15
15
212
63
211
use strict;
4
15
15
15
200
63
216
use warnings;
5
15
15
15
201
52
275
use Data::Dumper;
6
7#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8# $Id: Action.pm 305 2006-09-28 19:18:01Z mik $
9#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
10
11$Tivoli::AccessManager::Admin::Action::VERSION = '0.04';
12
15
208
use Inline(C => 'DATA',
13                INC => '-I/opt/PolicyDirector/include',
14                LIBS => ' -lpthread -lpdadminapi -lstdc++',
15                CCFLAGS => '-Wall',
16# VERSION => '0.04',
17                NAME => 'Tivoli::AccessManager::Admin::Action',
18
15
15
214
52
          );
19
15
15
15
220
50
260
use Tivoli::AccessManager::Admin::Response;
20
21sub new {
22
12
1
94
    my $class = shift;
23
12
45
    my $cont = shift;
24
25
12
190
    unless ( defined($cont) and UNIVERSAL::isa($cont,'Tivoli::AccessManager::Admin::Context' ) ) {
26
2
39
        warn "Incorrect syntax -- did you forget the context?\n";
27
2
17
        return undef;
28    }
29
30
10
61
    if ( @_ % 2 ) {
31
1
19
        warn "Invalid syntax -- you did not send a hash\n";
32
1
9
        return undef;
33    }
34
9
95
    my %opts = @_;
35
36
9
70
    my $self = bless {}, $class;
37
9
84
    $self->{actionid} = $opts{actionid} || '';
38
9
64
    $self->{description} = $opts{description} || '';
39
9
60
    $self->{type} = $opts{type} || '';
40
9
40
    $self->{context} = $cont;
41
42
9
86
    return $self;
43}
44
45sub create {
46
13
1
226
    my $self = shift;
47
13
36
    my $rc;
48
13
129
    my $resp = Tivoli::AccessManager::Admin::Response->new;
49
50
13
81
    unless ( ref $self ) {
51
5
20
        my $pd = shift;
52
5
67
        unless ( UNIVERSAL::isa($pd, 'Tivoli::AccessManager::Admin::Context') ) {
53
1
11
            $resp->set_message('syntax error - no context');
54
1
9
            $resp->set_isok(0);
55
1
9
            return $resp;
56        }
57
4
35
        $self = $self->new( $pd, @_ );
58    }
59
60
12
65
    if ( @_ % 2 ) {
61
1
11
        $resp->set_message("Invalid syntax");
62
1
5
        $resp->set_isok(0);
63
1
6
        return $resp;
64    }
65
11
76
    my %opts = @_;
66
67
11
62
    unless ( $self->{actionid} ) {
68
2
28
        $self->{actionid} = $opts{actionid} || '';
69    }
70
71
11
55
    unless ( $self->{description} ) {
72
2
29
        $self->{description} = $opts{description} || '';
73    }
74
75
11
60
    unless ( $self->{type} ) {
76
2
28
        $self->{type} = $opts{type} || '';
77    }
78
79
11
160
    unless ( $self->{actionid} and $self->{description} and $self->{type} ) {
80
3
31
        $resp->set_isok(0);
81
3
24
        $resp->set_message("actionid, description and type must be defined" );
82
3
25
        return $resp;
83    }
84
85
8
41
    if ( defined $opts{group} ) {
86
2
89407
        $rc = $self->action_create_in_group($resp, $opts{group});
87    }
88    else {
89
6
276311
        $rc = $self->action_create($resp);
90    }
91
92
8
169
    $resp->isok and $resp->set_value( $self );
93
8
112
    return $resp;
94}
95
96sub delete {
97
8
1
35
    my $self = shift;
98
8
75
    my $resp = Tivoli::AccessManager::Admin::Response->new;
99
8
30
    my $rc;
100
101
8
50
    if ( @_ % 2 ) {
102
1
6
        $resp->set_message("Invalid syntax");
103
1
7
        $resp->set_isok(0);
104
1
18
        return $resp;
105    }
106
7
38
    my %opts = @_;
107
108
7
35
    if ( defined $opts{group} ) {
109
1
50202
        $rc = $self->action_delete_from_group($resp, $opts{group});
110    }
111    else {
112
6
324961
        $rc = $self->action_delete($resp);
113    }
114    # Because we need to rely on the information held in the perl code's
115    # cache, I want to make certain we zero it all out if the delete
116    # worked.
117
7
144
    if ( $resp->isok ) {
118
6
34
        $self->{actionid} = undef;
119
6
28
        $self->{description} = undef;
120
6
47
        $self->{type} = undef;
121    }
122
7
85
    return $resp;
123}
124
125sub group {
126
12
1
77
    my $self = shift;
127
12
118
    my $resp = Tivoli::AccessManager::Admin::Response->new;
128
12
38
    my $pd;
129
130
12
56
    if ( ref $self ) {
131
2
9
        $pd = $self->{context};
132    }
133    else {
134
10
38
        $pd = shift;
135
10
138
        unless ( UNIVERSAL::isa($pd, 'Tivoli::AccessManager::Admin::Context' ) ) {
136
1
13
            $resp->set_message( 'syntax error -- no context object' );
137
1
11
            $resp->set_isok(0);
138
1
11
            return $resp;
139        }
140    }
141
142
11
64
    if ( @_ % 2 ) {
143
1
8
        $resp->set_message("Invalid syntax");
144
1
7
        $resp->set_isok(0);
145
1
4
        return $resp;
146    }
147
10
63
    my %opts = @_;
148
10
79
    my %dispatch = ( create => \&action_group_create,
149                     remove => \&action_group_delete
150                 );
151
10
28
    my $rc;
152
153    DISPATCH:
154
10
38
    for my $com ( qw/remove create/ ) {
155
18
103
        next unless defined $opts{$com};
156
157
8
53
        if ( ref $opts{$com} eq 'ARRAY' ) {
158
4
4
8
15
            for my $grp ( @{$opts{$com}} ) {
159
8
358351
                $rc = $dispatch{$com}->( $pd, $resp, $grp );
160
8
172
                last DISPATCH unless $resp->isok;
161            }
162        }
163        else {
164
4
187127
            $rc =$dispatch{$com}->( $pd, $resp, $opts{$com} );
165
4
94
            last DISPATCH unless $resp->isok;
166        }
167    }
168
169
10
98
    if ( $resp->isok ) {
170
6
272068
        my @list = action_group_list( $pd, $resp );
171
6
140
        $resp->isok and $resp->set_value(\@list);
172    }
173
174
10
155
    return $resp;
175}
176
177sub list {
178
5
1
26
    my $self = shift;
179
5
14
    my ($pd,$class);
180
5
44
    my $resp = Tivoli::AccessManager::Admin::Response->new;
181
182
5
30
    if ( ref $self ) {
183
2
11
        $pd = $self->{context};
184
2
7
        $class = ref $self;
185    }
186    else {
187
3
10
        $pd = shift;
188
3
38
        unless ( UNIVERSAL::isa($pd, 'Tivoli::AccessManager::Admin::Context' ) ) {
189
1
11
            $resp->set_message( 'syntax error -- no context object' );
190
1
12
            $resp->set_isok(0);
191
1
8
            return $resp;
192        }
193
2
13
        $class = $self;
194    }
195
196
4
26
    if ( @_ % 2 ) {
197
1
7
        $resp->set_message("Invalid syntax");
198
1
6
        $resp->set_isok(0);
199
1
5
        return $resp;
200    }
201
3
21
    my %opts = @_;
202
3
8
    my (@rc,@objs);
203
204
3
16
    if ( defined $opts{group} ) {
205
2
88027
        @rc = action_list_in_group( $pd, $resp, $opts{group} );
206    }
207    else {
208
1
51905
        @rc = action_list( $pd, $resp );
209    }
210
211
3
65
    if ( $resp->isok ) {
212
2
9
        for ( @rc ) {
213
20
67
            bless $_, $class;
214
20
57
            $_->{context} = $pd;
215        }
216
2
21
        $resp->set_value(\@rc);
217    }
218
3
33
    return $resp;
219}
220
221
2
1
24
sub description { return $_[0]->{description} }
222
1
1
14
sub id { return $_[0]->{actionid} }
223
1
1
16
sub type { return $_[0]->{type} }
224
2251;
226
227 - 517
=head1 NAME

Tivoli::AccessManager::Admin::Action

=head1 SYNOPSIS

  use Tivoli::AccessManager::Admin;

  my $pd = Tivoli::AccessManager::Admin->new( password => 'N3ew0nk' );
  my ( @acts, $resp, @lists, @grps, @gnames );

  # Create an action via new and create
  $acts[0] = Tivoli::AccessManager::Admin::Action->new( $pd,
				  actionid    => 'Z',
				  description => 'Action Z!',
				  type        => 'This is action Z'
				);
  $resp = $acts[0]->create;

  # Or, create an action through create alone
  $resp = Tivoli::AccessManager::Admin::Action->create( $pd,
				      actionid    => 'X',
				      description => 'Action X!',
				      type        => 'This is action X'
				    );
  $acts[1] = $resp->value if $resp->isok;

  # Print the description, the type and the action id out
  for my $act ( @acts ) {
      print "Action ID  : " . $act->id . "\n";
      print "Description: " . $act->description . "\n";
      print "Type       : " . $act->type . "\n\n";
  }

  @gnames = qw/ateam dirty12 ratpack/;
  # Create some action groups.
  for my $name ( @gnames ) {
      $resp = Tivoli::AccessManager::Admin::Action->group( $pd, create => $name );
      push( @grps, $name ) if $resp->isok;
  }

  # Delete the groups
  for my $name ( @gnames ) {
      $resp = Tivoli::AccessManager::Admin::Action->group( $pd, delete => $name );
      push( @grps, $name ) if $resp->isok;
  }

  # Create them another way, just for fun
  $resp = Tivoli::AccessManager::Admin::Action->group( $pd, create => \@gnames );
  @grps = @gnames if $resp->isok;

  # Create a new actions in a group
  $resp = Tivoli::AccessManager::Admin::Action->create( $pd, 
				  actionid    => 'T',
				  description => 'Pity the fool',
				  type        => 'Mr T action',
				  group	      => 'ateam',
				);

  # Get the list of all the groups
  $resp = Tivoli::AccessManager::Admin::Action->group;

  # list the default actions 
  $resp = Tivoli::AccessManager::Admin::Action->list;
  for my $obj ( @{$resp->value} ) {
      printf "Found action %s -- %s\n",
	     $obj->id, $obj->description;
  }

  # list the actions in a group
  $resp = Tivoli::AccessManager::Admin::Action->list( group => 'ateam' );

=head1 DESCRIPTION

Tivoli::AccessManager::Admin::Action implements the interface to the action portion of the API.
I will warn you -- the underlying API is somewhat half baked.

=head1 CONSTRUCTORS

=head2 new( PDADMIN[, actionid =E<gt> ID, description =E<gt> DESC, type =E<gt> TYPE, group =E<gt> GROUP] )

Creates a blessed L<Tivoli::AccessManager::Admin::Action> object.  You will need to destroy this
object if you wish to change the context.

=head3 Parameters

=over 4

=item PDADMIN

An initialized L<Tivoli::AccessManager::Admin::Context> object.  This is the only required
parameter.

=item actionid =E<gt> ID

The action id to create.  This is currently limitted by the C API to one
character.

=item description =E<gt> DESC

A description of the action.

=item type =E<gt> TYPE

The action's type.  This is usually a one word description thst is displayed
by the WPM.

=item group =E<gt> GROUP

If provided, name the action group in which the action will be created.

=back

=head3 Returns

A blessed L<Tivoli::AccessManager::Admin::Action> object. 

=head2 create( PDADMIN, actionid =E<gt> ID, description =E<gt> DESC, type =E<gt> TYPE[, group =E<gt> GROUP] )

Instantiates a L<Tivoli::AccessManager::Admin::Context> object and creates the action in the
policy database if used as a class method.

=head3 Parameters

The parameters are identical to those for L</"new">.  Unlike L</"new">, they
are all required, except for the group name.

=head3 Returns

A blessed L<Tivoli::AccessManager::Admin::Action> object, buried in a L<Tivoli::AccessManager::Admin::Response>
object.

=head2 list(PDADMIN[, group =E<gt> GROUP] )

Lists all the defined actions.  The return is a list of L<Tivoli::AccessManager::Admin::Action>
objects, buried in a L<Tivoli::AccessManager::Admin::Response> object.

=head3 Parameters

=over 4

=item PDADMIN

An initialized L<Tivoli::AccessManager::Admin::Context> object.  This is the only required
arameter.

=item group =E<gt> GROUP

If provided, the return will be the list of actions within the named group.
It will otherwise search the default group.

=back

=head3 Returns

A list of blessed L<Tivoli::AccessManager::Admin::Action> objects.

=head1 CLASS METHODS

=head2 group(PDADMIN[, create =E<gt> name, remove =E<gt> name ] )

Lists, creates and/or deletes action groups.  If none of the optional
parameters are provided, L</"group"> will return a list of all the action
groups.

=head3 Parameters

=over 4

=item PDADMIN

An initialized L<Tivoli::AccessManager::Admin::Context> object.  This is the only required
parameter.

=item create =E<gt> name

The name of an action group to create.  This can also be a reference to an
array of group names.

=item remove =E<gt> name

The name of an action group to remove.  This can also be a reference to an
array of group names.  If create and remove are both specified, removes are
done first.

=back

=head3 Returns

Regardless of the operation performed, a list of action group names will be
returned.

=head1 METHODS

=head2 create( [actionid =E<gt> ID, description =E<gt> DESC, type =E<gt> TYPE, group =E<gt> GROUP] )

Yes, this can called as an instance method if you want.  Notice the different
signature -- the context object is no longer required.

=head3 Parameters

See L</"new">.  Any parameter yiu did not provide to L</"new"> must be
provided to L</"create">.

=head3 Returns

The results if the create operation

=head2 delete([group =E<gt> GROUP])

Deletes the action.

=head3 Parameters

=over 4

=item group =E<gt> GROUP

If provided, the action will be deleted from the named group.

=back

=head3 Returns

The results of the delete call.

=head2 id

Returns the action id.  This is a read-only method.

=head3 Parameters

None

=head3 Returns

The action id.

=head2 description

Returns the description.  This is a read-only method.

=head3 Parameters

None

=head3 Returns

The description.

=head2 type

Returns the type.  This is a read-only method.

=head3 Parameters

None

=head3 Returns

The type.

=head1 ACKNOWLEDGEMENTS

See L<Tivoli::AccessManager::Admin> for the list.  This was not possible without the help of a
bunch of people smarter than me.

=head1 BUGS

The underlying C API is very different from the other portions -- there is no
way to get an ivadmin_action struct w/o doing a list.  I have worked around
this in the perl code.  This is surely a bug.

There is no way to change the description or type w/o deleting the action and
recreating it.  

=head1 AUTHOR

Mik Firestone E<lt>mikfire@gmail.comE<gt>

=head1 COPYRIGHT

Copyright (c) 2004-2011 Mik Firestone.  All rights reserved.  This program is
free software; you can redistibute it and/or modify it under the same terms as
Perl itself.

All references to TAM, Tivoli Access Manager, etc are copyrighted, trademarked
and otherwise patented by IBM.


=cut
518