Установка базы данных CakePHP ACL: ARO / структура ACO?

В случае ArrayList: remove (int index) - если (индекс - позиция последнего элемента), он избегает без System.arraycopy() и не занимает времени для этого.

Время arraycopy увеличивается, если (индекс уменьшается), кстати, элементы списка также уменьшаются!

лучший эффективный способ удаления - удаление его элементов в порядке убывания: while(list.size()>0)list.remove(list.size()-1); // принимает O (1) while(list.size()>0)list.remove(0); // принимает O (факториал ( n))

//region prepare data
ArrayList<Integer> ints = new ArrayList<Integer>();
ArrayList<Integer> toRemove = new ArrayList<Integer>();
Random rdm = new Random();
long millis;
for (int i = 0; i < 100000; i++) {
    Integer integer = rdm.nextInt();
    ints.add(integer);
}
ArrayList<Integer> intsForIndex = new ArrayList<Integer>(ints);
ArrayList<Integer> intsDescIndex = new ArrayList<Integer>(ints);
ArrayList<Integer> intsIterator = new ArrayList<Integer>(ints);
//endregion

// region for index
millis = System.currentTimeMillis();
for (int i = 0; i < intsForIndex.size(); i++) 
   if (intsForIndex.get(i) % 2 == 0) intsForIndex.remove(i--);
System.out.println(System.currentTimeMillis() - millis);
// endregion

// region for index desc
millis = System.currentTimeMillis();
for (int i = intsDescIndex.size() - 1; i >= 0; i--) 
   if (intsDescIndex.get(i) % 2 == 0) intsDescIndex.remove(i);
System.out.println(System.currentTimeMillis() - millis);
//endregion

// region iterator
millis = System.currentTimeMillis();
for (Iterator<Integer> iterator = intsIterator.iterator(); iterator.hasNext(); )
    if (iterator.next() % 2 == 0) iterator.remove();
System.out.println(System.currentTimeMillis() - millis);
//endregion
  • для индексной петли: 1090 мс
  • для индекса desc: 519 мсек --- лучший
  • для итератора: 1043 мсек
21
задан Gaurav Sharma 3 May 2010 в 09:55
поделиться

1 ответ

Встроенная система ACL CakePHP действительно мощна, но плохо зарегистрированная с точки зрения деталей фактической реализации. Система, которую мы использовали с некоторым успехом во многих находящихся в CakePHP проектах, следующие.

Это - модификация некоторых систем доступа уровня группы, которые были зарегистрированы в другом месте . Цели нашей системы состоят в том, чтобы иметь простую систему, где пользователи авторизовываются на уровне группы, но они могут иметь определенные дополнительные права на объектах, которые были созданы ими, или на основе в расчете на пользователя. Мы хотели избежать необходимости создавать определенную запись для каждого пользователя (или, больше специально для каждого ARO) в aros_acos таблица.

у Нас есть таблица Users и таблица Roles.

Пользователи

user_id, user_name, role_id

Роли

id, role_name

Создают дерево ARO для каждой роли (у нас обычно есть 4 роли - Лишенный полномочий Гость (идентификатор 1), Авторизованный пользователь (идентификатор 2), Модератор сайта (идентификатор 3) и Администратор (идентификатор 4)):

cake acl create aro / Role.1

cake acl create aro 1 Role.2 ... etc ...

После этого необходимо использовать SQL или phpMyAdmin или подобный для добавления псевдонимов для всех них, поскольку инструмент командной строки пирога не делает этого. Мы используем 'Роль - {идентификатор}' и 'Пользователя - {идентификатор}' для всех наших.

Мы тогда создаем КОРНЕВОЙ ACO -

cake acl create aco / 'ROOT'

и затем создаем ACOS для всех контроллеров под этим КОРНЕВЫМ:

cake acl create aco 'ROOT' 'MyController' ... etc ...

До сих пор настолько нормальный. Мы добавляем дополнительное поле в aros_acos таблице, названной _editown, который мы можем использовать в качестве дополнительного действия в actionMap компонента ACL.

CREATE TABLE IF NOT EXISTS `aros_acos` (
`id` int(11) NOT NULL auto_increment,
`aro_id` int(11) default NULL,
`aco_id` int(11) default NULL,
`_create` int(11) NOT NULL default '0',
`_read` int(11) NOT NULL default '0',
`_update` int(11) NOT NULL default '0',
`_delete` int(11) NOT NULL default '0',
`_editown` int(11) NOT NULL default '0',
PRIMARY KEY  (`id`),
KEY `acl` (`aro_id`,`aco_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Мы можем тогда установить Подлинный компонент для использования метода 'свернувшегося молока', который проверяет требуемый контроллер/действие против AclComponent:: проверьте (). В app_controller у нас есть что-то вроде:

private function setupAuth() {
    if(isset($this->Auth)) {
        ....
        $this->Auth->authorize = 'crud';
        $this->Auth->actionMap = array( 'index'     => 'read',
                        'add'       => 'create',
                        'edit'      => 'update'
                        'editMine'  => 'editown',
                        'view'      => 'read'
                        ... etc ...
                        );
        ... etc ...
    }
}

Снова, это - довольно стандартный материал CakePHP. У нас тогда есть checkAccess метод в AppController, который добавляет в материале уровня группы, чтобы проверить, проверить ли группу ARO или пользователь ARO для доступа:

private function checkAccess() {
    if(!$user = $this->Auth->user()) {
        $role_alias = 'Role-1';
        $user_alias = null;
    } else {
        $role_alias = 'Role-' . $user['User']['role_id'];
        $user_alias = 'User-' . $user['User']['id'];
    }

    // do we have an aro for this user?
    if($user_alias && ($user_aro = $this->User->Aro->findByAlias($user_alias))) {
        $aro_alias = $user_alias;
    } else {
        $aro_alias = $role_alias;
    }

    if ('editown' == $this->Auth->actionMap[$this->action]) {
        if($this->Acl->check($aro_alias, $this->name, 'editown') and $this->isMine()) {
            $this->Auth->allow();
        } else {
            $this->Auth->authorize = 'controller';
            $this->Auth->deny('*');
        }
    } else {
        // check this user-level aro for access
        if($this->Acl->check($aro_alias, $this->name, $this->Auth->actionMap[$this->action])) {
            $this->Auth->allow();
        } else {
            $this->Auth->authorize = 'controller';
            $this->Auth->deny('*');
        }
    }
}

setupAuth() и checkAccess() методы называют в AppController beforeFilter(), обратный вызов. Существует isMine метод в AppControler также (см. ниже), который просто проверяет, что user_id требуемого объекта совпадает с в настоящее время аутентифицируемым пользователем. Я пропустил это для ясности.

Это - действительно все, которое существует к нему. Можно тогда позволить / запрещают особого доступа групп к определенному acos -

cake acl grant 'Role-2' 'MyController' 'read'

cake acl grant 'Role-2' 'MyController' 'editown'

cake acl deny 'Role-2' 'MyController' 'update'

cake acl deny 'Role-2' 'MyController' 'delete'

я уверен, что Вы получаете изображение.

Так или иначе, путь этого ответа дольше, чем я предназначил его, чтобы быть, и это, вероятно, не делает рядом ни с каким смыслом, но я надеюсь, что это - некоторая справка к Вам...

- редактирование -

Согласно просьбе, вот отредактированный (просто для ясности - существует много материала в нашем шаблонном коде, это бессмысленно здесь) isMine() метод, который мы имеем в нашем AppController. Я удалил много материала проверки ошибок также, но это - сущность его:

function isMine($model=null, $id=null, $usermodel='User', $foreignkey='user_id') {
    if(empty($model)) {
        // default model is first item in $this->uses array
        $model = $this->uses[0];
    }

    if(empty($id)) {
        if(!empty($this->passedArgs['id'])) {
        $id = $this->passedArgs['id'];
        } elseif(!empty($this->passedArgs[0])) {
            $id = $this->passedArgs[0];
        }
    }

    if(is_array($id)) {
        foreach($id as $i) {
            if(!$this->_isMine($model, $i, $usermodel, $foreignkey)) {
                return false;
            }
        }

        return true;
    }

    return $this->_isMine($model, $id, $usermodel, $foreignkey);
}


function _isMine($model, $id, $usermodel='User', $foreignkey='user_id') {
    $user = Configure::read('curr.loggedinuser'); // this is set in the UsersController on successful login

    if(isset($this->$model)) {
        $model = $this->$model;
    } else {
        $model = ClassRegistry::init($model);
    }

    //read model
    if(!($record = $model->read(null, $id))) {
        return false;
    }

    //get foreign key
    if($usermodel == $model->alias) {
        if($record[$model->alias][$model->primaryKey] == $user['User']['id']) {
            return true;
        }
    } elseif($record[$model->alias][$foreignkey] == $user['User']['id']) {
        return true;
    }

    return false;
}
49
ответ дан 29 November 2019 в 20:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: