#3: Implemented security when viewing an album and its photos

This commit is contained in:
Andy Heathershaw 2017-04-15 08:36:17 +01:00
parent 33275a8733
commit 045935c554
10 changed files with 67 additions and 37 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" serverName="Development">
<component name="PublishConfigData" autoUpload="On explicit save action" serverName="Development">
<serverData>
<paths name="Development">
<serverdata>
@ -10,5 +10,6 @@
</serverdata>
</paths>
</serverData>
<option name="myAutoUpload" value="ON_EXPLICIT_SAVE" />
</component>
</project>

View File

@ -66,10 +66,8 @@ class DbHelper
->withCount('photos');
}
public static function getAlbumByAliasForCurrentUser($urlAlias)
public static function getAlbumByAlias($urlAlias)
{
$album = Album::where('url_alias', $urlAlias)->first();
return $album;
return Album::where('url_alias', $urlAlias)->first();
}
}

View File

@ -17,13 +17,15 @@ class AlbumController extends Controller
{
public function index(Request $request, $albumUrlAlias)
{
$album = DbHelper::getAlbumByAliasForCurrentUser($albumUrlAlias);
$album = DbHelper::getAlbumByAlias($albumUrlAlias);
if (is_null($album))
{
App::abort(404);
return null;
}
$this->authorizeForUser($this->getUser(), 'view', $album);
$validViews = UserConfig::allowedAlbumViews();
$requestedView = strtolower($request->get('view'));
if (!in_array($requestedView, $validViews))
@ -36,8 +38,6 @@ class AlbumController extends Controller
}
}
$this->authorizeForUser($this->getUser(), 'album.view', $album);
if ($album->photos()->count() == 0)
{
$requestedView = 'empty';

View File

@ -20,14 +20,14 @@ class PhotoController extends Controller
{
public function download(Request $request, $albumUrlAlias, $photoFilename)
{
$album = DbHelper::getAlbumByAliasForCurrentUser($albumUrlAlias);
$album = DbHelper::getAlbumByAlias($albumUrlAlias);
if (is_null($album))
{
App::abort(404);
return null;
}
$this->authorizeForUser($this->getUser(), 'album.view', $album);
$this->authorizeForUser($this->getUser(), 'view', $album);
if (UserConfig::get('hotlink_protection'))
{
@ -75,14 +75,14 @@ class PhotoController extends Controller
public function show(Request $request, $albumUrlAlias, $photoFilename)
{
$album = DbHelper::getAlbumByAliasForCurrentUser($albumUrlAlias);
$album = DbHelper::getAlbumByAlias($albumUrlAlias);
if (is_null($album))
{
App::abort(404);
return null;
}
$this->authorizeForUser($this->getUser(), 'album.view', $album);
$this->authorizeForUser($this->getUser(), 'view', $album);
$photo = PhotoController::loadPhotoByAlbumAndFilename($album, $photoFilename);

View File

@ -45,6 +45,37 @@ class AlbumPolicy
'description' => 'edit'
])->first();
return $this->userHasPermission($user, $album, $permission);
}
public function view(User $user, Album $album)
{
if ($user->id == $album->user_id)
{
// The album's owner and can do everything
return true;
}
// Get the edit permission
$permission = Permission::where([
'section' => 'album',
'description' => 'view'
])->first();
return $this->userHasPermission($user, $album, $permission);
}
private function userHasPermission(User $user, Album $album, Permission $permission)
{
if ($user->isAnonymous())
{
$query = Album::query()->join('album_anonymous_permissions', 'album_anonymous_permissions.album_id', '=', 'albums.id')
->join('permissions', 'permissions.id', '=', 'album_anonymous_permissions.permission_id')
->where('permissions.id', $permission->id);
return $query->count() > 0;
}
// If any of the user's groups are granted the permission
/** @var Group $group */
foreach ($user->groups as $group)

View File

@ -45,4 +45,9 @@ class User extends Authenticatable
{
return $this->belongsToMany(Group::class, 'user_groups');
}
public function isAnonymous()
{
return $this->id == -1 && $this->name == 'Anonymous';
}
}

View File

@ -35,7 +35,7 @@
<h4 class="card-title"><a href="{{ $photo->url() }}">{{ $photo->name }}</a></h4>
</div>
<div class="card-footer">
<small class="text-muted"><i class="fa fa-fw fa-calendar"></i> {{ date('Y-m-d H:i', $photo->taken_at) }}</small>
<small class="text-muted"><i class="fa fa-fw fa-calendar"></i> {{ date('Y-m-d H:i', strtotime(!is_null($photo->taken_at) ? $photo->taken_at : $photo->created_at)) }}</small>
</div>
</div>
</div>

View File

@ -2,21 +2,15 @@
@section('title', $photo->name)
@section('breadcrumb')
<div class="breadcrumb">
<div class="container">
<ol class="breadcrumb">
<li><a href="{{ route('home') }}">Gallery</a></li>
<li><a href="{{ $return_album_url }}">{{ $photo->album->name }}</a></li>
<li class="active">{{ $photo->name }}</li>
</ol>
</div>
</div>
<li class="breadcrumb-item"><a href="{{ route('home') }}">Gallery</a></li>
<li class="breadcrumb-item"><a href="{{ $return_album_url }}">{{ $photo->album->name }}</a></li>
<li class="breadcrumb-item active">{{ $photo->name }}</li>
@endsection
@section('content')
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="col">
<h1>{{ $photo->name }}</h1>
@if (strlen($photo->description) > 0)
<p>{{ $photo->description }}</p>
@ -25,7 +19,7 @@
</div>
<div class="row">
<div class="col-xs-12 col-sm-8 content-body">
<div class="col-sm-8 content-body">
@if ($is_original_allowed)
<a href="{{ $photo->thumbnailUrl() }}">
@endif
@ -35,11 +29,11 @@
@endif
</div>
<div class="col-xs-12 col-sm-4">
<div class="panel panel-default">
<div class="panel-heading">Information about this photo:</div>
<div class="panel-body no-padding">
<table class="table table-striped photo-metadata no-margin-bottom">
<div class="col-sm-4">
<div class="card">
<div class="card-header">Information about this photo:</div>
<div class="card-block" style="padding: 0;">
<table class="table table-striped photo-metadata mb-0">
<thead>
<tr>
<th>Name</th>
@ -87,8 +81,8 @@
</div>
<div class="row">
<div class="col-xs-12">
<a href="{{ $return_album_url }}" class="btn btn-default">@lang('gallery.back_to_album', ['name' => $photo->album->name])</a>
<div class="col mt-4">
<a href="{{ $return_album_url }}" class="btn btn-secondary">&laquo; @lang('gallery.back_to_album', ['name' => $photo->album->name])</a>
</div>
</div>
</div>

View File

@ -12,12 +12,8 @@
<div class="col-md-4">
<h5>Album Permissions</h5>
@php ($permission = Theme::getPermission($all_permissions, 'album', 'list'))
<div class="checkbox">
<label for="permission|{{ $key_id }}|{{ $permission->id }}">
<input id="permission|{{ $key_id }}|{{ $permission->id }}" name="permissions[{{ $object_id }}][]" value="{{ $permission->id }}" type="checkbox"{{ call_user_func($callback, $callback_object, $permission) ? ' checked="checked"' : '' }} /> {{ trans(sprintf('permissions.%s.%s', $permission->section, $permission->description)) }}
</label>
</div>
@include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'list')])
@include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'view')])
</div>
</div>

View File

@ -0,0 +1,5 @@
<div class="checkbox">
<label for="permission|{{ $key_id }}|{{ $permission->id }}">
<input id="permission|{{ $key_id }}|{{ $permission->id }}" name="permissions[{{ $object_id }}][]" value="{{ $permission->id }}" type="checkbox"{{ call_user_func($callback, $callback_object, $permission) ? ' checked="checked"' : '' }} /> {{ trans(sprintf('permissions.%s.%s', $permission->section, $permission->description)) }}
</label>
</div>