diff --git a/application/Espo/Controllers/User.php b/application/Espo/Controllers/User.php index cee0202c25..8672786991 100644 --- a/application/Espo/Controllers/User.php +++ b/application/Espo/Controllers/User.php @@ -4,6 +4,5 @@ namespace Espo\Controllers; class User extends \Espo\Core\Controllers\Record { - } diff --git a/application/Espo/Core/Acl.php b/application/Espo/Core/Acl.php index f8e6643d39..09437afa4a 100644 --- a/application/Espo/Core/Acl.php +++ b/application/Espo/Core/Acl.php @@ -15,6 +15,7 @@ class Acl public function __construct(\Espo\Entities\User $user) { $this->user = $user; + $this->user->loadLinkMultipleField('teams'); $this->cacheFile = 'data/cache/application/acl/' . $user->id; @@ -22,21 +23,22 @@ class Acl $cached = include $this->cacheFile; } else { $this->load(); + $this->initSolid(); $this->buildCache(); } } - public function checkScope($subject, $action = null, $isOwner = null, $inTeam = null) + public function checkScope($scope, $action = null, $isOwner = null, $inTeam = null) { - if (isset($this->data[$scope])) { + if (array_key_exists($scope, $this->data)) { if ($this->data[$scope] === false) { return false; } if ($this->data[$scope] === true) { return true; } - if ($action) { - if (isset($this->data[$scope][$action])) { + if (!is_null($action)) { + if (array_key_exists($action, $this->data[$scope])) { $value = $this->data[$scope][$action]; if ($value === 'all' || $value === true) { @@ -45,9 +47,9 @@ class Acl if (!$value || $value === 'no') { return false; - } + } - if ($isOwner === null) { + if (is_null($isOwner)) { return true; } @@ -82,17 +84,38 @@ class Acl return true; } if (is_string($subject)) { - return $this->checkScope($subject, $action = null, $isOwner = null, $inTeam = null); + return $this->checkScope($subject, $action, $isOwner, $inTeam); } else { $entity = $subject; - $entityName = ltrim(get_class($entity), '\\'); - + $entityName = $entity->getEntityName(); return $this->checkScope($entityName, $action, $this->checkIsOwner($entity), $this->checkInTeam($entity)); } } + + public function checkReadOnlyTeam($scope) + { + if (isset($this->data[$scope]) && isset($this->data[$scope]['read'])) { + return $this->data[$scope]['read'] === 'team'; + } + return false; + } + + public function checkReadOnlyOwn($scope) + { + if ($this->user->isAdmin()) { + return false; + } + if (isset($this->data[$scope]) && isset($this->data[$scope]['read'])) { + return $this->data[$scope]['read'] === 'own'; + } + return false; + } public function checkIsOwner($entity) { + if ($this->user->isAdmin()) { + return false; + } $userId = $this->user->id; if ($userId === $entity->get('assignedUserId') || $userId === $entity->get('createdById')) { return true; @@ -133,6 +156,21 @@ class Acl $this->data = $this->merge($aclTables); } + + private function initSolid() + { + $this->data['User'] = array( + 'read' => 'all', + 'edit' => 'no', + 'delete' => 'no', + ); + $this->data['Team'] = array( + 'read' => 'all', + 'edit' => 'no', + 'delete' => 'no', + ); + $this->data['Role'] = false; + } private function merge($tables) { diff --git a/application/Espo/Core/Controllers/Record.php b/application/Espo/Core/Controllers/Record.php index 04f4ee322d..021b1f429b 100644 --- a/application/Espo/Core/Controllers/Record.php +++ b/application/Espo/Core/Controllers/Record.php @@ -33,17 +33,12 @@ abstract class Record extends Base public function actionRead($params) { $id = $params['id']; - $service = $this->getRecordService(); - $entity = $service->getEntity($id); + $entity = $this->getRecordService()->getEntity($id); if (empty($entity)) { throw new NotFound(); } - if (!$this->getAcl()->check($entity, 'read')) { - throw new Forbidden(); - } - return $entity->toArray(); } diff --git a/application/Espo/Core/ORM/Entity.php b/application/Espo/Core/ORM/Entity.php index 8df0e2e9fe..c991fc6cd8 100644 --- a/application/Espo/Core/ORM/Entity.php +++ b/application/Espo/Core/ORM/Entity.php @@ -4,6 +4,20 @@ namespace Espo\Core\ORM; class Entity extends \Espo\ORM\Entity { - + public function loadLinkMultipleField($field) + { + if ($this->hasRelation($field) && $this->hasField($field . 'Ids')) { + $collection = $this->get($field); + $ids = array(); + $names = new \stdClass(); + foreach ($collection as $e) { + $id = $e->id; + $ids[] = $id; + $names->$id = $e->get('name'); + } + $this->set($field . 'Ids', $ids); + $this->set($field . 'Names', $names); + } + } } diff --git a/application/Espo/Core/ORM/EntityManager.php b/application/Espo/Core/ORM/EntityManager.php index 0543321bc6..c7b6b8b7aa 100644 --- a/application/Espo/Core/ORM/EntityManager.php +++ b/application/Espo/Core/ORM/EntityManager.php @@ -32,6 +32,7 @@ class EntityManager extends \Espo\ORM\EntityManager public function normalizeEntityName($name) { return $this->espoMetadata->getEntityPath($name); - } + } + } diff --git a/application/Espo/Core/SelectManager.php b/application/Espo/Core/SelectManager.php index b695fd2c30..c47d42404f 100644 --- a/application/Espo/Core/SelectManager.php +++ b/application/Espo/Core/SelectManager.php @@ -27,11 +27,19 @@ class SelectManager { $this->entityName = $entityName; } - - public function getSelectParams(array $params, $withAcl = false) - { - $result = array(); - + + protected function limit($params, &$result) + { + if (isset($params['offset']) && !is_null($params['offset'])) { + $result['offset'] = $params['offset']; + } + if (isset($params['maxSize']) && !is_null($params['maxSize'])) { + $result['limit'] = $params['maxSize']; + } + } + + protected function order($params, &$result) + { if (!empty($params['sortBy'])) { $result['orderBy'] = $params['sortBy']; } @@ -42,14 +50,10 @@ class SelectManager $result['order'] = 'DESC'; } } - - if (isset($params['offset']) && !is_null($params['offset'])) { - $result['offset'] = $params['offset']; - } - if (isset($params['maxSize']) && !is_null($params['maxSize'])) { - $result['limit'] = $params['maxSize']; - } - + } + + protected function where($params, &$result) + { if (!empty($params['where']) && is_array($params['where'])) { $where = array(); @@ -101,12 +105,42 @@ class SelectManager } - //print_r($where); - //die; - $result['whereClause'] = $where; } + } + + protected function access(&$result) + { + if ($this->acl->checkReadOnlyOwn($this->entityName)) { + if (!array_key_exists('whereClause', $result)) { + $result['whereClause'] = array(); + } + $result['whereClause']['assignedUserId'] = $this->user->id; + } + if ($this->acl->checkReadOnlyTeam($this->entityName)) { + if (!array_key_exists('whereClause', $result)) { + $result['whereClause'] = array(); + } + if (!array_key_exists('joins', $result)) { + $result['joins'] = array(); + if (!in_array('teams', $result['joins'])) { + $result['joins'][] = 'teams'; + } + } + $result['whereClause']['Team.id'] = $this->user->get('teamsIds'); + } + } + public function getSelectParams(array $params, $withAcl = false) + { + $result = array(); + + $this->order($params, $result); + $this->limit($params, $result); + $this->where($params, $result); + if ($withAcl) { + $this->access($result); + } return $result; } diff --git a/application/Espo/Core/Utils/Api/Auth.php b/application/Espo/Core/Utils/Api/Auth.php index fc54bbf54c..5cac0386ca 100644 --- a/application/Espo/Core/Utils/Api/Auth.php +++ b/application/Espo/Core/Utils/Api/Auth.php @@ -42,7 +42,6 @@ class Auth extends \Slim\Middleware $authSec = $req->headers('PHP_AUTH_PW'); if ($authKey && $authSec) { - $isAuthenticated = false; $username = $authKey; @@ -51,20 +50,14 @@ class Auth extends \Slim\Middleware $user = $this->entityManager->getRepository('User')->findOne(array( 'whereClause' => array( 'userName' => $username, + 'password' => md5($password) ), )); - - if ($user instanceof \Espo\Entities\User) { - - $this->entityManager->setUser($user); - - if ($password == $user->get('password')) { - $this->container->setUser($user); - $isAuthenticated = true; - } + if ($user instanceof \Espo\Entities\User) { + $this->entityManager->setUser($user); + $this->container->setUser($user); + $isAuthenticated = true; } - - if ($isAuthenticated) { $this->next->call(); } else { diff --git a/application/Espo/Entities/User.php b/application/Espo/Entities/User.php index 7a58a7b347..448b780ecf 100644 --- a/application/Espo/Entities/User.php +++ b/application/Espo/Entities/User.php @@ -7,5 +7,5 @@ class User extends \Espo\Core\ORM\Entity public function isAdmin() { return $this->get('isAdmin'); - } + } } diff --git a/application/Espo/ORM/Entity.php b/application/Espo/ORM/Entity.php index f8e450f913..a7223f5f13 100644 --- a/application/Espo/ORM/Entity.php +++ b/application/Espo/ORM/Entity.php @@ -60,8 +60,11 @@ abstract class Entity implements IEntity } } - public function clear($name) + public function clear($name = null) { + if (is_null($name)) { + $this->reset(); + } unset($this->valuesContainer[$name]); } diff --git a/application/Espo/Services/Record.php b/application/Espo/Services/Record.php index 02723131c2..541c85a179 100644 --- a/application/Espo/Services/Record.php +++ b/application/Espo/Services/Record.php @@ -3,6 +3,7 @@ namespace Espo\Services; use \Espo\Core\Exceptions\Error; +use \Espo\Core\Exceptions\Forbidden; use \Espo\Core\Utils\Util; class Record extends \Espo\Core\Services\Base @@ -58,7 +59,14 @@ class Record extends \Espo\Core\Services\Base if (!empty($entity) && !empty($id)) { $this->loadLinkMultipleFields($entity); $this->loadParentNameFields($entity); - } + } + + if (!empty($entity) && !empty($id)) { + if (!$this->getAcl()->check($entity, 'read')) { + throw new Forbidden(); + } + } + return $entity; } @@ -67,18 +75,7 @@ class Record extends \Espo\Core\Services\Base $fieldDefs = $this->getMetadata()->get('entityDefs.' . $this->entityName . '.fields', array()); foreach ($fieldDefs as $field => $defs) { if ($defs['type'] == 'linkMultiple') { - if ($entity->hasRelation($field) && $entity->hasField($field . 'Ids')) { - $collection = $entity->get($field); - $ids = array(); - $names = new \stdClass(); - foreach ($collection as $e) { - $id = $e->id; - $ids[] = $id; - $names->$id = $e->get('name'); - } - $entity->set($field . 'Ids', $ids); - $entity->set($field . 'Names', $names); - } + $entity->loadLinkMultipleField($field); } } } diff --git a/application/Espo/Services/User.php b/application/Espo/Services/User.php new file mode 100644 index 0000000000..08d59f75c8 --- /dev/null +++ b/application/Espo/Services/User.php @@ -0,0 +1,39 @@ +clear('password'); + return $entity; + } + + public function findEntities($params) + { + $result = parent::findEntities($params); + foreach ($result['collection'] as $entity) { + $entity->clear('password'); + } + return $result; + } + + public function createEntity($data) + { + if (array_key_exists('password', $data)) { + $data['password'] = md5($data['password']); + } + return parent::createEntity($data); + } + + public function updateEntity($id, $data) + { + if (array_key_exists('password', $data)) { + $data['password'] = md5($data['password']); + } + return parent::updateEntity($id, $data); + } +} +