Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 277
AuthActivityService
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 11
3782.00
0.00% covered (danger)
0.00%
0 / 277
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 __clone
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 2
 getInstance
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 5
 createOrUpdateAuthActivityLog
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 20
 createAuthActivity
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 17
 updateAuthActivity
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 17
 generateAuthActivityMessage
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 22
 searchUserAuthLogActivity
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 53
 exportLoginActivity
0.00% covered (danger)
0.00%
0 / 1
132.00
0.00% covered (danger)
0.00%
0 / 83
 getColumnValue
0.00% covered (danger)
0.00%
0 / 1
156.00
0.00% covered (danger)
0.00%
0 / 31
 getLastExportedExcel
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 24
<?php
namespace com\linways\core\ams\professional\service;
use com\linways\base\util\SecurityUtils;
use com\linways\core\ams\professional\constant\AuthActions;
use com\linways\core\ams\professional\constant\ResourceContext;
use com\linways\core\ams\professional\constant\UserType;
use com\linways\core\ams\professional\dto\AsyncReport;
use com\linways\core\ams\professional\dto\AuthActivityLog;
use com\linways\core\ams\professional\exception\ProfessionalException;
use com\linways\core\ams\professional\mapper\AuthActivityServiceMapper;
use com\linways\core\ams\professional\request\AddAuthActivityLogRequest;
use com\linways\core\ams\professional\request\AsyncReportDeleteRequest;
use com\linways\core\ams\professional\request\ExportAllLoginActivityRequest;
use com\linways\core\ams\professional\request\GenerateReportAndUploadRequest;
use com\linways\core\ams\professional\request\GetPreSignedUrlRequest;
use com\linways\core\ams\professional\request\SearchUserAuthLogActivityRequest;
use com\linways\core\ams\professional\response\LoginActivityResponse;
use com\linways\core\ams\professional\util\ExportExcelAndUploadUtil;
/**
 *
 * @Date 28/04/20
 * @author  JithinVijayan <jithin@linways.com>
 */
class AuthActivityService extends BaseService
{
    /**
     * Presence of a static member variable
     *
     * @var null
     */
    private static $_instance = null;
    /**
     * Mapper variable
     * @var array
     */
    private $mapper = [];
    /**
     * Initialise mapper, logger, hooks here
     *
     * ReportGenderService constructor.
     */
    private function __construct()
    {
        $this->mapper = AuthActivityServiceMapper::getInstance()->getMapper();
    }
    /**
     * Prevent any object or instance of that class to be cloned
     */
    private function __clone()
    {
    }
    /**
     * Have a single globally accessible static method
     *
     * @return AuthActivityService|null
     */
    public static function getInstance()
    {
        if (!is_object(self::$_instance))
            self::$_instance = new self ();
        return self::$_instance;
    }
    /**
     * @param AddAuthActivityLogRequest $request
     * @return String
     * @throws ProfessionalException
     */
    public function createOrUpdateAuthActivityLog(AddAuthActivityLogRequest $request)
    {
        if (empty($request->action)) {
            throw new ProfessionalException(ProfessionalException::INVALID_AUTH_ACTION, "Invalid action");
        }
        if (!in_array($request->userType, [UserType::STUDENT, UserType::STAFF])) {
            throw new ProfessionalException(ProfessionalException::INVALID_USER_TYPE, "Invalid user type details given");
        }
        if (empty($request->userId)) {
            throw new ProfessionalException(ProfessionalException::INVALID_USER_ID, "Invalid user details given");
        }
        try {
            if (!empty($request->authLogId)) {
                return $this->updateAuthActivity($request);
            } else {
                return $this->createAuthActivity($request);
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * Creating activity log
     * @param AddAuthActivityLogRequest $request
     * @return String
     * @throws ProfessionalException
     */
    private function createAuthActivity(AddAuthActivityLogRequest $request)
    {
        $id = SecurityUtils::getRandomString();
        try {
            $activity = new \stdClass();
            $activity->message = $this->generateAuthActivityMessage($request->action);
            $activity->action = $request->action;
            $activity->time = date("d-m-Y h:i:s A");
            $activities = [$activity];
            $activities = json_encode($activities);
            $sql = "INSERT INTO lin_auth_log (id, user_id, user_type, auth_activity, created_date, updated_date) 
                VALUES ('$id',$request->userId,'$request->userType','$activities',UTC_TIMESTAMP(),UTC_TIMESTAMP())";
            $this->executeQueryForObject($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $id;
    }
    /**
     * Updating auth log table by pushing activity to the log json
     *
     * @param AddAuthActivityLogRequest $request
     * @return string
     * @throws ProfessionalException
     */
    private function updateAuthActivity(AddAuthActivityLogRequest $request)
    {
        try {
            $activity = new \stdClass();
            $activity->message = $this->generateAuthActivityMessage($request->action);
            $activity->action = $request->action;
            $activity->time = date("d-m-Y h:i:s A");
            $activity = json_encode($activity);
            $sql = "UPDATE lin_auth_log 
                    SET auth_activity = JSON_ARRAY_APPEND(auth_activity,'$',CAST('$activity' AS JSON)),
                    updated_date =UTC_TIMESTAMP()    
                    WHERE id = '$request->authLogId'";
            $this->executeQuery($sql);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $request->authLogId;
    }
    /**
     * @param $action
     * @return string
     * @throws ProfessionalException
     */
    private function generateAuthActivityMessage($action)
    {
        switch ($action) {
            case AuthActions::OTP_CREATION_FAILED:
                return "OTP created successfully";
            case AuthActions::OTP_SEND:
                return "OTP send successfully";
            case AuthActions::OTP_VERIFICATION_FAILED:
                return "OTP verification failed";
            case AuthActions::OTP_SENDING_FAILED:
                return "OTP sending failed";
            case AuthActions::OTP_VERIFIED:
                return "OTP verified successfully";
            case AuthActions::USER_CREDENTIALS_VERIFIED:
                return "User credentials verified successfully";
            case AuthActions::OTP_RESENT:
                return "Resent OTP initiated";
            case AuthActions::USER_LOGIN_PREVENTED:
                return "User login prevented by administrator";
            default:
                throw new ProfessionalException(ProfessionalException::INVALID_AUTH_ACTION, "Invalid auth action given");
        }
    }
    /**
     * @param SearchUserAuthLogActivityRequest $request
     * @return LoginActivityResponse|object
     * @throws ProfessionalException
     */
    public function searchUserAuthLogActivity(SearchUserAuthLogActivityRequest $request)
    {
        $staffUserType = UserType::STAFF;
        $studentUserType = UserType::STUDENT;
        $limitQuery = "";
        $conditions = "";
        $limitConditions = "";
        if (!empty($request->userId)) {
            $conditions .= " AND lal.user_id = $request->userId ";
            $limitConditions .= " AND user_id = $request->userId ";
        }
        if (!empty($request->userType)) {
            $conditions .= " AND lal.user_type = '$request->userType";
            $limitConditions .= " AND user_type = '$request->userType'";
        }
        if (!empty($request->startDate) && !empty($request->endDate)) {
            $request->startDate = date("Y-m-d H:i:s", strtotime($request->startDate));
            $request->endDate = date("Y-m-d H:i:s", strtotime($request->endDate));
            $conditions .= " AND lal.created_date BETWEEN '$request->startDate' AND  '$request->endDate'";
            $limitConditions .= " AND created_date BETWEEN '$request->startDate' AND  '$request->endDate'";
        }
        if (!empty($request->deptId)) {
            $conditions .= " AND d.deptID = $request->deptId ";
        }
        if(!empty($request->staffId)) {
            $conditions .= " AND sa.staffID = $request->staffId ";
        }
        if ($request->addPagination) {
            $limitQuery = " INNER JOIN (SELECT id FROM lin_auth_log WHERE 1=1 $limitConditions 
                            ORDER BY created_date DESC LIMIT $request->startIndex,$request->endIndex ) 
                            AS temp ON temp.id = lal.id ";
        }
        $response = new LoginActivityResponse();
        $sql = "SELECT lal.id,auth_activity,staffID as staff_id,staffName as staff_name, d.deptName as department_name,
                sa.staffCode as staff_code,st.studentID as student_id,st.studentName as student_name,
                b.batchName as batch_name, st.regNo as student_register_number,
                DATE_FORMAT(CONVERT_TZ(lal.created_date,'+00:00',@@global.time_zone),'%d-%m-%Y %h:%i:%s %p') as created_date
                FROM lin_auth_log lal 
                $limitQuery
                LEFT JOIN staffaccounts sa ON sa.staffID = lal.user_id AND lal.user_type ='$staffUserType'
                LEFT JOIN studentaccount st ON st.studentID = lal.user_id AND  lal.user_type = '$studentUserType'
                LEFT JOIN department d ON d.deptID =sa.deptID
                LEFT JOIN batches b ON b.batchID =st.batchID
                WHERE 1=1 $conditions ORDER BY lal.created_date DESC";
        $totalSql = "SELECT COUNT(id) as totalRecords 
                    FROM lin_auth_log WHERE 1=1 $limitConditions";
        try {
            $response->totalRecords = (int)$this->executeQueryForObject($totalSql)->totalRecords;
            $response->loginActivities = $this->executeQueryForList($sql, $this->mapper[AuthActivityServiceMapper::SEARCH_AUTH_ACTIVITY_LOG]);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return $response;
    }
    /**
     * @param ExportAllLoginActivityRequest $request
     * @throws ProfessionalException
     */
    public function exportLoginActivity($request)
    {
        try {
            $awsSecretKey = SecurityUtils::decryptAndVerify($request->awsSecretKey, '1162a2a3dcf2d18d16a873a74fc801qw');
            $awsAccessKey = SecurityUtils::decryptAndVerify($request->awsAccessKey, '1162a2a3dcf2d18d16a873a74fc801qw');
            $awsBucket = SecurityUtils::decryptAndVerify($request->awsBucketName, '1162a2a3dcf2d18d16a873a74fc801qw');
            $removeRequest = new AsyncReportDeleteRequest();
            $removeRequest->context = ResourceContext::STAFF_LOGIN_ACTIVITY_REPORT;
            $removeRequest->toDate = date('Y-m-d');
            $removeRequest->awsAccessKey = $awsAccessKey;
            $removeRequest->awsClientSecretKey = $awsSecretKey;
            AsyncReportService::getInstance()->deleteAsyncReport($removeRequest);
            /**
             * Fetching report data from the database
             */
            $getDataRequest = new SearchUserAuthLogActivityRequest();
            $getDataRequest->startDate = $request->startDate;
            $getDataRequest->endDate = $request->endDate;
            $getDataRequest->userType = UserType::STAFF;
            $getDataRequest->addPagination = false;
            $response = AuthActivityService::getInstance()->searchUserAuthLogActivity($getDataRequest);
            $formats = CommonService::getInstance()->getSettings("AUTH_ACTIVITY_LOG", "AUTH_ACTIVITY_LOG_REPORT_FORMAT");
            $formats = json_decode($formats);
            $defaultFormat = null;
            foreach ($formats as $format) {
                if ($format->default) {
                    $defaultFormat = $format;
                    break;
                }
            }
            if (empty($defaultFormat)) {
                throw new ProfessionalException(ProfessionalException::REPORT_FORMAT_NOT_CONFIGURED, "Report format not configured");
            }
            $loginActivities = [];
            foreach ($response->loginActivities as $activity) {
                $loginActivity = new \stdClass();
                $loginActivity->staff = $activity->staff;
                $loginActivity->id = $activity->id;
                $loginActivity->student = $activity->student;
                $createdDate = new \DateTime($activity->createdDate);
                $loginActivity->createdDate = $createdDate->format("d-m-Y h:i:s A");
                $loginActivity->logs = [];
                foreach ($defaultFormat->fields as $field) {
                    if ($field->action === "COLUMN_OPERATION") {
                        $formattedLog = new \stdClass();
                        $formattedLog->action = $field->action;
                        $formattedLog->value = $this->getColumnValue($activity, $field);
                        $loginActivity->logs[] = $formattedLog;
                    } else {
                        $isFieldFound = false;
                        foreach ($activity->activityLogs as $log) {
                            if ($log->action === $field->action) {
                                $dateTime = new \DateTime($log->time);
                                $formattedLog = new \stdClass();
                                $formattedLog->action = $field->action;
                                $formattedLog->value = $dateTime->format("h:i:s A");
                                $loginActivity->logs[] = $formattedLog;
                                $isFieldFound = true;
                                break;
                            }
                        }
                        if (!$isFieldFound) {
                            $formattedLog = new \stdClass();
                            $formattedLog->action = $field->action;
                            $formattedLog->value = "-";
                            $loginActivity->logs[] = $formattedLog;
                        }
                    }
                }
                $loginActivities[] = $loginActivity;
            }
            /**
             * Generating excels and uploading
             */
            $exportRequest = new GenerateReportAndUploadRequest();
            $exportRequest->asyncReportId = $request->asyncReportId;
            $exportRequest->createdBy = $request->createdBy;
            $exportRequest->updatedBy = $request->updatedBy;
            $exportRequest->templateName = "exports/export_staff_auth_activity.twig";
            $exportRequest->context = ResourceContext::STAFF_LOGIN_ACTIVITY_REPORT;
            $exportRequest->awsAccessKey = $awsAccessKey;
            $exportRequest->awsSecretKey = $awsSecretKey;
            $exportRequest->awsBucketName = $awsBucket;
            $exportRequest->twigData = ["loginActivities" => $loginActivities, "format" => $defaultFormat];
            $exportRequest->reportName = $request->reportName;
            ExportExcelAndUploadUtil::generateReportAndUpload($exportRequest);
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
    /**
     * @param $activityLog
     * @param $field
     * @return string
     * @throws ProfessionalException
     */
    private function getColumnValue($activityLog, $field)
    {
        $lOperand = null;
        $rOperand = null;
        foreach ($activityLog->activityLogs as $log) {
            if ($log->action === $field->loperand && empty($lOperand)) {
                $lOperand = $log;
            }
            if ($log->action === $field->roperand && empty($rOperand)) {
                $rOperand = $log;
            }
            if (!empty($lOperand) && !empty($rOperand)) {
                break;
            }
        }
        try {
            if ($lOperand && $rOperand) {
                switch ($field->operator) {
                    case "SUBTRACT":
                        $firstDate = new \DateTime($lOperand->time);
                        $secondDate = new \DateTime($rOperand->time);
                        $interval = $firstDate->diff($secondDate);
                        return $interval->format("%h:%i:%s");
                    default:
                        throw new ProfessionalException(ProfessionalException::REPORT_FORMAT_NOT_CONFIGURED, "Report format not configured properly");
                }
            }
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
        return "-";
    }
    /**
     * @param bool $generateUrl
     * @return Object|null
     * @throws ProfessionalException
     */
    public function getLastExportedExcel($generateUrl = false)
    {
        $context = ResourceContext::STAFF_LOGIN_ACTIVITY_REPORT;
        $sql = "SELECT ar.id,ar.report_details as reportDetails,lr.path,lr.id as resourceId,DATE_FORMAT(ar.created_date,'%d-%m-%Y') as createdDate 
                FROM async_reports ar
                LEFT JOIN lin_resource lr ON ar.lin_resource_id = lr.id
                WHERE ar.context ='$context' ORDER BY ar.updated_date DESC";
        try {
            $exportedExcel = $this->executeQueryForObject($sql);
            if ($generateUrl && $exportedExcel && !empty($exportedExcel->resourceId)) {
                $request = new GetPreSignedUrlRequest();
                $request->accessKey = getenv('AWS_ACCESS_KEY');
                $request->secretKey = getenv('AWS_CLIENT_SECRET_KEY');
                $request->resourceId = $exportedExcel->resourceId;
                $response = ResourceService::getInstance()->getPreSignedUrlByResourceId($request);
                $exportedExcel->url = $response->url;
                return $exportedExcel;
            } elseif ($exportedExcel) {
                return $exportedExcel;
            }
            return null;
        } catch (\Exception $e) {
            throw new ProfessionalException($e->getCode(), $e->getMessage());
        }
    }
}