import rt 2.0.14
[freeside.git] / rt / lib / RT / Group.pm
1 # $Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Group.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $
2 # Copyright 2000 Jesse Vincent <jesse@fsck.com>
3 # Released under the terms of the GNU Public License
4 #
5 #
6
7 =head1 NAME
8
9   RT::Group - RT\'s group object
10
11 =head1 SYNOPSIS
12
13   use RT::Group;
14 my $group = new RT::Group($CurrentUser);
15
16 =head1 DESCRIPTION
17
18 An RT group object.
19
20 =head1 AUTHOR
21
22 Jesse Vincent, jesse@fsck.com
23
24 =head1 SEE ALSO
25
26 RT
27
28 =head1 METHODS
29
30
31 =begin testing
32
33 ok (require RT::TestHarness);
34 ok (require RT::Group);
35
36 =end testing
37
38 =cut
39
40
41 package RT::Group;
42 use RT::Record;
43 use RT::GroupMember;
44 use RT::ACE;
45
46 use vars qw|@ISA|;
47 @ISA= qw(RT::Record);
48
49
50 # {{{ sub _Init
51 sub _Init  {
52   my $self = shift; 
53   $self->{'table'} = "Groups";
54   return ($self->SUPER::_Init(@_));
55 }
56 # }}}
57
58 # {{{ sub _Accessible 
59 sub _Accessible  {
60     my $self = shift;
61     my %Cols = (
62                 Name => 'read/write',
63                 Description => 'read/write',
64                 Pseudo => 'read'
65                );
66     return $self->SUPER::_Accessible(@_, %Cols);
67 }
68 # }}}
69
70 # {{{ sub Load 
71
72 =head2 Load
73
74 Load a group object from the database. Takes a single argument.
75 If the argument is numerical, load by the column 'id'. Otherwise, load by
76 the "Name" column which is the group's textual name
77
78 =cut
79
80 sub Load  {
81     my $self = shift;
82     my $identifier = shift || return undef;
83     
84     #if it's an int, load by id. otherwise, load by name.
85     if ($identifier !~ /\D/) {
86         $self->SUPER::LoadById($identifier);
87     }
88     else {
89         $self->LoadByCol("Name",$identifier);
90     }
91 }
92
93 # }}}
94
95 # {{{ sub Create
96
97 =head2 Create
98
99 Takes a paramhash with three named arguments: Name, Description and Pseudo.
100 Pseudo is used internally by RT for certain special ACL decisions.
101
102 =cut
103
104 sub Create {
105     my $self = shift;
106     my %args = ( Name => undef,
107                  Description => undef,
108                  Pseudo => 0,
109                  @_);
110     
111     unless ($self->CurrentUser->HasSystemRight('AdminGroups')) {
112         $RT::Logger->warning($self->CurrentUser->Name ." Tried to create a group without permission.");
113         return(0, 'Permission Denied');
114     }
115     
116     my $retval = $self->SUPER::Create(Name => $args{'Name'},
117                                       Description => $args{'Description'},
118                                       Pseudo => $args{'Pseudo'});
119     
120     return ($retval);
121 }
122
123 # }}}
124
125 # {{{ sub Delete
126
127 =head2 Delete
128
129 Delete this object
130
131 =cut
132
133 sub Delete {
134     my $self = shift;
135     
136     unless ($self->CurrentUser->HasSystemRight('AdminGroups')) {
137         return (0, 'Permission Denied');
138     }
139     
140     return($self->SUPER::Delete(@_));    
141 }
142
143 # }}}
144
145 # {{{ MembersObj
146
147 =head2 MembersObj
148
149 Returns an RT::GroupMembers object of this group's members.
150
151 =cut
152
153 sub MembersObj {
154     my $self = shift;
155     unless (defined $self->{'members_obj'}) {
156         use RT::GroupMembers;
157         $self->{'members_obj'} = new RT::GroupMembers($self->CurrentUser);
158         
159         #If we don't have rights, don't include any results
160         $self->{'members_obj'}->LimitToGroup($self->id);
161         
162     }
163     return ($self->{'members_obj'});
164     
165 }
166
167 # }}}
168
169 # {{{ AddMember
170
171 =head2 AddMember
172
173 AddMember adds a user to this group.  It takes a user id.
174 Returns a two value array. the first value is true on successful 
175 addition or 0 on failure.  The second value is a textual status msg.
176
177 =cut
178
179 sub AddMember {
180     my $self = shift;
181     my $new_member = shift;
182
183     my $new_member_obj = new RT::User($self->CurrentUser);
184     $new_member_obj->Load($new_member);
185     
186     unless ($self->CurrentUser->HasSystemRight('AdminGroups')) {
187         #User has no permission to be doing this
188         return(0, "Permission Denied");
189     }
190
191     unless ($new_member_obj->Id) {
192         $RT::Logger->debug("Couldn't find user $new_member");
193         return(0, "Couldn't find user");
194     }   
195
196     if ($self->HasMember($new_member_obj->Id)) {
197         #User is already a member of this group. no need to add it
198         return(0, "Group already has member");
199     }
200     
201     my $member_object = new RT::GroupMember($self->CurrentUser);
202     $member_object->Create( UserId => $new_member_obj->Id, 
203                             GroupId => $self->id );
204     return(1, "Member added");
205 }
206
207 # }}}
208
209 # {{{ HasMember
210
211 =head2 HasMember
212
213 Takes a user Id and returns a GroupMember Id if that user is a member of 
214 this group.
215 Returns undef if the user isn't a member of the group or if the current
216 user doesn't have permission to find out. Arguably, it should differentiate
217 between ACL failure and non membership.
218
219 =cut
220
221 sub HasMember {
222     my $self = shift;
223     my $user_id = shift;
224
225     #Try to cons up a member object using "LoadByCols"
226
227     my $member_obj = new RT::GroupMember($self->CurrentUser);
228     $member_obj->LoadByCols( UserId => $user_id, GroupId => $self->id);
229
230     #If we have a member object
231     if (defined $member_obj->id) {
232         return ($member_obj->id);
233     }
234
235     #If Load returns no objects, we have an undef id. 
236     else {
237         return(undef);
238     } 
239 }
240
241 # }}}
242
243 # {{{ DeleteMember
244
245 =head2 DeleteMember
246
247 Takes the user id of a member.
248 If the current user has apropriate rights,
249 removes that GroupMember from this group.
250 Returns a two value array. the first value is true on successful 
251 addition or 0 on failure.  The second value is a textual status msg.
252
253 =cut
254
255 sub DeleteMember {
256     my $self = shift;
257     my $member = shift;
258
259     unless ($self->CurrentUser->HasSystemRight('AdminGroups')) {
260         #User has no permission to be doing this
261         return(0,"Permission Denied");
262     }
263
264     my $member_user_obj = new RT::User($self->CurrentUser);
265     $member_user_obj->Load($member);
266     
267     unless ($member_user_obj->Id) {
268         $RT::Logger->debug("Couldn't find user $member");
269         return(0, "User not found");
270     }   
271
272     my $member_obj = new RT::GroupMember($self->CurrentUser);
273     unless ($member_obj->LoadByCols ( UserId => $member_user_obj->Id,
274                                       GroupId => $self->Id )) {
275         return(0, "Couldn\'t load member");  #couldn\'t load member object
276     }
277     
278     #If we couldn't load it, return undef.
279     unless ($member_obj->Id()) {
280         return (0, "Group has no such member");
281     }   
282     
283     #Now that we've checked ACLs and sanity, delete the groupmember
284     my $val = $member_obj->Delete();
285     if ($val) {
286         return ($val, "Member deleted");
287     }
288     else {
289         return (0, "Member not deleted");
290     }
291 }
292
293 # }}}
294
295 # {{{ ACL Related routines
296
297 # {{{ GrantQueueRight
298
299 =head2 GrantQueueRight
300
301 Grant a queue right to this group.  Takes a paramhash of which the elements
302 RightAppliesTo and RightName are important.
303
304 =cut
305
306 sub GrantQueueRight {
307     
308     my $self = shift;
309     my %args = ( RightScope => 'Queue',
310                  RightName => undef,
311                  RightAppliesTo => undef,
312                  PrincipalType => 'Group',
313                  PrincipalId => $self->Id,
314                  @_);
315    
316     #ACLs get checked in ACE.pm
317     
318     my $ace = new RT::ACE($self->CurrentUser);
319     
320     return ($ace->Create(%args));
321 }
322
323 # }}}
324
325 # {{{ GrantSystemRight
326
327 =head2 GrantSystemRight
328
329 Grant a system right to this group. 
330 The only element that's important to set is RightName.
331
332 =cut
333 sub GrantSystemRight {
334     
335     my $self = shift;
336     my %args = ( RightScope => 'System',
337                  RightName => undef,
338                  RightAppliesTo => 0,
339                  PrincipalType => 'Group',
340                  PrincipalId => $self->Id,
341                  @_);
342     
343     # ACLS get checked in ACE.pm
344     
345     my $ace = new RT::ACE($self->CurrentUser);
346     return ($ace->Create(%args));
347 }
348
349
350 # }}}
351
352
353 # {{{ sub _Set
354 sub _Set {
355     my $self = shift;
356
357     unless ($self->CurrentUser->HasSystemRight('AdminGroups')) {
358         return (0, 'Permission Denied');
359     }   
360
361     return ($self->SUPER::_Set(@_));
362
363 }
364 # }}}