diff --git a/etc/dev.localhost.localdomain.psgi b/etc/dev.localhost.localdomain.psgi index 31a4e55c9..6ed510b33 100644 --- a/etc/dev.localhost.localdomain.psgi +++ b/etc/dev.localhost.localdomain.psgi @@ -1,42 +1,48 @@ BEGIN { - - # This is just a temporary hack - our $WEBGUI_ROOT = '/data/WebGUI'; - our $WEBGUI_DOMAINS = '/data/domains'; - our $WEBGUI_CONFIG = 'dev.localhost.localdomain'; + # Define your site settings here + # These are the config values that normally appear in your wre's + # site.modperl.conf and site.modproxy.conf + our $WEBGUI_ROOT = '/data/WebGUI'; + our $WEBGUI_CONFIG = 'dev.localhost.localdomain'; + our $DOCUMENT_ROOT = '/data/domains/dev.localhost.localdomain/public'; } use local::lib $WEBGUI_ROOT; use WebGUI; -use Plack::Middleware; use Plack::Builder; -my $app = sub { +my %SETTINGS = ( + 'wg.WEBGUI_ROOT' => $WEBGUI_ROOT, + 'wg.WEBGUI_CONFIG' => "$WEBGUI_CONFIG.conf", + 'wg.DOCUMENT_ROOT' => $DOCUMENT_ROOT, + 'wg.DIR_CONFIG.WebguiRoot' => $WEBGUI_ROOT, + 'wg.DIR_CONFIG.WebguiConfig' => "$WEBGUI_CONFIG.conf", +); + +my $wg = sub { my $env = shift; - $env->{'wg.WEBGUI_ROOT'} = $WEBGUI_ROOT; - $env->{'wg.WEBGUI_CONFIG'} = "$WEBGUI_CONFIG.conf"; - $env->{'wg.DIR_CONFIG.WebguiRoot'} = $env->{'wg.WEBGUI_ROOT'}; - $env->{'wg.DIR_CONFIG.WebguiConfig'} = $env->{'wg.WEBGUI_CONFIG'}; + @{$env}{ keys %SETTINGS } = values %SETTINGS; WebGUI::handle_psgi($env); }; -# Apply some Middleware builder { - # /extras + # /extras - deliver via Plack::Middleware::Static add 'Plack::Middleware::Static', path => qr{^/extras/}, - root => "$WEBGUI_ROOT/www/"; + root => "$SETTINGS{'wg.WEBGUI_ROOT'}/www/"; - # /uploads (ignore .wgaccess for now..) - add 'Plack::Middleware::Static', - path => qr{^/uploads/}, - root => "$WEBGUI_DOMAINS/dev.localhost.localdomain/public/"; + # /uploads - deliver via Plack::Middleware::WGAccess + # This takes the place of WebGUI::URL::Uploads in handling .wgaccess and + # delivery of static files in /uploads + add 'Plack::Middleware::WGAccess', + path => qr{^/uploads/}, + settings => {%SETTINGS}; add 'Plack::Middleware::XFramework', framework => 'WebGUI'; - # Already enabled by plackup script + # AccessLog already enabled by default if you are using the plackup script # add 'Plack::Middleware::AccessLog', # format => "combined"; - $app; + $wg; } diff --git a/lib/Plack/Middleware/WGAccess.pm b/lib/Plack/Middleware/WGAccess.pm new file mode 100644 index 000000000..ce7b71228 --- /dev/null +++ b/lib/Plack/Middleware/WGAccess.pm @@ -0,0 +1,104 @@ +package Plack::Middleware::WGAccess; +use strict; +use warnings; +use base qw/Plack::Middleware::Static/; +use Path::Class 'dir'; +__PACKAGE__->mk_accessors('settings'); + +=head1 NAME + +Plack::Middleware::WGAccess + +=head1 DESCRIPTION + +Plack Middleware that delivers static files with .wgaccess awareness + +=cut + +sub _handle_static { + my($self, $env) = @_; + + # Populate $env with $self->settings so that we get consistent wg API behaviour + my %settings = %{$self->settings}; + @{$env}{keys %settings} = values %settings; + + # Populate $self->root from $SETTINGS so that it doesn't need to be specified in psgi file + $self->root($settings{'wg.DOCUMENT_ROOT'}); + + ####################################### + # 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") { + + # Construct request,server,config in the usual way + require WebGUI::Session::Plack; + my $request = WebGUI::Session::Plack->new( env => $env ); + my $server = $request->server; + + my $session = $request->pnotes('wgSession'); + unless (defined $session) { + $session = WebGUI::Session->open($server->dir_config('WebguiRoot'), $request->dir_config('WebguiConfig'), $request, $server); + } + 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