License updated to GPLv3

🧲 New features
Custom user role permissions
Employee edit form updated
Employee daily task list
Attendance and employee distribution charts on dashboard
Improvements to company structure and company assets module
Improved tables for displaying data in several modules
Faster data loading (specially for employee module)
Initials based profile pictures
Re-designed login page
Re-designed user profile page
Improvements to filtering
New REST endpoints for employee qualifications

🐛 Bug fixes
Fixed, issue with managers being able to create performance reviews for employees who are not their direct reports
Fixed, issues related to using full profile image instead of using smaller version of profile image
Changing third gender to other
Improvements and fixes for internal frontend data caching
This commit is contained in:
Thilina Pituwala
2020-10-31 19:02:37 +01:00
parent 86b8345505
commit b1df0037db
29343 changed files with 867614 additions and 2191082 deletions

View File

@@ -4,11 +4,17 @@ namespace Attendance\Admin\Api;
use Attendance\Common\Model\Attendance;
use Attendance\Rest\AttendanceRestEndPoint;
use Classes\AbstractModuleManager;
use Classes\SystemTasks\SystemTasksService;
use Classes\UIManager;
class AttendanceAdminManager extends AbstractModuleManager
{
public function initialize()
{
SystemTasksService::getInstance()->registerTaskCreator((new AttendanceTaskCreator()));
}
public function initializeUserClasses()
{
}

View File

@@ -0,0 +1,66 @@
<?php
namespace Attendance\Admin\Api;
use Attendance\Rest\AttendanceRestEndPoint;
use Classes\BaseService;
use Classes\SystemTasks\DTO\Task;
use Classes\SystemTasks\TaskCreator;
class AttendanceTaskCreator implements TaskCreator
{
public function getTasksCreators()
{
$taskCreators = [];
$taskCreators[1] = function () {
if (!$this->isUserCheckedIn()) {
return (new Task(Task::PRIORITY_ERROR, 'You are currently not checked-in'))
->setLink(
CLIENT_BASE_URL.'?g=modules&n=attendance&m=module_Time_Management',
'Visit Attendance'
);
}
return null;
};
$taskCreators[2] = function () {
if ($this->userNeedToCheckOut()) {
return (new Task(Task::PRIORITY_INFO, 'Remember to checkout after finishing work'))
->setLink(
CLIENT_BASE_URL.'?g=modules&n=attendance&m=module_Time_Management',
'Visit Attendance'
)->setDetails('You have checked in for the day and, should checkout, after finishing work');
}
return null;
};
return $taskCreators;
}
protected function isUserCheckedIn()
{
$attendanceRest = new AttendanceRestEndPoint();
$employeeId = BaseService::getInstance()->getCurrentUserProfileId();
if (!$employeeId) {
return true;
}
$attendance = $attendanceRest->findAttendance($employeeId, 'today');
return $attendance->id !== null;
}
protected function userNeedToCheckOut()
{
$attendanceRest = new AttendanceRestEndPoint();
$employeeId = BaseService::getInstance()->getCurrentUserProfileId();
if (!$employeeId) {
return true;
}
$attendance = $attendanceRest->findAttendance($employeeId, 'today');
return $attendance->in_time && empty($attendance->out_time);
}
}

View File

@@ -61,7 +61,7 @@ class AttendanceStatus extends BaseModel
return array_values($employees);
}
// @codingStandardsIgnoreStart
public function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
{
// @codingStandardsIgnoreEnd
$shift = intval(SettingsManager::getInstance()->getSetting("Attendance: Shift (Minutes)"));

View File

@@ -26,7 +26,7 @@ class AttendanceRestEndPoint extends RestEndPoint
return $obj;
}
public function listAll(User $user)
public function listAll(User $user, $parameter = null)
{
$query = new DataQuery('Attendance');
$query->addColumn('id');
@@ -237,8 +237,12 @@ class AttendanceRestEndPoint extends RestEndPoint
return new IceResponse(IceResponse::ERROR, $response->getData(), 400);
}
protected function findAttendance($employeeId, $date)
public function findAttendance($employeeId, $date)
{
if ($date === 'today') {
$date = explode(' ', $this->getServerTime())[0];
}
if (strpos($date, ' ')) {
$date = explode(' ', $date)[0];
}

View File

@@ -0,0 +1,165 @@
<?php
namespace Charts\Admin\Api;
use Attendance\Common\Model\Attendance;
use Classes\IceResponse;
use Classes\SubActionManager;
use TimeSheets\Common\Model\EmployeeTimeEntry;
class ChartsActionManager extends SubActionManager
{
public function getTimeUtilization($req)
{
if (empty($req->start)) {
$req->start = date("Y-m-01");
}
if (empty($req->end)) {
$req->end = date("Y-m-t", strtotime($req->start));
}
//Find Time Entries
$employeeTimeEntry = new EmployeeTimeEntry();
if (empty($req->employee)) {
$timeEntryList = $employeeTimeEntry->Find(
"date(date_start) >= ? and date(date_end) <= ?",
array($req->start, $req->end)
);
} else {
$timeEntryList = $employeeTimeEntry->Find(
"employee = ? and date(date_start) >= ? and date(date_end) <= ?",
array($req->employee, $req->start, $req->end)
);
}
$seconds = 0;
$graphTimeArray = array();
foreach ($timeEntryList as $entry) {
$seconds = (strtotime($entry->date_end) - strtotime($entry->date_start));
$key = date("Y-m-d", strtotime($entry->date_end));
if (isset($graphTimeArray[$key])) {
$graphTimeArray[$key] += $seconds;
} else {
$graphTimeArray[$key] = $seconds;
}
}
//$minutes = (int)($seconds/60);
//Find Attendance Entries
$attendance = new Attendance();
if (empty($req->employee)) {
$atteandanceList = $attendance->Find(
"date(in_time) >= ? and date(out_time) <= ? and in_time < out_time",
array($req->start, $req->end)
);
} else {
$atteandanceList = $attendance->Find(
"employee = ? and date(in_time) >= ? and date(out_time) <= ? and in_time < out_time",
array($req->employee, $req->start, $req->end)
);
}
$seconds = 0;
$graphAttendanceArray = array();
foreach ($atteandanceList as $entry) {
$seconds = (strtotime($entry->out_time) - strtotime($entry->in_time));
$key = date("Y-m-d", strtotime($entry->in_time));
if (isset($graphAttendanceArray[$key])) {
$graphAttendanceArray[$key] += $seconds;
} else {
$graphAttendanceArray[$key] = $seconds;
}
}
$data = array();
$data[] = array("key"=>"Hours in Attendance", "values"=>array());
$data[] = array("key"=>"Hours Worked", "values"=>array());
//Iterate date range
$interval = \DateInterval::createFromDateString('1 day');
$period = new \DatePeriod(new \DateTime($req->start), $interval, new \DateTime($req->end));
/* @var \DateTime $dt */
foreach ($period as $dt) {
$key = $dt->format("Y-m-d");
if (isset($graphAttendanceArray[$key])) {
$data[0]['values'][] = array("x"=>$key, "y"=>round(($graphAttendanceArray[$key]/3600), 2));
} else {
$data[0]['values'][] = array("x"=>$key, "y"=>0);
}
if (isset($graphTimeArray[$key])) {
$data[1]['values'][] = array("x"=>$key, "y"=>round(($graphTimeArray[$key]/3600), 2));
} else {
$data[1]['values'][] = array("x"=>$key, "y"=>0);
}
}
return new IceResponse(IceResponse::SUCCESS, $data);
}
public function getAttendance($req)
{
if (empty($req->start)) {
$req->start = date("Y-m-01");
}
if (empty($req->end)) {
$req->end = date("Y-m-t", strtotime($req->start));
}
//Find Attendance Entries
$attendance = new Attendance();
if (empty($req->employee)) {
$atteandanceList = $attendance->Find(
"date(in_time) >= ? and date(out_time) <= ? and in_time < out_time",
array($req->start, $req->end)
);
} else {
$atteandanceList = $attendance->Find(
"employee = ? and date(in_time) >= ? and date(out_time) <= ? and in_time < out_time",
array($req->employee, $req->start, $req->end)
);
}
$seconds = 0;
$graphAttendanceArray = array();
foreach ($atteandanceList as $entry) {
$seconds = (strtotime($entry->out_time) - strtotime($entry->in_time));
$key = date("Y-m-d", strtotime($entry->in_time));
if (isset($graphAttendanceArray[$key])) {
$graphAttendanceArray[$key] += $seconds;
} else {
$graphAttendanceArray[$key] = $seconds;
}
}
$data[0] = array();
$data[0] = array("key"=>"Attendance", "values"=>array());
//Iterate date range
$interval = \DateInterval::createFromDateString('1 day');
$period = new \DatePeriod(new \DateTime($req->start), $interval, new \DateTime($req->end));
/* @var \DateTime $dt */
foreach ($period as $dt) {
$key = $dt->format("Y-m-d");
if (isset($graphAttendanceArray[$key])) {
$data[0]['values'][] = array("x"=>$key, "y"=>round(($graphAttendanceArray[$key]/3600), 2));
} else {
$data[0]['values'][] = array("x"=>$key, "y"=>0);
}
}
return new IceResponse(IceResponse::SUCCESS, $data);
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Charts\Admin\Api;
use Charts\Admin\Rest\ChartsRestEndpoint;
use Classes\AbstractModuleManager;
use Classes\Macaw;
use Employees\Rest\EmployeeRestEndPoint;
class ChartsAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
}
public function setupRestEndPoints()
{
Macaw::get(REST_API_PATH.'charts/company-leave-entitlement', function () {
$empRestEndPoint = new ChartsRestEndpoint();
$empRestEndPoint->process('getCompanyLeaveEntitlement');
});
Macaw::get(REST_API_PATH.'charts/employee-check-ins', function () {
$empRestEndPoint = new ChartsRestEndpoint();
$empRestEndPoint->process('getCompanyEmployeeCheckIns');
});
Macaw::get(REST_API_PATH.'charts/employees-distribution', function () {
$empRestEndPoint = new ChartsRestEndpoint();
$empRestEndPoint->process('getEmployeeDistribution');
});
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Charts\Admin\Rest;
use Attendance\Common\Model\AttendanceStatus;
use Classes\IceResponse;
use Classes\RestEndPoint;
use Employees\Common\Model\Employee;
use Leaves\User\Api\LeavesActionManager;
use Users\Common\Model\User;
use Utils\LogManager;
class ChartsRestEndpoint extends RestEndPoint
{
public function getCompanyLeaveEntitlement(User $user)
{
$data = [
'pending' => 0,
'approved' => 0,
'remaining' => 0,
];
$leaveActionManager = new LeavesActionManager();
$employee = new Employee();
$employees = $employee->Find('status = ?', ['Active']);
foreach ($employees as $employee) {
$leaveEntitlements = $leaveActionManager->getEntitlementByEmployee($employee)->getObject();
foreach ($leaveEntitlements as $leaveEntitlement) {
$data['pending'] += $leaveEntitlement['pendingLeaves'];
$data['approved'] += $leaveEntitlement['approvedLeaves'];
$data['remaining'] += $leaveEntitlement['totalLeaves']
- ( $leaveEntitlement['pendingLeaves'] + $leaveEntitlement['approvedLeaves']);
}
}
return new IceResponse(IceResponse::SUCCESS, $data);
}
public function getEmployeeDistribution(User $user)
{
$data = [];
$query = <<<'SQL'
select c.title as name, count(e.id) as value
from Employees e
left join CompanyStructures c
on e.department = c.id
group by department
SQL;
$user->DB()->SetFetchMode(ADODB_FETCH_ASSOC);
$rs = $user->DB()->Execute($query);
foreach ($rs as $rowId => $row) {
$name = $row['name'];
$data[empty($name) ? 'Not Assigned' : $name] = $row['value'];
}
return new IceResponse(IceResponse::SUCCESS, $data);
}
public function getCompanyEmployeeCheckIns(User $user)
{
$attendanceStatus = new AttendanceStatus();
$attendanceStatusList = $attendanceStatus->Find("1 = 1");
$countClockedIn = 0;
$countClockedOut = 0;
$countNotClockedIn = 0;
foreach ($attendanceStatusList as $att) {
if ($att->statusId === 1) {
$countClockedOut++;
} elseif ($att->statusId === 0) {
$countClockedIn++;
} else {
$countNotClockedIn++;
}
}
$data = [];
$data['Checked-In'] = $countClockedIn;
$data['Checked Out'] = $countClockedOut;
$data['Not Started'] = $countNotClockedIn;
return new IceResponse(IceResponse::SUCCESS, $data);
}
}

View File

@@ -22,6 +22,10 @@ abstract class AbstractModuleManager
private $moduleType = null;
private $actionManager = null;
public function initialize()
{
}
/**
* Override this method in module manager class to define user classes.
* A user class is a class that is mapped to a table having a field named profile.

View File

@@ -12,6 +12,7 @@ namespace Classes;
use Classes\Crypt\AesCtr;
use Classes\Email\EmailSender;
use Classes\Exception\IceHttpException;
use Company\Common\Model\CompanyStructure;
use Employees\Common\Model\Employee;
use Employees\Common\Model\EmployeeApproval;
@@ -23,6 +24,7 @@ use Model\Setting;
use Modules\Common\Model\Module;
use Permissions\Common\Model\Permission;
use Users\Common\Model\User;
use Users\Common\Model\UserRole;
use Utils\LogManager;
use Utils\SessionUtils;
@@ -155,6 +157,11 @@ class BaseService
return $list;
}
public function getModelClassMap()
{
return $this->modelClassMap;
}
public function addModelClass($modelClass, $fullQualifiedName)
{
$this->modelClassMap[$modelClass] = $fullQualifiedName;
@@ -245,7 +252,7 @@ class BaseService
$countFilterQuery = $response[0];
$countFilterQueryData = $response[1];
} else {
$defaultFilterResp = \Classes\BaseService::getInstance()->buildDefaultFilterQuery($filter);
$defaultFilterResp = BaseService::getInstance()->buildDefaultFilterQuery($filter);
$countFilterQuery = $defaultFilterResp[0];
$countFilterQueryData = $defaultFilterResp[1];
}
@@ -253,9 +260,9 @@ class BaseService
}
if (in_array($table, \Classes\BaseService::getInstance()->userTables)
if (in_array($table, BaseService::getInstance()->userTables)
&& !$skipProfileRestriction && !$isSubOrdinates) {
$cemp = \Classes\BaseService::getInstance()->getCurrentProfileId();
$cemp = BaseService::getInstance()->getCurrentProfileId();
$sql = "Select count(id) as count from "
. $obj->_table . " where " . SIGN_IN_ELEMENT_MAPPING_FIELD_NAME . " = ? " . $countFilterQuery;
array_unshift($countFilterQueryData, $cemp);
@@ -263,8 +270,8 @@ class BaseService
$rowCount = $obj->DB()->Execute($sql, $countFilterQueryData);
} else {
if ($isSubOrdinates) {
$cemp = \Classes\BaseService::getInstance()->getCurrentProfileId();
$profileClass = \Classes\BaseService::getInstance()->getFullQualifiedModelClassName(
$cemp = BaseService::getInstance()->getCurrentProfileId();
$profileClass = BaseService::getInstance()->getFullQualifiedModelClassName(
ucfirst(SIGN_IN_ELEMENT_MAPPING_FIELD_NAME)
);
$subordinate = new $profileClass();
@@ -1273,15 +1280,10 @@ class BaseService
public function checkSecureAccess($type, $object, $table, $request)
{
//Construct permission method
$permMethod = "get".str_replace(' ', '', $this->currentUser->user_level)."Access";
$userOnlyMeAccessRequestField = $object->getUserOnlyMeAccessRequestField();
$userOnlyMeAccessField = $object->getUserOnlyMeAccessField();
if (method_exists($object, $permMethod)) {
$accessMatrix = $object->$permMethod($this->currentUser->user_roles);
} else {
$accessMatrix = $object->getDefaultAccessLevel();
}
$accessMatrix = $object->getRoleBasedAccess($this->currentUser->user_level, $this->currentUser->user_roles);
if (in_array($type, $accessMatrix)) {
//The user has required permission, so return true
@@ -1314,15 +1316,11 @@ class BaseService
}
}
$ret['status'] = "ERROR";
$ret['message'] = $type." ".get_class($object)." Access violation";
echo json_encode($ret);
$exception = new \Exception(
sprintf(
'%s : %s',
'Access violation',
json_encode([$type, $table, get_class($object), $request, json_encode($this->currentUser)])
)
$action = PermissionManager::ACCESS_LIST_DESCRIPTION[$type];
$message = "You are not allowed to $action object type ".$object->table.'.';
$exception = new IceHttpException(
$message,
403
);
LogManager::getInstance()->notifyException($exception);
throw $exception;
@@ -1802,7 +1800,7 @@ END;
$companyStructure->Load('id = ?', array($parentCompanyStructure));
}
} while (!empty($companyStructure->id)
&& !empty($parentCompanyStructure)
&& !empty($parentCompanyStructure)
);
}
@@ -1938,4 +1936,21 @@ END;
{
return defined('QUERY_CACHE') && QUERY_CACHE === true;
}
public function getCurrentDBUser()
{
$user = BaseService::getInstance()->getCurrentUser();
if (empty($user)) {
return new IceResponse(IceResponse::ERROR);
}
$dbUser = new User();
$dbUser->Load("id = ?", array($user->id));
return $dbUser;
}
public function getAccessToken()
{
$dbUser = $this->getCurrentDBUser();
return RestApiManager::getInstance()->getAccessTokenForUser($dbUser);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Classes\Common;
use Pimple\Container;
class IceContainer extends Container
{
public function get($serviceName)
{
return $this[$serviceName];
}
public function set($serviceName, $callback)
{
$this[$serviceName] = $callback;
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace Classes\Exception;
class IceHttpException extends \Exception
{
}

View File

@@ -56,10 +56,10 @@ class FileService
}
}
public function checkAddSmallProfileImage($profileImage)
public function checkAddSmallProfileImageS3($profileImage)
{
$file = new File();
$file->Load('name = ?', array($profileImage->name."_small"));
$file->Load('file_group = ? and employee = ?', array('profile_image_small', $profileImage->employee));
if (empty($file->id)) {
LogManager::getInstance()->info("Small profile image ".$profileImage->name."_small not found");
@@ -70,7 +70,6 @@ class FileService
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
$file->$signInMappingField = $profileImage->$signInMappingField;
$file->filename = $file->name.str_replace($profileImage->name, "", $profileImage->filename);
$file->file_group = $profileImage->file_group;
file_put_contents("/tmp/".$file->filename."_orig", file_get_contents($largeFileUrl));
@@ -78,7 +77,7 @@ class FileService
//Resize image to 100
$img = new \Classes\SimpleImage("/tmp/".$file->filename."_orig");
$img->fitToWidth(100);
$img->fitToWidth(140);
$img->save("/tmp/".$file->filename);
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
@@ -100,7 +99,18 @@ class FileService
LogManager::getInstance()->info("Upload Result:".print_r($result, true));
$file->employee = $profileImage->employee;
$file->file_group = 'profile_image_small';
$file->size = filesize(CLIENT_BASE_PATH.'data/'.$file->filename);
$file->size_text = $this->getReadableSize($file->size);
if (!empty($result)) {
$fileDelete = new File();
$fileDelete->Load('filename = ?', [$file->filename]);
if ($fileDelete->filename === $file->filename) {
$fileDelete->Delete();
}
$file->Save();
}
@@ -113,16 +123,56 @@ class FileService
return $file;
}
public function checkAddSmallProfileImage($profileImage)
{
$file = new File();
$file->Load('file_group = ? and employee = ?', array('profile_image_small', $profileImage->employee));
if (empty($file->id)) {
LogManager::getInstance()->info("Small profile image ".$profileImage->name."_small not found");
$largeFileUrl = $this->getFileUrl($profileImage->name);
file_put_contents("/tmp/".$profileImage->filename."_orig", file_get_contents($largeFileUrl));
if (file_exists("/tmp/".$profileImage->filename."_orig")) {
//Resize image to 100
$file->name = $profileImage->name."_small";
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
$file->$signInMappingField = $profileImage->$signInMappingField;
$file->filename = $file->name.str_replace($profileImage->name, "", $profileImage->filename);
$img = new \Classes\SimpleImage("/tmp/".$profileImage->filename."_orig");
$img->fitToWidth(140);
$img->save(CLIENT_BASE_PATH.'data/'.$file->filename);
$file->employee = $profileImage->employee;
$file->file_group = 'profile_image_small';
$file->size = filesize(CLIENT_BASE_PATH.'data/'.$file->filename);
$file->size_text = $this->getReadableSize($file->size);
$file->Save();
unlink("/tmp/".$file->filename."_orig");
return $file;
}
return null;
}
return $file;
}
public function updateSmallProfileImage($profile)
{
$file = new File();
$file->Load('name = ?', array('profile_image_'.$profile->id));
$file->Load('file_group = ? and employee = ?', array('profile_image', $profile->id));
if ($file->name == 'profile_image_'.$profile->id) {
if ($file->employee == $profile->id) {
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
if ($uploadFilesToS3 == "1") {
try {
$fileNew = $this->checkAddSmallProfileImage($file);
$fileNew = $this->checkAddSmallProfileImageS3($file);
if (!empty($fileNew)) {
$file = $fileNew;
}
@@ -147,23 +197,16 @@ class FileService
} catch (\Exception $e) {
LogManager::getInstance()->error("Error generating profile image: ".$e->getMessage());
LogManager::getInstance()->notifyException($e);
if ($profile->gender == 'Female') {
$profile->image = BASE_URL."images/user_female.png";
} else {
$profile->image = BASE_URL."images/user_male.png";
}
$profile->image = $this->generateProfileImage($profile->first_name, $profile->last_name);
}
} elseif (substr($file->filename, 0, 8) === 'https://') {
$profile->image = $file->filename;
} else {
$profile->image = CLIENT_BASE_URL.'data/'.$file->filename;
$fileNew = $this->checkAddSmallProfileImage($file);
$profile->image = CLIENT_BASE_URL.'data/'.$fileNew->filename;
}
} else {
if ($profile->gender == 'Female') {
$profile->image = BASE_URL."images/user_female.png";
} else {
$profile->image = BASE_URL."images/user_male.png";
}
$profile->image = $this->generateProfileImage($profile->first_name, $profile->last_name);
}
return $profile;
@@ -172,9 +215,9 @@ class FileService
public function updateProfileImage($profile)
{
$file = new File();
$file->Load('name = ?', array('profile_image_'.$profile->id));
$file->Load('file_group = ? and employee = ?', array('profile_image', $profile->id));
if ($file->name == 'profile_image_'.$profile->id) {
if ($file->employee == $profile->id) {
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
if ($uploadFilesToS3 == "1") {
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
@@ -200,11 +243,7 @@ class FileService
$profile->image = CLIENT_BASE_URL.'data/'.$file->filename;
}
} else {
if ($profile->gender == 'Female') {
$profile->image = BASE_URL."images/user_female.png";
} else {
$profile->image = BASE_URL."images/user_male.png";
}
$profile->image = $this->generateProfileImage($profile->first_name, $profile->last_name);
}
return $profile;
@@ -249,26 +288,29 @@ class FileService
public function deleteProfileImage($profileId)
{
$file = new File();
$file->Load('name = ?', array('profile_image_'.$profileId));
if ($file->name == 'profile_image_'.$profileId) {
$ok = $file->Delete();
if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else {
return false;
$profilesImages = $file->Find('file_group = ? and employee = ?', array('profile_image', $profileId));
foreach ($profilesImages as $file) {
if ($file->employee == $profileId) {
$ok = $file->Delete();
if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else {
return false;
}
}
}
$file = new File();
$file->Load('name = ?', array('profile_image_'.$profileId."_small"));
if ($file->name == 'profile_image_'.$profileId."_small") {
$ok = $file->Delete();
if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else {
return false;
$profilesImages = $file->Find('file_group = ? and employee = ?', array('profile_image_small', $profileId));
foreach ($profilesImages as $file) {
if ($file->employee == $profileId) {
$ok = $file->Delete();
if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else {
return false;
}
}
}
@@ -330,4 +372,20 @@ class FileService
return round(pow(1024, $base - floor($base)), $precision) .' '. $suffixes[floor($base)];
}
public function generateProfileImage($first, $last)
{
$seed = substr($first, 0, 1);
if (empty($last)) {
$seed .= substr($first, -1);
} else {
$seed .= substr($last, 0, 1);
}
md5($seed . $last);
return sprintf(
'https://avatars.dicebear.com/api/initials/:%s.svg',
$seed . substr(md5($first . $last), -5)
);
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Classes;
use Firebase\JWT\JWT;
class JwtTokenService
{
public function create($expire = 3600)
{
$secret = APP_SEC.APP_PASSWORD;
$resp = BaseService::getInstance()->getAccessToken();
$payload = array(
"token" => $resp->getData(),
"expire" => time() + $expire,
);
return JWT::encode($payload, $secret);
}
public function getBaseToken($jwtToken)
{
$secret = APP_SEC.APP_PASSWORD;
$jwt = JWT::decode($jwtToken, $secret, array('HS256'));
if (time() > intval($jwt->expire)) {
return null;
}
return $jwt->token;
}
}

View File

@@ -65,6 +65,7 @@ class ModuleAccessService
return count(array_intersect($userRoles, $moduleUserRoles)) > 0;
}
return in_array($user->user_level, $moduleUserLevels);
return in_array($user->user_level, $moduleUserLevels)
|| count(array_intersect($userRoles, $moduleUserRoles)) > 0;
}
}

View File

@@ -16,7 +16,14 @@ class PermissionManager
{
const RESTRICTED_USER_LEVELS = ['Restricted Admin', 'Restricted Manager', 'Restricted Employee'];
public function isRestrictedUserLevel($userLevel)
const ACCESS_LIST_DESCRIPTION = [
'get' => 'List',
'element' => 'View Details',
'save' => 'Add/Edit',
'delete' => 'Delete',
];
public static function isRestrictedUserLevel($userLevel)
{
return in_array($userLevel, self::RESTRICTED_USER_LEVELS);
}
@@ -50,4 +57,10 @@ class PermissionManager
return $subIds;
}
public static function checkGeneralAccess($object)
{
$currentUser = BaseService::getInstance()->getCurrentUser();
return $object->getRoleBasedAccess($currentUser->user_level, $currentUser->user_roles);
}
}

View File

@@ -178,23 +178,34 @@ class RestEndPoint
protected function getCombinedValue($nameField, $targetObject)
{
$values = explode("+", $nameField);
if (count($values) == 1) {
return $targetObject->{$nameField};
}
$objVal = '';
foreach ($values as $value) {
if ($objVal != "") {
$objVal .= " ";
if (is_string($nameField)) {
$values = explode("+", $nameField);
if (count($values) == 1) {
return $targetObject->{$nameField};
}
if (substr($value, 0, 1) !== ':') {
$objVal .= $targetObject->{$value};
} else {
$objVal .= substr($value, 1);
$objVal = '';
foreach ($values as $value) {
if ($objVal != "") {
$objVal .= " ";
}
if (substr($value, 0, 1) !== ':') {
$objVal .= $targetObject->{$value};
} else {
$objVal .= substr($value, 1);
}
}
return $objVal;
} elseif (is_array($nameField)) {
$objVal = [];
foreach ($nameField as $value) {
$objVal[$value] = $targetObject->{$value};
}
return $objVal;
}
return $objVal;
return null;
}
protected function cleanObject($obj)
@@ -221,7 +232,7 @@ class RestEndPoint
return $obj;
}
public function listAll(User $user)
public function listAll(User $user, $parameter = null)
{
return new IceResponse(IceResponse::ERROR, "Method not Implemented", 404);
}
@@ -403,13 +414,20 @@ class RestEndPoint
private function getBearerToken()
{
$headers = $this->getAuthorizationHeader();
$token = '';
// HEADER: Get the access token from the header
if (!empty($headers)) {
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
return $matches[1];
$token = $matches[1];
}
}
return null;
if (strlen($token) > 32) {
$tokenService = new JwtTokenService();
$token = $tokenService->getBaseToken($token);
}
return $token;
}
protected function getRequestBody()

View File

@@ -0,0 +1,107 @@
<?php
namespace Classes\SystemTasks\DTO;
class Task implements \JsonSerializable
{
const PRIORITY_ERROR = 100;
const PRIORITY_WARNING = 50;
const PRIORITY_INFO = 20;
const PRIORITY_OK = 10;
protected $priority;
protected $text;
protected $link;
protected $action;
protected $details;
/**
* Task constructor.
* @param $priority
* @param $text
*/
public function __construct($priority, $text)
{
$this->priority = $priority;
$this->text = $text;
}
/**
* @return mixed
*/
public function getPriority()
{
return $this->priority;
}
/**
* @param mixed $priority
*/
public function setPriority($priority): Task
{
$this->priority = $priority;
return $this;
}
/**
* @return mixed
*/
public function getText()
{
return $this->text;
}
/**
* @param mixed $text
*/
public function setText($text): Task
{
$this->text = $text;
return $this;
}
/**
* @return mixed
*/
public function getLink()
{
return $this->link;
}
/**
* @param mixed $link
* @param string $action
* @return Task
*/
public function setLink($link, $action = 'Fix'): Task
{
$this->link = $link;
$this->action = $action;
return $this;
}
/**
* @param mixed $details
*/
public function setDetails($details): Task
{
$this->details = $details;
return $this;
}
public function jsonSerialize()
{
return [
'priority' => $this->priority,
'text' => $this->text,
'link' => $this->link,
'action' => $this->action,
'details' => $this->details,
];
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace Classes\SystemTasks;
use Classes\SystemTasks\DTO\Task;
class SystemTasksService
{
protected $taskCreators = [];
private static $me = null;
private function __construct()
{
}
public static function getInstance()
{
if (empty(self::$me)) {
self::$me = new SystemTasksService();
}
return self::$me;
}
public function registerTaskCreator(TaskCreator $taskCreator)
{
$this->taskCreators[] = $taskCreator;
}
protected function prepareTaskCreatorCallbacks()
{
$taskGenerators = [];
foreach ($this->taskCreators as $taskCreator) {
$taskList = $taskCreator->getTasksCreators();
foreach ($taskList as $order => $callback) {
$nextOrder = $order * 1000;
while (isset($taskGenerators[$nextOrder])) {
$nextOrder = 1 + $nextOrder;
}
$taskGenerators[$nextOrder] = $callback;
}
}
return $taskGenerators;
}
public function getAdminTasks()
{
$tasks = [];
$taskGenerators = $this->prepareTaskCreatorCallbacks();
ksort($taskGenerators);
foreach ($taskGenerators as $key => $callback) {
$task = $callback();
if (!empty($task)) {
$tasks[] = $task;
}
}
return $tasks;
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace Classes\SystemTasks;
interface TaskCreator
{
public function getTasksCreators();
}

View File

@@ -268,7 +268,7 @@ class UIManager
{
$currentCountryCode = $currentLanguage;
if ($currentLanguage === 'en') {
$currentCountryCode = 'gb';
$currentCountryCode = 'un';
} elseif ($currentLanguage === 'zh') {
$currentCountryCode = 'cn';
} elseif ($currentLanguage === 'ja') {

View File

@@ -1,7 +1,10 @@
<?php
namespace Dashboard\Admin\Api;
use Charts\Admin\Rest\ChartsRestEndpoint;
use Classes\AbstractModuleManager;
use Classes\Macaw;
use Dashboard\Admin\Rest\DashboardRestEndpoint;
class DashboardAdminManager extends AbstractModuleManager
{
@@ -21,4 +24,12 @@ class DashboardAdminManager extends AbstractModuleManager
public function setupModuleClassDefinitions()
{
}
public function setupRestEndPoints()
{
Macaw::get(REST_API_PATH.'tasks', function () {
$restEndPoint = new DashboardRestEndpoint();
$restEndPoint->process('getTaskList');
});
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Dashboard\Admin\Rest;
use Classes\IceResponse;
use Classes\RestEndPoint;
use Classes\SystemTasks\SystemTasksService;
use Users\Common\Model\User;
class DashboardRestEndpoint extends RestEndPoint
{
public function getTaskList(User $user)
{
$systemTasksService = SystemTasksService::getInstance();
//return new IceResponse(IceResponse::SUCCESS, []);
return new IceResponse(IceResponse::SUCCESS, $systemTasksService->getAdminTasks());
}
}

View File

@@ -75,13 +75,23 @@ class DataActionManager extends SubActionManager
$sample[] = $column->sampleValue;
}
$output = fopen('php://output', 'w');
header('Content-Type:application/csv');
header('Content-Disposition:attachment;filename='.$dataImport->name.'.csv');
$file = sha1(rand(4500, 100000) . time(). CLIENT_BASE_URL);
$output = fopen('/tmp/'.$file, 'w');
fputcsv($output, $headers);
fputcsv($output, $sample);
fclose($output);
header('Content-Type:application/csv');
header('Content-Type: application/octet-stream');
header('Content-Disposition:attachment;filename='.$dataImport->name.'.csv');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('/tmp/'.$file));
readfile('/tmp/'.$file);
ob_flush();
flush();
unlink('/tmp/'.$file);
die();
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Documents\Admin\Api;
use Classes\BaseService;
use Classes\SystemTasks\DTO\Task;
use Classes\SystemTasks\TaskCreator;
use Employees\Common\Model\Employee;
class DocumentTaskCreator implements TaskCreator
{
public function getTasksCreators()
{
$taskCreators = [];
$taskCreators[1] = function () {
$expiredDocumentCount = $this->getMyExpiredDocumentCount();
if ($expiredDocumentCount > 0) {
(new Task(
Task::PRIORITY_ERROR,
sprintf(
'You have %s expired documents %s',
$expiredDocumentCount,
$expiredDocumentCount > 0 ? 's' : ''
)
))->setLink(
CLIENT_BASE_URL.'?g=modules&n=documents&m=module_Documents',
'Check Documents'
);
}
return null;
};
return $taskCreators;
}
protected function getMyExpiredDocumentCount()
{
$user = BaseService::getInstance()->getCurrentUser();
$employee = new Employee();
$employee->Load('id = ?', [$user->employee]);
if (empty($employee->id)) {
return 0;
}
$query = "select count(id) as c from EmployeeDocuments where employee = ? and valid_until < ?";
$user->DB()->SetFetchMode(ADODB_FETCH_ASSOC);
$rs = $user->DB()->Execute($query, [$employee->id, date('Y-m-d')]);
$count = $rs->fields['c'];
return $count;
}
}

View File

@@ -2,10 +2,16 @@
namespace Documents\Admin\Api;
use Classes\AbstractModuleManager;
use Classes\SystemTasks\SystemTasksService;
class DocumentsAdminManager extends AbstractModuleManager
{
public function initialize()
{
SystemTasksService::getInstance()->registerTaskCreator((new DocumentTaskCreator()));
}
public function initializeUserClasses()
{
}

View File

@@ -44,7 +44,7 @@ class CompanyDocument extends BaseModel
}
// @codingStandardsIgnoreStart
public function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
{
// @codingStandardsIgnoreEnd
$res = parent::Find($whereOrderBy, $bindarr, $pkeysArr, $extra);

View File

@@ -12,7 +12,11 @@ use Classes\AbstractModuleManager;
use Classes\Macaw;
use Classes\UIManager;
use Employees\Common\Model\Employee;
use Employees\Rest\EmployeeCertificationsRestEndPoint;
use Employees\Rest\EmployeeEducationRestEndPoint;
use Employees\Rest\EmployeeLanguageRestEndPoint;
use Employees\Rest\EmployeeRestEndPoint;
use Employees\Rest\EmployeeSkillsRestEndPoint;
class EmployeesAdminManager extends AbstractModuleManager
{
@@ -56,6 +60,30 @@ class EmployeesAdminManager extends AbstractModuleManager
$empRestEndPoint = new EmployeeRestEndPoint();
$empRestEndPoint->process('delete', $pathParams);
});
// Employee skills
Macaw::get(REST_API_PATH.'employees/(:num)/skills', function ($pathParams) {
$empRestEndPoint = new EmployeeSkillsRestEndPoint();
$empRestEndPoint->process('listAll', $pathParams);
});
// Employee education
Macaw::get(REST_API_PATH.'employees/(:num)/educations', function ($pathParams) {
$empRestEndPoint = new EmployeeEducationRestEndpoint();
$empRestEndPoint->process('listAll', $pathParams);
});
// Employee certifications
Macaw::get(REST_API_PATH.'employees/(:num)/certifications', function ($pathParams) {
$empRestEndPoint = new EmployeeCertificationsRestEndpoint();
$empRestEndPoint->process('listAll', $pathParams);
});
// Employee languages
Macaw::get(REST_API_PATH.'employees/(:num)/languages', function ($pathParams) {
$empRestEndPoint = new EmployeeLanguageRestEndpoint();
$empRestEndPoint->process('listAll', $pathParams);
});
}
public function initializeDatabaseErrorMappings()

View File

@@ -0,0 +1,53 @@
<?php
namespace Employees\Rest;
use Classes\Data\Query\DataQuery;
use Classes\Data\Query\Filter;
use Classes\RestEndPoint;
use Qualifications\Common\Model\EmployeeCertification;
use Qualifications\Common\Model\EmployeeEducation;
use Users\Common\Model\User;
class EmployeeCertificationsRestEndpoint extends RestEndPoint
{
public function getModelObject($id)
{
$obj = new EmployeeCertification();
$obj->Load("id = ?", array($id));
return $obj;
}
public function listAll(User $user, $parameter = null)
{
$query = new DataQuery('EmployeeCertification');
$query->addFilter(new Filter('employee', $parameter));
$mapping = <<<JSON
{
"certification_id": [ "Certification", "id", "name" ],
"employee": [ "Employee", "id", "first_name+last_name" ]
}
JSON;
$query->setFieldMapping($mapping);
$limit = self::DEFAULT_LIMIT;
if (isset($_GET['limit']) && intval($_GET['limit']) > 0) {
$limit = intval($_GET['limit']);
}
$query->setLength($limit);
if (!empty($_GET['filters'])) {
$query->setFilters($_GET['filters']);
}
if (isset($_GET['sortField']) && !empty($_GET['sortField'])) {
$query->setSortColumn($_GET['sortField']);
$query->setSortingEnabled(true);
$query->setSortOrder(
empty($_GET['sortOrder']) || $_GET['sortOrder'] === 'ascend' ? 'ASC' : 'DESC'
);
}
return $this->listByQuery($query);
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace Employees\Rest;
use Classes\Data\Query\DataQuery;
use Classes\Data\Query\Filter;
use Classes\RestEndPoint;
use Qualifications\Common\Model\EmployeeEducation;
use Users\Common\Model\User;
class EmployeeEducationRestEndpoint extends RestEndPoint
{
public function getModelObject($id)
{
$obj = new EmployeeEducation();
$obj->Load("id = ?", array($id));
return $obj;
}
public function listAll(User $user, $parameter = null)
{
$query = new DataQuery('EmployeeEducation');
$query->addFilter(new Filter('employee', $parameter));
$mapping = <<<JSON
{
"education_id": [ "Education", "id", "name" ],
"employee": [ "Employee", "id", "first_name+last_name" ]
}
JSON;
$query->setFieldMapping($mapping);
$limit = self::DEFAULT_LIMIT;
if (isset($_GET['limit']) && intval($_GET['limit']) > 0) {
$limit = intval($_GET['limit']);
}
$query->setLength($limit);
if (!empty($_GET['filters'])) {
$query->setFilters($_GET['filters']);
}
if (isset($_GET['sortField']) && !empty($_GET['sortField'])) {
$query->setSortColumn($_GET['sortField']);
$query->setSortingEnabled(true);
$query->setSortOrder(
empty($_GET['sortOrder']) || $_GET['sortOrder'] === 'ascend' ? 'ASC' : 'DESC'
);
}
return $this->listByQuery($query);
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Employees\Rest;
use Classes\Data\Query\DataQuery;
use Classes\Data\Query\Filter;
use Classes\RestEndPoint;
use Qualifications\Common\Model\Certification;
use Qualifications\Common\Model\EmployeeCertification;
use Qualifications\Common\Model\EmployeeEducation;
use Qualifications\Common\Model\EmployeeLanguage;
use Qualifications\Common\Model\Language;
use Users\Common\Model\User;
class EmployeeLanguageRestEndpoint extends RestEndPoint
{
public function getModelObject($id)
{
$obj = new EmployeeLanguage();
$obj->Load("id = ?", array($id));
return $obj;
}
public function listAll(User $user, $parameter = null)
{
$query = new DataQuery('EmployeeLanguage');
$query->addFilter(new Filter('employee', $parameter));
$mapping = <<<JSON
{
"language_id": [ "Language", "id", "description" ],
"employee": [ "Employee", "id", "first_name+last_name" ]
}
JSON;
$query->setFieldMapping($mapping);
$limit = self::DEFAULT_LIMIT;
if (isset($_GET['limit']) && intval($_GET['limit']) > 0) {
$limit = intval($_GET['limit']);
}
$query->setLength($limit);
if (!empty($_GET['filters'])) {
$query->setFilters($_GET['filters']);
}
if (isset($_GET['sortField']) && !empty($_GET['sortField'])) {
$query->setSortColumn($_GET['sortField']);
$query->setSortingEnabled(true);
$query->setSortOrder(
empty($_GET['sortOrder']) || $_GET['sortOrder'] === 'ascend' ? 'ASC' : 'DESC'
);
}
return $this->listByQuery($query);
}
}

View File

@@ -3,6 +3,7 @@ namespace Employees\Rest;
use Classes\BaseService;
use Classes\Data\Query\DataQuery;
use Classes\Data\Query\Filter;
use Classes\IceResponse;
use Classes\PermissionManager;
use Classes\RestEndPoint;
@@ -20,10 +21,10 @@ class EmployeeRestEndPoint extends RestEndPoint
return $obj;
}
public function listAll(User $user)
public function listAll(User $user, $parameter = null)
{
$query = new DataQuery('Employee');
$query->addFilter(new Filter('employee', $parameter));
$mapping = <<<JSON
{
"job_title": [ "JobTitle", "id", "name" ],

View File

@@ -0,0 +1,52 @@
<?php
namespace Employees\Rest;
use Classes\Data\Query\DataQuery;
use Classes\Data\Query\Filter;
use Classes\RestEndPoint;
use Qualifications\Common\Model\EmployeeSkill;
use Users\Common\Model\User;
class EmployeeSkillsRestEndPoint extends RestEndPoint
{
public function getModelObject($id)
{
$obj = new EmployeeSkill();
$obj->Load("id = ?", array($id));
return $obj;
}
public function listAll(User $user, $parameter = null)
{
$query = new DataQuery('EmployeeSkill');
$query->addFilter(new Filter('employee', $parameter));
$mapping = <<<JSON
{
"skill_id": [ "Skill", "id", "name" ],
"employee": [ "Employee", "id", "first_name+last_name" ]
}
JSON;
$query->setFieldMapping($mapping);
$limit = self::DEFAULT_LIMIT;
if (isset($_GET['limit']) && intval($_GET['limit']) > 0) {
$limit = intval($_GET['limit']);
}
$query->setLength($limit);
if (!empty($_GET['filters'])) {
$query->setFilters($_GET['filters']);
}
if (isset($_GET['sortField']) && !empty($_GET['sortField'])) {
$query->setSortColumn($_GET['sortField']);
$query->setSortingEnabled(true);
$query->setSortOrder(
empty($_GET['sortOrder']) || $_GET['sortOrder'] === 'ascend' ? 'ASC' : 'DESC'
);
}
return $this->listByQuery($query);
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Employees\Services;
use Employees\Common\Model\Employee;
class EmployeesService
{
public function getDirectReports($employeeId)
{
$sub = new Employee();
$subordinates = $sub->Find("supervisor = ?", array($employeeId));
return $subordinates;
}
}

View File

@@ -88,7 +88,7 @@ class EmployeesActionManager extends SubActionManager
$employee->subordinates = $subordinates;
$fs = FileService::getInstance();
$employee = $fs->updateProfileImage($employee);
$employee = $fs->updateSmallProfileImage($employee);
if (!empty($employee->birthday)) {
$employee->birthday = date("F jS, Y", strtotime($employee->birthday));

View File

@@ -27,7 +27,7 @@ class CalculationHook extends BaseModel
}
// @codingStandardsIgnoreStart
function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
{
return BaseService::getInstance()->getCalculationHooks();
}

View File

@@ -27,7 +27,7 @@ class Country extends BaseModel
}
// @codingStandardsIgnoreStart
function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
{
$allowedCountriesStr = SettingsManager::getInstance()->getSetting('System: Allowed Countries');
$allowedCountries = array();

View File

@@ -27,7 +27,7 @@ class CurrencyType extends BaseModel
}
// @codingStandardsIgnoreStart
function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
{
$allowedCountriesStr = SettingsManager::getInstance()->getSetting('System: Allowed Currencies');
$allowedCountries = array();

View File

@@ -26,7 +26,7 @@ class Nationality extends BaseModel
return array("get","element");
}
// @codingStandardsIgnoreStart
function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
{
$allowedCountriesStr = SettingsManager::getInstance()->getSetting('System: Allowed Nationality');
$allowedCountries = array();

View File

@@ -6,6 +6,7 @@ use Classes\IceResponse;
use Classes\ModuleAccess;
use Classes\ModuleAccessService;
use Modules\Common\Model\Module;
use Users\Common\Model\UserRole;
use Utils\LogManager;
class BaseModel extends \ADOdb_Active_Record
@@ -29,21 +30,21 @@ class BaseModel extends \ADOdb_Active_Record
return array("get","element","save","delete");
}
private function getRestrictedAccess($userRoles, $allowedAccessMatrix)
public function getMatchingUserRoles($userRoles)
{
if (empty($userRoles)) {
return $this->getDefaultAccessLevel();
return false;
}
$userRoles = json_decode($userRoles, true);
if (empty($userRoles)) {
return $this->getDefaultAccessLevel();
return false;
}
$moduleAccessData = $this->getModuleAccess();
if (empty($moduleAccessData)) {
return $this->getDefaultAccessLevel();
return false;
}
$modules = [];
@@ -56,35 +57,69 @@ class BaseModel extends \ADOdb_Active_Record
}
if (empty($modules)) {
return $this->getDefaultAccessLevel();
return false;
}
foreach ($modules as $module) {
if (empty($module->user_roles) || $module->user_roles == '[]') {
continue;
}
if (count(array_intersect($userRoles, json_decode($module->user_roles, true))) > 0) {
return $allowedAccessMatrix;
$matchingUserRoles = array_intersect($userRoles, json_decode($module->user_roles, true));
if (count($matchingUserRoles) > 0) {
return $matchingUserRoles;
}
}
return $this->getDefaultAccessLevel();
return false;
}
public function getRestrictedAdminAccess($userRoles)
public function getRoleBasedAccess($userLevel, $userRoles)
{
return $this->getRestrictedAccess($userRoles, $this->getAdminAccess());
$permissionMethod = "get".str_replace(' ', '', $userLevel)."Access";
$allowedAccessMatrix = $this->$permissionMethod();
$userRoles = $this->getMatchingUserRoles($userRoles);
if ($userRoles === false) {
return $allowedAccessMatrix === null ? $this->getDefaultAccessLevel() : $allowedAccessMatrix;
}
$permissions = $allowedAccessMatrix === null ? $this->getDefaultAccessLevel() : $allowedAccessMatrix;
;
foreach ($userRoles as $role) {
$userRole = new UserRole();
$userRole->Load('id = ?', [$role]);
try {
$userRolePermissions = json_decode($userRole->additional_permissions);
foreach ($userRolePermissions as $tablePermissions) {
if ($tablePermissions->table === $this->table) {
$permissions = array_unique(
array_merge(
$permissions,
json_decode($tablePermissions->permissions, true)
)
);
}
}
} catch (\Exception $e) {
}
}
return $permissions;
}
public function getRestrictedManagerAccess($userRoles)
public function getRestrictedAdminAccess()
{
return $this->getRestrictedAccess($userRoles, $this->getAdminAccess());
return $this->getAdminAccess();
}
public function getRestrictedEmployeeAccess($userRoles)
public function getRestrictedManagerAccess()
{
return $this->getRestrictedAccess($userRoles, $this->getAdminAccess());
return $this->getManagerAccess();
}
public function getRestrictedEmployeeAccess()
{
return $this->getEmployeeAccess();
}
public function getManagerAccess()

View File

@@ -74,23 +74,6 @@ class Setting extends BaseModel
return new IceResponse(IceResponse::SUCCESS, "");
}
public function executePreSaveActions($obj)
{
if ($obj->name == 'Leave: Select Leave Period from Employee Department Country') {
$oldSetting = new Setting();
$oldSetting->Load('name = ?', ['Leave: Select Leave Period from Employee Department Country']);
if (class_exists('\Leaves\Common\Model\EmployeeLeave')) {
$employeeLeave = new \Leaves\Common\Model\EmployeeLeave();
$employeeLeaves = $employeeLeave->Find("1 = 1 limit 1", []);
if (count($employeeLeaves) === 1) {
$obj->value = $oldSetting->value;
}
}
}
return new IceResponse(IceResponse::SUCCESS, $obj);
}
public function executePreUpdateActions($obj)
{
return $this->executePreSaveActions($obj);

View File

@@ -12,7 +12,7 @@ class EmployeeOvertimeApproval extends EmployeeOvertime
{
// @codingStandardsIgnoreStart
public function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
{
// @codingStandardsIgnoreEnd
return $this->findApprovals(new EmployeeOvertime(), $whereOrderBy, $bindarr, $pkeysArr, $extra);

View File

@@ -32,7 +32,7 @@ class ClientProjectTimeReport extends PDFReportBuilder implements PDFReportBuild
$projects = $project->Find("client = ?", array($request['client']));
$projectsStr = "";
$projectIds = '';
$projectIds = [];
$projectsMap = array();
foreach ($projects as $pro) {
$projectIds[] = $pro->id;

View File

@@ -15,7 +15,7 @@ use Model\BaseModel;
class StaffDirectory extends Employee
{
// @codingStandardsIgnoreStart
public function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
{
// @codingStandardsIgnoreEnd
$res = parent::Find($whereOrderBy, $bindarr, $pkeysArr, $extra);

View File

@@ -7,7 +7,7 @@ use Classes\Data\Query\DataQuery;
class StaffDirectoryRestEndPoint extends RestEndPoint
{
public function listAll(User $user)
public function listAll(User $user, $parameter = null)
{
$query = new DataQuery('StaffDirectory');
$query->setFieldMapping(

View File

@@ -69,7 +69,10 @@ class TimeSheetsActionManager extends SubActionManager
$timeSheet->status = $req->status;
//Auto approve admin timesheets
if ($req->status == 'Submitted' && BaseService::getInstance()->getCurrentUser()->user_level == 'Admin') {
if ($req->status == 'Submitted'
&& BaseService::getInstance()->getCurrentUser()->user_level == 'Admin'
&& empty($employee->supervisor)
) {
$timeSheet->status = 'Approved';
}

View File

@@ -12,7 +12,7 @@ class EmployeeTravelRecordApproval extends EmployeeTravelRecord
{
// @codingStandardsIgnoreStart
public function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
public function Find($whereOrderBy, $bindarr = false, $cache = false, $pkeysArr = false, $extra = array())
{
// @codingStandardsIgnoreEnd
return $this->findApprovals(

View File

@@ -60,8 +60,7 @@ class User extends BaseModel
}
}
$permissionManager = new PermissionManager();
if ($permissionManager->isRestrictedUserLevel($obj->user_level) && empty($obj->default_module)) {
if (PermissionManager::isRestrictedUserLevel($obj->user_level) && empty($obj->default_module)) {
return new IceResponse(
IceResponse::ERROR,
'Restricted users must always have a default module'

View File

@@ -0,0 +1,70 @@
<?php
namespace Users\Rest;
use Classes\BaseService;
use Classes\IceResponse;
use Classes\PasswordManager;
use Classes\RestApiManager;
use Classes\RestEndPoint;
use Users\Common\Model\User;
use Utils\LogManager;
class UserRestEndPoint extends RestEndPoint
{
public function post(User $user)
{
$body = $this->getRequestBody();
if (!isset($body['grant_type']) || $body['grant_type'] !== 'password') {
return new IceResponse(IceResponse::ERROR, 'Missing grant_type', 400);
}
if (!isset($body['client_id'])) {
return new IceResponse(IceResponse::ERROR, 'Missing client_id', 400);
}
if (!isset($body['client_secret'])) {
return new IceResponse(IceResponse::ERROR, 'Missing client_secret', 400);
}
if (!isset($body['username'])) {
return new IceResponse(IceResponse::ERROR, 'Missing username', 400);
}
if (!isset($body['password'])) {
return new IceResponse(IceResponse::ERROR, 'Missing password', 400);
}
$user = new User();
$user->Load(
"username = ? or email = ?",
[
$body['username'],
$body['username'],
]
);
if (!PasswordManager::verifyPassword($body['password'], $user->password)) {
return new IceResponse(IceResponse::ERROR, 'Incorrect username or password', 401);
}
$resp = RestApiManager::getInstance()->getAccessTokenForUser($user);
if ($resp->getStatus() != IceResponse::SUCCESS) {
LogManager::getInstance()->error(
"Error occurred while creating REST Api access token for ".$user->username
);
return new IceResponse(IceResponse::ERROR, 'Error generating access token', 401);
}
$responseData = [
"access_token" => $resp->getData(),
"token_type" => "bearer",
"expires_in" => 3600,
"scope" => strtolower($user->user_level),
];
return new IceResponse(IceResponse::SUCCESS, $responseData, 200);
}
}