feat(offers): 未驗證教練的課程不對公開端點曝光
is_verified 原本只有 Admin toggle 開關、無任何業務約束(稽核 P1-1)。 - DivingOffer 新增 visibleToPublic scope:provider_id null 或教練已驗證 - 公開 index/show 套用過濾,未驗證教練課程列表排除、詳情 404 - toggle-verified 後 flush diving_offers 快取標籤,切換立即生效 - 新增 provider-verification 規格(含已知限制註記)與 7 條可見性測試 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\API;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class AdminUserController extends Controller
|
||||
{
|
||||
@@ -144,6 +145,9 @@ class AdminUserController extends Controller
|
||||
$profile->is_verified = !$profile->is_verified;
|
||||
$profile->save();
|
||||
|
||||
// 驗證狀態影響公開課程列表的可見性,需立即讓快取失效
|
||||
Cache::tags(['diving_offers'])->flush();
|
||||
|
||||
$msg = $profile->is_verified ? '教練已驗證' : '已取消驗證';
|
||||
return response()->json(['status' => true, 'message' => $msg, 'data' => ['is_verified' => $profile->is_verified]]);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class DivingOfferController extends Controller
|
||||
$cacheKey = 'diving_offers_' . md5(serialize($request->all()));
|
||||
|
||||
$result = Cache::tags(['diving_offers'])->remember($cacheKey, 180, function () use ($request, $perPage) {
|
||||
$query = DivingOffer::query();
|
||||
$query = DivingOffer::query()->visibleToPublic();
|
||||
|
||||
if ($q = $request->query('q')) {
|
||||
$query->where(function ($sub) use ($q) {
|
||||
@@ -55,7 +55,7 @@ class DivingOfferController extends Controller
|
||||
|
||||
public function show(int $id)
|
||||
{
|
||||
$offer = DivingOffer::with('courseImages')->find($id);
|
||||
$offer = DivingOffer::with('courseImages')->visibleToPublic()->find($id);
|
||||
|
||||
if (!$offer) {
|
||||
return response()->json(['status' => false, 'message' => '課程不存在'], 404);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -53,6 +54,18 @@ class DivingOffer extends Model
|
||||
return $this->belongsTo(User::class, 'provider_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 公開端點可見性:未驗證教練的課程不對外曝光。
|
||||
* provider_id 為 null 的課程(平台自有資料)不受此限制。
|
||||
*/
|
||||
public function scopeVisibleToPublic(Builder $query): Builder
|
||||
{
|
||||
return $query->where(function (Builder $visible) {
|
||||
$visible->whereNull('provider_id')
|
||||
->orWhereHas('provider.providerProfile', fn (Builder $profile) => $profile->where('is_verified', true));
|
||||
});
|
||||
}
|
||||
|
||||
public function schedules()
|
||||
{
|
||||
return $this->hasMany(CourseSchedule::class, 'diving_offer_id');
|
||||
|
||||
Reference in New Issue
Block a user