Skip to content

Commit

Permalink
[collection] publish policy
Browse files Browse the repository at this point in the history
  • Loading branch information
rastislav-chynoransky committed Apr 11, 2024
1 parent 8609e38 commit 25b2558
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 45 deletions.
12 changes: 8 additions & 4 deletions app/Http/Controllers/CollectionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ public function store()
if ($v->passes()) {
$collection = new Collection();

$collection->frontends = array_intersect($input['frontends'] ?? [], \auth()->user()->frontends);
if (Gate::allows('publish', $collection)) {
$collection->frontends = array_intersect($input['frontends'] ?? [], \auth()->user()->frontends);
}

// store translatable attributes
foreach (\Config::get('translatable.locales') as $i => $locale) {
Expand Down Expand Up @@ -151,9 +153,11 @@ public function update($id)

$collection = Collection::find($id);

$currentOutOfScope = array_diff($collection->frontends, \auth()->user()->frontends);
$newInScope = array_intersect($input['frontends'] ?? [], \auth()->user()->frontends);
$collection->frontends = array_merge($currentOutOfScope, $newInScope);
if (Gate::allows('publish', $collection)) {
$currentOutOfScope = array_diff($collection->frontends, \auth()->user()->frontends);
$newInScope = array_intersect($input['frontends'] ?? [], \auth()->user()->frontends);
$collection->frontends = array_merge($currentOutOfScope, $newInScope);
}

foreach (\Config::get('translatable.locales') as $i => $locale) {
if (hasTranslationValue($locale, $collection->translatedAttributes)) {
Expand Down
13 changes: 13 additions & 0 deletions app/Policies/CollectionPolicy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Policies;

use App\User;

class CollectionPolicy
{
public function publish(User $user)
{
return in_array('publisher', $user->roles, true);
}
}
8 changes: 4 additions & 4 deletions app/Providers/AuthServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ class AuthServiceProvider extends ServiceProvider
public function boot()
{
Gate::define('administer', function ($user) {
return $user->role === 'admin';
return in_array('admin', $user->roles, true);
});

Gate::define('edit', function ($user) {
return $user->role === 'editor';
return in_array('editor', $user->roles, true);
});

Gate::define('import', function ($user) {
return $user->role === 'importer';
return in_array('importer', $user->roles, true);
});

Gate::before(function ($user) {
if ($user->role === 'admin') {
if (in_array('admin', $user->roles, true)) {
return true;
}
});
Expand Down
8 changes: 5 additions & 3 deletions app/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
class User extends Authenticatable
{
use HasFactory;
public static $roles = ['admin', 'editor', 'importer'];
public static $roles = ['admin', 'editor', 'importer', 'publisher'];

protected $fillable = ['name', 'email', 'role', 'username', 'frontends'];
protected $fillable = ['name', 'email', 'roles', 'username', 'frontends'];

/**
* The attributes that should be hidden for arrays.
Expand All @@ -21,12 +21,14 @@ class User extends Authenticatable

public static $rules = [
'name' => 'required',
'role' => 'in:admin,editor,importer|required',
'roles' => 'array|required',
'roles.*' => 'in:admin,editor,importer,publisher',
'email' => 'email|required',
'username' => 'required',
];

protected $casts = [
'roles' => 'array',
'frontends' => 'array',
];
}
5 changes: 5 additions & 0 deletions database/factories/CollectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ public function definition()
'text' => fake()->sentence,
];
}

public function webumenia()
{
return $this->state(['frontends' => ['webumenia']]);
}
}
2 changes: 1 addition & 1 deletion database/factories/UserFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function definition()
'username' => fake()->userName(),
'name' => fake()->name(),
'email' => fake()->safeEmail(),
'role' => 'editor',
'roles' => ['editor'],
'password' => bcrypt(Str::random(10)),
'remember_token' => Str::random(10),
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
*/
public function up(): void
{
DB::statement("ALTER TABLE collections ADD COLUMN frontends JSON DEFAULT (JSON_ARRAY('webumenia'))");
DB::statement("ALTER TABLE collections ADD COLUMN frontends JSON DEFAULT (JSON_ARRAY())");
DB::table('collections')->update(['frontends' => '["webumenia"]']);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
DB::statement("ALTER TABLE users ADD COLUMN roles JSON DEFAULT (JSON_ARRAY())");

DB::table('users')
->eachById(function ($user) {
DB::table('users')
->where('id', $user->id)
->update(['roles' => json_encode([$user->role])]);
});

Schema::table('users', function (Blueprint $table) {
$table->dropColumn('role');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('role');
});

DB::table('users')
->eachById(function ($user) {
$roles = json_decode($user->roles);
DB::table('users')
->where('id', $user->id)
->update(['role' => $roles[0]]);
});

Schema::table('users', function (Blueprint $table) {
$table->dropColumn('roles');
});
}
};
4 changes: 3 additions & 1 deletion resources/views/collections/form.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<!-- translatable -->
<div class="col-md-12">

@can('publish', $collection ?? App\Collection::class)
<div class="form-group">
{{ Form::label('frontends[]', 'Publikovať na') }}
<div>
Expand All @@ -44,6 +45,7 @@
@endforeach
</div>
</div>
@endcan

<!-- Nav tabs -->
<ul class="nav nav-tabs top-space" role="tablist">
Expand Down Expand Up @@ -108,7 +110,7 @@
@endif
</div>
</div>
@can('administer')
@can('publish', $collection ?? App\Collection::class)
<div class="col-md-6">
<div class="form-group checkbox">
{!! Form::label('published_at', 'Publikovať') !!}
Expand Down
4 changes: 2 additions & 2 deletions resources/views/users/form.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
</div>
<div class="col-md-12">
<div class="form-group">
{!! Form::label('role', 'Skupina') !!}
{!! Form::label('roles[]', 'Skupina') !!}
<div>
@foreach(\App\User::$roles as $role)
<label class="radio-inline">
{{ Form::radio('role', $role, options: ['class' => 'form-control']) }} {{ $role }}
{{ Form::checkbox('roles[]', $role, options: ['class' => 'form-control']) }} {{ $role }}
</label>
@endforeach
</div>
Expand Down
50 changes: 29 additions & 21 deletions tests/BrowserKit/CollectionViewTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@ public function testIndexSortedByName()
{
$user = User::factory()->create();

$collectionB = Collection::factory()->create([
'name' => 'b',
'published_at' => '2000-01-01 00:00:00',
'user_id' => $user->id,
]);
$collectionA = Collection::factory()->create([
'name' => 'a',
'published_at' => '2000-01-01 00:00:00',
'user_id' => $user->id,
]);
$collectionB = Collection::factory()
->webumenia()
->create([
'name' => 'b',
'published_at' => '2000-01-01 00:00:00',
'user_id' => $user->id,
]);
$collectionA = Collection::factory()
->webumenia()
->create([
'name' => 'a',
'published_at' => '2000-01-01 00:00:00',
'user_id' => $user->id,
]);

$response = $this->route('get', 'frontend.collection.index', ['sort_by' => 'name']);
$data = $response->original->getData();
Expand All @@ -38,17 +42,21 @@ public function testIndexSortedByNameTranslationFallback()
{
$user = User::factory()->create();

$collectionB = Collection::factory()->create([
'name' => 'b',
'published_at' => '2000-01-01 00:00:00',
'user_id' => $user->id,
]);
$collectionC = Collection::factory()->create([
'name' => 'a',
'name:en' => 'c',
'published_at' => '2000-01-01 00:00:00',
'user_id' => $user->id,
]);
$collectionB = Collection::factory()
->webumenia()
->create([
'name' => 'b',
'published_at' => '2000-01-01 00:00:00',
'user_id' => $user->id,
]);
$collectionC = Collection::factory()
->webumenia()
->create([
'name' => 'a',
'name:en' => 'c',
'published_at' => '2000-01-01 00:00:00',
'user_id' => $user->id,
]);

app()->setLocale('en'); // request en route
$response = $this->route('get', 'frontend.collection.index', ['sort_by' => 'name']);
Expand Down
20 changes: 12 additions & 8 deletions tests/Views/Frontend/ItemViewTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ public function testGetItemDetail()
public function testListsAssociatedPublishedCollections()
{
$item = Item::factory()->create();
$publishedCollection = Collection::factory()->create([
'is_published' => true,
'name' => 'a published collection',
]);
$unpublishedCollection = Collection::factory()->create([
'is_published' => false,
'name' => 'an unpublished collection',
]);
$publishedCollection = Collection::factory()
->webumenia()
->create([
'is_published' => true,
'name' => 'a published collection',
]);
$unpublishedCollection = Collection::factory()
->webumenia()
->create([
'is_published' => false,
'name' => 'an unpublished collection',
]);

$publishedCollection->items()->save($item);
$unpublishedCollection->items()->save($item);
Expand Down

0 comments on commit 25b2558

Please sign in to comment.