]> www.wagner.pp.ru Git - oss/stilllife.git/blobdiff - forum/forum
Отлажена работа кода проверки прав (хотя бы для администратора)
[oss/stilllife.git] / forum / forum
index 91961bfa7bb3425ccc452a1d399b49a89cad3e72..c7148594e2a7af9b78902be411f14f866af78a93 100755 (executable)
@@ -36,9 +36,25 @@ my %actions = (
        openidlogin=>\&openid_login,
        openidvfy =>\&openid_verify
 );     
+#
+#  Уровень прав, которые необходимо иметь пользователю для совершения
+#  определенного действия
+#  иерархия вида undef < banned < normal < author < moderator <admin
+#  Если операция не упомянута в данном массив, то значит можно всем, в
+#  том числе  и анониму.
+# Слово login означает, что вообще-то это normal, но пользователь может
+# логиниться непосредственно в процессе выполнения операции.
+my %permissions = (
+       reply => "login",
+       edit => "author",
+       delete => "author",
+       newtopic => "normal",
+       move => "moderator",
+       newforum => "moderator",
+       profile => "normal",
+       setrights => "admin",
+);     
 
-
-       
 my $cgi = new CGI;
 print STDERR "--------------------\n";
 my $forum=get_forum_config();
@@ -83,8 +99,14 @@ if ($cgi->request_method ne "POST") {
        # Запрос методом POST. Вызываем обработчик
        for my $param ($cgi->param) {
                if (exists $actions{$param}) {
-                       $actions{$param}->($param,$cgi,$forum);
-                       exit;
+                       if (allow_operation($param,$cgi,$forum)) {
+                               $actions{$param}->($param,$cgi,$forum);
+                               exit;
+                       } else {
+                               show_error($forum,"У Вас нет прав на  выполнение этой
+                               операции")
+                       }
+
                }
        }
        print STDERR "Получены параметры ",join(" ",$cgi->param),"\n";
@@ -346,7 +368,6 @@ sub fix_forum_links {
                        $attr ="src";
                }
                my $link = $element->attr($attr);
-               print STDERR "Fixing link $link\n";
                # Абсолютная ссылка - оставляем как есть. 
                next ELEMENT if (! defined $link || $link=~/^\w+:/); 
                # Ссылка от корня сайта. 
@@ -363,7 +384,6 @@ sub fix_forum_links {
                    !($link =~ s!^forum\b!$script_with_path!)) {
                        $link = $forum->{"forumtop"}."/".$link 
                }       
-               print STDERR "Fixed to $link\n";
                $element->attr($attr,$link);
        }
 }              
@@ -501,7 +521,6 @@ sub authenticate {
        dbmopen %userbase,datafile($forum,"passwd"),0644;
        my $user = $cgi->param("user");
        my $password = $cgi->param("password");
-       print STDERR "user=>'$user'\npassword=>'$password'\n";
        $cgi->delete("password");
        if (! $userbase{$user}) {
          set_error($forum,"Неверное имя пользователя или пароль");
@@ -509,7 +528,7 @@ sub authenticate {
        }   
        my $userinfo = thaw($userbase{$user}) ;
        dbmclose %userbase;
-       while (my ($key,$val)=each %$userinfo) { print STDERR "$key => '$val'\n";}
+       #while (my ($key,$val)=each %$userinfo) { print STDERR "$key => '$val'\n";}
        if (crypt($password,$userinfo->{passwd}) eq $userinfo->{passwd}) {
                delete $userinfo->{"passwd"};
                $cgi->delete("password");
@@ -681,8 +700,24 @@ sub logout {
 }      
 sub allow_operation {
        my ($operation,$cgi,$forum) = @_;
-       return 1 if (grep $operation eq $_,"register","login","reply");
-
+       return 1 if (!exists($permissions{$operation})); 
+       if (!$forum->{authenticated}) {
+               return 1 if ($permissions{$operation} eq "login");
+               return 0;
+       }       
+       my $user = $forum->{authenticated}{user} ;
+       my $accesslevel=getrights($cgi,$forum);
+       # Если permissions{$operation} равны author, нам нужно извлечь
+       # текст из соответствующего файла и положить его в
+       # cgi->param("text"); Заодно определим и автора
+       my ($itemauthor,$itemtext)=get_message_by_id($cgi->param("id")) if
+               $permissions{$operation} eq "author";
+       
+       return 1 if ($accesslevel eq "admin");
+       return 0 if ($permissions{$operation} eq "admin");      
+       return 1 if ($accesslevel eq "moderator");
+       return 0 if $accesslevel eq "banned";   
+       return 0 if $permissions{$operation} eq "author" && $user ne $itemauthor;
        return 1;
 }
 
@@ -726,4 +761,50 @@ sub reply {
                }       
        }       
 }      
-               
+#
+# читает файлы прав доступа в дереве форума, и возвращает
+# статус текущего пользователя (undef - аноним, banned, normal,
+# moderator или admin
+
+sub getrights {
+       my ($cgi,$forum) = @_;
+       if (!$forum->{authenticated}) {
+               return undef;
+       }       
+       my $user = $forum->{authenticated}{user};
+       my $dir = $ENV{'PATH_TRANSLATED'};
+       $dir =~s/\/[^\/]+$// if (!-d $dir);
+       my $f;
+       my $user_status = "normal";
+       LEVEL:
+       while (length($dir)) {  
+               if (-f "$dir/perms.txt") {
+                       open $f,"<","$dir/perms.txt";
+                       my $status = undef;
+                       while (<$f>) {
+                               if (/^\[\s*(admins|moderators|banned)\s*\]/) {
+                                       $status = $1;
+                               } else {
+                                       chomp;
+                                       if  ($user eq $_ && defined $status) {
+                                               if ($status eq "banned") {
+                                                       return $status;
+                                               } 
+                                               if ($status eq "admins" ) {
+                                                       return "admin";
+                                               }
+                                               $user_status = "moderator";
+                                       }
+                               }       
+                       }
+                       close $f;
+                       last LEVEL if  -f "$dir/.forum";
+                       # Strip last path component.
+                       $dir =~s/\/[^\/]+$// 
+               }       
+       }               
+       return $user_status;
+
+}              
+
+