Add NAS file manager integration and all pending platform changes
- Installed p7h/nas-file-manager package via private VCS repo - Published config/nas-file-manager.php with super_admin middleware restriction - Added NAS env vars to .env.example - Created admin/nas-storage page with connection info panel and file browser widget - Added NAS Storage link to admin sidebar (super_admin only) - Added SuperAdminController@nasStorage method and admin.nas-storage route - Includes all accumulated branch changes: profile wall, 2FA, audit logs, settings panel, country/phone/timezone components, posts, slideshow, playlist shares, video downloads/shares, comment likes, notifications, social links, and more Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
d44490dfe0
commit
0b2e95ea65
161 files changed
+27496
-7250
No files matched your search
+105
-20
@@ -2,13 +2,15 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use App\Notifications\VerifyEmail;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
class User extends Authenticatable
|
||||
class User extends Authenticatable implements MustVerifyEmail
|
||||
{
|
||||
use HasApiTokens, HasFactory, Notifiable;
|
||||
|
||||
@@ -29,6 +31,18 @@ class User extends Authenticatable
|
||||
'tiktok',
|
||||
'birthday',
|
||||
'location',
|
||||
'gender',
|
||||
'nationality',
|
||||
'phone_code',
|
||||
'phone_number',
|
||||
'timezone',
|
||||
'whatsapp',
|
||||
'google_location',
|
||||
'social_phone',
|
||||
'social_email',
|
||||
'two_factor_secret',
|
||||
'two_factor_enabled',
|
||||
'banner',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
@@ -37,10 +51,47 @@ class User extends Authenticatable
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'two_factor_enabled' => 'boolean',
|
||||
];
|
||||
|
||||
protected $appends = ['avatar_url', 'banner_url'];
|
||||
|
||||
// Auto-generate a unique slug-based username when creating a user without one
|
||||
protected static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
static::creating(function (User $user) {
|
||||
if (empty($user->username)) {
|
||||
$user->username = static::generateUniqueUsername($user->name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static function generateUniqueUsername(string $name): string
|
||||
{
|
||||
$base = substr(Str::slug(trim($name)), 0, 18);
|
||||
if ($base === '') {
|
||||
$base = 'user';
|
||||
}
|
||||
do {
|
||||
$slug = $base . '-' . Str::lower(Str::random(6));
|
||||
} while (static::where('username', $slug)->exists());
|
||||
|
||||
return $slug;
|
||||
}
|
||||
|
||||
// Returns the channel URL slug — the username, auto-generated and saved if missing
|
||||
public function getChannelAttribute(): string
|
||||
{
|
||||
if (empty($this->username)) {
|
||||
$this->username = static::generateUniqueUsername($this->name);
|
||||
$this->saveQuietly();
|
||||
}
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
// Relationships
|
||||
public function videos()
|
||||
{
|
||||
@@ -67,6 +118,11 @@ class User extends Authenticatable
|
||||
return $this->hasMany(Playlist::class);
|
||||
}
|
||||
|
||||
public function posts()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Post::class);
|
||||
}
|
||||
|
||||
public function getAvatarUrlAttribute()
|
||||
{
|
||||
if ($this->avatar) {
|
||||
@@ -76,6 +132,19 @@ class User extends Authenticatable
|
||||
return 'https://i.pravatar.cc/150?u='.$this->id;
|
||||
}
|
||||
|
||||
public function getBannerUrlAttribute(): ?string
|
||||
{
|
||||
if ($this->banner) {
|
||||
return asset('storage/banners/'.$this->banner);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function sendEmailVerificationNotification(): void
|
||||
{
|
||||
$this->notify(new VerifyEmail);
|
||||
}
|
||||
|
||||
// Role helper methods
|
||||
public function isSuperAdmin()
|
||||
{
|
||||
@@ -92,31 +161,47 @@ class User extends Authenticatable
|
||||
return $this->role === 'user' || $this->role === null;
|
||||
}
|
||||
|
||||
// Placeholder for subscriber count (would need a separate table in full implementation)
|
||||
public function getSubscriberCountAttribute()
|
||||
// Users who subscribe TO this channel
|
||||
public function subscribers()
|
||||
{
|
||||
// For now, return a placeholder - in production this would come from a subscriptions table
|
||||
return rand(100, 10000);
|
||||
return $this->belongsToMany(
|
||||
User::class,
|
||||
'user_subscriptions',
|
||||
'channel_id',
|
||||
'subscriber_id'
|
||||
)->withPivot('created_at');
|
||||
}
|
||||
|
||||
// Get social links as an array
|
||||
public function getSocialLinksAttribute()
|
||||
// Channels this user subscribes to
|
||||
public function subscriptions()
|
||||
{
|
||||
return [
|
||||
'twitter' => $this->twitter,
|
||||
'instagram' => $this->instagram,
|
||||
'facebook' => $this->facebook,
|
||||
'youtube' => $this->youtube,
|
||||
'linkedin' => $this->linkedin,
|
||||
'tiktok' => $this->tiktok,
|
||||
];
|
||||
return $this->belongsToMany(
|
||||
User::class,
|
||||
'user_subscriptions',
|
||||
'subscriber_id',
|
||||
'channel_id'
|
||||
)->withPivot('created_at');
|
||||
}
|
||||
|
||||
public function isSubscribedTo(User $channel): bool
|
||||
{
|
||||
return $this->subscriptions()->where('channel_id', $channel->id)->exists();
|
||||
}
|
||||
|
||||
public function getSubscriberCountAttribute(): int
|
||||
{
|
||||
return $this->subscribers()->count();
|
||||
}
|
||||
|
||||
// Check if user has any social links
|
||||
public function socialLinks()
|
||||
{
|
||||
return $this->hasMany(UserSocialLink::class)->orderBy('sort_order');
|
||||
}
|
||||
|
||||
public function hasSocialLinks()
|
||||
{
|
||||
return $this->twitter || $this->instagram || $this->facebook ||
|
||||
$this->youtube || $this->linkedin || $this->tiktok;
|
||||
return $this->socialLinks()->exists();
|
||||
}
|
||||
|
||||
// Get formatted website URL
|
||||
|
||||
Reference in new issue
Block a user