File Coverage

blib/lib/Elive/Entity/Group.pm
Criterion Covered Total %
statement 18 73 24.6
branch 0 28 0.0
condition 0 17 0.0
subroutine 6 13 46.1
pod 4 4 100.0
total 28 135 20.7


line stmt bran cond sub pod time code
1             package Elive::Entity::Group;
2 7     7   19705 use warnings; use strict;
  7     7   9  
  7         203  
  7         29  
  7         11  
  7         179  
3              
4 7     7   502 use Mouse;
  7         22099  
  7         36  
5 7     7   1994 use Mouse::Util::TypeConstraints;
  7         9  
  7         36  
6              
7 7     7   523 use Carp;
  7         11  
  7         573  
8              
9             extends 'Elive::Entity';
10              
11 7     7   2770 use Elive::Entity::Group::Members;
  7         14  
  7         5095  
12              
13             __PACKAGE__->entity_name('Group');
14             __PACKAGE__->collection_name('Groups');
15              
16             has 'groupId' => (is => 'rw', isa => 'Str', required => 1);
17             __PACKAGE__->primary_key('groupId');
18              
19             has 'name' => (is => 'rw', isa => 'Str',
20             documentation => 'name of the group');
21             __PACKAGE__->_alias(groupName => 'name', freeze => 1);
22              
23             has 'members' => (is => 'rw', isa => 'Elive::Entity::Group::Members',
24             coerce => 1,
25             documentation => "ids of users or sub-groups");
26             __PACKAGE__->_alias(groupMembers => 'members', freeze => 1);
27             __PACKAGE__->_alias(entry => 'members');
28              
29             has 'domain' => (is => 'rw', isa => 'Any',
30             documentation => 'ldap domain?');
31              
32             has 'dn' => (is => 'rw', isa => 'Str',
33             documentation => 'LDAP Domain (where applicable)');
34              
35             sub BUILDARGS {
36 0     0 1   my $class = shift;
37 0           my $spec = shift;
38              
39 0           my $args;
40 0 0 0       if ($spec && ! ref $spec) {
41 0           my $group_id = $spec;
42 0           $group_id =~ s{^ \s* \* \s*}{}x; # just in case leading '*' leaks
43 0           $args = {groupId => $group_id};
44             }
45             else {
46 0           $args = $spec;
47             }
48              
49 0           return $args;
50             }
51              
52             coerce 'Elive::Entity::Group' => from 'HashRef|Str'
53             => via {Elive::Entity::Group->new($_) };
54              
55             sub stringify {
56 0     0 1   my $class = shift;
57 0           my $data = shift;
58 0 0 0       $data ||= $class if (ref $class);
59              
60 0           my $prefix = '';
61              
62 0 0         if (Elive::Util::_reftype($data) eq 'HASH') {
63 0 0         if (exists $data->{userId}) {
    0          
64 0           $data = $data->{userId}
65             }
66             elsif (exists $data->{groupId}) {
67 0           $prefix = '*';
68             }
69             }
70              
71 0           return $prefix . $class->SUPER::stringify($data, @_);
72              
73             }
74              
75             # _restful_url()
76             # remove any leading '*'
77              
78             sub _restful_url {
79 0     0     my $self = shift;
80 0           my $connection = shift;
81 0           my $id = shift;
82 0           $id =~ s{^\*}{};
83 0           return $self->SUPER::_restful_url($connection, $id);
84             }
85              
86             =head1 NAME
87              
88             Elive::Entity::Group - Elluminate Group entity instance class
89              
90             =head1 DESCRIPTION
91              
92             Groups of users are typically used to specify session participants.
93              
94             This class is used to query and maintain groups.
95              
96             The C property contains the group members as an array of user IDs
97             or sub-group objects.
98              
99             If the a site is configured for LDAP, groups are mapped to LDAP groups.
100             Group access becomes read-only. The affected methods are: C, C,
101             and C.
102              
103             =cut
104              
105             sub _freeze {
106 0     0     my $class = shift;
107 0           my $app_data = shift;
108              
109 0           $app_data = $class->SUPER::_freeze($app_data, @_);
110 0 0         $app_data->{groupId} =~ s{^\*}{} if $app_data->{groupId};
111              
112 0           return $app_data;
113             }
114              
115             sub _thaw {
116 0     0     my $class = shift;
117 0           my $db_data = shift;
118 0   0       my $path = shift || '';
119              
120 0 0         return $db_data unless ref $db_data;
121              
122 0           return $class->SUPER::_thaw($db_data, $path, @_);
123             }
124              
125             =head1 METHODS
126              
127             =cut
128              
129             =head2 insert
130              
131             #
132             # insert from an array of User Ids. Elements may be integers, strings
133             # and/or user objects.
134             #
135             my $alice = Elive::Entity::User->get_by_loginName('alice');
136             my $bob = Elive::Entity::User->get_by_loginName('bob');
137              
138             my $group = Elive::Entity::Group->insert({
139             name => 'Elluminati',
140             # following are all ok
141             members => [111111, '222222', $alice->userId, $bob ],
142             },
143             );
144              
145             #
146             # insert from a comma separated string of user IDs
147             #
148             my $group = Elive::Entity::Group->insert({
149             name => 'Elluminati',
150             members => '111111,222222,333333',
151             },
152             );
153              
154             Inserts a new group.
155              
156             =cut
157              
158             =head2 update
159              
160             $group->update({members => [111111,'222222', $alice->userId, $bob]});
161             $group->update({members => '111111,222222,333333'});
162              
163             Updates an existing group.
164              
165             =cut
166              
167             sub update {
168 0     0 1   my ($self, $data, %opt) = @_;
169             #
170             # updateGroup barfs unless the groupName is included as a parameter.
171             #
172 0           $self->set(%$data);
173 0           my @changed = $self->is_changed;
174 0           push (@changed, 'name')
175 0 0         unless grep {$_ eq 'name'} @changed;
176              
177 0           return $self->SUPER::update( undef, %opt, changed => \@changed);
178             }
179              
180             =head2 expand_members
181              
182             This is a utility method that includes the sum total of all members in
183             the group, including those in recursively nested sub-groups. The list
184             is further reduced to only include unique members.
185              
186             my @all_members = $group_obj->expand_members();
187              
188             It returns C as an array of strings.
189              
190             =cut
191              
192             sub expand_members {
193 0     0 1   my $self = shift;
194 0           my %seen = @_;
195              
196 0           my @members;
197              
198 0 0         foreach (@{ $self->members || []}) {
  0            
199 0           my @elements;
200              
201 0 0 0       if (Scalar::Util::blessed($_)
      0        
202             && $_->can('groupId')
203             && $_->can('expand_members')) {
204             # recursive expansion
205 0 0         @elements = $_->expand_members(%seen)
206             unless $seen{g => $_->groupId}++;
207             }
208             else {
209 0           @elements = (Elive::Util::string($_));
210             }
211              
212 0           foreach my $member (@elements) {
213 0 0         $member = Elive::Util::string($member)
214             if ref $member;
215              
216 0 0 0       if (defined $member && $member =~ m{^\*}) {
217             # should be caught in BUILDARGS anyway...
218 0           carp "skipping unexpanded group: $member";
219             }
220             else {
221 0 0         push(@members, $member)
222             unless $seen{u => $member}++;
223             }
224             }
225             }
226              
227 0           @members = sort @members;
228 0           return @members;
229             }
230              
231             1;