345 lines
10 KiB
PHP
345 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\User;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Validation\ValidationException;
|
|
use OpenApi\Attributes as OA;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
|
|
|
|
#[OA\Tag(
|
|
name: "Auth",
|
|
description: "Autenticación de usuarios"
|
|
)]
|
|
|
|
class AuthController extends Controller
|
|
{
|
|
|
|
public function register(Request $request)
|
|
{
|
|
$request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'email' => 'required|string|email|max:255|unique:users',
|
|
'password' => 'required|string|min:8|confirmed',
|
|
]);
|
|
|
|
$user = User::create([
|
|
'name' => $request->name,
|
|
'email' => $request->email,
|
|
'password' => Hash::make($request->password),
|
|
]);
|
|
|
|
$token = $user->createToken('auth_token')->plainTextToken;
|
|
|
|
return response()->json([
|
|
'access_token' => $token,
|
|
'token_type' => 'Bearer',
|
|
]);
|
|
}
|
|
|
|
|
|
|
|
#[OA\Post(
|
|
path: "/api/login_interno",
|
|
summary: "Autenticación de usuarios internos",
|
|
tags: ["Auth"],
|
|
requestBody: new OA\RequestBody(
|
|
required: true,
|
|
content: new OA\JsonContent(
|
|
required: ["email", "password"],
|
|
properties: [
|
|
new OA\Property(property: "email", type: "string", example: "usuario"),
|
|
new OA\Property(property: "password", type: "string", example: "******")
|
|
]
|
|
)
|
|
),
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: "Login correcto",
|
|
content: new OA\JsonContent(
|
|
properties: [
|
|
new OA\Property(property: "message", type: "string", example: "Login correcto")
|
|
]
|
|
)
|
|
),
|
|
new OA\Response(
|
|
response: 401,
|
|
description: "Credenciales incorrectas",
|
|
content: new OA\JsonContent(
|
|
properties: [
|
|
new OA\Property(property: "message", type: "string", example: "Credenciales incorrectas")
|
|
]
|
|
)
|
|
)
|
|
]
|
|
)]
|
|
public function login_interno(Request $request)
|
|
{
|
|
try {
|
|
$request->validate([
|
|
'email' => 'required',
|
|
'password' => 'required'
|
|
]);
|
|
|
|
$url = env('SIPA_URL') . '/' . $request->email . '/autenticar';
|
|
|
|
$response = Http::asForm()->post($url, [
|
|
'email' => $request->email,
|
|
'password' => $request->password
|
|
]);
|
|
|
|
$status = $response->status();
|
|
$body = $response->body();
|
|
|
|
// Credenciales incorrectas
|
|
if ($status === 404 && str_contains($body, '<html')) {
|
|
return response()->json(['message' => 'Credenciales incorrectas'], 401);
|
|
}
|
|
|
|
// Invalida token antiguo si existe
|
|
$existingToken = Cache::get("sipa_user_token:{$request->email}");
|
|
if ($existingToken) {
|
|
Cache::forget("sipa_token:{$existingToken}");
|
|
}
|
|
|
|
// Generar token nuevo
|
|
$token = bin2hex(random_bytes(32));
|
|
|
|
// Guardar token en cache (2h)
|
|
Cache::put("sipa_token:{$token}", $request->email, 120*60);
|
|
Cache::put("sipa_user_token:{$request->email}", $token, 120*60);
|
|
|
|
// Respuesta SIPA
|
|
$data = $response->json() ?: [];
|
|
|
|
// 🔹 SOLO ESTO SE AGREGA (formato estándar Bearer)
|
|
$data['access_token'] = $token;
|
|
$data['token_type'] = 'Bearer';
|
|
$data['expires_in'] = 120*60;
|
|
|
|
return response()->json($data, $status);
|
|
|
|
} catch (\Throwable $e) {
|
|
return response()->json([
|
|
'message' => 'Error interno',
|
|
'error_real' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
|
|
#[OA\Post(
|
|
path: "/api/login_alumno",
|
|
summary: "Autenticación de alumnos",
|
|
tags: ["Auth"],
|
|
requestBody: new OA\RequestBody(
|
|
required: true,
|
|
content: new OA\JsonContent(
|
|
required: ["email", "password"],
|
|
properties: [
|
|
new OA\Property(property: "email", type: "string", example: "usuario"),
|
|
new OA\Property(property: "password", type: "string", example: "******")
|
|
]
|
|
)
|
|
),
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: "Login correcto",
|
|
content: new OA\JsonContent(
|
|
properties: [
|
|
new OA\Property(property: "message", type: "string", example: "Login correcto")
|
|
]
|
|
)
|
|
),
|
|
new OA\Response(
|
|
response: 401,
|
|
description: "Credenciales incorrectas",
|
|
content: new OA\JsonContent(
|
|
properties: [
|
|
new OA\Property(property: "message", type: "string", example: "Credenciales incorrectas")
|
|
]
|
|
)
|
|
)
|
|
]
|
|
)]
|
|
public function login_alumno(Request $request)
|
|
{
|
|
$request->validate([
|
|
'email' => 'required',
|
|
'password' => 'required',
|
|
]);
|
|
|
|
$user = User::where('email', $request->email)->first();
|
|
|
|
if (! $user || ! Hash::check($request->password, $user->password)) {
|
|
throw ValidationException::withMessages([
|
|
'email' => ['The provided credentials are incorrect.'],
|
|
]);
|
|
}
|
|
|
|
$token = $user->createToken('auth_token')->plainTextToken;
|
|
|
|
return response()->json([
|
|
'access_token' => $token,
|
|
'token_type' => 'Bearer',
|
|
]);
|
|
}
|
|
|
|
|
|
#[OA\Post(
|
|
path: "/api/login_externo",
|
|
summary: "Autenticación de usuarios externos",
|
|
tags: ["Auth"],
|
|
requestBody: new OA\RequestBody(
|
|
required: true,
|
|
content: new OA\JsonContent(
|
|
required: ["email", "password"],
|
|
properties: [
|
|
new OA\Property(property: "email", type: "string", example: "usuario"),
|
|
new OA\Property(property: "password", type: "string", example: "******")
|
|
]
|
|
)
|
|
),
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: "Login correcto",
|
|
content: new OA\JsonContent(
|
|
properties: [
|
|
new OA\Property(property: "message", type: "string", example: "Login correcto")
|
|
]
|
|
)
|
|
),
|
|
new OA\Response(
|
|
response: 401,
|
|
description: "Credenciales incorrectas",
|
|
content: new OA\JsonContent(
|
|
properties: [
|
|
new OA\Property(property: "message", type: "string", example: "Credenciales incorrectas")
|
|
]
|
|
)
|
|
)
|
|
]
|
|
)]
|
|
public function login_externo(Request $request)
|
|
{
|
|
$request->validate([
|
|
'email' => 'required|email',
|
|
'password' => 'required',
|
|
]);
|
|
|
|
$user = User::where('email', $request->email)->first();
|
|
|
|
if (! $user || ! Hash::check($request->password, $user->password)) {
|
|
throw ValidationException::withMessages([
|
|
'email' => ['The provided credentials are incorrect.'],
|
|
]);
|
|
}
|
|
|
|
$token = $user->createToken('auth_token')->plainTextToken;
|
|
|
|
return response()->json([
|
|
'access_token' => $token,
|
|
'token_type' => 'Bearer',
|
|
]);
|
|
}
|
|
#[OA\Post(
|
|
path: "/api/logout-sipa",
|
|
summary: "Cerrar sesión e invalidar token",
|
|
security: [["bearerAuth" => []]],
|
|
tags: ["Auth"],
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: "Sesión cerrada",
|
|
content: new OA\JsonContent(
|
|
properties: [
|
|
new OA\Property(property: "message", type: "string", example: "Sesión cerrada correctamente")
|
|
]
|
|
)
|
|
),
|
|
new OA\Response(response: 401, description: "Token inválido o no enviado")
|
|
]
|
|
)]
|
|
|
|
public function logout_sipa(Request $request)
|
|
{
|
|
$header = $request->header('Authorization');
|
|
|
|
if (!$header || !str_starts_with($header, 'Bearer ')) {
|
|
return response()->json(['message' => 'Token requerido'], 401);
|
|
}
|
|
|
|
$token = str_replace('Bearer ', '', $header);
|
|
|
|
$email = Cache::get("sipa_token:{$token}");
|
|
|
|
if ($email) {
|
|
Cache::forget("sipa_token:{$token}");
|
|
Cache::forget("sipa_user_token:{$email}");
|
|
}
|
|
|
|
return response()->json([
|
|
'message' => 'Sesión cerrada correctamente'
|
|
]);
|
|
}
|
|
#[OA\Post(
|
|
path: "/api/refresh-sipa",
|
|
summary: "Renovar token",
|
|
security: [["bearerAuth" => []]],
|
|
tags: ["Auth"],
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: "Token renovado",
|
|
content: new OA\JsonContent(
|
|
properties: [
|
|
new OA\Property(property: "access_token", type: "string", example: "nuevo_token..."),
|
|
new OA\Property(property: "token_type", type: "string", example: "Bearer"),
|
|
new OA\Property(property: "expires_in", type: "integer", example: 7200)
|
|
]
|
|
)
|
|
),
|
|
new OA\Response(response: 401, description: "Token inválido o expirado")
|
|
]
|
|
)]
|
|
// 🔹 Refresh
|
|
public function refresh_sipa(Request $request)
|
|
{
|
|
$header = $request->header('Authorization');
|
|
|
|
if (!$header || !str_starts_with($header, 'Bearer ')) {
|
|
return response()->json(['message' => 'Token requerido'], 401);
|
|
}
|
|
|
|
$oldToken = str_replace('Bearer ', '', $header);
|
|
|
|
$email = Cache::get("sipa_token:{$oldToken}");
|
|
|
|
if (!$email) {
|
|
return response()->json(['message' => 'Token inválido o expirado'], 401);
|
|
}
|
|
|
|
Cache::forget("sipa_token:{$oldToken}");
|
|
|
|
$newToken = bin2hex(random_bytes(32));
|
|
$ttl = 120 * 60;
|
|
|
|
Cache::put("sipa_token:{$newToken}", $email, $ttl);
|
|
Cache::put("sipa_user_token:{$email}", $newToken, $ttl);
|
|
|
|
return response()->json([
|
|
'access_token' => $newToken,
|
|
'token_type' => 'Bearer',
|
|
'expires_in' => $ttl
|
|
]);
|
|
}
|
|
} |