Преглед изворни кода

WIP: Implement domain blocks

Emelia Smith пре 1 година
родитељ
комит
652654e24f

+ 38 - 0
app/Http/Controllers/Api/ApiController.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use Illuminate\Http\Request;
+use App\Http\Controllers\Controller;
+
+class ApiController extends Controller {
+  public function json($res, $headers = [], $code = 200) {
+    return response()->json($res, $code, $this->filterHeaders($headers), JSON_UNESCAPED_SLASHES);
+  }
+
+  public function linksForCollection($paginator) {
+    $link = null;
+
+    if ($paginator->onFirstPage()) {
+      if ($paginator->hasMorePages()) {
+          $link = '<'.$paginator->nextPageUrl().'>; rel="prev"';
+      }
+    } else {
+      if ($paginator->previousPageUrl()) {
+          $link = '<'.$paginator->previousPageUrl().'>; rel="next"';
+      }
+
+      if ($paginator->hasMorePages()) {
+          $link .= ($link ? ', ' : '').'<'.$paginator->nextPageUrl().'>; rel="prev"';
+      }
+    }
+
+    return $link;
+  }
+
+  private function filterHeaders($headers) {
+    return array_filter($headers, function($v, $k) {
+      return $v != null;
+    }, ARRAY_FILTER_USE_BOTH);
+  }
+}

+ 76 - 0
app/Http/Controllers/Api/V1/Admin/DomainBlocksController.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace App\Http\Controllers\Api\V1\Admin;
+
+use Illuminate\Http\Request;
+use Illuminate\Validation\Rule;
+use App\Http\Controllers\Api\ApiController;
+use App\Instance;
+use App\Services\InstanceService;
+use App\Http\Resources\MastoApi\Admin\DomainBlockResource;
+
+class DomainBlocksController extends ApiController {
+  public function index(Request $request) {
+    $this->validate($request, [
+      'limit' => 'sometimes|integer|max:100|min:1',
+    ]);
+
+    $limit = $request->input('limit', 100);
+
+    $res = Instance::moderated()
+      ->orderBy('id')
+      ->cursorPaginate($limit)
+      ->withQueryString();
+
+    return $this->json(DomainBlockResource::collection($res), [
+      'Link' => $this->linksForCollection($res)
+    ]);
+  }
+
+  public function show(Request $request, $id) {
+    $res = Instance::moderated()
+      ->findOrFail($id);
+
+    return $this->json(new DomainBlockResource($res));
+  }
+
+  public function create(Request $request) {
+    $this->validate($request, [
+      'domain' => 'required|string|min:1|max:120',
+      'severity' => [
+        'sometimes',
+        Rule::in(['noop', 'silence', 'suspend'])
+      ],
+      'reject_media' => 'sometimes|required|boolean',
+      'reject_reports' => 'sometimes|required|boolean',
+      'private_comment' => 'sometimes|string|min:1|max:1000',
+      'public_comment' => 'sometimes|string|min:1|max:1000',
+      'obfuscate' => 'sometimes|required|boolean'
+    ]);
+    
+    $domain = $request->input('domain');
+    $severity = $request->input('severity');
+    $private_comment = $request->input('private_comment');
+
+		abort_if(!strpos($domain, '.'), 400, 'Invalid domain');
+		abort_if(!filter_var($domain, FILTER_VALIDATE_DOMAIN), 400, 'Invalid domain');
+
+    $existing = Instance::moderated()->whereDomain($domain)->first();
+
+    if ($existing) {
+      return $this->json([
+        'error' => 'A domain block already exists for this domain',
+        'existing_domain_block' => new DomainBlockResource($existing)
+      ], [], 422);
+    }
+
+    $domain_block = Instance::updateOrCreate(
+      [ 'domain' => $domain ],
+      [ 'banned' => $severity === 'suspend', 'unlisted' => $severity === 'silence', 'notes' => [$private_comment]]
+    );
+
+    InstanceService::refresh();
+
+    return $this->json(new DomainBlockResource($domain_block));
+  }
+}

+ 39 - 0
app/Http/Resources/MastoApi/Admin/DomainBlockResource.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Http\Resources\MastoApi\Admin;
+
+use Illuminate\Http\Request;
+use Illuminate\Http\Resources\Json\JsonResource;
+
+class DomainBlockResource extends JsonResource
+{
+    /**
+     * Transform the resource into an array.
+     *
+     * @return array<string, mixed>
+     */
+    public function toArray(Request $request): array
+    {
+        $severity = 'noop';
+        if ($this->banned) {
+            $severity = 'suspend';
+        } else if ($this->unlisted) {
+            $severity = 'silence';
+        }
+
+        return [
+            'id' => $this->id,
+            'domain' => $this->domain,
+            'severity' => $severity,
+            // Using the updated_at value as this is going to be the closest to
+            // when the domain was banned
+            'created_at' => $this->updated_at,
+            // We don't have data for these fields
+            'reject_media' => false,
+            'reject_reports' => false,
+            'private_comment' => $this->notes ? join('; ', $this->notes) : null,
+            'public_comment' => $this->limit_reason,
+            'obfuscate' => false
+        ];
+    }
+}

+ 7 - 0
app/Instance.php

@@ -22,6 +22,13 @@ class Instance extends Model
         'notes'
         'notes'
     ];
     ];
 
 
+    // To get all moderated instances, we need to search where (banned OR unlisted)
+    public function scopeModerated($query): void {
+        $query->where(function ($query) {
+            $query->where('banned', true)->orWhere('unlisted', true);
+        });
+    }
+
     public function profiles()
     public function profiles()
     {
     {
         return $this->hasMany(Profile::class, 'domain', 'domain');
         return $this->hasMany(Profile::class, 'domain', 'domain');

+ 6 - 0
routes/api.php

@@ -101,6 +101,12 @@ Route::group(['prefix' => 'api'], function() use($middleware) {
 
 
         Route::get('statuses/{id}/history', 'StatusEditController@history')->middleware($middleware);
         Route::get('statuses/{id}/history', 'StatusEditController@history')->middleware($middleware);
         Route::put('statuses/{id}', 'StatusEditController@store')->middleware($middleware);
         Route::put('statuses/{id}', 'StatusEditController@store')->middleware($middleware);
+
+        Route::group(['prefix' => 'admin'], function() use($middleware) {
+            Route::get('domain_blocks', 'Api\V1\Admin\DomainBlocksController@index')->middleware($middleware);
+            Route::post('domain_blocks', 'Api\V1\Admin\DomainBlocksController@create')->middleware($middleware);
+            Route::get('domain_blocks/{id}', 'Api\V1\Admin\DomainBlocksController@show')->middleware($middleware);
+        })->middleware($middleware);
     });
     });
 
 
     Route::group(['prefix' => 'v2'], function() use($middleware) {
     Route::group(['prefix' => 'v2'], function() use($middleware) {