Skip to content

Commit

Permalink
Merge pull request #7 from sebastjan-hribar/add_app_module_to_policies
Browse files Browse the repository at this point in the history
Add app module to policies
  • Loading branch information
sebastjan-hribar committed Jan 8, 2022
2 parents 12440aa + 2b7c594 commit 4ceb66d
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 144 deletions.
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:
rokku (0.6.2)
rokku (0.7.0)
hanami-controller (~> 1.0)
hanami-router (~> 1.0)

Expand Down
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ end
### Role based authorization

#### Prerequisites
The current user must be stored in the `@user` variable and must have the attribute of `roles`. Rokku supports `roles`both as a type of `Array` and `String`.
The current user must be stored in the `@user` variable and must have the attribute of `roles`. Rokku supports `roles` both as a type of `Array` and `String`.
For example, the `@user.roles` could either be a simple string like 'admin' or an array of roles like `['level_1', 'level_2', 'level_3']`.

```ruby
Expand All @@ -61,14 +61,22 @@ For example:
@authorized_roles_for_update = ['admin']
```

Then we can check if a user is authorized for the `Post` controller and `Update`action.
Then we can check if a user is authorized for the `mightyPoster` application, `Post` controller and `Update`action.

```ruby
authorized?("post", "update")
authorized?("mightyposter", "post", "update")
```

A complete example of using Rokku in a Hanami 1.3 applications is available [here](https://sebastjan-hribar.github.io/programming/2022/01/08/rokku-with-hanami.html).


### Changelog

#### 0.7.0

* Policies are now scoped under application module so it is possible to have two `Dashboard` policies for two different applications.
* Readme update.

#### 0.6.0

* Change to accept a string or an array as roles.
Expand Down
4 changes: 2 additions & 2 deletions lib/rokku.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ module Rokku
#
# Example: redirect_to "/" unless authorized?("post", create")

def authorized?(controller, action)
def authorized?(application, controller, action)
input_roles = @user.roles
roles = []
if input_roles.class == String
roles << input_roles
else
roles = input_roles
end
Object.const_get(controller.downcase.capitalize + "Policy").new(roles).send("#{action.downcase}?")
Object.const_get("#{application}::#{controller.downcase.capitalize}Policy").new(roles).send("#{action.downcase}?")
end
end
end
Expand Down
92 changes: 47 additions & 45 deletions lib/rokku/commands/commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,57 +49,59 @@ def self.run
# Uncomment the needed actions and define appropriate user roles.

def self.generate_policy(app_name, controller_name)
app_name = app_name
app_name = app_name.downcase.capitalize
controller = controller_name.downcase.capitalize
policy_txt = <<-TXT
class #{controller}Policy
def initialize(roles)
@user_roles = roles
# Uncomment the required roles and add the
# appropriate user role to the @authorized_roles* array.
# @authorized_roles_for_new = []
# @authorized_roles_for_create = []
# @authorized_roles_for_show = []
# @authorized_roles_for_index = []
# @authorized_roles_for_edit = []
# @authorized_roles_for_update = []
# @authorized_roles_for_destroy = []
end
def new?
(@authorized_roles_for_new & @user_roles).any?
end
def create?
(@authorized_roles_for_create & @user_roles).any?
end
def show?
(@authorized_roles_for_show & @user_roles).any?
end
def index?
(@authorized_roles_for_index & @user_roles).any?
end
def edit?
(@authorized_roles_for_edit & @user_roles).any?
end
def update?
(@authorized_roles_for_update & @user_roles).any?
end
def destroy?
(@authorized_roles_for_destroy & @user_roles).any?
module #{app_name}
class #{controller}Policy
def initialize(roles)
@user_roles = roles
# Uncomment the required roles and add the
# appropriate user role to the @authorized_roles* array.
# @authorized_roles_for_new = []
# @authorized_roles_for_create = []
# @authorized_roles_for_show = []
# @authorized_roles_for_index = []
# @authorized_roles_for_edit = []
# @authorized_roles_for_update = []
# @authorized_roles_for_destroy = []
end
def new?
(@authorized_roles_for_new & @user_roles).any?
end
def create?
(@authorized_roles_for_create & @user_roles).any?
end
def show?
(@authorized_roles_for_show & @user_roles).any?
end
def index?
(@authorized_roles_for_index & @user_roles).any?
end
def edit?
(@authorized_roles_for_edit & @user_roles).any?
end
def update?
(@authorized_roles_for_update & @user_roles).any?
end
def destroy?
(@authorized_roles_for_destroy & @user_roles).any?
end
end
end
TXT

FileUtils.mkdir_p "lib/#{app_name}/policies" unless File.directory?("lib/#{app_name}/policies")
unless File.file?("lib/#{app_name}/policies/#{controller}Policy.rb")
File.open("lib/#{app_name}/policies/#{controller}Policy.rb", 'w') { |file| file.write(policy_txt) }
FileUtils.mkdir_p "lib/#{app_name.downcase}/policies" unless File.directory?("lib/#{app_name.downcase}/policies")
unless File.file?("lib/#{app_name.downcase}/policies/#{controller}Policy.rb")
File.open("lib/#{app_name.downcase}/policies/#{controller}Policy.rb", 'w') { |file| file.write(policy_txt) }
end
puts("Generated policy: lib/#{app_name}/policies/#{controller}Policy.rb") if File.file?("lib/#{app_name}/policies/#{controller}Policy.rb")
puts("Generated policy: lib/#{app_name.downcase}/policies/#{controller}Policy.rb") if File.file?("lib/#{app_name.downcase}/policies/#{controller}Policy.rb")
end
end
2 changes: 1 addition & 1 deletion lib/rokku/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Rokku
VERSION = "0.6.2"
VERSION = "0.7.0"
end
137 changes: 88 additions & 49 deletions test/authorization_test.rb
Original file line number Diff line number Diff line change
@@ -1,80 +1,119 @@
require 'test_helper'
require_relative '../lib/rokku/commands/commands.rb'
require_relative 'testApp/lib/firstApp/policies/TaskPolicy.rb'
require_relative 'testApp/lib/web/policies/TaskPolicy.rb'
require_relative 'testApp/lib/admin/policies/TaskPolicy.rb'
include Commands

describe 'Authorization' do
before do
@application_name = 'firstApp'
@action = Web::Controllers::Task::New.new
@controller_name = @action.controller_name.split("::")[2]
@action_name = @action.controller_name.split("::")[3]
@action_web = Web::Controllers::Task::New.new
@app_name_web = @action_web.controller_name.split("::")[0]
@controller_name_web = @action_web.controller_name.split("::")[2]
@action_name_web = @action_web.controller_name.split("::")[3]

@action_admin = Admin::Controllers::Task::New.new
@app_name_admin = @action_admin.controller_name.split("::")[0]
@controller_name_admin = @action_admin.controller_name.split("::")[2]
@action_name_admin = @action_admin.controller_name.split("::")[3]
end

describe 'with authorized user and one role as a string' do
describe 'with authorized user and one role as a string for Web-Task-New' do
before do
@user = User.new(id: 1, name: 'Tester', hashed_pass: '123',
roles: 'level_one_user')
@roles = @user.roles
end
end

after do
@user = nil
end

it 'authorizes the user' do
assert authorized?(@controller_name, @action_name), 'User is authorized'
assert authorized?(@app_name_web, @controller_name_web, @action_name_web), 'User is authorized'
end
end

describe 'with authorized user and roles as an array of roles' do
before do
@user = User.new(id: 1, name: 'Tester', hashed_pass: '123',
roles: ['level_one_user', 'level_two_user'])
@roles = @user.roles
end
describe 'with authorized user and roles as an array of roles for Web-Task-New' do
before do
@user = User.new(id: 1, name: 'Tester', hashed_pass: '123',
roles: ['level_one_user', 'level_two_user'])
@roles = @user.roles
end

after do
@user = nil
end
after do
@user = nil
end

it 'authorizes the user' do
assert authorized?(@controller_name, @action_name), 'User is authorized'
end
end
it 'authorizes the user' do
assert authorized?(@app_name_web, @controller_name_web, @action_name_web), 'User is authorized'
end
end

describe 'with unauthorized user' do
before do
@user = User.new(id: 1, name: 'Tester', hashed_pass: '123', roles: 'guest_user')
end
describe 'with unauthorized user' do
before do
@user = User.new(id: 1, name: 'Tester', hashed_pass: '123', roles: 'guest_user')
end

after do
@user = nil
end
after do
@user = nil
end

it 'doesnt authorize the user' do
refute authorized?(@controller_name, @action_name), 'User is not authorized'
end
end
it 'doesnt authorize the user' do
refute authorized?(@app_name_web, @controller_name_web, @action_name_web), 'User is not authorized'
end
end

describe 'policy file creation' do
before do
@new_controller = 'Post'
end
describe 'with authorized user and roles as an array of roles for Admin-Task-New' do
before do
@user = User.new(id: 1, name: 'Tester', hashed_pass: '123',
roles: ['level_two_user', 'level_three_user'])
@roles = @user.roles
end

after do
Dir.chdir('test/testApp') do
File.delete("lib/#{@application_name}/policies/#{@new_controller}Policy.rb")
end
end
after do
@user = nil
end

it 'generates policy' do
Dir.chdir('test/testApp') do
Commands.generate_policy(@application_name, @new_controller)
generated_policy_string = "lib/#{@application_name}/policies/#{@new_controller}Policy.rb"
assert File.file?("lib/#{@application_name}/policies/#{@new_controller}Policy.rb"), "The file lib/#{@application_name}/policies/#{@new_controller}Policy.rb is generated"
assert File.readlines(generated_policy_string).grep(/authorized_roles_for_new/).size > 0, 'The file has content authorized_roles_for_new.'
end
end
it 'authorizes the user' do
assert authorized?(@app_name_admin, @controller_name_admin, @action_name_admin), 'User is authorized'
end
end

describe 'with unauthorized user' do
before do
@user = User.new(id: 1, name: 'Tester', hashed_pass: '123', roles: 'guest_user')
end

after do
@user = nil
end

it 'doesnt authorize the user' do
refute authorized?(@app_name_admin, @controller_name_admin, @action_name_admin), 'User is not authorized'
end
end

describe 'policy file creation' do
before do
@new_controller = 'Post'
end

after do
Dir.chdir('test/testApp') do
file = "lib/#{@application_name.downcase}/policies/#{@new_controller}Policy.rb"
File.delete if file
end
end

it 'generates policy' do
Dir.chdir('test/testApp') do
Commands.generate_policy(@application_name, @new_controller)
generated_policy_string = "lib/#{@application_name.downcase}/policies/#{@new_controller}Policy.rb"
assert File.file?("lib/#{@application_name.downcase}/policies/#{@new_controller}Policy.rb"), "The file lib/#{@application_name.downcase}/policies/#{@new_controller}Policy.rb is generated"
assert File.readlines(generated_policy_string).grep(/authorized_roles_for_new/).size > 0, 'The file has content authorized_roles_for_new.'
assert File.readlines(generated_policy_string).grep(/#{@application_name.downcase.capitalize}/).size > 0, "The file has content #{@application_name.downcase.capitalize}."
end
end
end
end
end
13 changes: 13 additions & 0 deletions test/setup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,16 @@ def controller_name
end
end
end

module Admin
module Controllers
class Task
class New
include Hanami::Action
def controller_name
self.class.name
end
end
end
end
end

0 comments on commit 4ceb66d

Please sign in to comment.