Skip to content

Commit

Permalink
v0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
wbotelhos committed Sep 5, 2021
1 parent 4a228ab commit 8b085ab
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 7 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
# v0.2.0

## Break Changes

- The permissions format now is:

```
{
permissions: [
['controller', 'action'],
['controller2', 'action2'],
]
}
```

## Fixes

- Calls the `Authorizy::BaseCop#access?` as the first check intercepting all requests;

## Features

- Added RSpec matcher to make the test easier;

# v0.1.0

## Features
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
authorizy (0.1.0)
authorizy (0.2.0)

GEM
remote: https://rubygems.org/
Expand Down
92 changes: 87 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ The column `authorizy` is a JSON column that has a key called `permission` with
```ruby
{
permissions: [
{ controller: :users, action: :create },
{ controller: :users, action: :update },
[users, :create],
[users, :update],
}
}
```
Expand Down Expand Up @@ -93,8 +93,8 @@ Authorizy.configure do |config|
config.dependencies = {
payments: {
index: [
{ controller: 'system/users', action: :index },
{ controller: 'system/enrollments', action: :index },
['system/users', :index],
['system/enrollments', :index],
]
}
}
Expand All @@ -105,7 +105,7 @@ So now if a have the permission `payments#index` I'll receive more two permissio

### Cop

Sometimes we need to allow access in runtime because the permission will depend on the request data and/or some dynamic logic. For this you can create a *Cop* class, the inherit from `Authorizy::BaseCop`, to allow it based on logic. It works like a [Interceptor](https://en.wikipedia.org/wiki/Interceptor_pattern).
Sometimes we need to allow access in runtime because the permission will depend on the request data and/or some dynamic logic. For this you can create a *Cop* class, that inherits from `Authorizy::BaseCop`, to allow it based on logic. It works like a [Interceptor](https://en.wikipedia.org/wiki/Interceptor_pattern).

First, you need to configure your cop:

Expand All @@ -130,6 +130,7 @@ end
```

As you can see, you have access to a couple of variables: `action`, `controller`, `current_user`, `params`, and `session`.
When you return `false`, the authorization will be denied, when you return `true` your access will be allowed.

If your controller has a namespace, just use `__` to separate the modules name:

Expand All @@ -140,6 +141,16 @@ class AuthorizyCop < Authorizy::BaseCop
end
```

If you want to intercept all request as the first Authorizy check, you can override the `access?` method:

```ruby
class AuthorizyCop < Authorizy::BaseCop
def access?
return true if current_user.admin?
end
end
```

### Current User

By default Authorizy fetch the current user from the variable `current_user`. You have a config, that receives the controller context, where you can change it:
Expand Down Expand Up @@ -188,3 +199,74 @@ Using on jBuilder view:
```ruby
json.create_link new_users_url if authorizy?(:users, :create)
```
# Specs
To test some routes you'll need to give or not permission to the user, for that you have to ways, where the first is give permission to the user via session:
```ruby
before do
sign_in(current_user)
session[:permissions] = [[:users, :create]]
end
```
Or you can put the permission directly in the current user:
```ruby
before do
sign_in(current_user)
current_user.update(permissions: [[:users, :create]])
end
```
## Checks
We have a couple of check, here is the order:
1. `Authorizy::BaseCop#access?`;
2. `session[:permissions]`;
3. `current_user.authorizy['permissions']`;
4. `Authorizy::BaseCop#controller_name`;
## Performance
If you have few permissions, you can save the permissions in the session and avoid hit database many times, but if you have a couple of them, maybe it's a good idea save it in some place like [Redis](https://redis.io).
## Management
It's a good idea you keep your permissions in the database, so the customer can change it dynamic. You can load all permissions when the user is logged and cache it later. For cache expiration, you can trigger a refresh everytime that the permissions change.
## Database Structure
Inside database you can use the following relation to dynamicly change your permissions:
```ruby
plans -> plans_permissions <- permissions
|
v
role_plan_permissions
^
|
roles
```

## RSpec

You can test you app passing through all authorizy layers:

```ruby
user = User.create!(permission: { permissions: [[:users, :create]] })

expect(user).to be_authorized(:users, :create)
```

Or make sure the user does not have access:

```ruby
user = User.create!(permission: {})

expect(user).not_to be_authorized(:users, :create)
```
2 changes: 1 addition & 1 deletion lib/authorizy/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Authorizy
VERSION = '0.1.0'
VERSION = '0.2.0'
end

0 comments on commit 8b085ab

Please sign in to comment.