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-09-06 06:21 pm

[dw-free] implement admin/impersonate.bml as dw-free

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

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

Add /admin/impersonate tool.

Patch by [personal profile] afuna.

Files modified:
  • cgi-bin/LJ/User.pm
  • htdocs/admin/impersonate.bml
  • htdocs/admin/impersonate.bml.text
  • htdocs/admin/userlog.bml
--------------------------------------------------------------------------------
diff -r 4388e4653fad -r a81a6da8ecc1 cgi-bin/LJ/User.pm
--- a/cgi-bin/LJ/User.pm	Sun Sep 06 18:04:56 2009 +0000
+++ b/cgi-bin/LJ/User.pm	Sun Sep 06 18:21:55 2009 +0000
@@ -927,9 +927,12 @@ sub logout_all {
     $u->_logout_common;
 }
 
+sub make_fake_login_session {
+    return $_[0]->make_login_session( 'once', undef, 1 );
+}
 
 sub make_login_session {
-    my ($u, $exptype, $ipfixed) = @_;
+    my ( $u, $exptype, $ipfixed, $fake_login ) = @_;
     $exptype ||= 'short';
     return 0 unless $u;
 
@@ -940,15 +943,18 @@ sub make_login_session {
         'exptype' => $exptype,
         'ipfixed' => $ipfixed,
     };
+    $sess_opts->{nolog} = 1 if $fake_login;
 
     my $sess = LJ::Session->create($u, %$sess_opts);
     $sess->update_master_cookie;
 
     LJ::User->set_remote($u);
 
-    # add a uniqmap row if we don't have one already
-    my $uniq = LJ::UniqCookie->current_uniq;
-    LJ::UniqCookie->save_mapping($uniq => $u);
+    unless ( $fake_login ) {
+        # add a uniqmap row if we don't have one already
+        my $uniq = LJ::UniqCookie->current_uniq;
+        LJ::UniqCookie->save_mapping($uniq => $u);
+    }
 
     # restore scheme and language
     my $bl = LJ::Lang::get_lang($u->prop('browselang'));
@@ -978,11 +984,13 @@ sub make_login_session {
         "expiretime" => $etime,
     });
 
-    # activity for cluster usage tracking
-    LJ::mark_user_active($u, 'login');
-
-    # activity for global account number tracking
-    $u->note_activity('A');
+    unless ( $fake_login ) {
+        # activity for cluster usage tracking
+        LJ::mark_user_active($u, 'login');
+    
+        # activity for global account number tracking
+        $u->note_activity('A');
+    }
 
     return 1;
 }
diff -r 4388e4653fad -r a81a6da8ecc1 htdocs/admin/impersonate.bml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/impersonate.bml	Sun Sep 06 18:21:55 2009 +0000
@@ -0,0 +1,90 @@
+<?_c
+#
+# admin/impersonate.bml
+#
+# Allow someone trusted to log in as another user for a limited
+# amount of time.
+#
+# Authors:
+#      Afuna <coder.dw@afunamatata.com>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself. For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+_c?><?page
+body<=
+<?_code
+{
+    use strict;
+    use vars qw/ %POST @errors /;
+
+    if ( $LJ::USE_SSL && !$LJ::IS_SSL ) {
+        return BML::redirect( "$LJ::SSLROOT/admin/impersonate" );
+    }
+
+    my $remote = LJ::get_remote();
+    return "<?needlogin?>" unless $remote;
+
+    my @displayprivs = ( "canview:*" );
+    my $numprivs = @displayprivs;
+
+    return BML::ml( "admin.noprivserror", { numprivs => $numprivs, needprivs => "<b>" . join( ", ", @displayprivs ) . "</b>" } )
+        unless $remote->has_priv( canview => '*' );
+
+    my $ret;
+
+    if ( LJ::did_post() && LJ::check_referer( '/admin/impersonate.bml' ) ) {
+        return LJ::error_list( $ML{'error.invalidform'} ) unless LJ::check_form_auth();
+
+        my $u = LJ::load_user( $POST{username} );
+        push @errors, BML::ml( '.error.invaliduser', { user => LJ::ehtml( $POST{username} ) } ) unless $u;
+
+        my $password = $POST{password};
+        push @errors, $ML{'.error.invalidpassword'} unless $password && $password eq $remote->password;
+
+        my $reason = LJ::ehtml( LJ::trim( $POST{reason} ) );
+        push @errors, $ML{'.error.emptyreason'} unless $reason;
+
+        $remote->logout;
+
+        if ( $u->make_fake_login_session ) {
+            # log for auditing
+            $remote->log_event( 'impersonator', { actiontarget => $u->id, remote => $remote, reason => $reason } );
+            $u->log_event( 'impersonated', { actiontarget => $u->id, remote => $remote, reason => $reason } );
+            LJ::statushistory_add( $u->id, $remote->id, 'impersonate', $reason );
+    
+            return BML::redirect( $LJ::SITEROOT );
+
+        } else {
+            push @errors, $ML{'.error.failedlogin'};
+        }
+    }
+
+    $ret .= LJ::error_list( @errors ) if @errors;
+
+    $ret .= "<form method='POST'>";
+    $ret .= LJ::form_auth();
+
+    $ret .= LJ::labelfy( 'impersonate_username', $ML{'.form.username' } );
+    $ret .= LJ::html_text( { id => 'impersonate_username', name => 'username', maxlength => '25', size => '25', value => $POST{username} } ) . "<br />";
+
+    $ret .= LJ::labelfy( 'impersonate_password', $ML{'.form.password'} );
+    $ret .= LJ::html_text( { id => 'impersonate_password', name => 'password', type => 'password', size => '25' } ) . "<br />";
+
+    $ret .= LJ::labelfy( 'impersonate_reason', $ML{'.form.reason'} );
+    $ret .= LJ::html_text( { id => 'impersonate_reason', name => 'reason', maxlength => '255', size => '50', value => $POST{reason} } ) . "<br />";
+    $ret .= "<input type='submit' value='Submit' />";
+    $ret .= "</form>";
+
+    return $ret;
+}
+_code?>
+<=body
+title=><?_ml .title _ml?>
+head<=
+<?_code return $headextra; _code?>
+<=head
+page?>
diff -r 4388e4653fad -r a81a6da8ecc1 htdocs/admin/impersonate.bml.text
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/admin/impersonate.bml.text	Sun Sep 06 18:21:55 2009 +0000
@@ -0,0 +1,15 @@
+.error.emptyreason=A reason is required.
+
+.error.failedlogin=Attempt to impersonate failed.
+
+.error.invalidpassword=Password is incorrect.
+
+.error.invaliduser=Could not load user '[[user]]'.
+
+.form.password=Password:
+
+.form.reason=Reason:
+
+.form.username=Usename:
+
+.title=Impersonate
diff -r 4388e4653fad -r a81a6da8ecc1 htdocs/admin/userlog.bml
--- a/htdocs/admin/userlog.bml	Sun Sep 06 18:04:56 2009 +0000
+++ b/htdocs/admin/userlog.bml	Sun Sep 06 18:21:55 2009 +0000
@@ -109,6 +109,11 @@ FORM
             # TODO: parse out e_unixtime and s_unixtime and display?
         } elsif ($row->{action} eq 'delete_userpic') {
             $action = "Deleted userpic #$extra->{picid}";
+        } elsif ( $row->{action} eq 'impersonated' ) {
+            $action = "Was impersonated: " . LJ::ehtml( $extra->{reason} );
+        } elsif ( $row->{action} eq 'impersonator' ) {
+            my $u = LJ::load_userid( $row->{actiontarget} );
+            $action = "Did impersonate on " . ( $u ? $u->ljuser_display : "(no target)" ) . ": " .  LJ::ehtml( $extra->{reason} );
         } elsif (my $info = LJ::run_hook('userlog_rows', $row)) {
             $action = $info;
         } else {
--------------------------------------------------------------------------------

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