mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2009-11-24 08:03 pm

[dw-free] "Maintainer only" posting security in communities

[commit: http://hg.dwscoalition.org/dw-free/rev/e36a761d81b3]

http://bugs.dwscoalition.org/show_bug.cgi?id=1589

Add 'Maintainers' security option when posting entries to communities.

Patch by [personal profile] afuna.

Files modified:
  • bin/upgrading/en.dat
  • cgi-bin/DW/Logic/LogItems.pm
  • cgi-bin/LJ/Entry.pm
  • cgi-bin/LJ/S2/DayPage.pm
  • cgi-bin/LJ/S2/MonthPage.pm
  • cgi-bin/LJ/Setting/MinSecurity.pm
  • cgi-bin/LJ/Talk.pm
  • cgi-bin/LJ/User.pm
  • cgi-bin/ljhooks.pl
  • cgi-bin/ljprotocol.pl
  • cgi-bin/weblib.pl
  • htdocs/js/entry.js
  • htdocs/tools/endpoints/getsecurityoptions.bml
--------------------------------------------------------------------------------
diff -r dbaae7e52705 -r e36a761d81b3 bin/upgrading/en.dat
--- a/bin/upgrading/en.dat	Tue Nov 24 19:51:11 2009 +0000
+++ b/bin/upgrading/en.dat	Tue Nov 24 20:03:33 2009 +0000
@@ -2751,6 +2751,8 @@ setting.minsecurity.option.select.friend
 
 setting.minsecurity.option.select.members=members
 
+setting.minsecurity.option.select.admin=administrators
+
 setting.minsecurity.option.select.private=just me (private)
 
 setting.minsecurity.option.select.public=everyone (public)
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/DW/Logic/LogItems.pm
--- a/cgi-bin/DW/Logic/LogItems.pm	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/DW/Logic/LogItems.pm	Tue Nov 24 20:03:33 2009 +0000
@@ -412,8 +412,11 @@ sub recent_items
 
     # decide what level of security the remote user can see
     my $secwhere = "";
-    if ($userid == $remoteid || $args{'viewall'}) {
+    if ( $userid == $remoteid
+        || ( $remote && $remote->can_manage( $u ) )
+        || $args{'viewall'} ) {
         # no extra where restrictions... user can see all their own stuff
+        # community administrators can also see everything in their comms
         # alternatively, if 'viewall' opt flag is set, security is off.
     } elsif ($mask) {
         # can see public or things with them in the mask
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/LJ/Entry.pm
--- a/cgi-bin/LJ/Entry.pm	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/LJ/Entry.pm	Tue Nov 24 20:03:33 2009 +0000
@@ -764,24 +764,34 @@ sub visible_to
     # owners can always see their own.
     return 1 if $userid == $remoteid;
 
-    # other people can't read private
-    return 0 if $self->{'security'} eq "private";
+    # should be 'usemask' or 'private' security from here out, otherwise
+    # assume it's something new and return 0
+    return 0 unless $self->{security} eq "usemask" || $self->{security} eq "private";
 
-    # should be 'usemask' security from here out, otherwise
-    # assume it's something new and return 0
-    return 0 unless $self->{'security'} eq "usemask";
-
-    # if it's usemask, we have to refuse non-personal journals,
-    # so we have to load the user
     return 0 unless $remote->is_individual;
 
-    # check if it's a community and they're a member
-    return 1 if $self->journal->is_community &&
+    if ( $self->security eq "private" ) {
+        # other people can't read private on personal journals
+        return 0 if $self->journal->is_individual;
+
+        # but community administrators can read private entries on communities
+        return 1 if $self->journal->is_community && $remote->can_manage( $self->journal );
+
+        # private entry on a community; we're not allowed to see this
+        return 0;
+    }
+
+    if ( $self->security eq "usemask" ) {
+        # check if it's a community and they're a member
+        return 1 if $self->journal->is_community &&
                 $remote->member_of( $self->journal );
+    
+        my $gmask = $self->journal->trustmask( $remote );
+        my $allowed = (int($gmask) & int($self->{'allowmask'}));
+        return $allowed ? 1 : 0;  # no need to return matching mask
+    }
 
-    my $gmask = $self->journal->trustmask( $remote );
-    my $allowed = (int($gmask) & int($self->{'allowmask'}));
-    return $allowed ? 1 : 0;  # no need to return matching mask
+    return 0;
 }
 
 # returns hashref of (kwid => tag) for tags on the entry
@@ -1548,8 +1558,12 @@ sub get_log2_recent_user
         last unless $left;
         last if $notafter and $item->{'rlogtime'} > $notafter;
         next unless $remote || $item->{'security'} eq 'public';
-        next if $item->{'security'} eq 'private'
-            and $item->{'journalid'} != $remote->{'userid'};
+
+        if ( $item->{security} eq 'private' and $item->{journalid} != $remote->{userid} ) {
+            my $ju = LJ::load_userid( $item->{journalid} );
+            next unless $remote->can_manage( $ju );
+        }
+
         if ($item->{'security'} eq 'usemask') {
             next unless $remote->is_individual;
             my $permit = ($item->{'journalid'} == $remote->{'userid'});
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/LJ/S2/DayPage.pm
--- a/cgi-bin/LJ/S2/DayPage.pm	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/LJ/S2/DayPage.pm	Tue Nov 24 20:03:33 2009 +0000
@@ -52,7 +52,7 @@ sub DayPage
         ( $viewall, $viewsome ) =
             $remote->view_priv_check( $u, $get->{viewall}, 'day' );
 
-        if ( $viewall || $remote->equals( $u ) ) {
+        if ( $viewall || $remote->equals( $u ) || $remote->can_manage( $u ) ) {
             $secwhere = "";   # see everything
         } elsif ( $remote->is_individual ) {
             my $gmask = $u->is_community ? $remote->member_of( $u ) : $u->trustmask( $remote );
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/LJ/S2/MonthPage.pm
--- a/cgi-bin/LJ/S2/MonthPage.pm	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/LJ/S2/MonthPage.pm	Tue Nov 24 20:03:33 2009 +0000
@@ -52,7 +52,7 @@ sub MonthPage
         ( $viewall, $viewsome ) =
             $remote->view_priv_check( $u, $get->{viewall}, 'month' );
 
-        if ( $viewall || $remote->equals( $u ) ) {
+        if ( $viewall || $remote->equals( $u ) || $remote->can_manage( $u ) ) {
             $secwhere = "";   # see everything
         } elsif ( $remote->is_individual ) {
             my $gmask = $u->is_community ? $remote->member_of( $u ) : $u->trustmask( $remote );
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/LJ/Setting/MinSecurity.pm
--- a/cgi-bin/LJ/Setting/MinSecurity.pm	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/LJ/Setting/MinSecurity.pm	Tue Nov 24 20:03:33 2009 +0000
@@ -30,9 +30,11 @@ sub option {
     my @options = (
         "" => $class->ml('setting.minsecurity.option.select.public'),
         friends => $u->is_community ? $class->ml('setting.minsecurity.option.select.members') : $class->ml('setting.minsecurity.option.select.friends'),
+        private => $u->is_community ?
+        $class->ml( 'setting.minsecurity.option.select.admin' ) :
+        $class->ml( 'setting.minsecurity.option.select.private' )
     );
-    push @options, ( private => $class->ml('setting.minsecurity.option.select.private') )
-        if $u->is_personal;
+
 
     my $ret = "<label for='${key}minsecurity'>" . $class->ml('setting.minsecurity.option') . "</label> ";
     $ret .= LJ::html_select({
@@ -48,11 +50,7 @@ sub save {
     my ($class, $u, $args) = @_;
 
     my $val = $class->get_arg($args, "minsecurity");
-    if ($u->is_community) {
-        $val = "" unless $val =~ /^(friends)$/;
-    } else {
-        $val = "" unless $val =~ /^(friends|private)$/;
-    }
+    $val = "" unless $val =~ /^(friends|private)$/;
 
     $u->set_prop( newpost_minsecurity => $val );
 
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/LJ/Talk.pm
--- a/cgi-bin/LJ/Talk.pm	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/LJ/Talk.pm	Tue Nov 24 20:03:33 2009 +0000
@@ -258,7 +258,7 @@ sub check_viewable
         my $journalname = $journal->username;
 
         if (defined $remote) {
-            if ( $journal->is_community && ! $journal->is_closed_membership && $remote ) {
+            if ( $journal->is_community && ! $journal->is_closed_membership && $remote && $item->{security} ne "private" ) {
                 return $err->( BML::ml( 'talk.error.notauthorised.comm.open', { aopts => "href='$LJ::SITEROOT/community/join?comm=$journalname'" } ) );
             } elsif ( $journal->is_community && $journal->is_closed_membership ) {
                 return $err->( BML::ml( 'talk.error.notauthorised.comm.closed' ) );
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/LJ/User.pm
--- a/cgi-bin/LJ/User.pm	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/LJ/User.pm	Tue Nov 24 20:03:33 2009 +0000
@@ -7711,27 +7711,37 @@ sub can_view
     # owners can always see their own.
     return 1 if $userid == $remoteid;
 
-    # other people can't read private
-    return 0 if $item->{'security'} eq "private";
-
-    # should be 'usemask' security from here out, otherwise
+    # should be 'usemask' or 'private' security from here out, otherwise
     # assume it's something new and return 0
-    return 0 unless $item->{'security'} eq "usemask";
-
-    # if it's usemask, we have to refuse non-personal journals,
-    # so we have to load the user
+    return 0 unless $item->{security} eq "usemask" || $item->{security} eq "private";
+
     return 0 unless $remote->is_individual;
 
     # this far down we have to load the user
     my $u = LJ::want_user( $userid ) or return 0;
 
-    # check if it's a community and they're a member
-    return 1 if $u->is_community &&
-                $remote->member_of( $u );
-
-    # now load allowmask
-    my $allowed = ( $u->trustmask( $remoteid ) & int($item->{'allowmask'}) );
-    return $allowed ? 1 : 0;  # no need to return matching mask
+    if ( $item->{security} eq "private" ) {
+        # other people can't read private on personal journals
+        return 0 if $u->is_individual;
+
+        # but community administrators can read private entries on communities
+        return 1 if $u->is_community && $remote->can_manage( $u );
+
+        # private entry on a community; we're not allowed to see this
+        return 0;
+    }
+
+    if ( $item->{security} eq "usemask" ) {
+        # check if it's a community and they're a member
+        return 1 if $u->is_community &&
+                    $remote->member_of( $u );
+    
+        # now load allowmask
+        my $allowed = ( $u->trustmask( $remoteid ) & int($item->{'allowmask'}) );
+        return $allowed ? 1 : 0;  # no need to return matching mask
+    }
+
+    return 0;
 }
 
 
@@ -8021,7 +8031,7 @@ sub get_daycounts
                 "viewall", "calendar" );
         }
 
-        if ( $remote->userid == $uid || $viewall ) {
+        if ( $remote->userid == $uid || $viewall || $remote->can_manage( $u ) ) {
             $secwhere = "";   # see everything
             $memkind = 'a'; # all
         } elsif ( $remote->is_individual ) {
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/ljhooks.pl
--- a/cgi-bin/ljhooks.pl	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/ljhooks.pl	Tue Nov 24 20:03:33 2009 +0000
@@ -112,12 +112,9 @@ register_setter("newpost_minsecurity", s
         $$err = "Illegal value.  Must be 'public', 'access' (for personal journals), 'members' (for communities), or 'private'";
         return 0;
     }
-    # Don't let commmunities be private or access-locked
+    # Don't let commmunities be access-locked
     if ( $u->is_community ) {
-        if ( $value eq "private" ) {
-            $$err = "newpost_minsecurity cannot be private for communities";
-            return 0;
-        } elsif ( $value eq "access" ) {
+       if ( $value eq "access" ) {
             $$err = "newpost_minsecurity cannot be access-locked for communities (use 'members' instead)";
             return 0;
         }
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/ljprotocol.pl
--- a/cgi-bin/ljprotocol.pl	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/ljprotocol.pl	Tue Nov 24 20:03:33 2009 +0000
@@ -40,10 +40,11 @@ my %e = (
      # User Errors
      "100" => [ E_PERM, "Invalid username" ],
      "101" => [ E_PERM, "Invalid password" ],
-     "102" => [ E_PERM, "Can't use custom/private security on shared/community journals." ],
+     "102" => [ E_PERM, "Can't use custom security on community journals." ],
      "103" => [ E_PERM, "Poll error" ],
      "104" => [ E_TEMP, "Error adding one or more friends" ],
      "105" => [ E_PERM, "Challenge expired" ],
+     "106" => [ E_PERM, "Can only use administrator-locked security on community journals you manage." ],
      "150" => [ E_PERM, "Can't post as non-user" ],
      "151" => [ E_TEMP, "Banned from journal" ],
      "152" => [ E_PERM, "Can't make back-dated entries in non-personal journal." ],
@@ -1184,11 +1185,16 @@ sub postevent
 
     my $qsecurity = $dbh->quote($security);
 
-    ### make sure user can't post with "custom/private security" on shared journals
+    ### make sure user can't post with "custom security" on communities
     return fail($err,102)
-        if ($ownerid != $posterid && # community post
-            ($req->{'security'} eq "private" ||
-            ($req->{'security'} eq "usemask" && $qallowmask != 1 )));
+        if $ownerid != $posterid && # community post
+           $req->{'security'} eq "usemask" && $qallowmask != 1;
+
+    ## make sure user can't post with "private security" on communities they don't manage
+    return fail( $err, 106 )
+        if $ownerid != $posterid && # community post
+           $req->{'security'} eq "private" &&
+           ! $u->can_manage( $uowner );
 
     # make sure this user isn't banned from posting here (if
     # this is a community journal)
@@ -1632,11 +1638,16 @@ sub editevent
     return fail($err, 203, "Invalid friends group security set.")
         if $qallowmask > 1 && $qallowmask % 2;
 
-    ### make sure user can't change a post to "custom/private security" on shared journals
+    ### make sure user can't post with "custom security" on communities
     return fail($err,102)
-        if ($ownerid != $posterid && # community post
-            ($req->{'security'} eq "private" ||
-            ($req->{'security'} eq "usemask" && $qallowmask != 1 )));
+        if $ownerid != $posterid && # community post
+           $req->{'security'} eq "usemask" && $qallowmask != 1;
+
+    ## make sure user can't post with "private security" on communities they don't manage
+    return fail( $err, 106 )
+        if $ownerid != $posterid && # community post
+           $req->{'security'} eq "private" &&
+           ! $u->can_manage( $uowner );
 
     # make sure the new entry's under the char limit
     # NOTE: as in postevent, this requires $req->{event} to be binary data
diff -r dbaae7e52705 -r e36a761d81b3 cgi-bin/weblib.pl
--- a/cgi-bin/weblib.pl	Tue Nov 24 19:51:11 2009 +0000
+++ b/cgi-bin/weblib.pl	Tue Nov 24 20:03:33 2009 +0000
@@ -1828,6 +1828,7 @@ PREVIEW
                 my $string_friends = LJ::ejs(BML::ml('label.security.accesslist'));
                 my $string_friends_comm = LJ::ejs(BML::ml('label.security.members'));
                 my $string_private = LJ::ejs(BML::ml('label.security.private2'));
+                my $string_admin = LJ::ejs( BML::ml( 'label.security.maintainers' ) );
                 my $string_custom = LJ::ejs(BML::ml('label.security.custom'));
 
                 $out .= qq{
@@ -1836,12 +1837,15 @@ PREVIEW
                     UpdateFormStrings.friends = "$string_friends";
                     UpdateFormStrings.friends_comm = "$string_friends_comm";
                     UpdateFormStrings.private = "$string_private";
-                    UpdateFormStrings.custom = "$string_custom";</script>
+                    UpdateFormStrings.custom = "$string_custom";
+                    UpdateFormStrings.admin = "$string_admin";</script>
                 };
+
 
                 $$onload .= " setColumns();" if $remote;
                 my @secs = ("public", $string_public, "friends", $is_comm ? $string_friends_comm : $string_friends);
                 push @secs, ("private", $string_private) unless $is_comm;
+                push @secs, ( "private", $string_admin ) if $is_comm && $remote && $remote->can_manage( $usejournalu );
 
                 my ( @secopts, @trust_groups );
                 @trust_groups = $remote->trust_groups if $remote;
diff -r dbaae7e52705 -r e36a761d81b3 htdocs/js/entry.js
--- a/htdocs/js/entry.js	Tue Nov 24 19:51:11 2009 +0000
+++ b/htdocs/js/entry.js	Tue Nov 24 20:03:33 2009 +0000
@@ -412,6 +412,9 @@ function changeSecurityOptions(defaultjo
                     if (data.ret['is_comm']) {
                         $('security').options[0] = new Option(UpdateFormStrings.public, 'public');
                         $('security').options[1] = new Option(UpdateFormStrings.friends_comm, 'friends');
+                        if ( data.ret['can_manage'] ) {
+                            $('security').options[2] = new Option(UpdateFormStrings.admin, 'private');
+                        }
                     } else {
                         $('security').options[0] = new Option(UpdateFormStrings.public, 'public');
                         $('security').options[1] = new Option(UpdateFormStrings.friends, 'friends');
diff -r dbaae7e52705 -r e36a761d81b3 htdocs/tools/endpoints/getsecurityoptions.bml
--- a/htdocs/tools/endpoints/getsecurityoptions.bml	Tue Nov 24 19:51:11 2009 +0000
+++ b/htdocs/tools/endpoints/getsecurityoptions.bml	Tue Nov 24 20:03:33 2009 +0000
@@ -19,6 +19,7 @@
 
     my %ret = (
         is_comm => $u->is_comm ? 1 : 0,
+        can_manage =>  $remote && $remote->can_manage( $u ) ? 1 : 0,
     );
 
     return JSON::objToJson({ ret => \%ret }) unless $remote && $remote->can_post_to($u);
--------------------------------------------------------------------------------

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org