#71, #111: Implemented security checking in the JSON feed methods. Also users now automatically inherit the anonymous permissions by way of an additional check specifically against the anonymous user first

This commit is contained in:
Andy Heathershaw 2018-11-18 21:39:19 +00:00
parent 2394bbd077
commit f36aa61506
8 changed files with 178 additions and 5 deletions

View File

@ -16,6 +16,25 @@ class PermissionsHelper
public function getAlbumIDs($permission = 'list', User $user = null)
{
$result = [];
// First check if the anonymous user can do what is being requested - if so, the permission would also inherit
// to logged-in users
$anonymousUsersCan = DB::table('album_permissions_cache')
->join('permissions', 'permissions.id', '=', 'album_permissions_cache.permission_id')
->where([
['album_permissions_cache.user_id', null],
['permissions.section', 'album'],
['permissions.description', $permission]
])
->select('album_permissions_cache.album_id')
->distinct()
->get();
foreach ($anonymousUsersCan as $item)
{
$result[] = $item->album_id;
}
$query = DB::table('album_permissions_cache')
->join('permissions', 'permissions.id', '=', 'album_permissions_cache.permission_id')
->where([
@ -29,7 +48,10 @@ class PermissionsHelper
foreach ($query as $item)
{
$result[] = $item->album_id;
if (!in_array($item->album_id, $result))
{
$result[] = $item->album_id;
}
}
return $result;
@ -42,6 +64,23 @@ class PermissionsHelper
public function userCan_Album(Album $album, User $user, $permission)
{
// First check if the anonymous user can do what is being requested - if so, the permission would also inherit
// to logged-in users
$anonymousUsersCan = DB::table('album_permissions_cache')
->join('permissions', 'permissions.id', '=', 'album_permissions_cache.permission_id')
->where([
['album_permissions_cache.album_id', $album->id],
['album_permissions_cache.user_id', null],
['permissions.section', 'album'],
['permissions.description', $permission]
])
->count() > 0;
if ($anonymousUsersCan)
{
return true;
}
return DB::table('album_permissions_cache')
->join('permissions', 'permissions.id', '=', 'album_permissions_cache.permission_id')
->where([

View File

@ -23,6 +23,7 @@ use App\Services\AlbumService;
use App\Services\PhotoService;
use App\Storage;
use App\User;
use App\UserActivity;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
@ -698,6 +699,9 @@ class AlbumController extends Controller
}
}
// Add an activity record
$this->createActivityRecord($album, 'album.created');
// Rebuild the permissions cache
$helper = new PermissionsHelper();
$helper->rebuildCache();
@ -782,6 +786,21 @@ class AlbumController extends Controller
return redirect(route('albums.show', ['id' => $id]));
}
private function createActivityRecord(Album $album, $type, $activityDateTime = null)
{
if (is_null($activityDateTime))
{
$activityDateTime = new \DateTime();
}
$userActivity = new UserActivity();
$userActivity->user_id = $this->getUser()->id;
$userActivity->activity_at = $activityDateTime;
$userActivity->type = $type;
$userActivity->album_id = $album->id;
$userActivity->save();
}
/**
* @param $id
* @return Album

View File

@ -70,8 +70,31 @@ class UserController extends Controller
$params = [];
$params['user_name'] = $userName;
$params['user_url'] = $userProfileUrl;
$params['photo_name'] = $activity->photo->name;
$params['photo_url'] = $activity->photo->url();
if (!is_null($activity->photo))
{
// Check the user has access
if (!$this->getUser()->can('view', $activity->photo))
{
continue;
}
$params['photo_name'] = $activity->photo->name;
$params['photo_url'] = $activity->photo->url();
}
if (!is_null($activity->album))
{
// Check the user has access
if (!$this->getUser()->can('view', $activity->album))
{
continue;
}
$params['album_name'] = $activity->album->name;
$params['album_url'] = $activity->album->url();
}
$newItem['params'] = $params;
$result[] = $newItem;
@ -238,6 +261,7 @@ class UserController extends Controller
$result = [];
$activities = UserActivity::with('photo')
->with('photoComment')
->with('album')
->where([
'user_id' => $user->id
])
@ -261,8 +285,31 @@ class UserController extends Controller
$params = [];
$params['user_name'] = $userName;
$params['user_url'] = $userProfileUrl;
$params['photo_name'] = $activity->photo->name;
$params['photo_url'] = $activity->photo->url();
if (!is_null($activity->photo))
{
// Check the user has access
if (!$this->getUser()->can('view', $activity->photo))
{
continue;
}
$params['photo_name'] = $activity->photo->name;
$params['photo_url'] = $activity->photo->url();
}
if (!is_null($activity->album))
{
// Check the user has access
if (!$this->getUser()->can('view', $activity->album))
{
continue;
}
$params['album_name'] = $activity->album->name;
$params['album_url'] = $activity->album->url();
}
$newItem['params'] = $params;
$result[] = $newItem;

View File

@ -83,4 +83,15 @@ class PhotoPolicy
return $user->can('post-comment', $photo->album);
}
public function view(User $user, Photo $photo)
{
if ($user->id == $photo->user_id)
{
// The photo's owner can do everything
return true;
}
return $user->can('view', $photo->album);
}
}

View File

@ -8,6 +8,11 @@ class UserActivity extends Model
{
protected $table = 'user_activity';
public function album()
{
return $this->belongsTo(Album::class);
}
public function photo()
{
return $this->belongsTo(Photo::class);

View File

@ -0,0 +1,39 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddAlbumActivityColumn extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('user_activity', function (Blueprint $table)
{
$table->unsignedInteger('album_id')->nullable(true);
$table->foreign('album_id')
->references('id')->on('albums')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('user_activity', function (Blueprint $table)
{
$table->dropForeign('user_activity_album_id_foreign');
$table->dropColumn('album_id');
});
}
}

View File

@ -181,6 +181,16 @@ function UserViewModel(urls)
'<a href="' + data[i].params.photo_url + '">' + data[i].params.photo_name + '</a>'
);
}
// Album name
if (data[i].params.album_name && data[i].params.album_url)
{
data[i].description = data[i].description
.replace(
':album_name',
'<a href="' + data[i].params.album_url + '">' + data[i].params.album_name + '</a>'
);
}
}
self.feed_items = data;

View File

@ -93,6 +93,9 @@ return [
'title' => 'My Activity Feed'
],
'user_feed_type' => [
'album' => [
'created' => ':user_name created the :album_name album.'
],
'photo' => [
'comment_replied' => ':user_name replied to a comment on the :photo_name photo.',
'commented' => ':user_name commented on the :photo_name photo.',