#3: Implemented security when viewing an album and its photos
This commit is contained in:
parent
33275a8733
commit
045935c554
@ -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>
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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';
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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">« @lang('gallery.back_to_album', ['name' => $photo->album->name])</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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>
|
Loading…
Reference in New Issue
Block a user