Add bookmark ownership

This commit is contained in:
Annika Backstrom 2024-05-31 00:01:16 +01:00
parent e5ad6e0eb8
commit ea841070eb
Signed by: annika
GPG Key ID: 3561F004DE1D9AFE
8 changed files with 91 additions and 30 deletions

View File

@ -3,6 +3,7 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\Jobs\ImportBookmark; use App\Jobs\ImportBookmark;
use App\Models\User;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use RuntimeException; use RuntimeException;
@ -15,7 +16,7 @@ class ImportBookmarks extends Command
* *
* @var string * @var string
*/ */
protected $signature = 'app:import-bookmarks {json_file}'; protected $signature = 'app:import-bookmarks {user} {json_file}';
/** /**
* The console command description. * The console command description.
@ -29,6 +30,8 @@ class ImportBookmarks extends Command
*/ */
public function handle() public function handle()
{ {
$user = User::find($this->argument('user'));
$json_file_path = $this->argument('json_file'); $json_file_path = $this->argument('json_file');
if (!file_exists($json_file_path)) { if (!file_exists($json_file_path)) {
throw new RuntimeException('Unable to find JSON file'); throw new RuntimeException('Unable to find JSON file');
@ -38,7 +41,7 @@ class ImportBookmarks extends Command
$bookmarks = json_decode($json, true); $bookmarks = json_decode($json, true);
foreach (array_chunk($bookmarks, self::$perBatch) as $bookmarks_json) { foreach (array_chunk($bookmarks, self::$perBatch) as $bookmarks_json) {
ImportBookmark::dispatch(...$bookmarks_json); ImportBookmark::dispatch($user, ...$bookmarks_json);
} }
} }
} }

View File

@ -3,19 +3,26 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Bookmark; use App\Models\Bookmark;
use App\Models\Tag;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Routing\Controllers\HasMiddleware;
class BookmarkController extends Controller class BookmarkController extends Controller implements HasMiddleware
{ {
public static function middleware()
{
return [
'auth',
];
}
/** /**
* Display a listing of the resource. * Display a listing of the resource.
*/ */
public function index() public function index(Request $request)
{ {
return view( return view(
'bookmarks.index', [ 'bookmarks.index', [
'bookmarks' => Bookmark::orderByDesc('created_at')->paginate(20), 'bookmarks' => $request->user()->bookmarks()->orderByDesc('created_at')->paginate(20),
] ]
); );
} }
@ -34,6 +41,7 @@ class BookmarkController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
$bookmark = new Bookmark; $bookmark = new Bookmark;
$bookmark->user()->associate($request->user());
$bookmark->title = $request->post('title'); $bookmark->title = $request->post('title');
$bookmark->description = $request->post('description', ''); $bookmark->description = $request->post('description', '');
$bookmark->href = $request->post('href'); $bookmark->href = $request->post('href');
@ -51,8 +59,10 @@ class BookmarkController extends Controller
/** /**
* Display the specified resource. * Display the specified resource.
*/ */
public function show(Bookmark $bookmark) public function show(Request $request, Bookmark $bookmark)
{ {
abort_unless($bookmark->user()->is($request->user()), 404);
return view( return view(
'bookmarks.show', [ 'bookmarks.show', [
'bookmark' => $bookmark, 'bookmark' => $bookmark,
@ -63,8 +73,10 @@ class BookmarkController extends Controller
/** /**
* Show the form for editing the specified resource. * Show the form for editing the specified resource.
*/ */
public function edit(Bookmark $bookmark) public function edit(Request $request, Bookmark $bookmark)
{ {
abort_unless($bookmark->user()->is($request->user()), 404);
return view( return view(
'bookmarks.edit', [ 'bookmarks.edit', [
'bookmark' => $bookmark, 'bookmark' => $bookmark,
@ -77,6 +89,8 @@ class BookmarkController extends Controller
*/ */
public function update(Request $request, Bookmark $bookmark) public function update(Request $request, Bookmark $bookmark)
{ {
abort_unless($bookmark->user()->is($request->user()), 404);
$bookmark->title = $request->post('title'); $bookmark->title = $request->post('title');
$bookmark->description = $request->post('description', ''); $bookmark->description = $request->post('description', '');
$bookmark->href = $request->post('href'); $bookmark->href = $request->post('href');

View File

@ -2,12 +2,19 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Bookmark;
use App\Models\Tag; use App\Models\Tag;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Routing\Controllers\HasMiddleware;
class TagController extends Controller class TagController extends Controller implements HasMiddleware
{ {
public static function middleware()
{
return [
'auth',
];
}
/** /**
* Display a listing of the resource. * Display a listing of the resource.
*/ */
@ -35,13 +42,15 @@ class TagController extends Controller
/** /**
* Display the specified resource. * Display the specified resource.
*/ */
public function show(Tag $tag) public function show(Request $request, Tag $tag)
{ {
$bookmarks = $tag->bookmarks()->where('user_id', $request->user()->id)->latest();
return view( return view(
'tag.show', [ 'tag.show', [
'tag' => $tag, 'tag' => $tag,
'tag_count' => $tag->bookmarks()->count(), 'tag_count' => $bookmarks->count(),
'bookmarks' => $tag->bookmarks()->latest()->paginate(20), 'bookmarks' => $bookmarks->paginate(20),
] ]
); );
} }

View File

@ -5,6 +5,7 @@ namespace App\Jobs;
use App\Models\Bookmark; use App\Models\Bookmark;
use App\Models\BookmarkTag; use App\Models\BookmarkTag;
use App\Models\Tag; use App\Models\Tag;
use App\Models\User;
use DateTimeImmutable; use DateTimeImmutable;
use DateTimeInterface; use DateTimeInterface;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
@ -22,7 +23,7 @@ class ImportBookmark implements ShouldQueue
/** /**
* Create a new job instance. * Create a new job instance.
*/ */
public function __construct(array ...$bookmarks_json) public function __construct(protected User $user, array ...$bookmarks_json)
{ {
$this->bookmarks_json = $bookmarks_json; $this->bookmarks_json = $bookmarks_json;
} }
@ -36,6 +37,7 @@ class ImportBookmark implements ShouldQueue
$created_at = DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601_EXPANDED, $bookmark_json['time']); $created_at = DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601_EXPANDED, $bookmark_json['time']);
$bookmark = new Bookmark; $bookmark = new Bookmark;
$bookmark->user()->associate($this->user);
$bookmark->href = $bookmark_json['href']; $bookmark->href = $bookmark_json['href'];
$bookmark->title = $bookmark_json['description']; $bookmark->title = $bookmark_json['description'];
$bookmark->description = $bookmark_json['extended']; $bookmark->description = $bookmark_json['extended'];
@ -43,18 +45,7 @@ class ImportBookmark implements ShouldQueue
$bookmark->updated_at = $created_at; $bookmark->updated_at = $created_at;
$bookmark->save(); $bookmark->save();
$tags = []; $bookmark->syncTagsFromString($bookmark_json['tags']);
$tokens = explode(' ', $bookmark_json['tags']);
foreach ($tokens as $tag_raw) {
$tag = Tag::firstOrCreate(
[
'name' => $tag_raw,
]
);
$tags[$tag->id] = true;;
}
$bookmark->tags()->sync(array_keys($tags));
} }
} }
} }

View File

@ -4,8 +4,8 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
class Bookmark extends Model class Bookmark extends Model
{ {
@ -33,4 +33,9 @@ class Bookmark extends Model
{ {
return $this->belongsToMany(Tag::class); return $this->belongsToMany(Tag::class);
} }
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
} }

View File

@ -4,6 +4,7 @@ namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail; // use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
@ -44,4 +45,9 @@ class User extends Authenticatable
'password' => 'hashed', 'password' => 'hashed',
]; ];
} }
public function bookmarks(): HasMany
{
return $this->hasMany(Bookmark::class);
}
} }

View File

@ -0,0 +1,33 @@
<?php
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table(
'bookmarks', function (Blueprint $table) {
$table->foreignId('user_id')->after('id')->index();
}
);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table(
'bookmarks', function (Blueprint $table) {
$table->dropColumn('user_id');
}
);
}
};

View File

@ -11,14 +11,14 @@ Route::get(
} }
); );
Route::resource('bookmarks', BookmarkController::class)->middleware(['auth', 'verified']); Route::resource('bookmarks', BookmarkController::class);
Route::post('/bookmarks/{bookmark}', [BookmarkController::class, 'update'])->middleware(['auth', 'verified']); Route::post('/bookmarks/{bookmark}', [BookmarkController::class, 'update']);
Route::resource('tags', TagController::class)->parameters( Route::resource('tags', TagController::class)->parameters(
[ [
'tags' => 'tag:name', // tag names in url, rather than ids 'tags' => 'tag:name', // tag names in url, rather than ids
] ]
)->middleware(['auth', 'verified']); );
Route::get( Route::get(
'/dashboard', function () { '/dashboard', function () {