(file) Return to Access.pm CVS log (file) (dir) Up to [RizwankCVS] / geekymedia_web / twiki / lib / TWiki

  1 rizwank 1.1 # Module of TWiki Collaboration Platform, http://TWiki.org/
  2             #
  3             # Copyright (C) 2000-2004 Peter Thoeny, peter@thoeny.com
  4             #
  5             # For licensing info read license.txt file in the TWiki root.
  6             # This program is free software; you can redistribute it and/or
  7             # modify it under the terms of the GNU General Public License
  8             # as published by the Free Software Foundation; either version 2
  9             # of the License, or (at your option) any later version.
 10             #
 11             # This program is distributed in the hope that it will be useful,
 12             # but WITHOUT ANY WARRANTY; without even the implied warranty of
 13             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14             # GNU General Public License for more details, published at
 15             # http://www.gnu.org/copyleft/gpl.html
 16             #
 17             # Notes:
 18             # - Latest version at http://twiki.org/
 19             # - Installation instructions in $dataDir/TWiki/TWikiDocumentation.txt
 20             # - Customize variables in wikicfg.pm when installing TWiki.
 21             # - Optionally change wikicfg.pm for custom extensions of rendering rules.
 22 rizwank 1.1 # - Upgrading TWiki is easy as long as you only customize wikicfg.pm.
 23             # - Check web server error logs for errors, i.e. % tail /var/log/httpd/error_log
 24             
 25             =begin twiki
 26             
 27             ---+ TWiki::Access Package
 28             
 29             This package manages access control to view and change topics. Plugins
 30             should only use the equivalent interface in TWiki::Func.
 31             
 32             =cut
 33             
 34             package TWiki::Access;
 35             
 36             use strict;
 37             
 38             use vars qw(
 39                 %allGroups @processedGroups
 40             );
 41             
 42             # =========================
 43 rizwank 1.1 =pod
 44             
 45             ---++ initializeAccess()
 46             | Description: | Basic module initialization, called from TWiki::initialize |
 47             
 48             =cut
 49             
 50             sub initializeAccess
 51             {
 52                 %allGroups = ();
 53                 @processedGroups = ();
 54             }
 55             
 56             # =========================
 57             # Are there any security restrictions for this Web
 58             # (ignoring settings on individual pages).
 59             =pod
 60             
 61             ---++ sub permissionsSet (  $web  )
 62             
 63             Not yet documented.
 64 rizwank 1.1 
 65             =cut
 66             
 67             sub permissionsSet
 68             {
 69                 my( $web ) = @_;
 70                 
 71                 my $permSet = 0;
 72                 
 73                 my @types = qw/ALLOW DENY/;
 74                 my @actions = qw/CHANGE VIEW RENAME/;
 75                 
 76                 OUT: foreach my $type ( @types ) {
 77                     foreach my $action ( @actions ) {
 78                         my $pref = $type . "WEB" . $action;
 79                         my $prefValue = TWiki::Prefs::getPreferencesValue( $pref, $web ) || "";
 80                         if( $prefValue !~ /^\s*$/ ) {
 81                             $permSet = 1;
 82                             last OUT;
 83                         }
 84                     }
 85 rizwank 1.1     }
 86                 
 87                 return $permSet;
 88             }
 89             
 90             # =========================
 91             =pod
 92             
 93             ---++ checkAccessPermission( $action, $user, $text, $topic, $web ) ==> $ok
 94             | Description:          | Check if user is allowed to access topic |
 95             | Parameter: =$action=  | "VIEW", "CHANGE", "CREATE", etc. |
 96             | Parameter: =$user=    | Remote WikiName, e.g. "Main.PeterThoeny" |
 97             | Parameter: =$text=    | If empty: Read "$theWebName.$theTopicName" to check permissions |
 98             | Parameter: =$topic=   | Topic name to check, e.g. "SomeTopic" |
 99             | Parameter: =$web=     | Web, e.g. "Know" |
100             | Return:    =$ok=      | 1 if OK to access, 0 if no permission |
101             
102             =cut
103             
104             sub checkAccessPermission
105             {
106 rizwank 1.1     my( $theAccessType, $theUserName,
107                     $theTopicText, $theTopicName, $theWebName ) = @_;
108             
109             #AS 2001-11-04 see Codev.UnchangeableTopicBug
110                 if ( $TWiki::doSuperAdminGroup && 
111             	 $TWiki::superAdminGroup ) {
112             	if ( &userIsInGroup( $theUserName, $TWiki::superAdminGroup ) ) {
113             	    return 1;
114             	}
115                 }
116             #/AS
117             
118                 $theAccessType = uc( $theAccessType );  # upper case
119                 if( ! $theWebName ) {
120                     $theWebName = $TWiki::webName;
121                 }
122                 if( ! $theTopicText ) {
123                     # text not supplied as parameter, so read topic
124                     $theTopicText = &TWiki::Store::readWebTopic( $theWebName, $theTopicName );
125                 }
126                 ##&TWiki::writeDebug( "checkAccessPermission: Type $theAccessType, user $theUserName, topic $theTopicName" );
127 rizwank 1.1 
128                 # parse the " * Set (ALLOWTOPIC|DENYTOPIC)$theAccessType = " in body text
129                 my @denyList = ();
130                 my @allowList = ();
131                 foreach( split( /\n/, $theTopicText ) ) {
132                     if( /^\s+\*\sSet\s(ALLOWTOPIC|DENYTOPIC)$theAccessType\s*\=\s*(.*)/ ) {
133                         if( $2 ) {
134                             my $allowOrDeny = $1;        # "ALLOWTOPIC" or "DENYTOPIC"
135                             my @tmpList = map { getUsersOfGroup( $_ ) }
136                                           prvGetUserList( $2 );
137                             ##my $tmp = join( ', ', @tmpList );
138                             ##&TWiki::writeDebug( "  Topic $allowOrDeny$theAccessType: {$tmp}" );
139                             if( $allowOrDeny eq "DENYTOPIC" ) {
140                                 @denyList = @tmpList;
141                             } else {
142                                 @allowList = @tmpList;
143                             }
144                         }
145                     }
146                 }
147                 
148 rizwank 1.1     # if empty, get access permissions from preferences
149                 if( ! @denyList ) {
150                     my $tmpVal = &TWiki::Prefs::getPreferencesValue( "DENYWEB$theAccessType", $theWebName );
151                     @denyList  = map { getUsersOfGroup( $_ ) }
152                                  prvGetUserList( $tmpVal );
153                     ##my $tmp = join( ', ', @denyList );
154                     ##&TWiki::writeDebug( "  Prefs DENYWEB$theAccessType: {$tmp}" );
155                 }
156                 if( ! @allowList ) {
157                     my $tmpVal = &TWiki::Prefs::getPreferencesValue( "ALLOWWEB$theAccessType", $theWebName );
158                     @allowList  = map { getUsersOfGroup( $_ ) }
159                                   prvGetUserList( $tmpVal );
160                     ##my $tmp = join( ', ', @allowList );
161                     ##&TWiki::writeDebug( "  Prefs ALLOWWEB$theAccessType: {$tmp}" );
162                 }
163             
164                 # access permission logic
165                 if( @denyList ) {
166                     if( grep { /^$theUserName$/ } @denyList  ) {
167                         # user is on deny list
168                         ##&TWiki::writeDebug( "  return 0, user is on deny list" );
169 rizwank 1.1             return 0;
170                     }
171                 }
172                 if( @allowList ) {
173                     if( grep { /^$theUserName$/ } @allowList  ) {
174                         # user is on allow list
175                         ##&TWiki::writeDebug( "  return 1, user is on allow list" );
176                         return 1;
177                     } else {
178                         # user is not on allow list
179                         ##&TWiki::writeDebug( "  return 0, user is not on allow list" );
180                         return 0;
181                     }
182                 }
183                 # allow is undefined, so grant access
184                 ##&TWiki::writeDebug( "  return 1, allow is undefined" );
185                 return 1;
186             }
187             
188             # =========================
189             =pod
190 rizwank 1.1 
191             ---++ getListOfGroups(  ) ==> @listOfGroups
192             | Description:        | get a list of groups definedin this TWiki |
193             | Return:    =@listOfGroups=    | list of all the groups |
194             
195             =cut
196             
197             sub getListOfGroups
198             {
199                 my $text = &TWiki::Search::searchWeb(
200                      "inline"        => "1",
201                      "search"        => "Set GROUP =",
202                      "web"           => "all",
203                      "topic"         => "*Group",
204                      "type"          => "regex",
205                      "nosummary"     => "on",
206                      "nosearch"      => "on",
207                      "noheader"      => "on",
208                      "nototal"       => "on",
209                      "noempty"       => "on",
210             	 "format"	 => "\$web.\$topic",
211 rizwank 1.1      );
212             
213                 my ( @list ) =  split ( /\n/, $text );	
214                 return @list;
215             }
216             
217             # =========================
218             =pod
219             
220             ---++ getGroupsUserIsIn( $user ) ==> @listOfGroups
221             | Description:        | get a list of groups a user is in |
222             | Parameter: =$user=  | Remote WikiName, e.g. "Main.PeterThoeny" |
223             | Return:    =@listOfGroups=    | list os all the WikiNames for a group |
224             
225             =cut
226             
227             sub getGroupsUserIsIn
228             {
229                 my( $theUserName ) = @_;
230             
231                 my $userTopic = prvGetWebTopicName( $TWiki::mainWebname, $theUserName );
232 rizwank 1.1     my @grpMembers = ();
233                 my @listOfGroups = getListOfGroups();
234                 my $group;
235             
236             	&TWiki::writeDebug("Checking [$userTopic]");
237                 foreach $group ( @listOfGroups) {
238                     if ( userIsInGroup ( $userTopic, $group )) {
239             	    	push ( @grpMembers, $group );
240             		}
241                 }
242             
243                 return @grpMembers;
244             }
245             
246             # =========================
247             =pod
248             
249             ---++ userIsInGroup( $user, $group ) ==> $ok
250             | Description:        | Check if user is a member of a group |
251             | Parameter: =$user=  | Remote WikiName, e.g. "Main.PeterThoeny" |
252             | Parameter: =$group= | Group name, e.g. "Main.EngineeringGroup" |
253 rizwank 1.1 | Return:    =$ok=    | 1 user is in group, 0 if not |
254             | TODO: | what are we checking if we are not specifying a Group? |
255             | | more detailed documentation@! |
256             
257             =cut
258             
259             sub userIsInGroup
260             {
261                 my( $theUserName, $theGroupTopicName ) = @_;
262             
263                 my $usrTopic = prvGetWebTopicName( $TWiki::mainWebname, $theUserName );
264                 my $grpTopic = prvGetWebTopicName( $TWiki::mainWebname, $theGroupTopicName );
265                 my @grpMembers = ();
266             
267                 if( $grpTopic !~ /.*Group$/ ) {
268                     # not a group, so compare user to user
269                     push( @grpMembers, $grpTopic );
270                 } elsif( ( %allGroups ) && ( exists $allGroups{ $grpTopic } ) ) {
271                     # group is allready known
272                     @grpMembers = @{ $allGroups{ $grpTopic } };
273                 } else {
274 rizwank 1.1         @grpMembers = prvGetUsersOfGroup( $grpTopic, 1 );
275                 }
276             
277                 my $isInGroup = grep { /^$usrTopic$/ } @grpMembers;
278                 return $isInGroup;
279             }
280             
281             # =========================
282             =pod
283             
284             ---++ getUsersOfGroup( $group ) ==> @users
285             | Description:         | Get all members of a group; groups are expanded recursively |
286             | Parameter: =$group=  | Group topic name, e.g. "Main.EngineeringGroup" |
287             | Return:    =@users=  | List of users, e.g. ( "Main.JohnSmith", "Main.JaneMiller" ) |
288             
289             =cut
290             
291             sub getUsersOfGroup
292             {
293                 my( $theGroupTopicName ) = @_;
294                 ##TWiki::writeDebug( "group is $theGroupTopicName" );
295 rizwank 1.1     return prvGetUsersOfGroup( $theGroupTopicName, 1 );
296             }
297             
298             # =========================
299             =pod
300             
301             ---++ sub prvGetUsersOfGroup (  $theGroupTopicName, $theFirstCall  )
302             
303             Not yet documented.
304             
305             =cut
306             
307             sub prvGetUsersOfGroup
308             {
309                 my( $theGroupTopicName, $theFirstCall ) = @_;
310             
311                 my @resultList = ();
312                 # extract web and topic name
313                 my $topic = $theGroupTopicName;
314                 my $web = $TWiki::mainWebname;
315                 $topic =~ /^([^\.]*)\.(.*)$/;
316 rizwank 1.1     if( $2 ) {
317                     $web = $1;
318                     $topic = $2;
319                 }
320                 ##TWiki::writeDebug( "Web is $web, topic is $topic" );
321             
322                 if( $topic !~ /.*Group$/ ) {
323                     # return user, is not a group
324                     return ( "$web.$topic" );
325                 }
326             
327                 # check if group topic is already processed
328                 if( $theFirstCall ) {
329                     # FIXME: Get rid of this global variable
330                     @processedGroups = ();
331                 } elsif( grep { /^$web\.$topic$/ } @processedGroups ) {
332                     # do nothing, already processed
333                     return ();
334                 }
335                 push( @processedGroups, "$web\.$topic" );
336             
337 rizwank 1.1     # read topic
338                 my $text = &TWiki::Store::readWebTopic( $web, $topic );
339             
340                 # reset variables, defensive coding needed for recursion
341                 (my $baz = "foo") =~ s/foo//;
342             
343                 # extract users
344                 my $user = "";
345                 my @glist = ();
346                 foreach( split( /\n/, $text ) ) {
347                     if( /^\s+\*\sSet\sGROUP\s*\=\s*(.*)/ ) {
348                         if( $1 ) {
349                             @glist = prvGetUserList( $1 );
350                         }
351                     }
352                 }
353                 foreach( @glist ) {
354                     if( /.*Group$/ ) {
355                         # $user is actually a group
356                         my $group = $_;
357                         if( ( %allGroups ) && ( exists $allGroups{ $group } ) ) {
358 rizwank 1.1                 # allready known, so add to list
359                             push( @resultList, @{ $allGroups{ $group } } );
360                         } else {
361                             # call recursively
362                             my @userList = prvGetUsersOfGroup( $group, 0 );
363                             # add group to allGroups hash
364                             $allGroups{ $group } = [ @userList ];
365                             push( @resultList, @userList );
366                         }
367                     } else {
368                         # add user to list
369                         push( @resultList, $_ );
370                     }
371                 }
372                 ##TWiki::writeDebug( "Returning group member list of @resultList" );
373                 return @resultList;
374             }
375             
376             # =========================
377             =pod
378             
379 rizwank 1.1 ---++ sub prvGetWebTopicName (  $theWebName, $theTopicName  )
380             
381             Not yet documented.
382             
383             =cut
384             
385             sub prvGetWebTopicName
386             {
387                 my( $theWebName, $theTopicName ) = @_;
388                 $theTopicName =~ s/%MAINWEB%/$theWebName/go;
389                 $theTopicName =~ s/%TWIKIWEB%/$theWebName/go;
390                 if( $theTopicName =~ /[\.]/ ) {
391                     $theWebName = "";  # to suppress warning
392                 } else {
393                     $theTopicName = "$theWebName\.$theTopicName";
394                 }
395                 return $theTopicName;
396             }
397             
398             # =========================
399             =pod
400 rizwank 1.1 
401             ---++ sub prvGetUserList (  $theItems  )
402             
403             Not yet documented.
404             
405             =cut
406             
407             sub prvGetUserList
408             {
409                 my( $theItems ) = @_;
410                 # comma delimited list of users or groups
411                 # i.e.: "%MAINWEB%.UserA, UserB, Main.UserC  # something else"
412                 $theItems =~ s/(<[^>]*>)//go;     # Remove HTML tags
413                 # TODO: i18n fix for user name
414                 $theItems =~ s/\s*([a-zA-Z0-9_\.\,\s\%]*)\s*(.*)/$1/go; # Limit list
415                 my @list = map { prvGetWebTopicName( $TWiki::mainWebname, $_ ) }
416                            split( /[\,\s]+/, $theItems );
417                 return @list;
418             }
419             
420             # =========================
421 rizwank 1.1 
422             1;
423             
424             # EOF

Rizwan Kassim
Powered by
ViewCVS 0.9.2