first commit
This commit is contained in:
334
app/Http/Controllers/AuthController.php
Normal file
334
app/Http/Controllers/AuthController.php
Normal file
@@ -0,0 +1,334 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Exceptions\Entities\AuthorizationException;
|
||||
use App\Exceptions\Entities\DeprecatedApiException;
|
||||
use App\Helpers\Recaptcha;
|
||||
use App\Http\Requests\Auth\LoginRequest;
|
||||
use App\Http\Transformers\AuthTokenTransformer;
|
||||
use Cache;
|
||||
use Exception;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class AuthController extends BaseController
|
||||
{
|
||||
/**
|
||||
* @apiDefine AuthHeader
|
||||
* @apiHeader {String} Authorization Token for user auth
|
||||
* @apiHeaderExample {json} Authorization Header Example
|
||||
* {
|
||||
* "Authorization": "bearer 16184cf3b2510464a53c0e573c75740540fe..."
|
||||
* }
|
||||
*/
|
||||
|
||||
public function __construct(protected Recaptcha $recaptcha)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} /auth/login Login
|
||||
* @apiDescription Get user Token
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName Login
|
||||
* @apiGroup Auth
|
||||
*
|
||||
* @apiParam {String} email User email
|
||||
* @apiParam {String} password User password
|
||||
* @apiParam {String} [recaptcha] Recaptcha token
|
||||
*
|
||||
* @apiParamExample {json} Request Example
|
||||
* {
|
||||
* "email": "johndoe@example.com",
|
||||
* "password": "amazingpassword",
|
||||
* "recaptcha": "03AOLTBLR5UtIoenazYWjaZ4AFZiv1OWegWV..."
|
||||
* }
|
||||
* @apiUse User
|
||||
* @apiUse 400Error
|
||||
* @apiUse ParamsValidationError
|
||||
* @apiUse UnauthorizedError
|
||||
* @apiUse UserDeactivatedError
|
||||
* @apiUse CaptchaError
|
||||
* @apiUse LimiterError
|
||||
*/
|
||||
public function login(LoginRequest $request): JsonResponse
|
||||
{
|
||||
$credentials = $request->only(['email', 'password', 'recaptcha']);
|
||||
|
||||
$this->recaptcha->check($credentials);
|
||||
|
||||
if (!auth()->attempt([
|
||||
'email' => $credentials['email'],
|
||||
'password' => $credentials['password'],
|
||||
])) {
|
||||
$this->recaptcha->incrementCaptchaAmounts();
|
||||
$this->recaptcha->check($credentials);
|
||||
throw new AuthorizationException(AuthorizationException::ERROR_TYPE_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$user = auth()->user();
|
||||
if (!$user || !$user->active) {
|
||||
$this->recaptcha->incrementCaptchaAmounts();
|
||||
throw new AuthorizationException(AuthorizationException::ERROR_TYPE_USER_DISABLED);
|
||||
}
|
||||
|
||||
if ($user->invitation_sent) {
|
||||
$user->invitation_sent = false;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
$this->recaptcha->clearCaptchaAmounts();
|
||||
|
||||
if (preg_match('/' . config('auth.cattr-client-agent') . '/', $request->header('User_agent'))) {
|
||||
$user->client_installed = 1;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
return responder()->success([
|
||||
'token' => $user->createToken(Str::uuid())->plainTextToken,
|
||||
], new AuthTokenTransformer)->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} /auth/logout Logout
|
||||
* @apiDescription Invalidate current token
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName Logout
|
||||
* @apiGroup Auth
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
*
|
||||
* @apiSuccessExample {json} Response Example
|
||||
* HTTP/1.1 204 OK
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse UnauthorizedError
|
||||
*/
|
||||
public function logout(Request $request): JsonResponse
|
||||
{
|
||||
$request->user()->currentAccessToken()->delete();
|
||||
|
||||
return responder()->success()->respond(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} /auth/logout-from-all Logout from all
|
||||
* @apiDescription Invalidate all user tokens
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName Logout all
|
||||
* @apiGroup Auth
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
*
|
||||
* @apiSuccessExample {json} Response Example
|
||||
* HTTP/1.1 204 OK
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse UnauthorizedError
|
||||
*/
|
||||
public function logoutFromAll(Request $request): JsonResponse
|
||||
{
|
||||
$request->user()->tokens()->delete();
|
||||
|
||||
return responder()->success()->respond(204);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} /auth/me Me
|
||||
* @apiDescription Get authenticated User Entity
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName Me
|
||||
* @apiGroup Auth
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
*
|
||||
* @apiSuccess {Integer} id ID of the user
|
||||
* @apiSuccess {String} full_name Full name of the user
|
||||
* @apiSuccess {String} email Email of the user
|
||||
* @apiSuccess {String} [url] URL of the user (optional)
|
||||
* @apiSuccess {Integer} company_id Company ID of the user
|
||||
* @apiSuccess {String} [avatar] Avatar URL of the user (optional)
|
||||
* @apiSuccess {Boolean} screenshots_active Indicates if screenshots are active
|
||||
* @apiSuccess {Boolean} manual_time Indicates if manual time tracking is allowed
|
||||
* @apiSuccess {Integer} computer_time_popup Time interval for computer time popup
|
||||
* @apiSuccess {Boolean} blur_screenshots Indicates if screenshots are blurred
|
||||
* @apiSuccess {Boolean} web_and_app_monitoring Indicates if web and app monitoring is enabled
|
||||
* @apiSuccess {Integer} screenshots_interval Interval for taking screenshots
|
||||
* @apiSuccess {Boolean} active Indicates if the user is active
|
||||
* @apiSuccess {String} [deleted_at] Deletion timestamp (if applicable, otherwise null)
|
||||
* @apiSuccess {String} created_at Creation timestamp
|
||||
* @apiSuccess {String} updated_at Last update timestamp
|
||||
* @apiSuccess {String} [timezone] Timezone of the user (optional)
|
||||
* @apiSuccess {Boolean} important Indicates if the user is marked as important
|
||||
* @apiSuccess {Boolean} change_password Indicates if the user needs to change password
|
||||
* @apiSuccess {Integer} role_id Role ID of the user
|
||||
* @apiSuccess {String} user_language Language of the user
|
||||
* @apiSuccess {String} type Type of the user (e.g., "employee")
|
||||
* @apiSuccess {Boolean} invitation_sent Indicates if invitation is sent to the user
|
||||
* @apiSuccess {Integer} nonce Nonce value of the user
|
||||
* @apiSuccess {Boolean} client_installed Indicates if client is installed
|
||||
* @apiSuccess {Boolean} permanent_screenshots Indicates if screenshots are permanent
|
||||
* @apiSuccess {String} last_activity Last activity timestamp of the user
|
||||
* @apiSuccess {Boolean} online Indicates if the user is online
|
||||
* @apiSuccess {Boolean} can_view_team_tab Indicates if the user can view team tab
|
||||
* @apiSuccess {Boolean} can_create_task Indicates if the user can create tasks
|
||||
*
|
||||
* @apiSuccessExample {json} Response Example:
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "id": 1,
|
||||
* "full_name": "Admin",
|
||||
* "email": "admin@cattr.app",
|
||||
* "url": "",
|
||||
* "company_id": 1,
|
||||
* "avatar": "",
|
||||
* "screenshots_active": 1,
|
||||
* "manual_time": 0,
|
||||
* "computer_time_popup": 300,
|
||||
* "blur_screenshots": false,
|
||||
* "web_and_app_monitoring": true,
|
||||
* "screenshots_interval": 5,
|
||||
* "active": 1,
|
||||
* "deleted_at": null,
|
||||
* "created_at": "2023-10-26T10:26:17.000000Z",
|
||||
* "updated_at": "2024-02-15T19:06:42.000000Z",
|
||||
* "timezone": null,
|
||||
* "important": 0,
|
||||
* "change_password": 0,
|
||||
* "role_id": 0,
|
||||
* "user_language": "en",
|
||||
* "type": "employee",
|
||||
* "invitation_sent": false,
|
||||
* "nonce": 0,
|
||||
* "client_installed": 0,
|
||||
* "permanent_screenshots": 0,
|
||||
* "last_activity": "2023-10-26 10:26:17",
|
||||
* "online": false,
|
||||
* "can_view_team_tab": true,
|
||||
* "can_create_task": true
|
||||
* }
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse UnauthorizedError
|
||||
*/
|
||||
public function me(Request $request): JsonResponse
|
||||
{
|
||||
return responder()->success($request->user())->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} /auth/desktop-key Issue key
|
||||
* @apiDescription Issues key for desktop auth
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName Issue key
|
||||
* @apiGroup Auth
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
* @apiUse User
|
||||
* @apiUse UnauthorizedError
|
||||
*/
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws Exception
|
||||
*/
|
||||
public function issueDesktopKey(Request $request): JsonResponse
|
||||
{
|
||||
$token = Str::random(40);
|
||||
|
||||
$lifetime = now()->addMinutes(config('auth.lifetime_minutes.desktop_token'));
|
||||
|
||||
Cache::store('octane')->put(
|
||||
sha1($request->ip()) . ":$token",
|
||||
$request->user()->id,
|
||||
$lifetime,
|
||||
);
|
||||
return responder()->success([
|
||||
'token' => $token,
|
||||
'type' => 'desktop',
|
||||
'expires' => now()->addMinutes(config('auth.lifetime_minutes.desktop_token'))->toIso8601String(),
|
||||
], new AuthTokenTransformer)->meta(['frontend_uri' => config('app.frontend_url')])->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {put} /auth/desktop-key Key auth
|
||||
* @apiDescription Exchange desktop key to JWT
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName Key auth
|
||||
* @apiGroup Auth
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
* @apiUse User
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse UnauthorizedError
|
||||
*/
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws Exception
|
||||
*/
|
||||
public function authDesktopKey(Request $request): JsonResponse
|
||||
{
|
||||
$token = $request->header('Authorization');
|
||||
|
||||
if (!$token) {
|
||||
throw new AuthorizationException(AuthorizationException::ERROR_TYPE_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$token = explode(' ', $token);
|
||||
|
||||
if (count($token) !== 2 || $token[0] !== 'desktop' || !Cache::store('octane')->has(sha1($request->ip()) . ":$token[1]")) {
|
||||
throw new AuthorizationException(AuthorizationException::ERROR_TYPE_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$user = auth()->loginUsingId(Cache::store('octane')->get(sha1($request->ip()) . ":$token[1]"));
|
||||
|
||||
if (!optional($user)->active) {
|
||||
throw new AuthorizationException(AuthorizationException::ERROR_TYPE_USER_DISABLED);
|
||||
}
|
||||
|
||||
return responder()->success([
|
||||
'token' => $user->createToken(Str::uuid())->plainTextToken,
|
||||
], new AuthTokenTransformer)->respond();
|
||||
}
|
||||
|
||||
/**
|
||||
* @apiDeprecated Exists only for compatibility with old Cattr client
|
||||
* @api {post} /auth/refresh Refresh
|
||||
* @apiDescription Refreshes JWT
|
||||
*
|
||||
* @apiVersion 4.0.0
|
||||
* @apiName Refresh
|
||||
* @apiGroup Auth
|
||||
*
|
||||
* @apiUse AuthHeader
|
||||
*
|
||||
* @apiSuccess {String} access_token Token
|
||||
* @apiSuccess {String} token_type Token Type
|
||||
* @apiSuccess {String} expires_in Token TTL 8601String Date
|
||||
*
|
||||
* @apiUse 400Error
|
||||
* @apiUse UnauthorizedError
|
||||
*/
|
||||
|
||||
/**
|
||||
* @return JsonResponse
|
||||
* @deprecated Exists only for compatibility with old Cattr client
|
||||
*/
|
||||
public function refresh(): JsonResponse
|
||||
{
|
||||
throw new DeprecatedApiException();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user