tachiban 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3fbe2ce6b5eb049f1a610456e1071a346881c14df1222f9963f9821fb02681b9
4
- data.tar.gz: 8e085cd08268eef3597869b00bc42361e08baac42f8de346d92e559e81a8466b
3
+ metadata.gz: 6a4772cbc2387fbc462f6fd7f0bb3e1738521e1ede9a4d8b02e6cda05ab9ffc1
4
+ data.tar.gz: 16069ee6e897992462ce538ec514fdeef1c2798014f573265e293e15603f8b42
5
5
  SHA512:
6
- metadata.gz: d6c945ffabc49f82f57782db4bb145c3eab6a1a719ae84219f95bf6a7d25a2022b564ace70c1fca45eab965c28db136fb669ef095bf52c4b4eaeb1e58d5b96cc
7
- data.tar.gz: a498df67c718b21dee1ebbe0d1bba26002b9c11734a1fda51f3c6a9bfded7721f467377f0a0a7ade8677df15187420752ccb1f83616072120f2a6b67806a9fcb
6
+ metadata.gz: d8d446ac3dd3f8762154859b8a32369d2e92a8eeb570a05bffdb8bc9674ed1676d288c8e71a1666887beda650e91db0c98becf306db4f097ff9ff00f1defac60
7
+ data.tar.gz: 4745b414ecf91bb84564b54febbab5febcd1c40d0e0df454140286b454b9af5938546a91da8f3f17ae7612a598eeada823f5e8616d8fc8377a90383089c36db6
data/README.md CHANGED
@@ -10,11 +10,7 @@ offers the following functionalities (with methods listed below
10
10
  - Authentication
11
11
  - Session handling
12
12
  - Password reset
13
- - Authorization
14
-
15
- The Tachiban logic (apart from the Authorization) and code were extracted from a Hanami based web app using
16
- Hanami::Model and was also used in a Camping based web app using Active Record.
17
-
13
+ - Authorization has been moved to [Rokku](https://github.com/sebastjan-hribar/rokku)
18
14
 
19
15
  ## Installation
20
16
 
@@ -48,22 +44,16 @@ end
48
44
  Prior to logging in or authenticating the user, retrieve the entity from the
49
45
  database and assign it to the instance variable of `@user`.
50
46
 
51
- The password reset methods require the user entity to have the following attributes:
52
- **token** and **password_reset_sent_at (set as `Time.now`)**. The token can be used to compose
53
- the password reset url and to later retrieve the correct user from
54
- the database when the user visits the password reset url.
55
-
56
- The **password_reset_sent_at** can be used to check the reset link validity.
47
+ In addition to that, the user entity must have the following attributes:
57
48
 
58
- The only prerequisite for the authorization is the attribute of **role** for the user entity.
49
+ * **token** (used to compose the password reset url and get the user from the database)
50
+ * **password_reset_sent_at** (set as `Time.now` to check the reset link validity)
51
+ * **hashed_pass** (to hold the generated hashed password)
59
52
 
60
53
 
61
54
  ### Usage
62
55
 
63
56
  #### Signup
64
- The entity for which authentication is used must have the
65
- attribute `hashed_pass` to hold the generated hashed password.
66
-
67
57
  To create a user with a hashed password use the `hashed_password(password)`
68
58
  method for the password and store it as the user's attribute `hashed_pass`.
69
59
 
@@ -81,14 +71,14 @@ def call(params)
81
71
  end
82
72
  ```
83
73
 
84
- #### Login
74
+ #### Authentication and login
85
75
  To authenticate a user use the `authenticated?(input_password)` method and log
86
76
  them in with the `login` method. Authentication is successful if the user exists and passwords match.
87
77
 
88
- The user is logged in by setting the user object as the `session[:current_user]`.
78
+ The user is logged in by setting the user object ID as the `session[:current_user]`.
89
79
  After the user is logged in the session start time is defined as
90
- `session[:session_start_time] = Time.now`. A flash message is also
91
- assigned as `flash[:success_notice] = flash_message`.
80
+ `session[:session_start_time] = Time.now`. A default flash message is also
81
+ assigned as 'You have been successfully logged in.'.
92
82
 
93
83
  The `session[:session_start_time]` is then used by the `session_expired?`
94
84
  method to determine whether the session has expired or not.
@@ -101,11 +91,9 @@ email = params[:entity_session][:email]
101
91
  password = params[:entity_session][:password]
102
92
 
103
93
  @user = EntityRepository.new.find_by_email(email)
104
- login("You have been successfully logged in.") if authenticated?(password)
94
+ login if authenticated?(password)
105
95
  ```
106
96
 
107
-
108
- #### Authentication
109
97
  To check whether the user is logged in use the `check_for_logged_in_user` method.
110
98
  If the user is not logged in the `logout` method takes over.
111
99
 
@@ -116,10 +104,10 @@ expired and then restarts the session start time if the session
116
104
  is still valid or proceeds with the following if the session
117
105
  has expired:
118
106
 
119
- - setting the `session[:current_user]` to `nil`
120
- - a flash message is set: `flash[:failed_notice] = "Your session has expired"`
107
+ - setting the `session[:current_user]` to `nil`,
108
+ - a flash message is set: `flash[:failed_notice] = "Your session has expired"`,
121
109
  - redirects to the `routes.root_path` which can be overwritten by assigning
122
- a different url to @redirect_url
110
+ a different url to @redirect_url.
123
111
 
124
112
 
125
113
  The `session_expired?` method compares the session start time
@@ -132,7 +120,7 @@ by default, but can be overwritten) with the current time.
132
120
  if session_expired?
133
121
  @redirect_url ||= routes.root_path
134
122
  session[:current_user] = nil
135
- flash[:failed_notice] = "Your session has expired"
123
+ flash[:failed_notice] = "Your session has expired."
136
124
  redirect_to @redirect_url
137
125
  else
138
126
  restart_session_counter
@@ -189,37 +177,26 @@ password_reset_url_valid?(link_validity)
189
177
  ```
190
178
 
191
179
 
192
- #### Authorization
193
- Authorization support was setup as inspired by [this blog post](http://billpatrianakos.me/blog/2013/10/22/authorize-users-based-on-roles-and-permissions-without-a-gem/).
194
-
195
- Authorization features support the generation of policy files for each controller where authorized roles are specified for each action.
196
-
197
- ```ruby
198
- tachiban -n mightyPoster -p post
199
- ```
200
- The above CLI command will generate a policy file for the application mightyPoster (not the project) and the controller post. The file will be generated as `myProject/lib/mightyPoster/policies/PostPolicy.rb`
201
-
202
- Each application would have its own `app/policies` folders.
180
+ ### ToDo
203
181
 
204
- **The command must be run in the project root folder.**
182
+ - Add full Hanami app for testing purposes.
205
183
 
206
- Once the file is generated the authorized roles variables in the initialize block for required actions need to be uncommneted and supplied with specific roles.
184
+ ### Changelog
207
185
 
208
- Then we can check if a user is authorized:
186
+ #### 0.7.0
209
187
 
210
- ```ruby
211
- authorized?(controller, role, action)
212
- ```
188
+ Authorization was moved to a separate gem [Rokku](https://github.com/sebastjan-hribar/rokku).
189
+ Readme update.
213
190
 
191
+ Method: `Tachiban::login`
192
+ <br>Change:
193
+ Default flash message and redirect url provided.
214
194
 
215
- ### ToDo
216
195
 
217
- - Add support for level based authorizations. [x]
218
- - Add generators for adding authorization rules to existing policies.
219
- - Add generators for entities with required attributes.
196
+ #### 0.6.1
220
197
 
198
+ Dependency change for **rake** to ">= 12.3.3".
221
199
 
222
- ### Changelog
223
200
 
224
201
  #### 0.6.0
225
202
 
@@ -231,10 +208,6 @@ Method: `Tachiban::logout`
231
208
  <br>Change:
232
209
  Added `session.clear` to remove any other values upon logout.
233
210
 
234
- #### 0.6.1
235
-
236
- Dependency change for **rake** to ">= 12.3.3".
237
-
238
211
 
239
212
 
240
213
  ## Development
data/bin/tachiban CHANGED
@@ -1,2 +1 @@
1
1
  #!/usr/bin/env ruby
2
- require_relative "../lib/tachiban/commands/commands.rb"
data/lib/tachiban.rb CHANGED
@@ -5,7 +5,6 @@ require 'hanami/action/session'
5
5
 
6
6
  module Hanami
7
7
  module Tachiban
8
-
9
8
  private
10
9
 
11
10
  # ### Signup ###
@@ -19,7 +18,6 @@ private
19
18
  BCrypt::Password.create(password)
20
19
  end
21
20
 
22
-
23
21
  # ### Login ###
24
22
 
25
23
  # The authenticated? method returns true if the the following criteria
@@ -31,7 +29,6 @@ private
31
29
  @user && BCrypt::Password.new(@user.hashed_pass) == input_pass
32
30
  end
33
31
 
34
-
35
32
  # The login method can be used in combination with the authenticated? method to
36
33
  # log the user in if the authenticated? method returns true. The user is
37
34
  # logged in by setting the user object id as the session[:current_user].
@@ -39,28 +36,34 @@ private
39
36
  # by the session_expired? method to determine whether the session has
40
37
  # expired or not.
41
38
 
39
+ # There are two defualt values set: one for flash message and
40
+ # the other for redirect url. Both can be overwritten by assigning
41
+ # new values for @flash_message and @login_redirect_url.
42
+
42
43
  # Example:
43
44
  # login if authenticated?(input_pass)
44
45
 
45
- def login(flash_message)
46
+ def login
46
47
  session[:current_user] = @user.id
47
48
  session[:session_start_time] = Time.now
48
- flash[:success_notice] = flash_message
49
+ @flash_message ||= 'You have been successfully logged in.'
50
+ flash[:success_notice] = @flash_message
51
+ @login_redirect_url ||= routes.root_path
52
+ redirect_to @login_redirect_url
49
53
  end
50
54
 
51
-
52
55
  # The logout method sets the current user in the session to nil
53
- # and performs a redirect to the @redirect_to which is set to
54
- # routes.root_path and can be overwritten as needed with a specific url.
56
+ # and performs a redirect to the redirect_url which is set to
57
+ # /login, but can be overwritten as needed with a specific url
58
+ # by setting a new value for @logout_redirect_url.
55
59
 
56
60
  def logout
57
61
  session[:current_user] = nil
58
62
  session.clear
59
- @redirect_url ||= routes.root_path
60
- redirect_to @redirect_url
63
+ @logout_redirect_url ||= '/login'
64
+ redirect_to @logout_redirect_url
61
65
  end
62
66
 
63
-
64
67
  # ### Authentication ###
65
68
 
66
69
  # The check_for_logged_in_user method can be used to check for each
@@ -68,10 +71,9 @@ private
68
71
  # the logout method takes over.
69
72
 
70
73
  def check_for_logged_in_user
71
- logout unless session[:current_user]
74
+ logout unless session[:current_user]
72
75
  end
73
76
 
74
-
75
77
  # ### Session handling ###
76
78
 
77
79
  # Session handling includes methods session_expired?,
@@ -88,7 +90,6 @@ private
88
90
  end
89
91
  end
90
92
 
91
-
92
93
  # The restart_session_counter method resets the session start time to
93
94
  # Time.now. It's used in the handle session method.
94
95
 
@@ -96,7 +97,6 @@ private
96
97
  session[:session_start_time] = Time.now
97
98
  end
98
99
 
99
-
100
100
  # The handle_session method is used to handle the incoming requests
101
101
  # based on the the session expiration. If the session has expired the
102
102
  # session user is set to nil, a flash message of "Your session has expired"
@@ -110,16 +110,14 @@ private
110
110
  if session_expired?
111
111
  @redirect_url ||= routes.root_path
112
112
  session[:current_user] = nil
113
- flash[:failed_notice] = "Your session has expired"
113
+ flash[:failed_notice] = 'Your session has expired.'
114
114
  redirect_to @redirect_url
115
115
  else
116
116
  restart_session_counter
117
117
  end
118
118
  end
119
119
 
120
-
121
120
  # ### Password reset ###
122
-
123
121
  def token
124
122
  SecureRandom.urlsafe_base64
125
123
  end
@@ -137,20 +135,6 @@ private
137
135
  def password_reset_url_valid?(link_validity)
138
136
  Time.now > @user.password_reset_sent_at + link_validity
139
137
  end
140
-
141
-
142
- # ### Authorization ###
143
- # The authorized? method checks if the specified user has the required role
144
- # and permission to access the action. It returns true or false and
145
- # provides the basis for further actions in either case.
146
- #
147
- # Example: redirect_to "/" unless authorized?
148
-
149
- def authorized?(controller, role, action)
150
- Object.const_get(controller.downcase.capitalize + "Policy").new(role).send("#{action.downcase}?")
151
- end
152
-
153
-
154
138
  end
155
139
  end
156
140
 
@@ -1,3 +1,3 @@
1
1
  module Tachiban
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tachiban
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastjan Hribar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-02 00:00:00.000000000 Z
11
+ date: 2021-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -191,8 +191,6 @@ files:
191
191
  - bin/setup
192
192
  - bin/tachiban
193
193
  - lib/tachiban.rb
194
- - lib/tachiban/commands/commands.rb
195
- - lib/tachiban/policy_generator/policy_generator.rb
196
194
  - lib/tachiban/version.rb
197
195
  - tachiban.gemspec
198
196
  homepage: https://github.com/sebastjan-hribar/tachiban
@@ -1,45 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'optparse'
3
- require_relative "../policy_generator/policy_generator.rb"
4
-
5
-
6
- options = {}
7
- optparse = OptionParser.new do |opts|
8
- opts.banner = "\nHanami authorization policy generator
9
- Usage: tachiban -n myapp -p user
10
- Flags:
11
- \n"
12
-
13
- opts.on("-n", "--app_name APP", "Specify the application name for the policy") do |app_name|
14
- options[:app_name] = app_name
15
- end
16
-
17
- opts.on("-p", "--policy POLICY", "Specify the policy name") do |policy|
18
- options[:policy] = policy
19
- end
20
-
21
- opts.on("-h", "--help", "Displays help") do
22
- puts opts
23
- exit
24
- end
25
-
26
- end
27
-
28
-
29
- begin
30
- optparse.parse!
31
- puts "Add flag -h or --help to see usage instructions." if options.empty?
32
- mandatory = [:app_name, :policy]
33
- missing = mandatory.select{ |arg| options[arg].nil? }
34
- unless missing.empty?
35
- raise OptionParser::MissingArgument.new(missing.join(', '))
36
- end
37
-
38
- rescue OptionParser::InvalidOption, OptionParser::MissingArgument
39
- puts $!.to_s
40
- puts optparse
41
- exit
42
- end
43
-
44
- puts "Performing task with options: #{options.inspect}"
45
- generate_policy("#{options[:app_name]}", "#{options[:policy]}") if options[:policy]
@@ -1,58 +0,0 @@
1
- require 'fileutils'
2
-
3
- # The generate_policy method creates the policy file for specified
4
- # application and controller. By default all actions to check against
5
- # are commented out.
6
- # Uncomment the needed actions and define appropriate user role.
7
-
8
- def generate_policy(app_name, controller_name)
9
- app_name = app_name
10
- controller = controller_name.downcase.capitalize
11
- policy_txt = <<-TXT
12
- class #{controller}Policy
13
- def initialize(role)
14
- @user_role = role
15
-
16
- # Uncomment the required roles and add the
17
- # appropriate user role to the @authorized_roles* array.
18
-
19
- # @authorized_roles_for_new = []
20
- # @authorized_roles_for_create = []
21
- # @authorized_roles_for_show = []
22
- # @authorized_roles_for_index = []
23
- # @authorized_roles_for_edit = []
24
- # @authorized_roles_for_update = []
25
- # @authorized_roles_for_destroy = []
26
- end
27
-
28
- def new?
29
- @authorized_roles_for_new.include? @user_role
30
- end
31
- def create?
32
- @authorized_roles_for_create.include? @user_role
33
- end
34
- def show?
35
- @authorized_roles_for_show.include? @user_role
36
- end
37
- def index?
38
- @authorized_roles_for_index.include? @user_role
39
- end
40
- def edit?
41
- @authorized_roles_for_edit.include? @user_role
42
- end
43
- def update?
44
- @authorized_roles_for_update.include? @user_role
45
- end
46
- def destroy?
47
- @authorized_roles_for_destroy.include? @user_role
48
- end
49
- end
50
- TXT
51
-
52
-
53
- FileUtils.mkdir_p "lib/#{app_name}/policies" unless File.directory?("lib/#{app_name}/policies")
54
- unless File.file?("lib/#{app_name}/policies/#{controller}Policy.rb")
55
- File.open("lib/#{app_name}/policies/#{controller}Policy.rb", 'w') { |file| file.write(policy_txt) }
56
- end
57
- puts("Generated policy: lib/#{app_name}/policies/#{controller}Policy.rb") if File.file?("lib/#{app_name}/policies/#{controller}Policy.rb")
58
- end