TimeTrex/classes/modules/users/UserIdentificationFactory.class.php

369 lines
11 KiB
PHP
Raw Permalink Normal View History

2022-12-13 07:10:06 +01:00
<?php
/*********************************************************************************
*
* TimeTrex is a Workforce Management program developed by
* TimeTrex Software Inc. Copyright (C) 2003 - 2021 TimeTrex Software Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY TIMETREX, TIMETREX DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
*
* You should have received a copy of the GNU Affero General Public License along
* with this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
*
* You can contact TimeTrex headquarters at Unit 22 - 2475 Dobbin Rd. Suite
* #292 West Kelowna, BC V4T 2E9, Canada or at email address info@timetrex.com.
*
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by TimeTrex" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by TimeTrex".
*
********************************************************************************/
/**
* @package Modules\Users
*/
class UserIdentificationFactory extends Factory {
protected $table = 'user_identification';
protected $pk_sequence_name = 'user_identification_id_seq'; //PK Sequence name
var $user_obj = null;
/**
* @param $name
* @param null $parent
* @return array|null
*/
function _getFactoryOptions( $name, $parent = null ) {
$retval = null;
switch ( $name ) {
case 'type':
$retval = [
1 => TTi18n::gettext( 'Employee Sequence' ), //Company specific employee sequence number, primarily for timeclocks. Should be less than 65535.
5 => TTi18n::gettext( 'Password History' ), //Web interface password history
10 => TTi18n::gettext( 'iButton' ),
20 => TTi18n::gettext( 'USB Fingerprint' ), //Biometric Data -- This is purged when employees are terminated.
30 => TTi18n::gettext( 'Barcode' ), //For barcode readers and USB proximity card readers.
35 => TTi18n::gettext( 'QRcode' ), //For cameras to read QR code badges.
40 => TTi18n::gettext( 'Proximity Card' ), //Mainly for proximity cards on timeclocks.
//
//Biometric data -- This is purged when employees are terminated.
//
70 => TTi18n::gettext( 'Face Image (v1)' ), //Raw image of cropped face in as high of quality as possible, and cropped 10-20% larger than the face itself.
71 => TTi18n::gettext( 'Face Image (v2)' ), //Raw image of cropped face in as high of quality as possible, and cropped 10-20% larger than the face itself.
75 => TTi18n::gettext( 'Facial Recognition' ), //Luxand v5 SDK templates.
76 => TTi18n::gettext( 'Facial Recognition (v2)' ), //Luxand v6.1 SDK templates, App v4.0+
77 => TTi18n::gettext( 'Facial Recognition (v3)' ), //Luxand v7 SDK templates, App v4.5+
//78 => TTi18n::gettext( 'Facial Recognition (v4)' ), //Luxand vX SDK templates, App vX.X+ -- Future use.
//79-90 -- Luxand SDK versions.
100 => TTi18n::gettext( 'TimeClock FingerPrint (v9)' ), //TimeClocks v9 algo
101 => TTi18n::gettext( 'TimeClock FingerPrint (v10)' ), //TimeClocks v10 algo
//
//Biometric data -- This is purged when employees are terminated.
//
];
break;
}
return $retval;
}
/**
* @return null
*/
function getUserObject() {
if ( is_object( $this->user_obj ) ) {
return $this->user_obj;
} else {
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
$this->user_obj = $ulf->getById( $this->getUser() )->getCurrent();
return $this->user_obj;
}
}
/**
* @return bool|mixed
*/
function getUser() {
return $this->getGenericDataValue( 'user_id' );
}
/**
* @param string $value UUID
* @return bool
*/
function setUser( $value ) {
$value = TTUUID::castUUID( $value );
return $this->setGenericDataValue( 'user_id', $value );
}
/**
* @return bool|int
*/
function getType() {
return $this->getGenericDataValue( 'type_id' );
}
/**
* @param $value
* @return bool
*/
function setType( $value ) {
$value = (int)trim( $value );
//This needs to be stay as TimeTrex Client application still uses names rather than IDs.
$key = Option::getByValue( $value, $this->getOptions( 'type' ) );
if ( $key !== false ) {
$value = $key;
}
return $this->setGenericDataValue( 'type_id', $value );
}
/*
For fingerprints,
10 = Fingerprint 1 Pass 0.
11 = Fingerprint 1 Pass 1.
12 = Fingerprint 1 Pass 2.
20 = Fingerprint 2 Pass 0.
21 = Fingerprint 2 Pass 1.
...
*/
/**
* @return bool|mixed
*/
function getNumber() {
return $this->getGenericDataValue( 'number' );
}
/**
* @param $value
* @return bool
*/
function setNumber( $value ) {
$value = trim( $value );
//Pull out only digits
$value = $this->Validator->stripNonNumeric( $value );
return $this->setGenericDataValue( 'number', $value );
}
/**
* @param string $user_id UUID
* @param int $type_id
* @param $value
* @return bool
*/
function isUniqueValue( $user_id, $type_id, $value ) {
$ph = [
'user_id' => TTUUID::castUUID( $user_id ),
'type_id' => (int)$type_id,
'value' => (string)$value,
];
$uf = TTnew( 'UserFactory' ); /** @var UserFactory $uf */
$query = 'select a.id
from ' . $this->getTable() . ' as a,
' . $uf->getTable() . ' as b
where a.user_id = b.id
AND b.company_id = ( select z.company_id from ' . $uf->getTable() . ' as z where z.id = ? and z.deleted = 0 )
AND a.type_id = ?
AND a.value = ?
AND ( a.deleted = 0 AND b.deleted = 0 )';
$id = $this->db->GetOne( $query, $ph );
//Debug::Arr($id, 'Unique Value: '. $value, __FILE__, __LINE__, __METHOD__, 10);
if ( $id === false ) {
return true;
} else {
if ( $id == $this->getId() ) {
return true;
}
}
return false;
}
/**
* @return bool|mixed
*/
function getValue() {
return $this->getGenericDataValue( 'value' );
}
/**
* @param $value
* @return bool
*/
function setValue( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'value', $value );
}
/**
* @return bool|mixed
*/
function getExtraValue() {
return $this->getGenericDataValue( 'extra_value' );
}
/**
* @param $value
* @return bool
*/
function setExtraValue( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'extra_value', $value );
}
/**
* @param bool $ignore_warning
* @return bool
*/
function Validate( $ignore_warning = true ) {
//
// BELOW: Validation code moved from set*() functions.
//
// User
if ( $this->getUser() != TTUUID::getZeroID() ) {
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
$this->Validator->isResultSetWithRows( 'user',
$ulf->getByID( $this->getUser() ),
TTi18n::gettext( 'Invalid Employee' )
);
}
// Type
$this->Validator->inArrayKey( 'type',
$this->getType(),
TTi18n::gettext( 'Incorrect Type' ),
$this->getOptions( 'type' )
);
// Number
$this->Validator->isFloat( 'number',
$this->getNumber(),
TTi18n::gettext( 'Incorrect Number' )
);
// Value
$this->Validator->isLength( 'value',
$this->getValue(),
TTi18n::gettext( 'Value is too short or too long' ),
1,
1024000 ); //Need relatively large face images.
// Extra Value
if ( $this->getExtraValue() !== false ) {
$this->Validator->isLength( 'extra_value',
$this->getExtraValue(),
TTi18n::gettext( 'Extra Value is too long' ),
1,
1024000
);
}
//
// ABOVE: Validation code moved from set*() functions.
//
if ( $this->getValue() == false ) {
$this->Validator->isTRUE( 'value',
false,
TTi18n::gettext( 'Value is not defined' ) );
} else {
$this->Validator->isTrue( 'value',
$this->isUniqueValue( $this->getUser(), $this->getType(), $this->getValue() ),
TTi18n::gettext( 'Value is already in use, please enter a different one' ) );
}
return true;
}
/**
* @return bool
*/
function preSave() {
if ( $this->getNumber() == '' ) {
$this->setNumber( 0 );
}
return true;
}
/**
* @return bool
*/
function postSave() {
$this->removeCache( $this->getId() );
if ( $this->getDeleted() == false && ( $this->getType() == 70 || $this->getType() == 71 ) ) { //Face Images
if ( ( $this->getType() == 71 && $this->getNumber() == 4 ) || ( $this->getType() == 70 && $this->getNumber() == 0 ) ) { //Center image.
$u_obj = $this->getUserObject(); /** @var UserListFactory $u_obj */
if ( $u_obj->isPhotoExists() == false ) {
Debug::Text( 'Photo does not exist, using enrolled image for this user: ' . $u_obj->getId(), __FILE__, __LINE__, __METHOD__, 10 );
$dir = $u_obj->getStoragePath( $u_obj->getCompany(), $u_obj->getId() );
Debug::Text( ' Storage Path: ' . $dir, __FILE__, __LINE__, __METHOD__, 10 );
if ( isset( $dir ) ) {
@mkdir( $dir, 0700, true );
if ( @disk_free_space( $dir ) > ( strlen( $this->getValue() ) * 2 ) ) {
$file_name = $dir . DIRECTORY_SEPARATOR . TTUUID::castUUID( $u_obj->getId() ) . '.jpg';
$file_data = base64_decode( $this->getValue() );
$success = file_put_contents( $file_name, $file_data );
if ( $success == true ) {
TTLog::addEntry( $u_obj->getId(), 10, TTi18n::getText( 'Photo - Source: Face Enrollment' ), null, $u_obj->getTable() );
Debug::Text( 'User profile photo updated successfully!', __FILE__, __LINE__, __METHOD__, 10 );
} else {
Debug::Text( 'ERROR: Unable to write data to: ' . $file_name, __FILE__, __LINE__, __METHOD__, 10 );
}
} else {
Debug::Text( 'ERROR: Not enough disk space free, unable to save photo to user profile!', __FILE__, __LINE__, __METHOD__, 10 );
}
}
} else {
Debug::Text( 'User profile already has a photo, not overwriting with enrolled photo...', __FILE__, __LINE__, __METHOD__, 10 );
}
}
}
return true;
}
/**
* @param $log_action
* @return bool
*/
function addLog( $log_action ) {
//Don't do detail logging for this, as it will store entire figerprints in the log table.
return TTLog::addEntry( $this->getId(), $log_action, TTi18n::getText( 'Employee Identification - Employee' ) . ': ' . UserListFactory::getFullNameById( $this->getUser() ) . ' ' . TTi18n::getText( 'Type' ) . ': ' . Option::getByKey( $this->getType(), $this->getOptions( 'type' ) ), null, $this->getTable() );
}
}
?>