GithubHelp home page GithubHelp logo

lock's People

Contributors

driesvints avatar grahamcampbell avatar mickrip avatar njohns-grovo avatar remipelhate avatar zspine avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lock's Issues

PhalconDriver assertion failures

Hi guys,

I'm trying to write a Phalcon driver for Lock, but testing it with the PersistentDriverTestCase you've provided, I get 10 failures. Since Phalcon's ORM isn't much different from Laravel's Eloquent, to which you've kindly provided a driver, I felt it should be a pretty easy job converting that driver to Phalcon, but I'm at a loss now.
Maybe these failures give you a clue what I've done wrong or where to look for the problems? The failures are as follows:

it_can_check_multiple_permissions_at_once
PersistentDriverTestCase.php:230

it_can_clear_multiple_permissions_at_once
PersistentDriverTestCase.php:242

it_only_clears_the_requested_permissions
PersistentDriverTestCase.php:255

it_only_clears_permissions_on_the_given_resource
PersistentDriverTestCase.php:268

it_can_clear_every_single_permission_for_a_lock_instance
PersistentDriverTestCase.php:282

it_can_toggle_multiple_permissions_at_once
PersistentDriverTestCase.php:329

it_can_check_actions_from_aliases
PersistentDriverTestCase.php:367

it_can_work_with_roles
PersistentDriverTestCase.php:402

it_can_return_allowed_resource_ids
PersistentDriverTestCase.php:452

it_can_return_denied_resource_ids
PersistentDriverTestCase.php:470

I'm grateful and happy about any feedback you can give me. Thank you for coding this very cool package.
Cheers, Christian

Allowed/Denied caller/role for a resource

Hi !

Is it possible to get an array of all callers and/or roles having privilege/restriction of a resource ?

For the moment, it's possible to make something like this $caller->getPersmissions()
But it would useful for me to be able to make something like this $resource->getAllowedCallers() (and the same for Roles and the same for "restriction" permission)

Individual users should be able to have different roles

Is it possible to have individual users have different roles? I see that get Caller::getCallerRoles() allows you to set what role you would like to have, but that is for all User instances.

I would like for getCallerRoles() to return a different value depending on who, I'm logged in as. I would like to query the db to return this value instead of having it hard coded. When I tried this approach, I realized that caller data and role data can never be set at the same time in the lock_permissions table.

Lock permission clear

Hi,

is there any particular reason why you only remove permission that is instance of Privilege but not Restriction?

The problem about creating new role and the structure.

Let's say I have three roles: Admin, Editor, User.

Admin can edits everyone's posts.
Editor can edits everyone's posts except admin's.
User can only edits their own posts.

Database structure

Post table

id author content
1 ImUser foobar.
2 ImEditor hello, world!
3 ImAdmin Hi!

User table

username rank
ImUser user
ImEditor editor
ImAdmin admin

User Permission table

Insert a new row each time the user create a post,

ImUser and ImEditor created the post, so they got the permission to edit their own post.

username action resource_type resource_id
ImUser edit posts 1
ImEditor edit posts 2

Role Permission table

Admin can edit any posts so we set the resource_id as null.

The row of the editor one has been inserted after ImUser created the post,

so editor has the permission to edit the post #1.

role action resource_type resource_id
admin edit posts NULL
editor edit posts 1

Problem

So If I want to create a new role named 'moderator' for example,

and moderator should've the permission to edit editor and user's posts,

but because we added the role after ImUser and ImEditor created their posts (#1 and #2)

now moderator has no permission to edit the post #1 and #2, how can I solve this problem?

And won't it be such a mess If I do really use this structure?

Think about this if I have many roles and posts:

role action resource_type resource_id
admin edit posts NULL
admin remove posts NULL
editor edit posts 1
editor remove posts 1
moderator edit posts 1
moderator remove posts 1

.. and many rows ..

Summarize

1.How do I fix the permission problem?
2.Is it bad to use this structure or everyone use it like this?

It's my first time to use the ACL system, any ideas even not an answer would be appreciated.

Flushing drivers

I think it would be better to be able to flush drivers at some point instead of updating them all upon request. This would allow saving roles at once. With a good ORM behind all queries to the database are optimized for the best performance.

Discussion: tagging stable

Good Evening!
I'm opening this issue as a discussion to find out what is left for this to be tagged as 1.0 stable? This pr ( #42 ) exists to provide an easy transition path to that in the interim but it would be great to get this 1.0-stable :)

Why differs the sample implementation of a driver from the laravel lock?

The Laravel lock uses a single table, see this file. But the example implementation in the readme.md shows two tables. Why? And why would I use the two tables instead of the single table from the Laravel plugin?

I'm asking because I'm building a CakePHP 3.0 plugin which has been so far surprisingly easy because the ORM is almost the same as Laravals. I copied the Laravel driver and started adapting the code and I think I'm already done with the very basics (test aside). My only show stopper right now is if I should or have to use one or two tables for a better implementation.

Edit: After reading the code a little more I guess the two table solutions would be better because I can see that the driver interface features Role and Caller methods? So I assume the methods that have Role in their name should use the roles table and the other methods the callers table? Is that how it is thought?

Additional tests, eg: allow edit of own posts

Maybe I missed it in the README, but how would you go about allowing a role/caller to only allow something based on an assertion (function, method, etc)? Like if you have a user/role, and you only want to allow them editing their own posts. I see the example of using a static integer, but not sure how you could instead do something like this. Just wondering.
Thank you.

Allow resources to inherit permissions

I've come to the conclusion that it would be nice if resources could inherit permissions from other resources. For example, take a contact entity. The contact could be either a person or a company. I want a caller or a role to both be able to create persons and companies but they should only be able to edit a person record and not a company. Currently this would be solved by doing the following:

$manager->caller($user)->allow('create', 'person');
$manager->caller($user)->allow('create', 'company');
$manager->caller($user)->allow('edit', 'person');

By allowing for permission inheritance through resources I could add a new method to the Resource interface called getInheritedResource which would return the resource type from which the resource inherits permissions from. So a Person entity could look like this:

<?php

use BeatSwitch\Lock\Resources\Resource

class Person extends Contact implements Resource
{
    private $id;

    public function getResourceType()
    {
        return 'person';
    }

    public function getResourceId()
    {
         return $this->id;
    }

    public function getInheritedResource()
    {
        return parent::getResourceType();
    }
}

And now it's easy to set permissions on a parent resource type and reducing the number of calls we have to make:

$manager->caller($user)->allow('create', 'contact');
$manager->caller($user)->allow('edit', 'person');

What do you guys think about this?

Schema

Is there a DB Schema? I can't seem to find it in this Repo...

Tying multiple users to a role

I can create a role by doing:

LockManager::role('auth-user')->allow('create', 'tasks');

That will be the equivalent of a database insert statement

//only auth-user's can create tasks
DB::table('lock_permissions')->insert(
    [
                'caller_type'       => null,
                'caller_id'         => null,
                'role'              => 'auth-user',
                'type'              => 'privilege',
                'action'            => 'create',
                'resource_type'     => 'tasks',
                'resource_id'       => null,
    ]
);

That makes sense.

I can create user a permission by doing:

LockManager::caller($user)->allow('create', 'tasks');

That would be an insert equivalent of (assuming the user has an id of 1):

//user with id of 1 can create tasks
DB::table('lock_permissions')->insert(
    [
                'caller_type'       => 'users',
                'caller_id'         => 1,
                'role'              => '', //notice that user doesn't have a role name
                'type'              => 'privilege',
                'action'            => 'create',
                'resource_type'     => 'tasks',
                'resource_id'       => null,
    ]
);

That makes since to me too.

Where things break down for me is when I want to create the auth-user role above but then attach multiple users to that role. It's repetitive to have individual user permissions that each allow access to create tasks.

Is that possible to do using this package? If so, could you provide an example of how to attach roles to users?

The other thing that really confused me was the use of

\BeatSwitch\Lock\Callers\Caller::getCallerRoles()

In the example you had this method return a static array ie) ['editor', 'publisher']. I would think that the getCallRoles() method would query the lock_permissions table and grab all the roles for that caller instance.

Storing Aliases

Hello Everyone,

I have a problem/question.

In the config there is the permissions section and on the comments it says that this should only be used if you are using the array driver.

so my question is where am I suppose to define what the aliases are? and are they not suppose to be stored in the database if you are using the database driver?

Thank You

Logic of results of allowing or denying permissions

This is an important one. Currently it's so that a top level allow or deny clears any lower level privilege or restriction. So for example, when you allow only an an action of create you basically get permission to create everything (every resource). It will also clear any restrictions in place for any resource where you wouldn't be allowed to create anything.

Practical example:

// Deny a caller from creating users and events.
$lock->deny('create', 'users');
$lock->deny('create', 'events');

// Allow the caller to create everything. After this he can both create users and events again.
$lock->allow('create');

This is the way I deem it to be logic but I don't know if the majority of you also thinks this is the logical way to do something.

Any thoughts or concerns that may arise? This is something I really want to tackle as early as possible so please give enough feedback on this.

Also: if you at any point find the current Acl not to behave in the way that makes sense for you then please tell me here so we can clear things out and improve it or make it more clear in the docs how things work.

Split driver interface into CallerDriver and RoleDriver?

I'm thinking about splitting these contracts so people can optionally implement the RoleDriver contract. This allows them to not specifically have to user the role functionality.

This could get messy if we also do #4 since we would have 4 interfaces that way.

Thoughts?

allowed method returns only explicit resource

the allowed method only return explicit resource -> it doesn't return resources allowed to role that a caller inherits.

Ie :
Role ABC has privilege on Resource 1
And
Caller XYZ has privilege on Resource 2
And
Caller XYZ has Role ABC

when I make : $lock->caller($caller)->allowed(xxxx), it returns only [Resource 2]

Add sync method to easily sync permissions for a resource

$manager->caller($caller)->sync(array $actions, $resource = null, $resourceId = null);

This will remove all allowed permissions which aren't in the $actions list and add allowed permissions which are in the $actions list. Could be useful when you need to change all of the actions at once,

Caching

I've just gone through the library, but didn't find any results for this one.

Is it possible to integrate caching somehow? IMO it is much more cheaper in performance to cache permission/privileges when using a persistent driver.

Should there be a find() method?

There seems to be one thing missing from this library that I miss from most ACL implementations but which IMHO is important for developers: Getting a list of resource IDs.

Imagine I have a couple of hundred users and a couple of thousand events. Right now it seems that the only way to get a list of events that a user can access is to load them all and check them in a loop. That is terribly inefficient.

I would like a method like this:

$lock->find('update', 'events'); // returns array of event IDs the caller is allowed to update

Split Driver interface into Driver\Read and Driver\Write?

I've currently created a ReadOnlyDriver but something tells me I could best split up the Driver interface into a Driver\Read and a Driver\Write and require the developer to optionally implement the write one. This would make it easier to set up a Lock instance which is only used for reading permissions from a storage.

Good idea?

An example of permission checking on a specific instance(s)

Consider the following url:
/users/1/tasks/2

I want to ensure that only the user with an id of 1 can get to their specific task.

I would also like to have a super admin (let's say that user as an id of 8) be able to access both

/users/8/tasks/4
and
/users/1/tasks/2

The super admin can access any task. Standard users that go to a task that isn't their own will get denied.

Is there a fetchOwn('tasks') method or a similar way to implement the example above?

Returning all permissions on a caller

Is there a way to return a list of all privileges and/or restrictions on a given caller?

I'd like to return a list of the logged in user's permissions so I can display/edit them in an admin panel, and I can't see a way to easily retrieve all permissions.

Thanks!

Rename clear method to something else?

Apparently clear is a bit too confusing to what it means. For some people it means clearing (allowing) someone to do something but it's currently implemented as removing permissions.

Any suggestions for another phrasing?

How to get all permissions?

We can use $lock->allowed() to retrieve a list of allowed resources.
How can we get the list of any available permission for a given caller?

Laravel sample app

Not an issue but a request.

Is it possible to see a very simple sample laravel app

Thanks

Should the Manager class handle multiple drivers?

Currently the Manager class accepts a single driver to store all permissions. I was thinking about allowing multiple drivers to be set. So some can be ready only with the storePermission and deletePermission methods not do anything on a read-only driver. But then you can do things like:

$manager->driver('production')->caller($caller)->can(...)
$manager->driver('local')->caller($user)->can(...)

This makes it easy to determine permissions locally for production settings.

Would this be a nice to have?

Move interfaces and exceptions where they belong

Currently the interfaces are in their own namespace Contracts. I believe each of these interfaces should be in the namespace where they belong.

For instance, the Caller interface and InvalidCaller exception should be in the Callers namespace. This adds more cohesion in the package and removes generic namespaces. Think about one namespace to rule them all. It makes it simpler. Classes inside the Callers namespace will no longer have to imported and when you look inside the namespace everything is nicely packed together.

Having them in a separate namespace, in my opinion, is a smell and feels like something is leaking.

Anyhow, this is my 2 cents. Do with it what you like!

Cheers

Our requirements - how to implement?

We have a role system whereby denial is always more important than an allow.

  1. A user can be assigned to many roles
  2. Each role has a number of resources and permissions
  3. Each permission has an allow/inherit/deny set of permissions.
  4. Inherit means basically do nothing
  5. Allow is only allowed if no deny is specified on any other roles for that action/resource

How can we implement this using lock?

Removing permission of specific resource removes all role permissions

Well i wrote a driver for Doctrine and thought I must have made a strange mistake. But it turns out that this error also happens with the ArrayDriver:

$manager->role('somegroup')->allow('update', 'jobs');
$manager->role('somegroup')->allow('create', 'jobs');
$manager->role('somegroup')->deny('update', 'jobs', 42);

In my logic this should only deny the resource "42" but the drivers removeRolePermission method receives a Permission object without a resource_id so it deletes the entire permission.

$this->assertTrue($manager->role('somegroup')->can('create', 'jobs')); // is true
$this->assertTrue($manager->role('somegroup')->can('update', 'jobs', 1)); // is false
$this->assertFalse($manager->role('somegroup')->can('update', 'jobs', 42)); // is false

Did i got something wrong?

Rename CallerTrait?

I'm not happy with suffixing traits with Trait. It's not very expressive. Perhaps one of the following?

  • CallerAware
  • LockAware
  • AclAware
  • ...

Preference? Suggestions?

Implement $lock->clear() method?

Would it make sense to implement a clear method for a lock instance to clear any matching permissions, either privileges or restrictions? This could be an easy way to clear permissions to get a fresh start. But I'm not sure if it would be very useful for many people.

The api would be:

public function clear(
    string|array $action,
    string|\BeatSwitch\Lock\Contracts\Resource $resource = null,
    int $resourceId = null
)

Thoughts?

0.1.0

These things need to be done before a stable 0.1.0 can be released.

Functionality

  • Action Aliases
  • Permission Conditions
  • Roles
  • Add abstract ReadOnlydriver
  • Extensive review and refactor of Lock class

Issues

Questions

Documentation

  • Write more extensive examples on using the Acl and the pre-defined classes that ship with the package. Also make sure to document the logic of the Acl and the hierarchy of permissions.
  • How to create drivers (and test them with the LockTestCase)
  • Create read-only driver
  • Document LockAware trait

Drivers

  • Write Laravel driver (separate package)

Package

  • Setup code coverage
  • Setup Scrutinizer
  • Add CONTRIBUTORS.md file
  • Add CHANGELOG.md file

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.