瀏覽代碼

Add Roles & Parental Controls

Daniel Supernault 1 年之前
父節點
當前提交
7dbdbf15a5

+ 10 - 0
app/Http/Controllers/Api/ApiV1Controller.php

@@ -98,6 +98,7 @@ use App\Jobs\MediaPipeline\MediaSyncLicensePipeline;
 use App\Services\DiscoverService;
 use App\Services\CustomEmojiService;
 use App\Services\MarkerService;
+use App\Services\UserRoleService;
 use App\Models\Conversation;
 use App\Jobs\FollowPipeline\FollowAcceptPipeline;
 use App\Jobs\FollowPipeline\FollowRejectPipeline;
@@ -1623,6 +1624,8 @@ class ApiV1Controller extends Controller
         ]);
 
         $user = $request->user();
+        abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action');
+
         AccountService::setLastActive($user->id);
 
         if($user->last_active_at == null) {
@@ -1792,6 +1795,7 @@ class ApiV1Controller extends Controller
         abort_if(!$request->user(), 403);
 
         $user = $request->user();
+        abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action');
         AccountService::setLastActive($user->id);
 
         $media = Media::whereUserId($user->id)
@@ -1831,6 +1835,7 @@ class ApiV1Controller extends Controller
         ]);
 
         $user = $request->user();
+        abort_if($user->has_roles && !UserRoleService::can('can-post', $user->id), 403, 'Invalid permissions for this action');
 
         if($user->last_active_at == null) {
             return [];
@@ -2419,8 +2424,13 @@ class ApiV1Controller extends Controller
         $max = $request->input('max_id');
         $limit = $request->input('limit') ?? 20;
         $user = $request->user();
+
         $remote = $request->has('remote');
         $local = $request->has('local');
+        $userRoleKey = $remote ? 'can-view-network-feed' : 'can-view-public-feed';
+        if($user->has_roles && !UserRoleService::can($userRoleKey, $user->id)) {
+            return [];
+        }
         $filtered = $user ? UserFilterService::filters($user->profile_id) : [];
         AccountService::setLastActive($user->id);
         $domainBlocks = UserFilterService::domainBlocks($user->profile_id);

+ 10 - 0
app/Http/Controllers/UserRolesController.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+
+class UserRolesController extends Controller
+{
+    //
+}

+ 23 - 0
app/Models/UserRoles.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+use App\User;
+
+class UserRoles extends Model
+{
+    use HasFactory;
+
+    protected $guarded = [];
+
+    protected $casts = [
+        'roles' => 'array'
+    ];
+
+    public function user()
+    {
+        return $this->belongsTo(User::class);
+    }
+}

+ 1 - 1
app/Providers/AuthServiceProvider.php

@@ -14,7 +14,7 @@ class AuthServiceProvider extends ServiceProvider
      * @var array
      */
     protected $policies = [
-        'App\Model' => 'App\Policies\ModelPolicy',
+        // 'App\Model' => 'App\Policies\ModelPolicy',
     ];
 
     /**

+ 111 - 0
app/Services/UserRoleService.php

@@ -0,0 +1,111 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\UserRoles;
+
+class UserRoleService
+{
+    public static function can($action, $id)
+    {
+        $roles = self::get($id);
+
+        return in_array($action, $roles) ? $roles[$action] : null;
+    }
+
+    public static function get($id)
+    {
+        if($roles = UserRoles::whereUserId($id)->first()) {
+            return $roles->roles;
+        }
+
+        return self::defaultRoles();
+    }
+
+    public static function roleKeys()
+    {
+        return array_keys(self::defaultRoles());
+    }
+
+    public static function defaultRoles()
+    {
+        return [
+            'account-force-private' => true,
+            'account-ignore-follow-requests' => true,
+
+            'can-view-public-feed' => true,
+            'can-view-network-feed' => true,
+            'can-view-discover' => true,
+
+            'can-post' => true,
+            'can-comment' => true,
+            'can-like' => true,
+            'can-share' => true,
+
+            'can-follow' => false,
+            'can-make-public' => false,
+        ];
+    }
+
+    public static function getRoles($id)
+    {
+        $myRoles = self::get($id);
+        $roleData = collect(self::roleData())
+            ->map(function($role, $k) use($myRoles) {
+                $role['value'] = $myRoles[$k];
+                return $role;
+            })
+            ->toArray();
+        return $roleData;
+    }
+
+    public static function roleData()
+    {
+        return [
+            'account-force-private' => [
+                'title' => 'Force Private Account',
+                'action' => 'Prevent changing account from private'
+            ],
+            'account-ignore-follow-requests' => [
+                'title' => 'Ignore Follow Requests',
+                'action' => 'Hide follow requests and associated notifications'
+            ],
+            'can-view-public-feed' => [
+                'title' => 'Hide Public Feed',
+                'action' => 'Hide the public feed timeline'
+            ],
+            'can-view-network-feed' => [
+                'title' => 'Hide Network Feed',
+                'action' => 'Hide the network feed timeline'
+            ],
+            'can-view-discover' => [
+                'title' => 'Hide Discover',
+                'action' => 'Hide the discover feature'
+            ],
+            'can-post' => [
+                'title' => 'Can post',
+                'action' => 'Allows new posts to be shared'
+            ],
+            'can-comment' => [
+                'title' => 'Can comment',
+                'action' => 'Allows new comments to be posted'
+            ],
+            'can-like' => [
+                'title' => 'Can Like',
+                'action' => 'Allows the ability to like posts and comments'
+            ],
+            'can-share' => [
+                'title' => 'Can Share',
+                'action' => 'Allows the ability to share posts and comments'
+            ],
+            'can-follow' => [
+                'title' => 'Can Follow',
+                'action' => 'Allows the ability to follow accounts'
+            ],
+            'can-make-public' => [
+                'title' => 'Can make account public',
+                'action' => 'Allows the ability to make account public'
+            ],
+        ];
+    }
+}

+ 30 - 0
database/migrations/2023_12_27_081801_create_user_roles_table.php

@@ -0,0 +1,30 @@
+<?php
+
+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::create('user_roles', function (Blueprint $table) {
+            $table->id();
+            $table->unsignedBigInteger('profile_id')->unique()->index();
+            $table->unsignedInteger('user_id')->unique()->index();
+            $table->json('roles')->nullable();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('user_roles');
+    }
+};

+ 28 - 0
database/migrations/2023_12_27_082024_add_has_roles_to_users_table.php

@@ -0,0 +1,28 @@
+<?php
+
+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('users', function (Blueprint $table) {
+            $table->boolean('has_roles')->default(false);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('users', function (Blueprint $table) {
+            $table->dropColumn('has_roles');
+        });
+    }
+};