An updated patch, incorperating above the previous changes a rewritten flattenNodegroup, minor tweaks to eliminate unnecessary calls to getRef() as well as the modifications discussed in the CB about isApproved() providing failure data in HTMLVARS. This patch is currently in use on the pmdev server. I used diff -uFsub to produce this patch.
--- NodeBase.pm 2005-08-24 00:39:41.433256400 +0200 +++ NodeBase.mod 2005-08-24 00:31:12.277006400 +0200 @@ -1919,7 +1919,7 @@ sub getRef sub isNodetype { my ($this, $NODE) = @_; - $this->getRef($NODE); + $this->getRef($NODE) if !ref $NODE; return 0 if (not ref $NODE); @@ -1947,14 +1947,8 @@ sub isNodetype sub isGroup { my ($this, $NODETYPE) = @_; - my $groupTable; - $this->getRef($NODETYPE); - - $groupTable = $$NODETYPE{grouptable}; - - return $groupTable if($groupTable); - - return 0; + $this->getRef($NODETYPE) if !ref $NODETYPE; + return $NODETYPE->{grouptable} || 0 } @@ -1963,25 +1957,27 @@ sub canCreateNode { my( $this, $USER, $TYPE )= @_; $TYPE = $this->getType( $TYPE ); + my $writers= $TYPE->{writers_user}; # The default is that everyone can create - return 1 if ! $TYPE->{writers_user}; - $this->isApproved( $USER, $TYPE->{writers_user} ); + return 1 if ! $writers; + return $this->isApproved( $USER, $writers, $TYPE ); } ##################################################################### +######## sub canDeleteNode { my( $this, $USER, $NODE )= @_; - $this->getRef($NODE); + $this->getRef($NODE) if !ref $NODE; + my $deleters= $NODE->{type}{deleters_user}; # The default is that nobody can delete - return 0 if ! $NODE || ! $NODE->{type}{deleters_user}; + return 0 if ! $NODE || ! $deleters; # -2 means "owner" can delete (anonymous?) - return $this->isApproved( $USER, $NODE->{author_user} ) - if -2 == $NODE->{type}{deleters_user}; + return $this->isApproved( $USER, $NODE->{author_user}, $NODE ) + if -2 == $deleters; - return $this->isApproved( $USER, $NODE->{type}{deleters_user} ); + return $this->isApproved( $USER, $deleters, $NODE ); } @@ -2001,7 +1997,7 @@ sub canUpdateNode { $updaters = $NODE->{author_user}; } - return $this->isApproved( $USER, $updaters ); + return $this->isApproved( $USER, $updaters, $NODE ); } @@ -2009,18 +2005,20 @@ sub canUpdateNode { sub canReadNode { my( $this, $USER, $NODE )= @_; - $this->getRef($NODE); + $this->getRef($NODE) if !ref($NODE); return 0 if ! $NODE; + my $readers= $NODE->{type}{readers_user}; + # the default is that everyone can read - return 1 if ! $NODE->{type}{readers_user}; + return 1 if !$readers; # -2 means only "owner" can read - return $this->isApproved( $USER, $NODE->{author_user} ) - if -2 == $NODE->{type}{readers_user}; + return $this->isApproved( $USER, $NODE->{author_user}, $NODE ) + if -2 == $readers; - return $this->isApproved( $USER, $$NODE{type}{readers_user} ); + return $this->isApproved( $USER, $readers, $NODE ); } @@ -2032,37 +2030,53 @@ sub canReadNode { # Checks to see if the given user is approved within a given gr +oup # # Parameters -# $user - reference to a user node hash (-1 if super user) -# $NODE - reference to a nodegroup that the user might be in +# $USER - reference to a user node hash (-1 if super user) +# $GROUP - reference to a nodegroup that the user might be in +# $NODE - optional reference to the item being tested against. +# its prescence allows rules to be applied against the +# the item. # # Returns # true if the user is authorized, false otherwise # sub isApproved { - my( $this, $USER, $NODE )= @_; + my( $this, $USER, $GROUP, $NODE )= @_; + + my $vars=\%Everything::HTML::HTMLVARS; - return 0 if ! $USER || ! $NODE; + delete $vars->{isApproved}; + return 0 if ! $USER || ! $GROUP; return 1 if $this->isGod($USER); my $user_id = $this->getId($USER); #you're always approved if it's yourself... - return 1 if $user_id == $this->getId($NODE); + return 1 if $user_id == $this->getId($GROUP); - foreach my $node ( @{ $this->selectNodegroupFlat($NODE) } ) { + foreach my $node ( @{ $this->selectNodegroupFlat($GROUP) } ) { return 1 if $user_id == $this->getId($node); if( $node->{type}{title} =~ /accessrule$/i ) { - my $res= eval $node->{code}; + my $RULE= $node; + my $res= do { + package Everything::HTML; + eval $node->{code}; + }; + if ($@ or (!$res and defined $res)) { + $vars->{isApproved}{rule}=$node; + $vars->{isApproved}{group}=$GROUP; + } if( $@ ) { Everything::printLog( "Access Rule eval error in $node->{node_id}\n" . "$@\n$node->{code}" ); + $vars->{isApproved}{error}=$@; return 0; } - return $res if defined $res; + return $res if defined $res; } } + $vars->{isApproved}{group}=$GROUP; return 0; } @@ -2127,7 +2141,7 @@ sub selectNodegroupFlat { my ($this, $NODE) = @_; - return $this->flattenNodegroup($NODE); + return $this->flattenNodegroup($NODE,{},[]); } @@ -2141,48 +2155,51 @@ sub selectNodegroupFlat # a single node is in its own "group". # # Parameters -# $NODE - the node (preferably a group node) in which to get th +e -# nodes that are within its group. +# $NODE - the node (preferably a group node) in which to get t +he +# nodes that are within its group. +# $seen - hash of id's already seen during traverse. This can +be used +# to filter the result set and is used internally for pr +eventing +# infinite recursion. +# $array - container for the result set. This can be used to "p +restuff" +# the array, and is used internally to avoid repeatedly +passing the +# results up the stack. # # Returns # An array of node hashrefs of all of the nodes in this group. # sub flattenNodegroup { - my ($this, $NODE, $groupsTraversed) = @_; - my @listref; - my $group; - - return undef if (not defined $NODE); - - # If groupsTraversed is not defined, initialize it to an empty - # hash reference. - $groupsTraversed ||= {}; # anonymous empty hash + my ( $this, $GROUP, $seen, $array ) = @_; - $this->getRef($NODE); + return if !$GROUP; - if ($this->isGroup($$NODE{type})) - { - # return if we have already been through this group. Otherwi +se, - # we will get stuck in infinite recursion. - return undef if($$groupsTraversed{$$NODE{node_id}}); - $$groupsTraversed{$$NODE{node_id}} = $$NODE{node_id}; + $seen||= {}; + $array||= []; - foreach my $groupref (@{ $$NODE{group} }) - { - $group = $this->flattenNodegroup($groupref); - push(@listref, @$group) if(defined $group); - } + $this->getRef($GROUP); - return \@listref; + if ( $this->isGroup($GROUP->{type}) ) { + my @items= @{ $GROUP->{group} }; + $this->getRef(@items); + foreach my $item (@items) { + if ( !$seen->{$item->{node_id}}++ ) { + if ( $this->isGroup($item->{type}) ) { + $this->flattenNodegroup($item,$seen,$array); + } + else { + push @$array,$item; + } + } + } } - else - { - return [$NODE]; + elsif ( !$seen->{$GROUP->{node_id}}++ ) { + push @$array,$GROUP; } + return $array; } + ##################################################################### +######## # Sub # insertIntoNodegroup
In reply to Re^6: Adding a 'rule' system to isApproved() (fewer tables)
by demerphq
in thread Adding a 'rule' system to isApproved()
by demerphq
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |