Your IP : 216.73.216.79


Current Path : /var/www/html/ebookingdbkl/frontend/controllers/
Upload File :
Current File : /var/www/html/ebookingdbkl/frontend/controllers/AuthController.php

<?php

namespace frontend\controllers;

use Yii;
use common\models\FrontendUser;
use yii\filters\VerbFilter;
use yii\web\Response;
use common\models\Notification;

class AuthController extends \yii\web\Controller
{
	public function beforeAction($action)
	{
	    \Yii::$app->response->format = Response::FORMAT_JSON;
	    return parent::beforeAction($action);
	}

    public function behaviors() {
		return [
		 	'authenticator' => [
				'class' => \sizeg\jwt\JwtHttpBearerAuth::class,
				'except' => [
					'login',
					'refresh-token',
					'options',
					'forget-password'
				],
			],
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'refresh-token' => ['post'],
                    'login' => ['post'],
                    'change-password' => ['post'],
                ],
            ],
        ];
	}
	
	public $enableCsrfValidation = false;
	

    public function actionChangePassword() {
        
        try {
            $user = FrontendUser::findOne(Yii::$app->user->id);
            $pass = isset($_POST['password']) ? $_POST['password'] : null;
    	
    	    if(empty($user)) {
    	        throw new \Exception('User does not exist');
    	    }
    	    
    	    if(empty($pass)) {
    	       throw new \Exception('password is required.');
    	    }
    	    
    	    $user->password_hash = Yii::$app->getSecurity()->generatePasswordHash($pass);
    	    
    	    if(!$user->save()) {
    	        throw new \Exception('Model Error :-' .  json_encode($user->errors));
    	    }
    	    
    	    return [
    	     'success' => true,
    	     'user_id' => Yii::$app->user->id
    	   ];
    	    
        } catch (\Throwable $t) {
            Yii::$app->response->statusCode = 500;
            return [
                'success' => false,
                'message' => $t->getMessage(),
            ];
        }
    }
    
    public function actionForgetPassword() {
        try {
            $empno = isset($_POST['emp_no']) ? $_POST['emp_no'] : null;
            
            if(empty($empno)) {
    	       throw new \Exception('emp_no / ic number is required.');
    	    }
    	    
            $user = FrontendUser::find()->where(['emp_no' => $empno])->one();

            if(empty($user)) {
				$user = FrontendUser::find()->where(['ic_number' => $empno])->one();
            }
    	
    	    if(empty($user)) {
    	        throw new \Exception('User does not exist');
    	    }
    	    
    	    if(empty($user->email)) {
    	        throw new \Exception('User does not have an email.');
    	    }
    	    
    	    $pass = Yii::$app->security->generateRandomString(8);
    	    $user->password_hash = Yii::$app->getSecurity()->generatePasswordHash($pass);
    	    
    	    if(!$user->save()) {
    	        throw new \Exception('Model Error :-' .  json_encode($user->errors));
    	    }
    	    
    	    
    	    //email
    	    Notification::email(0000, 'F_PASS', 
    	    	[
    	    		'subject' => 'Lupa kata laluan',
    	    		'content' => 'Salam Sejahtera '. $user->fullname .', Kata laluan telah di tukar kepada:- '. $pass . ' , Sila tukar kata laluan anda setelah anda berjaya log masuk.'
    	    	],
    	    	$user->email
    	    );
    	    
    	    return [
    	     'success' => true,
    	     'user_id' => $user->id,
    	     'email' => $user->email
    	   ];
    	    
        } catch (\Throwable $t) {
            Yii::$app->response->statusCode = 500;
            return [
                'success' => false,
                'message' => $t->getMessage(),
            ];
        }
    }
    
    private function generateJwt(\common\models\FrontendUser  $user) {
		$jwt = Yii::$app->jwt;
		$signer = $jwt->getSigner('HS256');
		$key = $jwt->getKey();
		$time = time();

		$jwtParams = Yii::$app->params['jwt'];

		return $jwt->getBuilder()
			->issuedBy($jwtParams['issuer'])
			->permittedFor($jwtParams['audience'])
			->identifiedBy($jwtParams['id'], true)
			->issuedAt($time)
			->expiresAt($time + $jwtParams['expire'])
			->withClaim('uid', $user->id)
			->getToken($signer, $key);
	}

	/**
	 * @throws yii\base\Exception
	 */
	private function generateRefreshToken(\common\models\FrontendUser  $user, \common\models\FrontendUser  $impersonator = null): \frontend\models\UserRefreshToken {
		$refreshToken = Yii::$app->security->generateRandomString(200);

		// TODO: Don't always regenerate - you could reuse existing one if user already has one with same IP and user agent
		$userRefreshToken = new \frontend\models\UserRefreshToken([
			'urf_userID' => $user->id,
			'urf_token' => $refreshToken,
			'urf_ip' => Yii::$app->request->userIP,
			'urf_user_agent' => Yii::$app->request->userAgent,
			'urf_created' => gmdate('Y-m-d H:i:s'),
		]);
		if (!$userRefreshToken->save()) {
			throw new \yii\web\ServerErrorHttpException('Failed to save the refresh token: '. $userRefreshToken->getErrorSummary(true));
		}

		// Send the refresh-token to the user in a HttpOnly cookie that Javascript can never read and that's limited by path
		Yii::$app->response->cookies->add(new \yii\web\Cookie([
			'name' => 'refresh-token',
			'value' => $refreshToken,
			'httpOnly' => true,
			'sameSite' => 'none',
			'secure' => true,
			'path' => '/auth/refresh-token',  //endpoint URI for renewing the JWT token using this refresh-token, or deleting refresh-token
		]));

		return $userRefreshToken;
	}
	
	public function actionLogin() {
		 if(isset($_POST) && !empty($_POST)) {
		    $_POST = filter_var_array($_POST, FILTER_SANITIZE_STRING);

            $model = new \common\models\FrontendLoginForm();
            $model->username = $_POST['username'];
            $model->password = $_POST['password'];

            
            if (!$model->login()) {
            	Yii::$app->response->statusCode = 401; // forbiden

                return $this->asJson([
					'success' => false,
					'message' => 'Invalid Login / Password.'
				]);
            }
            
			$user = Yii::$app->user->identity;

			$token = $this->generateJwt($user);

			$this->generateRefreshToken($user);

			return $this->asJson([
				'success' => true,
				'user' => $user,
				'token' => (string) $token,
			]);
		} else {
			return $this->asJson($model->getFirstErrors());
		}
	}
	
	public function actionRefreshToken() {
		$refreshToken = Yii::$app->request->cookies->getValue('refresh-token', false);
		if (!$refreshToken) {
			return new \yii\web\UnauthorizedHttpException('No refresh token found.');
		}

		$userRefreshToken = \frontend\models\UserRefreshToken::findOne(['urf_token' => $refreshToken]);

		if (Yii::$app->request->getMethod() == 'POST') {
			// Getting new JWT after it has expired
			if (!$userRefreshToken) {
				return new \yii\web\UnauthorizedHttpException('The refresh token no longer exists.');
			}

			$user = \common\models\FrontendUser::find()  //adapt this to your needs
				->where(['id' => $userRefreshToken->urf_userID])
				->andWhere(['not', ['status' => 'inactive']]) // change to proper status after the development
				->one();
			if (!$user) {
				$userRefreshToken->delete();
				return new \yii\web\UnauthorizedHttpException('The user is inactive.');
			}

			$token = $this->generateJwt($user);

			$this->asJson([
				'success' => true,
				'token' => (string) $token,
			]);

		} elseif (Yii::$app->request->getMethod() == 'DELETE') {
			// Logging out
			if ($userRefreshToken && !$userRefreshToken->delete()) {
				return new \yii\web\ServerErrorHttpException('Failed to delete the refresh token.');
			}

			return $this->asJson([
				'success' => true
			]);
		} else {
			
			return $this->asJson([
				'success' => false,
				'message' => 'The user is inactive.'
			]);
		}
	}
	
	public function afterSave($isInsert, $changedOldAttributes) {
		// Purge the user tokens when the password is changed
		if (array_key_exists('usr_password', $changedOldAttributes)) {
			\frontend\models\UserRefreshToken::deleteAll(['urf_userID' => $this->userID]);
		}

		return parent::afterSave($isInsert, $changedOldAttributes);
	}
}