############################################################################# # Sub # isApproved # # Purpose # Checks to see if the given user is approved within a given group # # Parameters # $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. # $NotGod - If the last parameter is the string 'notgod' # then isApproved will not consider gods to # to be automatically approved. # # Returns # true if the user is authorized, false otherwise # # Uses %Everything::HTML::HTMLVARS as a per-session cache # of the results as well as populating # $Everything::HTML::HTMLVARS{isApproved} # with a hash of the results. This hash should be treated # as read only, and may contain the following keys: # group => the last $GROUP checked # user => the last $USER checked # node => the last $NODE # rule => if a rule was responsible for a failure # it will be provided here # error => if an error occured during processing # a rule the value will be here # ret => the actual return value (0/1) # # Note this cache is per session, which means on average # it will be for one $USER and most likely three or four # groups. It wont be large. sub isApproved { my( $this, $USER, $GROUP, $NODE, $notgod )= @_; ($notgod,$NODE)=($NODE,$notgod) if $NODE eq 'notgod'; my $vars=\%Everything::HTML::HTMLVARS; $vars->{isApproved_calls}++; my $cachekey = join "|", map { ref $_ ? $_->{node_id} : $_ } $USER,$GROUP,$NODE?$NODE:0,$notgod?1:0 ; if (my $hash=$vars->{'isApproved.Lookup'}{$cachekey}) { $vars->{isApproved_calls_cachedret}++; $vars->{isApproved}=$hash; return $hash->{ret}; } else { $vars = $vars->{'isApproved.Lookup'}{$cachekey} = $vars->{isApproved} = {}; } $vars->{user}=$USER; $vars->{group}=$GROUP; $vars->{node}=$NODE; $vars->{notgod}=$notgod; return $vars->{isApproved}=0 if ! $USER || ! $GROUP; if ( !ref $GROUP ) { if ($GROUP=~/^\d+$/) { $GROUP=$this->getNodeById( $GROUP ); } else { my ($name,$type)=split /\s*\|\s*/,$GROUP; return $vars->{isApproved}=0 if ! $name; if ($type) { $GROUP=$this->getNode($name,$type); } else { $GROUP=undef; } $GROUP||=$this->getNode($name,'usergroup'); $GROUP||=$this->getNode($name,'accessrule'); } } return $vars->{isApproved}=0 if ! $GROUP; # We always say that gods are approved, # regardless of their true membership. # Is this really the right thing to do? # It maintains legacy behaviour, but its unclear # if this really is the best idea. (demerphq) return $vars->{ret}=1 if !$notgod && $this->isGod($USER); my $user_id = $this->getId($USER); #You're always approved if it's yourself... return $vars->{ret} = 1 if $user_id == $this->getId($GROUP); foreach my $node ( @{ $this->selectNodegroupFlat($GROUP) } ) { return $vars->{ret} = 1 if $user_id == $this->getId($node); if( $node->{type}{title} =~ /accessrule$/i ) { my $RULE= $node; my $res= do { package Everything::HTML; eval $node->{code}; }; if ($@ or (!$res and defined $res)) { $vars->{isApproved}{rule} = $node; } if( $@ ) { Everything::printLog( "Access Rule eval error in $node->{node_id}\n" . "$@\n$node->{code}" ); $vars->{error}=$@; return $vars->{ret} = 0; } return $vars->{ret}= $res if defined $res; } } return $vars->{ret} = 0; } ############################################################################# # Sub # isGod # # Purpose # Checks to see if a user is in the gods group. This includes root # and '-1' as gods. This also checks sub groups so you can have # other usergroups in the gods group. # # Parameters # $USER - an id or HASH ref to a user node. # # Returns # 1 if the user is a god, 0 otherwise # # Uses %Everything::HTML::HTMLVARS as a per-session cache # sub isGod { my ($this, $USER) = @_; my $user_id; my $usergroup; my $GODS; my $godsgroup; my $god; # he's my god too... return 1 if($USER == -1); $this->getRef($USER); my $vars=\%Everything::HTML::HTMLVARS; $vars->{isGod_calls}++; if (defined $vars->{'isGod.Lookup'}{$USER->{node_id}}) { $vars->{isGod_calls_cachedret}++; return $vars->{'isGod.Lookup'}{$USER->{node_id}} } $user_id = $this->getId($USER); $usergroup = $this->getType("usergroup"); ($GODS) = $this->getNode("gods", $usergroup); $godsgroup = $$GODS{group}; #$this->selectNodegroupFlat($GODS); my $is_god=0; foreach $god (@$godsgroup) { if ($user_id == $this->getId($god)) { $is_god=1; last; } } $vars->{'isGod.Lookup'}{$USER->{node_id}}=$is_god; return $is_god; }