diff --git a/app.psgi b/app.psgi index d42c34d7a..902dd0e6b 100644 --- a/app.psgi +++ b/app.psgi @@ -16,6 +16,9 @@ builder { config => $wg->config, error_docs => { 500 => "$root/www/maintenance.html" }; + # This one uses the Session object, so it comes after WebGUI::Middleware::Session + enable '+WebGUI::Middleware::WGAccess', config => $wg->config; + # Return the app $wg; }; diff --git a/lib/Plack/Middleware/WGAccess.pm b/lib/Plack/Middleware/WGAccess.pm deleted file mode 100644 index 4308a0b84..000000000 --- a/lib/Plack/Middleware/WGAccess.pm +++ /dev/null @@ -1,92 +0,0 @@ -package Plack::Middleware::WGAccess; -use strict; -use warnings; -use base qw/Plack::Middleware::Static/; -use Path::Class 'dir'; - -=head1 NAME - -Plack::Middleware::WGAccess - -=head1 DESCRIPTION - -Plack Middleware that delivers static files with .wgaccess awareness - -=cut - -sub _handle_static { - my($self, $env) = @_; - - ####################################### - # Copied from Plack::Middleware::Static::_handle_static - - my $path_match = $self->path or return; - - if ($env->{PATH_INFO} =~ m!\.\.[/\\]!) { - return $self->return_403; - } - - my $path = do { - my $matched; - local $_ = $env->{PATH_INFO}; - if (ref $path_match eq 'CODE') { - $matched = $path_match->($_); - } else { - $matched = $_ =~ $path_match; - } - return unless $matched; - $_; - } or return; - - my $docroot = dir($self->root || "."); - my $file = $docroot->file(File::Spec::Unix->splitpath($path)); - my $realpath = Cwd::realpath($file->absolute->stringify); - - # Is the requested path within the root? - if ($realpath && !$docroot->subsumes($realpath)) { - return $self->return_403; - } - - # Does the file actually exist? - if (!$realpath || !-f $file) { - return $self->return_404; - } - - # If the requested file present but lacking the permission to read it? - if (!-r $file) { - return $self->return_403; - } - - ############################### - # Copied from WebGUI::URL::Uploads - my $wgaccess = File::Spec::Unix->catfile($file->dir, '.wgaccess'); - if (-e $wgaccess) { - my $fileContents; - open(my $FILE, "<", $wgaccess); - while (my $line = <$FILE>) { - $fileContents .= $line; - } - close($FILE); - my @privs = split("\n", $fileContents); - unless ($privs[1] eq "7" || $privs[1] eq "1") { - my $request = Plack::Request->new( $env ); - -# my $session = $request->pnotes('wgSession'); - unless (defined $session) { -# $session = WebGUI::Session->open($env->{dir_config('WebguiRoot'), $request->dir_config('WebguiConfig'), $request ); - } - my $hasPrivs = ($session->var->get("userId") eq $privs[0] || $session->user->isInGroup($privs[1]) || $session->user->isInGroup($privs[2])); - $session->close(); - if ($hasPrivs) { - return $self->SUPER::_handle_static($env); # serve statically - } - else { - return $self->return_403; - } - } - } else { - return $self->SUPER::_handle_static($env); # serve statically - } -} - -1; \ No newline at end of file diff --git a/lib/WebGUI/Middleware/WGAccess.pm b/lib/WebGUI/Middleware/WGAccess.pm new file mode 100644 index 000000000..ba5d3d179 --- /dev/null +++ b/lib/WebGUI/Middleware/WGAccess.pm @@ -0,0 +1,69 @@ +package WebGUI::Middleware::WGAccess; +use strict; +use Plack::App::File; +use parent qw(Plack::Middleware); +use Path::Class 'dir'; + +=head1 NAME + +WebGUI::Middleware::WGAccess - control access to .wgaccess protected uploads + +=head1 DESCRIPTION + +This is PSGI middleware for WebGUI that delivers static files (uploads) with .wgaccess +awareness. + +This middleware should really only be used in development, for production you want +to be serving static files with something a lot faster. + +=cut + +use Plack::Util::Accessor qw( config ); + +sub call { + my $self = shift; + my $env = shift; + my $app = $self->app; + my $config = $self->config or die 'Mandatory config parameter missing'; + my $uploadsPath = $config->get('uploadsPath'); + my $uploadsURL = $config->get('uploadsURL'); + + my $path = $env->{PATH_INFO}; + my $matched = $path =~ s{^\Q$uploadsURL\E/}{}; + return $app->($env) unless $matched; + + my $root = dir($uploadsPath); + my $file = $root->file(File::Spec::Unix->splitpath($path)); + my $wgaccess = File::Spec::Unix->catfile($file->dir, '.wgaccess'); + + if (-e $wgaccess) { + my $fileContents; + open(my $FILE, "<", $wgaccess); + while (my $line = <$FILE>) { + $fileContents .= $line; + } + close($FILE); + my @privs = split("\n", $fileContents); + + unless ($privs[1] eq "7" || $privs[1] eq "1") { + my $session = $env->{'webgui.session'}; + my $hasPrivs = ($session->var->get("userId") eq $privs[0] || $session->user->isInGroup($privs[1]) || $session->user->isInGroup($privs[2])); + warn "has: $hasPrivs"; + warn $session->var->get("userId"); + warn $session->user->isInGroup($privs[1]); + warn $session->user->isInGroup($privs[2]); + if ($hasPrivs) { + $self->{file} ||= Plack::App::File->new; + return $self->{file}->serve_path($env, $file); # serve statically + } + else { + return [403, ['Content-Type' => 'text/plain'], ['Forbidden']]; + } + } + } + + $self->{file} ||= Plack::App::File->new; + return $self->{file}->serve_path($env, $file); # serve statically +} + +1; \ No newline at end of file