журнал (shhh) wrote in changelog,
журнал
shhh
changelog

[livejournal] r22252: LJSUP-12247: Implement requested scopes/...

Committer: nnikulochkina
LJSUP-12247: Implement requested scopes/permissions mapping for XML-RPC functions
U   trunk/cgi-bin/Apache/LiveJournal.pm
U   trunk/cgi-bin/ljprotocol.pl
Modified: trunk/cgi-bin/Apache/LiveJournal.pm
===================================================================
--- trunk/cgi-bin/Apache/LiveJournal.pm	2012-06-15 07:39:06 UTC (rev 22251)
+++ trunk/cgi-bin/Apache/LiveJournal.pm	2012-06-15 07:40:52 UTC (rev 22252)
@@ -2416,26 +2416,13 @@
     shift;   # get rid of package name that dispatcher includes.
     my $req = shift;
 
-    # For specified methods
-    if ($LJ::XMLRPC_VALIDATION_METHOD{$method}) {
-        # Deny access for accounts that have not validated their email
-        my $u = LJ::load_user($req->{'username'});
-        unless ($u){
-            die SOAP::Fault
-                ->faultstring("Unknown username.");
-        }
-        unless ($u->is_validated) {
-            die SOAP::Fault
-                ->faultstring("Account not validated.");
-       }
-    }
-
     if (@_) {
         # don't allow extra arguments
         die SOAP::Fault
             ->faultstring(LJ::Protocol::error_message(202))
             ->faultcode(202);
     }
+
     my $error = 0;
 
     ## All our functions take signle hashref as an argument.
@@ -2512,10 +2499,7 @@
         ## They are useless for Ops, but, yes, they can be useful for engineering debug.
         ##
         warn "LJ::XMLRPC::$method died: $@"
-            if $@ !~ /^\d+?\s*:/
-            and $@ !~ m/\s*:\s*Account not validated./
-            and $@ !~ "Unknown username.";
-
+            if $@ !~ /^\d+?\s*:/;
         die $@;
     }
 

Modified: trunk/cgi-bin/ljprotocol.pl
===================================================================
--- trunk/cgi-bin/ljprotocol.pl	2012-06-15 07:39:06 UTC (rev 22251)
+++ trunk/cgi-bin/ljprotocol.pl	2012-06-15 07:40:52 UTC (rev 22252)
@@ -22,6 +22,7 @@
                       LJ::PersistentQueue
                       LJ::PersonalStats::Ratings::Posts
                       LJ::PersonalStats::Ratings::Journals
+                      LJ::API::RateLimiter
                       );
 
 use LJ::TimeUtil;
@@ -29,6 +30,8 @@
 
 LJ::Config->load;
 
+
+
 use lib "$ENV{LJHOME}/cgi-bin";
 
 require "taglib.pl";
@@ -126,7 +129,13 @@
      "328" => E_PERM,
      "329" => E_PERM,
      "330" => E_PERM,
-
+     "331" => E_TEMP,
+     "332" => E_TEMP,
+     "333" => E_PERM,
+     "334" => E_PERM,
+     "335" => E_PERM,
+     "336" => E_TEMP,
+    
      # Limit errors
      "402" => E_TEMP,
      "404" => E_TEMP,
@@ -138,6 +147,7 @@
      "410" => E_PERM,
      "411" => E_TEMP,
      "412" => E_TEMP,
+     "413" => E_TEMP,
 
      # Server Errors
      "500" => E_TEMP,
@@ -317,7 +327,7 @@
 sub getpoll
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getpoll');
     my $u = $flags->{'u'};
 
     # check arguments
@@ -414,7 +424,7 @@
 sub editpoll
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'editpoll');
     my $u = $flags->{'u'};
 
     # check arguments
@@ -453,7 +463,7 @@
 sub votepoll
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'votepoll');
     my $u = $flags->{'u'};  # remote_id
 
     # check pollid
@@ -491,7 +501,7 @@
 sub checksession {
     my ($req, $err, $flags) = @_;
     return undef
-        unless authenticate($req, $err, $flags);
+        unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'checksession');
 
     my $u = $flags->{'u'};
 
@@ -511,7 +521,7 @@
 sub addcomment
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'addcomment');
     my $u = $flags->{'u'};
 
     return fail($err,200,"body") unless($req->{body});
@@ -574,7 +584,7 @@
 
     $flags->{allow_anonymous} = 1;
 
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getcomments');
     my $u = $flags->{'u'};
 
     my $journal;
@@ -785,7 +795,7 @@
 =cut
 sub deletecomments {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'deletecomments');
 
     my $u = $flags->{'u'};
     my $journal;
@@ -913,7 +923,7 @@
 
 sub updatecomments {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'updatecomments');
 
     my $u = $flags->{'u'};
     my $journal;
@@ -1110,7 +1120,7 @@
 =cut
 sub editcomment {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'editcomment');
 
     my $remote = $flags->{'u'};
     return fail($err, 318) if $remote && $remote->is_readonly;
@@ -1162,7 +1172,7 @@
 
 sub getrecentcomments {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getrecentcomments');
     my $u = $flags->{'u'};
 
     my $journal;
@@ -1240,7 +1250,7 @@
 sub getfriendspage
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getfriendspage');
     my $u = $flags->{'u'};
 
     my $itemshow = (defined $req->{itemshow}) ? $req->{itemshow} : 100;
@@ -1385,7 +1395,7 @@
 sub getinbox
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getinbox');
     my $u = $flags->{'u'};
 
     my $itemshow = (defined $req->{itemshow}) ? $req->{itemshow} : 100;
@@ -1490,7 +1500,7 @@
 sub setmessageread {
     my ($req, $err, $flags) = @_;
 
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'setmessageread');
 
     my $u = $flags->{'u'};
 
@@ -1542,7 +1552,7 @@
 
     return fail($err, 315) if $LJ::DISABLED{user_messaging};
 
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'sendmessage');
     my $u = $flags->{'u'};
 
     return fail($err, 305) if $u->statusvis eq 'S'; # suspended cannot send private messages
@@ -1615,7 +1625,7 @@
 sub login
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'login');
     return undef unless check_altusage($req, $err, $flags);
 
     my $u = $flags->{'u'};
@@ -1711,6 +1721,7 @@
     $res->{'fastserver'} = 1 if LJ::get_cap($uowner, "fastserver");
 
     ## user info
+    $res->{'username'} = $uowner->{'user'};
     $res->{'userid'} = $uowner->{'userid'};
     $res->{'fullname'} = $uowner->{'name'};
     LJ::text_out(\$res->{'fullname'}) if $ver >= 1;
@@ -1752,7 +1763,7 @@
 sub getfriendgroups
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getfriendgroups');
     my $u = $flags->{'u'};
     my $res = {
         xc3 => {
@@ -1774,7 +1785,7 @@
 sub getusertags
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getusertags');
     return undef unless check_altusage($req, $err, $flags);
 
     my $u = $flags->{'u'};
@@ -1795,7 +1806,7 @@
     my ($req, $err, $flags) = @_;
 
     $flags->{'allow_anonymous'} = 1;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getuserpics');
     $flags->{'ignorecanuse'} = 1;   #    function return public info
     return undef unless check_altusage($req, $err, $flags);
 
@@ -1831,7 +1842,8 @@
 sub getfriends
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getfriends');
+
     return fail($req,502) unless LJ::get_db_reader();
     my $u = $flags->{'u'};
     my $res = {
@@ -1874,7 +1886,7 @@
 sub friendof
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'friendof');
     return fail($req,502) unless LJ::get_db_reader();
     my $u = $flags->{'u'};
     my $res = {
@@ -1898,7 +1910,7 @@
 sub checkfriends
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'checkfriends');
     my $u = $flags->{'u'};
     my $res = {
         xc3 => {
@@ -1981,7 +1993,7 @@
 sub getdaycounts
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getdaycounts');
     return undef unless check_altusage($req, $err, $flags);
 
     my $u = $flags->{'u'};
@@ -2178,8 +2190,8 @@
     un_utf8_request($req);
 
     my $post_noauth = LJ::run_hook('post_noauth', $req);
-    return undef unless $post_noauth || authenticate($req, $err, $flags);
 
+    return undef unless $post_noauth || authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'postevent');
     my $spam = 0;
     LJ::run_hook('spam_detector', $req, \$spam);
     return fail($err,320) if $spam;
@@ -2938,7 +2950,7 @@
     my ($req, $err, $flags) = @_;
     un_utf8_request($req);
 
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'editevent');
 
     my $spam = 0;
     return undef unless LJ::run_hook('spam_detector', $req, \$spam);
@@ -3451,7 +3463,7 @@
     my ($req, $err, $flags) = @_;
 
     $flags->{allow_anonymous} = 1;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getevents');
 
     $flags->{'ignorecanuse'} = 1; # later we will check security levels, so allow some access to communities
     return undef unless check_altusage($req, $err, $flags);
@@ -4124,7 +4136,7 @@
 sub editfriends
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'editfriends');
 
     my $u = $flags->{'u'};
     my $userid = $u->{'userid'};
@@ -4340,7 +4352,7 @@
 sub editfriendgroups
 {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'editfriendgroups');
 
     my $u = $flags->{'u'};
     my $userid = $u->{'userid'};
@@ -4517,7 +4529,7 @@
 
 sub sessionexpire {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'sessionexpire');
     my $u = $flags->{u};
     my $res = {
         xc3 => {
@@ -4545,7 +4557,7 @@
 sub sessiongenerate {
     # generate a session
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'sessiongenerate');
 
     # sanitize input
     $req->{expiration} = 'short' unless $req->{expiration} eq 'long';
@@ -4673,7 +4685,7 @@
 
 sub syncitems {
     my ($req, $err, $flags) = @_;
-    return undef unless authenticate($req, $err, $flags);
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'syncitems');
     return undef unless check_altusage($req, $err, $flags);
     return fail($err, 506) if $LJ::DISABLED{'syncitems'};
 
@@ -4779,7 +4791,7 @@
     my ($req, $err, $flags) = @_;
 
     # logging in isn't necessary, but most console commands do require it
-    LJ::set_remote($flags->{'u'}) if authenticate($req, $err, $flags);
+    LJ::set_remote($flags->{'u'}) if authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'consolecommand');
 
     my $res = {
         xc3 => {
@@ -5025,40 +5037,43 @@
 {
     my ($req, $err, $flags) = @_;
 
-    my $username = $req->{'username'};
+    my $u;
 
-    # add flag to avoid authentication
-    if (!$username && $flags->{'allow_anonymous'}) {
-        undef $flags->{'u'};
+    my $auth_meth = $req->{'auth_method'} || "clear";
+    my $username  = $req->{'username'} || '';
+
+    my $check_user = sub {
+        return fail($err,100) unless $u;
+        return fail($err,100) if ($u->{'statusvis'} eq "X");
+        return fail($err,505) unless $u->{'clusterid'};
         return 1;
-    }
+    };
 
-    return fail($err,200) unless $username;
-    return fail($err,100) unless LJ::canonical_username($username);
+    unless ($auth_meth eq "oauth") {
+  
+        # add flag to avoid authentication
+        if (!$username && $flags->{'allow_anonymous'}) {
+            undef $flags->{'u'};
+            return 1;
+        }
 
-    my $u = $flags->{'u'};
-    unless ($u) {
-        my $dbr = LJ::get_db_reader();
-        return fail($err,502) unless $dbr;
-        $u = LJ::load_user($username);
-    }
+        return fail($err,200) unless $username;
+        return fail($err,100) unless LJ::canonical_username($username);
 
-    return fail($err,100) unless $u;
-    return fail($err,100) if ($u->{'statusvis'} eq "X");
-    return fail($err,505) unless $u->{'clusterid'};
+        $u = $flags->{'u'};
+        unless ($u) {
+            my $dbr = LJ::get_db_reader();
+            return fail($err,502) unless $dbr;
+            $u = LJ::load_user($username);
+        }
 
-    my $ip;
-    if (LJ::Request->is_inited) {
-        LJ::Request->notes("ljuser" => $u->{'user'}) unless LJ::Request->notes("ljuser");
-        LJ::Request->notes("journalid" => $u->{'userid'}) unless LJ::Request->notes("journalid");
-        $ip = LJ::Request->connection->remote_ip;
+        return unless $check_user->();
     }
 
     my $ip_banned = 0;
     my $chal_expired = 0;
     my $auth_check = sub {
 
-        my $auth_meth = $req->{'auth_method'} || "clear";
         if ($auth_meth eq "clear") {
             my $res = LJ::auth_okay($u,
                                     $req->{'password'},
@@ -5089,26 +5104,90 @@
             my $remote = LJ::get_remote();
             return $remote && $remote->{'user'} eq $username ? 1 : 0;
         }
+        if ($auth_meth eq "oauth"){
+            my $rate_limiter = LJ::Request->is_inited ? 
+              LJ::API::RateLimiter->new(LJ::Request->request) :
+              LJ::API::RateLimiter->new();
+
+            my $oauth = LJ::OAuth->new(rate_limiter => $rate_limiter);
+            
+            my $result = $oauth->have_access;
+            unless ($result->{http_status} == 200) {
+                return fail($err,331,$result->{oauth_problem}) if $result->{http_status} == 400;
+                return fail($err,332,$result->{oauth_problem}) if $result->{http_status} == 401;
+                return fail($err,334,$result->{oauth_problem}) if $result->{http_status} == 403;
+                return fail($err,413,$result->{oauth_problem}) if $result->{http_status} == 503;
+                return fail($err,101);
+            } 
+            $u = $result->{user};
+            return unless $check_user->();
+            $flags->{'user_access'} = $result->{access};
+            LJ::Session->record_login($u);
+        }
     };
 
     unless ($flags->{'nopassword'} ||
             $flags->{'noauth'} ||
             $auth_check->() )
     {
+        return undef if $$err;
         return fail($err,402) if $ip_banned;
         return fail($err,105) if $chal_expired;
         return fail($err,101);
     }
 
+    return 1 if ($flags->{'allow_anonymous'} && !$u);
+
     # if there is a require TOS revision, check for it now
     return fail($err, 156) unless $u->tosagree_verify;
 
     # remember the user record for later.
     $flags->{'u'} = $u;
+
+    if (LJ::Request->is_inited) {
+        LJ::Request->notes("ljuser" => $u->{'user'}) unless LJ::Request->notes("ljuser");
+        LJ::Request->notes("journalid" => $u->{'userid'}) unless LJ::Request->notes("journalid");
+    }
+
     return 1;
 }
 
+sub authorize
+{
+    my ($req, $err, $flags, $method) = @_;
+    
+    my $auth_method = $req->{'auth_method'};
 
+    return 1 if ($flags->{noauth});
+
+    if ($auth_method eq 'oauth') {
+
+        return fail($err,333) unless $flags->{'user_access'};
+        return fail($err,333) unless defined $LJ::XMLRPC_USER_ACCESS{$method};
+        
+        my $access_required = ref $LJ::XMLRPC_USER_ACCESS{$method} ? $LJ::XMLRPC_USER_ACCESS{$method} : [$LJ::XMLRPC_USER_ACCESS{$method}];
+        
+        my %user_access = map {$_ => 1} @{$flags->{'user_access'}};
+ 
+        foreach my $p (@$access_required){
+            return fail($err,333) unless ( $user_access{$p} || ($p =~ /(.+)_ro$/) && $user_access{"$1_rw"} );
+        }
+    } 
+
+    if ($LJ::XMLRPC_VALIDATION_METHOD{$method}) {
+        # Deny access for accounts that have not validated their email
+        my $u = $flags->{'u'} || LJ::load_user($req->{'username'});
+        unless ($u){
+            return fail($err,335);
+        }
+        unless ($u->is_validated) {
+            return fail($err,336);
+        }
+    }
+    
+    return 1;
+}
+
 sub fail
 {
     my $err  = shift;
@@ -5182,7 +5261,7 @@
     my ($req, $err, $flags) = @_;
 
     return undef
-        unless authenticate($req, $err, $flags);
+        unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'registerpush');
 
     my $u = $flags->{u};
 
@@ -5207,7 +5286,7 @@
 sub unregisterpush {
     my ($req, $err, $flags) = @_;
     return undef
-        unless authenticate($req, $err, $flags);
+        unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'unregisterpush');
 
     my $u = $flags->{u};
 
@@ -5225,7 +5304,7 @@
 sub pushsubscriptions {
     my ($req, $err, $flags) = @_;
     return undef
-        unless authenticate($req, $err, $flags);
+        unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'pushsubscriptions');
 
     my $u = $flags->{u};
     my @errors;
@@ -5260,7 +5339,7 @@
 sub resetpushcounter {
     my ($req, $err, $flags) = @_;
     return undef
-        unless authenticate($req, $err, $flags);
+        unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'resetpushcounter');
 
     my $u = $flags->{u};
 
@@ -5282,7 +5361,7 @@
 sub getpushlist {
     my ($req, $err, $flags) = @_;
     return undef
-        unless authenticate($req, $err, $flags);
+        unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getpushlist');
 
     my $u = $flags->{u};
 
@@ -5327,7 +5406,9 @@
 sub geteventsrating {
     my ($req, $err, $flags) = @_;
 
-    authenticate($req, $err, {%$flags, allow_anonymous => 1});
+    $flags->{allow_anonymous} = 1;
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'geteventsrating');
+
     my $user_id = $flags->{u} ? $flags->{u}->id : 0;
     
     return fail($err, 200, 'region') unless $req->{region};
@@ -5426,7 +5507,9 @@
 sub getusersrating {
     my ($req, $err, $flags) = @_;
 
-    authenticate($req, $err, {%$flags, allow_anonymous => 1});
+    $flags->{allow_anonymous} = 1;
+    return undef unless authenticate($req, $err, $flags) && authorize($req, $err, $flags, 'getusersrating');
+
     my $user_id = $flags->{u} ? $flags->{u}->id : 0;
 
     return fail($err, 200, 'region') unless $req->{region};

Tags: livejournal, nikulochkina, nnikulochkina, pl, pm
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments