Skip to content

Commit f65ac66

Browse files
committed
feat(content): adding files upload
1 parent f08aa78 commit f65ac66

File tree

11 files changed

+659
-27
lines changed

11 files changed

+659
-27
lines changed

app/Http/Controllers/Auth/SocialitePlusController.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
namespace App\Http\Controllers\Auth;
44

5-
use App\Http\Controllers\Controller;
65
use App\Models\User;
7-
use Blaspsoft\SocialitePlus\SocialitePlusFactory;
86
use Illuminate\Http\Request;
7+
use Blaspsoft\SocialitePlus\SocialitePlusFactory;
98
use Illuminate\Support\Facades\Auth;
9+
use App\Http\Controllers\Controller;
1010

1111
class SocialitePlusController extends Controller
1212
{
@@ -19,6 +19,8 @@ class SocialitePlusController extends Controller
1919

2020
/**
2121
* Create a new SocialLoginController instance.
22+
*
23+
* @param SocialitePlusFactory $socialitePlus
2224
*/
2325
public function __construct(SocialitePlusFactory $socialitePlus)
2426
{
@@ -28,12 +30,14 @@ public function __construct(SocialitePlusFactory $socialitePlus)
2830
/**
2931
* Redirect to the social login page
3032
*
33+
* @param string $provider
3134
* @return \Illuminate\Http\RedirectResponse
3235
*/
3336
public function redirect(string $provider)
3437
{
3538
try {
3639
return $this->socialitePlus->build($provider)->redirect();
40+
3741
} catch (\Exception $e) {
3842

3943
return redirect()->route('login')->with('error', $e->getMessage());
@@ -43,21 +47,20 @@ public function redirect(string $provider)
4347
/**
4448
* Handle the social login callback
4549
*
50+
* @param string $provider
51+
* @param Request $request
4652
* @return \Illuminate\Http\RedirectResponse
4753
*/
4854
public function callback(string $provider, Request $request)
4955
{
50-
if (! $request->has('code')) {
51-
return redirect()->route('login')->with('error', 'Invalid request');
52-
}
56+
if (!$request->has('code')) return redirect()->route('login')->with('error', 'Invalid request');
5357

5458
$user = $this->socialitePlus->build($provider)->user();
5559

5660
$existingUser = User::where('email', $user->getEmail())->first();
5761

5862
if ($existingUser) {
5963
Auth::login($existingUser);
60-
6164
return redirect()->intended('/dashboard');
6265
}
6366

app/Http/Controllers/ContentController.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace App\Http\Controllers;
44

5+
use App\Models\FileUpload;
56
use Illuminate\Http\Request;
7+
use Illuminate\Support\Facades\Auth;
68
use Inertia\Inertia;
79

810
class ContentController extends Controller
@@ -11,8 +13,14 @@ public function index(Request $request)
1113
{
1214
$subscribed = $request->user()->subscribed();
1315

16+
// Get only the current user's uploaded files
17+
$files = FileUpload::where('user_id', Auth::id())
18+
->orderBy('created_at', 'desc')
19+
->get();
20+
1421
return Inertia::render('content', [
1522
'subscribed' => $subscribed,
23+
'files' => $files,
1624
]);
1725
}
1826
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Models\FileUpload;
6+
use Illuminate\Http\Request;
7+
use Illuminate\Support\Facades\Auth;
8+
use Illuminate\Support\Facades\Log;
9+
use Illuminate\Support\Facades\Storage;
10+
use Illuminate\Support\Str;
11+
use Inertia\Inertia;
12+
13+
class FileUploadController extends Controller
14+
{
15+
/**
16+
* Display a listing of the uploaded files.
17+
*/
18+
public function index()
19+
{
20+
$files = FileUpload::where('user_id', Auth::id())
21+
->orderBy('created_at', 'desc')
22+
->get();
23+
24+
return Inertia::render('Content', [
25+
'files' => $files,
26+
'subscribed' => true, // Adjust based on your subscription logic
27+
]);
28+
}
29+
30+
/**
31+
* Store a newly uploaded file.
32+
*/
33+
public function store(Request $request)
34+
{
35+
$request->validate([
36+
'file' => 'required|file|max:204800', // 200MB max file size
37+
]);
38+
39+
$file = $request->file('file');
40+
$originalFilename = $file->getClientOriginalName();
41+
$filename = Str::uuid() . '.' . $file->getClientOriginalExtension();
42+
43+
// Store the file in the storage/app/uploads directory (private)
44+
$path = $file->storeAs('uploads', $filename);
45+
46+
// Create a new file upload record
47+
$fileUpload = FileUpload::create([
48+
'user_id' => Auth::id(),
49+
'filename' => $filename,
50+
'original_filename' => $originalFilename,
51+
'path' => $path,
52+
'mime_type' => $file->getMimeType(),
53+
'size' => $file->getSize(),
54+
'status' => 'uploaded', // Default status
55+
]);
56+
57+
// In a real application, you might queue a job here to process the file
58+
// ProcessFileJob::dispatch($fileUpload);
59+
60+
return redirect()->route('content.index')
61+
->with('success', 'File uploaded successfully.');
62+
}
63+
64+
/**
65+
* Download a file securely.
66+
*/
67+
public function download(FileUpload $fileUpload)
68+
{
69+
// Check if the user has permission to download this file
70+
if ($fileUpload->user_id !== Auth::id()) {
71+
abort(403, 'You do not have permission to access this file.');
72+
}
73+
74+
// Check if the file exists
75+
if (!Storage::exists($fileUpload->path)) {
76+
abort(404, 'File not found.');
77+
}
78+
79+
// Debugging information
80+
Log::info('Download requested by User: ' . Auth::id() . ' for File: ' . $fileUpload->id . ' Path: ' . $fileUpload->path);
81+
82+
// Force download the file
83+
return response()->download(
84+
storage_path('app/' . $fileUpload->path),
85+
$fileUpload->original_filename,
86+
['Content-Type' => $fileUpload->mime_type]
87+
);
88+
}
89+
90+
/**
91+
* Update the status of an uploaded file.
92+
*/
93+
public function updateStatus(FileUpload $fileUpload, Request $request)
94+
{
95+
$request->validate([
96+
'status' => 'required|in:uploaded,processing,processed',
97+
]);
98+
99+
$fileUpload->update([
100+
'status' => $request->status,
101+
]);
102+
103+
return redirect()->back()
104+
->with('success', 'File status updated successfully.');
105+
}
106+
107+
/**
108+
* Remove the specified file from storage.
109+
*/
110+
public function destroy(FileUpload $fileUpload)
111+
{
112+
// Check if user owns the file
113+
if ($fileUpload->user_id !== Auth::id()) {
114+
return redirect()->back()
115+
->with('error', 'You do not have permission to delete this file.');
116+
}
117+
118+
// Delete the file from storage (private)
119+
Storage::delete($fileUpload->path);
120+
121+
// Delete the database record
122+
$fileUpload->delete();
123+
124+
return redirect()->back()
125+
->with('success', 'File deleted successfully.');
126+
}
127+
}

app/Models/FileUpload.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
8+
9+
class FileUpload extends Model
10+
{
11+
use HasFactory;
12+
13+
/**
14+
* The attributes that are mass assignable.
15+
*
16+
* @var array<int, string>
17+
*/
18+
protected $fillable = [
19+
'user_id',
20+
'filename',
21+
'original_filename',
22+
'path',
23+
'mime_type',
24+
'size',
25+
'status',
26+
];
27+
28+
/**
29+
* Get the user that owns the file upload.
30+
*/
31+
public function user(): BelongsTo
32+
{
33+
return $this->belongsTo(User::class);
34+
}
35+
36+
/**
37+
* Get the file's download URL.
38+
*
39+
* @return string
40+
*/
41+
public function getUrlAttribute(): string
42+
{
43+
return route('content.download', $this->id);
44+
}
45+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::create('file_uploads', function (Blueprint $table) {
15+
$table->id();
16+
$table->foreignId('user_id')->constrained()->onDelete('cascade');
17+
$table->string('filename');
18+
$table->string('original_filename');
19+
$table->string('path');
20+
$table->string('mime_type')->nullable();
21+
$table->bigInteger('size')->nullable();
22+
$table->enum('status', ['uploaded', 'processing', 'processed'])->default('uploaded');
23+
$table->timestamps();
24+
});
25+
}
26+
27+
/**
28+
* Reverse the migrations.
29+
*/
30+
public function down(): void
31+
{
32+
Schema::dropIfExists('file_uploads');
33+
}
34+
};

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"class-variance-authority": "^0.7.1",
5050
"clsx": "^2.1.1",
5151
"concurrently": "^9.0.1",
52+
"date-fns": "^4.1.0",
5253
"framer-motion": "^12.6.3",
5354
"globals": "^15.14.0",
5455
"laravel-vite-plugin": "^1.0",

0 commit comments

Comments
 (0)