This commit is contained in:
Yuri Kuznetsov
2014-01-06 13:55:18 +02:00
parent a8feead8de
commit 4928076eb5
11 changed files with 174 additions and 61 deletions

View File

@@ -4,6 +4,5 @@ namespace Espo\Controllers;
class User extends \Espo\Core\Controllers\Record
{
}

View File

@@ -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)
{

View File

@@ -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();
}

View File

@@ -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);
}
}
}

View File

@@ -32,6 +32,7 @@ class EntityManager extends \Espo\ORM\EntityManager
public function normalizeEntityName($name)
{
return $this->espoMetadata->getEntityPath($name);
}
}
}

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -7,5 +7,5 @@ class User extends \Espo\Core\ORM\Entity
public function isAdmin()
{
return $this->get('isAdmin');
}
}
}

View File

@@ -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]);
}

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace Espo\Services;
class User extends Record
{
public function getEntity($id)
{
$entity = parent::getEntity($id);
$entity->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);
}
}