[MKDoc-commit] Patch from Sam adds group permissions checking to the newsletter code

chris at mkdoc.demon.co.uk chris at mkdoc.demon.co.uk
Mon Jul 25 11:01:25 BST 2005


Log Message:
-----------
Patch from Sam adds group permissions checking to the newsletter code

Tags:
----
mkdoc-1-6

Modified Files:
--------------
    mkd/tools/cron:
        020..newsletter.pl

-------------- next part --------------
Index: 020..newsletter.pl
===================================================================
RCS file: /var/spool/cvs/mkd/tools/cron/020..newsletter.pl,v
retrieving revision 1.1.2.17
retrieving revision 1.1.2.18
diff -Ltools/cron/020..newsletter.pl -Ltools/cron/020..newsletter.pl -u -r1.1.2.17 -r1.1.2.18
--- tools/cron/020..newsletter.pl
+++ tools/cron/020..newsletter.pl
@@ -12,6 +12,11 @@
 
 sub template_path { '/newsletter' }
 
+# keep caches to avoid repeated lookups of group permissions info.
+# These could be disabled if the extra memory used is too much but it
+# seems unlikely to get huge.
+our %DOCUMENT_GROUP_CACHE;
+our %USER_GROUP_CACHE;
 
 sub root
 {
@@ -145,7 +150,11 @@
         next unless ($h->{Pref_Score} > 0);
 	my $doc = $doc_t->get ( $h->{ID} );
 	next unless ($doc->is_showable());
-	
+
+        # check permissions (this can't go in the SQL above due to the
+        # tree-walking needed to test a document's group membership)
+        next unless user_can_see($self->user, $doc);
+        
 	$Text::Wrap::columns = 72;
 	$Text::Wrap::columns = 72;
 
@@ -183,6 +192,69 @@
     return $self->{"_cache_$mode"} = \@res;
 }
 
+# determine if user should be able to see this document, looking at
+# group permissions.  Returns 1 if the user has access, 0 if not.
+sub user_can_see {
+    my ($user, $document) = @_;
+
+    # lookup groups for the document, no groups means everyone can see it
+    my @doc_group_ids = find_groups($document);
+    return 1 unless @doc_group_ids;
+
+    # get a list of the user's groups
+    my @groups = user_groups($user);
+
+    # no results means the user wasn't in any of the groups, denied
+    return 0 unless @groups;
+
+    # allow through if the user is in one of the document's groups
+    my %groups = map { ($_->{Grp_ID}, 1) } @groups;
+    return 1 if grep { $groups{$_} } @doc_group_ids;
+    
+    # no dice
+    return 0;
+}
+
+# get a list of groups for a particular user
+sub user_groups {
+    my $user = shift;
+    return @{$USER_GROUP_CACHE{$user->id}} 
+      if $USER_GROUP_CACHE{$user->id};
+
+    my $editor_grp_t = flo::Standard::table('Editor_Grp');
+    my $con          = lib::sql::Condition->new(Editor_ID => $user->id);
+    my @groups       = $editor_grp_t->select(cols  => 'Grp_ID',
+                                             where => $con)->fetch_all;
+
+    $USER_GROUP_CACHE{$user->id} = \@groups;
+    return @groups;
+}
+
+# get groups for a document, looking up the tree
+sub find_groups {
+    my $document = shift;
+    my $document_grp_t = flo::Standard::table('Document_Grp');
+
+    return @{$DOCUMENT_GROUP_CACHE{$document->id}} 
+      if $DOCUMENT_GROUP_CACHE{$document->id};
+
+    # get list of all documents to check
+    my @documents = ($document, $document->ancestors);
+
+    # get results for each document 
+    my %groups;
+    foreach my $doc (@documents) {
+        my @res = $document_grp_t->select (
+	cols => 'Grp_ID',
+        where => lib::sql::Condition->new(Document_ID => $doc->id)
+                                      )->fetch_all();
+        $groups{$_->{Grp_ID}} = 1 for @res;
+    }
+
+    $DOCUMENT_GROUP_CACHE{$document->id} = [keys %groups];
+    return @{$DOCUMENT_GROUP_CACHE{$document->id}};
+}
+
 # translate a time to day-month-year for use with MySQL
 sub _time2date {
     my $self = shift;


More information about the MKDoc-commit mailing list