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

View File

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

View File

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

View File

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

View File

@ -45,6 +45,37 @@ class AlbumPolicy
'description' => 'edit' 'description' => 'edit'
])->first(); ])->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 // If any of the user's groups are granted the permission
/** @var Group $group */ /** @var Group $group */
foreach ($user->groups as $group) foreach ($user->groups as $group)

View File

@ -45,4 +45,9 @@ class User extends Authenticatable
{ {
return $this->belongsToMany(Group::class, 'user_groups'); 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> <h4 class="card-title"><a href="{{ $photo->url() }}">{{ $photo->name }}</a></h4>
</div> </div>
<div class="card-footer"> <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> </div>
</div> </div>

View File

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

View File

@ -12,12 +12,8 @@
<div class="col-md-4"> <div class="col-md-4">
<h5>Album Permissions</h5> <h5>Album Permissions</h5>
@php ($permission = Theme::getPermission($all_permissions, 'album', 'list')) @include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'list')])
<div class="checkbox"> @include(Theme::viewName('partials.permission_checkbox'), ['permission' => Theme::getPermission($all_permissions, 'album', 'view')])
<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>
</div> </div>
</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>