feat: api admin user and game policies
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\RegisterRequest;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use App\Models\User;
|
||||
use App\Http\Requests\RegisterRequest;
|
||||
|
||||
class AuthController extends Controller
|
||||
{
|
||||
@@ -24,6 +24,13 @@ class AuthController extends Controller
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
if ($user->blocked) {
|
||||
Auth::logout();
|
||||
|
||||
return response()->json(['message' => 'Your account is blocked. Please contact support.'], 403);
|
||||
}
|
||||
|
||||
$token = $user->createToken('auth-token')->plainTextToken;
|
||||
|
||||
return response()->json([
|
||||
|
||||
@@ -14,8 +14,21 @@ class GameController extends Controller
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('viewAny', Game::class);
|
||||
|
||||
$user = Auth::user();
|
||||
$query = Game::query()->with(["winner", "player1", "player2"]);
|
||||
|
||||
// Filter games based on user type
|
||||
if ($user->type !== 'A') {
|
||||
// Players can only see games they participate in
|
||||
$query->where(function ($q) use ($user) {
|
||||
$q->where('player1_user_id', $user->id)
|
||||
->orWhere('player2_user_id', $user->id);
|
||||
});
|
||||
}
|
||||
// Admins see all games (no filter needed)
|
||||
|
||||
if ($request->has("type") && in_array($request->type, ["3", "9"])) {
|
||||
$query->where("type", $request->type);
|
||||
}
|
||||
@@ -43,6 +56,8 @@ class GameController extends Controller
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('create', Game::class);
|
||||
|
||||
$validated = $request->validate([
|
||||
"type" => "required|in:3,9",
|
||||
]);
|
||||
@@ -81,6 +96,8 @@ class GameController extends Controller
|
||||
|
||||
public function join(Game $game)
|
||||
{
|
||||
$this->authorize('join', $game);
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
if ($game->player1_user_id == $user->id) {
|
||||
@@ -107,12 +124,16 @@ class GameController extends Controller
|
||||
|
||||
public function show(Game $game)
|
||||
{
|
||||
$this->authorize('view', $game);
|
||||
|
||||
$game->load(["player1", "player2", "winner"]);
|
||||
return response()->json($game);
|
||||
}
|
||||
|
||||
public function update(Request $request, Game $game)
|
||||
{
|
||||
$this->authorize('update', $game);
|
||||
|
||||
if ($game->status == "Ended") {
|
||||
return response()->json(["message" => "Game already ended"], 400);
|
||||
}
|
||||
@@ -135,4 +156,25 @@ class GameController extends Controller
|
||||
|
||||
return response()->json($game);
|
||||
}
|
||||
|
||||
public function resign(Game $game)
|
||||
{
|
||||
$this->authorize('resign', $game);
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
$game->update([
|
||||
'status' => 'Ended',
|
||||
'winner_user_id' => $game->player1_user_id === $user->id
|
||||
? $game->player2_user_id
|
||||
: $game->player1_user_id,
|
||||
'loser_user_id' => $user->id,
|
||||
'ended_at' => now(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'You have resigned from the game',
|
||||
'game' => $game->fresh(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ class UserController extends Controller
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('viewAny', User::class);
|
||||
|
||||
$query = User::query();
|
||||
|
||||
// Filtros úteis para o Backoffice
|
||||
@@ -41,6 +43,8 @@ class UserController extends Controller
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('create', User::class);
|
||||
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'nickname' => 'required|string|max:20|unique:users,nickname',
|
||||
@@ -73,7 +77,11 @@ class UserController extends Controller
|
||||
public function show(User $user)
|
||||
{
|
||||
$currentUser = Auth::user();
|
||||
if ($currentUser->id !== $user->id && $currentUser->type !== 'A') {
|
||||
|
||||
// Admins and owners get full profile, others get limited view
|
||||
if ($currentUser->type === 'A' || $currentUser->id === $user->id) {
|
||||
return response()->json($user);
|
||||
} else {
|
||||
return response()->json([
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
@@ -82,8 +90,6 @@ class UserController extends Controller
|
||||
'type' => $user->type,
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json($user);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,11 +98,7 @@ class UserController extends Controller
|
||||
*/
|
||||
public function update(Request $request, User $user)
|
||||
{
|
||||
$currentUser = Auth::user();
|
||||
|
||||
if ($currentUser->id !== $user->id && $currentUser->type !== 'A') {
|
||||
return response()->json(['message' => 'Unauthorized'], 403);
|
||||
}
|
||||
$this->authorize('update', $user);
|
||||
|
||||
$validated = $request->validate([
|
||||
'name' => 'sometimes|string|max:255',
|
||||
@@ -112,16 +114,8 @@ class UserController extends Controller
|
||||
Rule::unique('users')->ignore($user->id),
|
||||
],
|
||||
'password' => 'sometimes|string|min:3',
|
||||
'blocked' => 'sometimes|boolean',
|
||||
]);
|
||||
|
||||
if (isset($validated['blocked']) && $currentUser->type !== 'A') {
|
||||
return response()->json(
|
||||
['message' => 'Only admins can block users'],
|
||||
403,
|
||||
);
|
||||
}
|
||||
|
||||
// Lógica de Upload de Foto (Exemplo Básico)
|
||||
// if ($request->hasFile('photo_avatar')) {
|
||||
// $path = $request->file('photo_avatar')->store('avatars', 'public');
|
||||
@@ -139,24 +133,24 @@ class UserController extends Controller
|
||||
*/
|
||||
public function destroy(User $user)
|
||||
{
|
||||
$currentUser = Auth::user();
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
if ($currentUser->id !== $user->id && $currentUser->type !== 'A') {
|
||||
return response()->json(['message' => 'Unauthorized'], 403);
|
||||
// Check if user has transactions or games - if so, soft delete
|
||||
$hasTransactions = $user->transactions()->exists();
|
||||
$hasGames = Game::where(function ($q) use ($user) {
|
||||
$q->where('player1_user_id', $user->id)
|
||||
->orWhere('player2_user_id', $user->id);
|
||||
})->exists();
|
||||
|
||||
if ($hasTransactions || $hasGames) {
|
||||
$user->delete(); // Soft delete
|
||||
$message = 'User account deactivated (soft-deleted due to transaction/game history)';
|
||||
} else {
|
||||
$user->forceDelete(); // Hard delete
|
||||
$message = 'User permanently deleted';
|
||||
}
|
||||
|
||||
if ($currentUser->id === $user->id && $currentUser->type === 'A') {
|
||||
if ($user->type === 'A') {
|
||||
return response()->json(
|
||||
['message' => 'Admins cannot delete their own account'],
|
||||
403,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$user->delete();
|
||||
|
||||
return response()->json(['message' => 'User deleted successfully']);
|
||||
return response()->json(['message' => $message]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,11 +159,7 @@ class UserController extends Controller
|
||||
*/
|
||||
public function getMatches(Request $request, User $user)
|
||||
{
|
||||
$currentUser = Auth::user();
|
||||
|
||||
if ($currentUser->id !== $user->id && $currentUser->type !== 'A') {
|
||||
return response()->json(['message' => 'Unauthorized'], 403);
|
||||
}
|
||||
$this->authorize('view', $user);
|
||||
|
||||
$matches = Game::query()
|
||||
->where(function ($q) use ($user) {
|
||||
@@ -187,14 +177,21 @@ class UserController extends Controller
|
||||
|
||||
public function block(User $user)
|
||||
{
|
||||
$this->authorize('block', $user);
|
||||
|
||||
$user->blocked = true;
|
||||
$user->save();
|
||||
|
||||
// Revoke all active tokens for immediate effect
|
||||
$user->tokens()->delete();
|
||||
|
||||
return response()->json(['message' => 'User blocked successfully']);
|
||||
}
|
||||
|
||||
public function unblock(User $user)
|
||||
{
|
||||
$this->authorize('unblock', $user);
|
||||
|
||||
$user->blocked = false;
|
||||
$user->save();
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@ class GamePolicy
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
if ($user->blocked === 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,12 +20,9 @@ class GamePolicy
|
||||
*/
|
||||
public function view(User $user, Game $game): bool
|
||||
{
|
||||
if ($user->type === "A") {
|
||||
if ($user->type === 'A') {
|
||||
return true;
|
||||
}
|
||||
if ($user->blocked === 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
$game->player1_user_id === $user->id ||
|
||||
@@ -45,7 +39,7 @@ class GamePolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
if ($user->type === "A" || $user->blocked === 1) {
|
||||
if ($user->type === 'A') {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -54,12 +48,12 @@ class GamePolicy
|
||||
|
||||
public function join(User $user, Game $game): bool
|
||||
{
|
||||
if ($user->type === "A" || $user->blocked === 1) {
|
||||
if ($user->type === 'A') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
$game->status !== "waiting" ||
|
||||
$game->status !== 'waiting' ||
|
||||
$game->player1_user_id === $user->id
|
||||
) {
|
||||
return false;
|
||||
@@ -70,12 +64,12 @@ class GamePolicy
|
||||
|
||||
public function resign(User $user, Game $game): bool
|
||||
{
|
||||
if ($user->type === "A" || $user->blocked === 1) {
|
||||
if ($user->type === 'A') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
$game->status !== "ongoing" ||
|
||||
$game->status !== 'ongoing' ||
|
||||
($game->player1_user_id !== $user->id &&
|
||||
$game->player2_user_id !== $user->id)
|
||||
) {
|
||||
@@ -90,12 +84,12 @@ class GamePolicy
|
||||
*/
|
||||
public function update(User $user, Game $game): bool
|
||||
{
|
||||
if ($user->type === "A" || $user->blocked === 1) {
|
||||
if ($user->type === 'A') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
$game->status !== "ongoing" ||
|
||||
$game->status !== 'ongoing' ||
|
||||
($game->player1_user_id !== $user->id &&
|
||||
$game->player2_user_id !== $user->id)
|
||||
) {
|
||||
@@ -110,7 +104,8 @@ class GamePolicy
|
||||
*/
|
||||
public function delete(User $user, Game $game): bool
|
||||
{
|
||||
return false;
|
||||
// Only admins can delete games
|
||||
return $user->type === 'A';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
|
||||
class UserPolicy
|
||||
{
|
||||
@@ -12,7 +11,7 @@ class UserPolicy
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return false;
|
||||
return $user->type === 'A';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -20,7 +19,7 @@ class UserPolicy
|
||||
*/
|
||||
public function view(User $user, User $model): bool
|
||||
{
|
||||
return false;
|
||||
return $user->id === $model->id || $user->type === 'A';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,7 +27,7 @@ class UserPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return false;
|
||||
return $user->type === 'A';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +35,7 @@ class UserPolicy
|
||||
*/
|
||||
public function update(User $user, User $model): bool
|
||||
{
|
||||
return false;
|
||||
return $user->id === $model->id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +43,17 @@ class UserPolicy
|
||||
*/
|
||||
public function delete(User $user, User $model): bool
|
||||
{
|
||||
return false;
|
||||
return ($user->type === 'A' && $user->id !== $model->id) || ($user->type === 'P' && $user->id === $model->id);
|
||||
}
|
||||
|
||||
public function block(User $user, User $model): bool
|
||||
{
|
||||
return $user->type === 'A' && $user->id !== $model->id && $model->type === 'P';
|
||||
}
|
||||
|
||||
public function unblock(User $user, User $model): bool
|
||||
{
|
||||
return $user->type === 'A' && $user->id !== $model->id && $model->type === 'P';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
PORT=3000
|
||||
API_URL=http://localhost:8000/api
|
||||
Reference in New Issue
Block a user