[dw-free] Add priv-checking option to DW::Controller::controller()
[commit: http://hg.dwscoalition.org/dw-free/rev/0d9755820438]
http://bugs.dwscoalition.org/show_bug.cgi?id=2407
Add privcheck mode to controller base, so TT pages can easily check for
privileges.
Patch by
pauamma.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=2407
Add privcheck mode to controller base, so TT pages can easily check for
privileges.
Patch by
Files modified:
- cgi-bin/DW/Controller.pm
- cgi-bin/LJ/User.pm
--------------------------------------------------------------------------------
diff -r eec75d6d72ef -r 0d9755820438 cgi-bin/DW/Controller.pm
--- a/cgi-bin/DW/Controller.pm Fri Apr 23 01:29:23 2010 +0000
+++ b/cgi-bin/DW/Controller.pm Fri Apr 23 01:34:39 2010 +0000
@@ -7,7 +7,7 @@
# Authors:
# Mark Smith <mark@dreamwidth.org>
#
-# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+# Copyright (c) 2009-2010 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
@@ -55,6 +55,30 @@ sub success_ml {
}
# helper controller. give it a few arguments and it does nice things for you.
+#
+# Supported arguments: (1 stands for any true value, 0 for any false value)
+# - anonymous => 1 -- lets anonymous (not logged in) visitors view the page
+# - anonymous => 0 -- doesn't (default)
+# - authas => 1 -- allows ?authas= in URL, generates authas form (not permitted
+# if anonymous => 1 specified)
+# - authas => 0 -- doesn't (default)
+# - specify_user => 1 -- allows ?user= in URL (Note: requesting both authas and
+# specify_user is allowed, but probably not a good idea)
+# - specify_user => 0 -- doesn't (default)
+# - privcheck => $privs -- user must be logged in and have at least one priv of
+# the ones in this arrayref.
+# Example: [ "faqedit:guides", "faqcat", "admin:*" ]
+#
+# Returns one of:
+# - 0, $error_text (if there's an error)
+# - 1, $hashref (if everything looks good)
+#
+# Returned hashref can be passed to DW::Template->render_template as the 2nd
+# argument, and has the following keys:
+# - remote -- the remote user object or undef (LJ::get_remote())
+# - u -- user object for username in ?user= or ?authas= if present and valid,
+# otherwise same as remote
+# - authas_html -- HTML for the "switch user" form
sub controller {
my ( %args ) = @_;
@@ -62,8 +86,12 @@ sub controller {
my $fail = sub { return ( 0, $_[0] ); };
my $ok = sub { return ( 1, $vars ); };
- # ensure the arguments make sense... anonymous means we cannot authas
- delete $args{authas} if $args{anonymous};
+ # some argument combinations are invalid, so just die. this is something that should
+ # be caught in development...
+ die "Invalid usage of controller, check your calling arguments.\n"
+ if ( $args{authas} && $args{specify_user} ) ||
+ ( $args{authas} && $args{anonymous} ) ||
+ ( $args{privcheck} && $args{anonymous} );
# 'anonymous' pages must declare themselves, else we assume that a remote is
# necessary as most pages require a user
@@ -89,6 +117,25 @@ sub controller {
$vars->{authas_html} = LJ::make_authas_select( $vars->{remote}, { authas => $vars->{u}->user } );
}
+ # check user is suitably privved
+ if ( my $privs = $args{privcheck} ) {
+ # if they just gave us a string, throw it in an array
+ $privs = [ $privs ] unless ref $privs eq 'ARRAY';
+
+ # now iterate over the array and check. the user must have ANY
+ # of the privs to pass the test.
+ my $has_one = 0;
+ foreach my $priv ( @$privs ) {
+ last if $has_one = $vars->{remote}->has_priv( $priv );
+ }
+
+ # now if they have none, throw an error message
+ return $fail->( error_ml( 'admin.noprivserror',
+ { numprivs => scalar @$privs,
+ needprivs => join( ', ', sort @$privs ) } ) )
+ unless $has_one;
+ }
+
# everything good... let the caller know they can continue
return $ok->();
}
diff -r eec75d6d72ef -r 0d9755820438 cgi-bin/LJ/User.pm
--- a/cgi-bin/LJ/User.pm Fri Apr 23 01:29:23 2010 +0000
+++ b/cgi-bin/LJ/User.pm Fri Apr 23 01:34:39 2010 +0000
@@ -4974,6 +4974,16 @@ sub has_priv {
sub has_priv {
my ( $u, $priv, $arg ) = @_;
+ # check to see if the priv is packed, and unpack it if so, this allows
+ # someone to call $u->has_priv( "foo:*" ) instead of $u->has_priv( foo => '*' )
+ # which is helpful for some callers.
+ ( $priv, $arg ) = ( $1, $2 )
+ if $priv =~ /^(.+?):(.+)$/;
+
+ # at this point, if they didn't provide us with a priv, bail out
+ return 0 unless $priv;
+
+ # load what privileges the user has, if we haven't
LJ::load_user_privs($u, $priv)
unless $u->{'_privloaded'}->{$priv};
--------------------------------------------------------------------------------
