[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