AccessRestrictable 2

A Yii ActiveRecordBehavior that automatically applies conditions for access restriction to every query.

codemix/AccessRestrictable

Written in PHP by 2 contributors

Contribute

Need Support?


we offer maintenance, support and development services for all our open source projects.

Contact Us

AccessRestrictable

This behavior adds automatic access restriction to your ActiveRecord queries.

By doing so it introduces a new security layer right inside the models. If any user tries to access resources that he doesn't have permission to, the query result will simply be empty.

Installation

We recommend to install the extension with composer. Add this to the require section of your composer.json:

'codemix/accessrestrictable' : 'dev-master'

Note: There's no stable version yet.

You also need to include composer's autoloader on top of your index.php:

require_once __DIR__.'/protected/vendor/autoload.php';

Make sure to fix the path to your composer's vendor directory. Finally you also need to configure an alias in your main.php:

$vendor = realpath(__DIR__.'/../vendor');
return array(
    'alias' => array(
        'AccessRestrictable' => $vendor.'/codemix/AccessRestrictable/src/AccessRestrictable',
    ),
    ...

Configuration

To enable access restriction you have to attach the behavior to an ActiveRecord like so:

<?php
class Post extends CActiveRecord
{
    public function behaviors()
    {
        return array(
            'restrictable' => array(
                'class'             => 'AccessRestrictable\Behavior',

                // Optional settings with default values
                // 'enableRestriction' => true
            ),
        );
    }

Restrict read access

To restrict read access for all your queries, you can implement a beforeRead() method in your record. It can return a boolean to either apply no restriction at all (true) or restrict access completely (false).

Though the more common use case will be, to return a criteria that will be applied to all queries, and that limits the result set to records that the current user has access to. To do so the method can either return a CDbCriteria or an array with criteria parameters.

Here's an example:

public function beforeRead()
{
    $user   = Yii::app()->user;
    $table  = $this->getTableAlias();

    if($user->checkAccess('admin')) {
        return true;    // no restriction for administrators
    } elseif($user->checkAccess('organizationAdmin')) {
        $userRecord = User::model()->findByPk(Yii::app()->user->id);

        // Admins in an organisation are allowed to see all users from that organisation
        return array(
            'condition' => "$table.organisation_id = :organisation",
            'params'    => array(':organisation' => $userRecord->organisation_id),
        );
    } else {
        // All other users can only query their own user record
        return array(
            'condition' => "$table.user_id = :id",
            'params'    => array(':id' => Yii::app()->user->id),
        );
    }
}

Restrict write access

In order to restrict write access for records, you can implement a beforeWrite() method in your record. It will be called before any insert, update or delete operation and must returns, whether the operation should be performed.

For example:

public function beforeWrite()
{
    $user   = Yii::app()->user;

    if($user->checkAccess('admin')) {
        return true;    // admin can always write
    } elseif($user->checkAccess('organizationAdmin')) {
        $userRecord = User::model()->findByPk(Yii::app()->user->id);

        // Admins in an organisation are allowed to update all users from that organisation
        if($userRecord->organisation_id == $this->organisation_id) {
            return true;
        }
    } elseif($user->id==$this->id) {
        // All users can update their own user record
        return true;
    }

    // All others are denied
    return false;
}

Usage

If you've attached the behavior, then whenever you do a query like

<?php
$posts = Post::model()->findAll();

only the records that fullfill the beforeRead() condition will be returned.

In the same way any $post->save() will fail, if beforeWrite() returns false.

Override query restriction

But what if you want to query for all records, e.g. for an admin panel you may ask. You can use the unrestricted() scope for this:

<?php
$posts = Post::model()->unrestricted()->findAll();

Note: If you did another (restricted) query before, the restriction condition will be applied to the internal model criteria. To reset any potential scopes, you could either call resetScope() or pass true as argument to unrestricted().

Override write restriction

For write operations you can call the force() method before you write. This will bypass the beforeWrite() check and always save the record. For convenience it returns the same record, so you can easily chain your calls:

<?php
$post->force()->save();

Note: Validation rules are still applied. So if your record has validation errors, it will not be saved, even if you called force() before.

Disable automatic query and write restriction

You can also disable the automatic access restriction and only do restricted queries and writes on explicit demand. To do so you need to set enableRestriction to false in the behavior configuration.

You then can apply the restriction query condition through a named scope:

<?php
$posts = Post::model()->readable()->findAll();

For write operations you'd use the writeable() constraint:

<?php
$post->writeable()->save();

Limitations

Due to the limitations in the ActiveRecord implementation, the constraints from this behavior are not applied when you use one of the following methods:

  • deleteAll()
  • saveAttributes()
  • saveCounters()
  • findBySql()
  • findAllBySql()
  • countBySql()
  • exists()
  • updateByPk()
  • updateAll()
  • updateCounters()
  • deleteByPk()
  • deleteAll()
  • deleteAllByAttributes()

We recommend to avoid the above methods, or only use them if you're sure about the implications.





43 other PHP projects


phpwkhtmltopdfPHP 716

A slim PHP wrapper around wkhtmltopdf with an easy to use and clean OOP interface

php-pdftkPHP 213

A PDF conversion and form utility based on pdftk

yii2-localeurlsPHP 189

Automatic locale/language management for URLs

YiiRedisPHP 131

A set of wrappers for different data types in redis

yiipasswordPHP 81

Password strategies for Yii

yii2-dockerizedPHP 64

A template for docker based Yii 2 applications

YiiSolrPHP 50

A wrapper for the pecl solr library that provides common Yii constructs, such as models, data providers etc

php-shellcommandPHP 48

A simple object oriented interface to execute shell commands in PHP

Yii-Docs-GeneratorPHP 47

Generates HTML documentation for Yii applications

YiiGitPHP 36

A git wrapper for Yii, allows access to all git commands programatically

YiiElasticSearchPHP 32

Elastic Search client for Yii

YiiCurlPHP 30

A curl library for Yii

YiiStateMachinePHP 28

A state machine behavior for Yii

yii2-streamlogPHP 19

A Yii 2 log target for streams in URL format

oauth2yiiPHP 18

An OAuth2 client / server extension for the Yii framework

restyiiPHP 16

A RESTful extension for Yii.

packagecompressorPHP 16

A Javascript/CSS compressor based on Yii's package system

localeurlsPHP 12

Automatic locale/language management for URLs

php-excel-readerPHP 12

It reads the binary format of XLS files directly and can return values and formats from any cell. This project is the fork of http://code.google.com/p/php-excel-reader/ that, apparently, is no longer maintained.

pdfablePHP 10

A Yii extension to create PDFs with PHPWkHtmlToPdf/wkhtmltopdf

yii-api-vimPHP 8

Yii API manual plugin for VIM

yii2-excel-messagePHP 7

Translate messages via Excel files

xcrudcontrollerPHP 7

A base class to quickly build customized CRUD interfaces.

yii2-bs3activeformPHP 7

A Bootstrap 3 enhanced ActiveForm for Yii 2

php-tmpfilePHP 6

A convenience class for temporary files

handlebarsphpPHP 6

Transpiles handlebars templates into native PHP templates

Yii-Package-ManagerPHP 6

A package manager for Yii

php-orientdbPHP 5

A fast PHP driver for the OrientDB binary protocol.

yii2-apidoc-vimPHP 5

Yii2 apidoc as Vim helpfiles

translatablePHP 4

Transparent attribute translation for ActiveRecords

YiiUsersPHP 4

User management for Yii

flushablePHP 3

Yii dependency that allows to flush records from the cache

Yii-Resource-ManagerPHP 3

Helpers to allow Yii to interact with resources (files) of different types

bs3activeformPHP 2

A lightweight utility to render Bootstrap 3 forms in Yii

YiiEmailerPHP 2

Emailing functions for Yii

hybridauthmanagerPHP 1

An AuthManager for Yii that stores the hierarchy in a flat PHP file and the assignments in DB

defaultpersisterPHP 1

Yii extension to save and restore model values in user session.

YiiYaaPHP 1

YAA is an additional abstraction layer for Yii that aggregates a number of child models into a clean single model that is easy to cache

YiiLinkablePHP 1

A simple extension for Yii allowing easy and consistent access to model URLs and appropriate anchor text.

twittonioPHP

simple useless twitter client

yii2-base-appPHP

An alternative Yii2 application template for purists

YiiAbstractArrayModelPHP

Work with PHP files in Active Record way

xreturnablePHP

Yii extension to create URLs that allow to return to a page by storing its GET Parameters on a stack.