rodauth-rails 1.0.0 → 1.1.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 +4 -4
- data/CHANGELOG.md +4 -0
- data/LICENSE.txt +1 -1
- data/README.md +174 -135
- data/lib/generators/rodauth/templates/app/misc/rodauth_app.rb +3 -14
- data/lib/rodauth/rails/app.rb +17 -0
- data/lib/rodauth/rails/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8643f8a912963b78be7d03a815b813688304f4e4b2777a1fdade807f79a4c712
|
4
|
+
data.tar.gz: 31aadb16115fc826750b7d160dcb572ae9c24255d99a7c640abef5fd157bd319
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd27d717b3a01f0b5f43e346c0cd839e2703ee0db44f7503eb6ce80f7cffd4493f4ed9e208db474af56af536f675444170f16a6d47435e1f4ce2af38a7487916
|
7
|
+
data.tar.gz: bbac5b7492751e76886a5bcd275af78aada1026d2cd95ddee732817e8d7a5a154f559e5c27ce08606d444a1ffd4640f8522744bd13939f6491288d57c986fea0
|
data/CHANGELOG.md
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -95,8 +95,8 @@ config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
|
95
95
|
|
96
96
|
### Routes
|
97
97
|
|
98
|
-
Because requests to Rodauth endpoints are handled by
|
99
|
-
|
98
|
+
Because requests to Rodauth endpoints are handled by a Rack middleware (and not
|
99
|
+
a Rails controller), Rodauth routes will not show in `rails routes`.
|
100
100
|
|
101
101
|
Use the `rodauth:routes` rake task to view the list of endpoints based on
|
102
102
|
currently loaded features:
|
@@ -609,21 +609,12 @@ them under a name.
|
|
609
609
|
```rb
|
610
610
|
# app/misc/rodauth_app.rb
|
611
611
|
class RodauthApp < Rodauth::Rails::App
|
612
|
-
# primary configuration
|
613
|
-
configure
|
614
|
-
|
615
|
-
# secondary configuration
|
616
|
-
configure RodauthAdmin, :admin
|
612
|
+
configure RodauthMain # primary configuration
|
613
|
+
configure RodauthAdmin, :admin # secondary configuration
|
617
614
|
|
618
615
|
route do |r|
|
619
|
-
r.rodauth
|
620
|
-
|
621
|
-
r.on "admin" do
|
622
|
-
r.rodauth(:admin)
|
623
|
-
break # allow routing of other /admin/* requests to continue to Rails
|
624
|
-
end
|
625
|
-
|
626
|
-
# ...
|
616
|
+
r.rodauth # route primary rodauth requests
|
617
|
+
r.rodauth(:admin) # route secondary rodauth requests
|
627
618
|
end
|
628
619
|
end
|
629
620
|
```
|
@@ -635,7 +626,6 @@ class RodauthAdmin < Rodauth::Rails::Auth
|
|
635
626
|
prefix "/admin"
|
636
627
|
session_key_prefix "admin_"
|
637
628
|
remember_cookie_key "_admin_remember" # if using remember feature
|
638
|
-
# ...
|
639
629
|
|
640
630
|
# search views in `app/views/admin/rodauth` directory
|
641
631
|
rails_controller { Admin::RodauthController }
|
@@ -717,10 +707,6 @@ RodauthApp.rodauth.verify_account(account_login: "user@example.com")
|
|
717
707
|
RodauthApp.rodauth(:admin).close_account(account_login: "user@example.com")
|
718
708
|
```
|
719
709
|
|
720
|
-
The rodauth-rails gem additionally updates the internal rack env hash with your
|
721
|
-
`config.action_mailer.default_url_options`, which is used for generating email
|
722
|
-
links.
|
723
|
-
|
724
710
|
### Generating URLs
|
725
711
|
|
726
712
|
For generating authentication URLs outside of a request use the
|
@@ -781,104 +767,6 @@ Rodauth::Rails.rodauth(session: { two_factor_auth_setup: true })
|
|
781
767
|
Rodauth::Rails.rodauth(:admin, params: { "param" => "value" })
|
782
768
|
```
|
783
769
|
|
784
|
-
## How it works
|
785
|
-
|
786
|
-
### Middleware
|
787
|
-
|
788
|
-
rodauth-rails inserts a `Rodauth::Rails::Middleware` into your middleware
|
789
|
-
stack, which calls your Rodauth app for each request, before the request
|
790
|
-
reaches the Rails router.
|
791
|
-
|
792
|
-
```sh
|
793
|
-
$ rails middleware
|
794
|
-
...
|
795
|
-
use Rodauth::Rails::Middleware
|
796
|
-
run MyApp::Application.routes
|
797
|
-
```
|
798
|
-
|
799
|
-
The Rodauth app stores the `Rodauth::Auth` instance in the Rack env hash, which
|
800
|
-
is then available in your Rails app:
|
801
|
-
|
802
|
-
```rb
|
803
|
-
request.env["rodauth"] #=> #<Rodauth::Auth>
|
804
|
-
request.env["rodauth.admin"] #=> #<Rodauth::Auth> (if using multiple configurations)
|
805
|
-
```
|
806
|
-
|
807
|
-
For convenience, this object can be accessed via the `#rodauth` method in views
|
808
|
-
and controllers:
|
809
|
-
|
810
|
-
```rb
|
811
|
-
class MyController < ApplicationController
|
812
|
-
def my_action
|
813
|
-
rodauth #=> #<Rodauth::Auth>
|
814
|
-
rodauth(:admin) #=> #<Rodauth::Auth> (if using multiple configurations)
|
815
|
-
end
|
816
|
-
end
|
817
|
-
```
|
818
|
-
```erb
|
819
|
-
<% rodauth #=> #<Rodauth::Auth> %>
|
820
|
-
<% rodauth(:admin) #=> #<Rodauth::Auth> (if using multiple configurations) %>
|
821
|
-
```
|
822
|
-
|
823
|
-
### App
|
824
|
-
|
825
|
-
The `Rodauth::Rails::App` class is a [Roda] subclass that provides Rails
|
826
|
-
integration for Rodauth:
|
827
|
-
|
828
|
-
* uses Action Dispatch flash instead of Roda's
|
829
|
-
* uses Action Dispatch CSRF protection instead of Roda's
|
830
|
-
* sets [HMAC] secret to Rails' secret key base
|
831
|
-
* uses Action Controller for rendering templates
|
832
|
-
* runs Action Controller callbacks & rescue handlers around Rodauth actions
|
833
|
-
* uses Action Mailer for sending emails
|
834
|
-
|
835
|
-
The `configure` method wraps configuring the Rodauth plugin, forwarding
|
836
|
-
any additional [plugin options].
|
837
|
-
|
838
|
-
```rb
|
839
|
-
class RodauthApp < Rodauth::Rails::App
|
840
|
-
configure { ... } # defining default Rodauth configuration
|
841
|
-
configure(json: true) { ... } # passing options to the Rodauth plugin
|
842
|
-
configure(:admin) { ... } # defining multiple Rodauth configurations
|
843
|
-
end
|
844
|
-
```
|
845
|
-
|
846
|
-
The `route` block is provided by Roda, and it's called on each request before
|
847
|
-
it reaches the Rails router.
|
848
|
-
|
849
|
-
```rb
|
850
|
-
class RodauthApp < Rodauth::Rails::App
|
851
|
-
route do |r|
|
852
|
-
# ... called before each request ...
|
853
|
-
end
|
854
|
-
end
|
855
|
-
```
|
856
|
-
|
857
|
-
Since `Rodauth::Rails::App` is just a Roda subclass, you can do anything you
|
858
|
-
would with a Roda app, such as loading additional Roda plugins:
|
859
|
-
|
860
|
-
```rb
|
861
|
-
class RodauthApp < Rodauth::Rails::App
|
862
|
-
plugin :request_headers # easier access to request headers
|
863
|
-
plugin :typecast_params # methods for conversion of request params
|
864
|
-
plugin :default_headers, { "Foo" => "Bar" }
|
865
|
-
# ...
|
866
|
-
end
|
867
|
-
```
|
868
|
-
|
869
|
-
### Sequel
|
870
|
-
|
871
|
-
Rodauth uses the [Sequel] library for database queries, due to more advanced
|
872
|
-
database usage (SQL expressions, database-agnostic date arithmetic, SQL
|
873
|
-
function calls).
|
874
|
-
|
875
|
-
If ActiveRecord is used in the application, the `rodauth:install` generator
|
876
|
-
will have automatically configured Sequel to reuse ActiveRecord's database
|
877
|
-
connection, using the [sequel-activerecord_connection] gem.
|
878
|
-
|
879
|
-
This means that, from the usage perspective, Sequel can be considered just
|
880
|
-
as an implementation detail of Rodauth.
|
881
|
-
|
882
770
|
## Configuring
|
883
771
|
|
884
772
|
### Configuration methods
|
@@ -897,23 +785,6 @@ methods:
|
|
897
785
|
| `rails_controller` | Controller class to use for rendering and CSRF protection. |
|
898
786
|
| `rails_account_model` | Model class connected with the accounts table. |
|
899
787
|
|
900
|
-
### General configuration
|
901
|
-
|
902
|
-
The `Rodauth::Rails` module has a few config settings available as well:
|
903
|
-
|
904
|
-
| Name | Description |
|
905
|
-
| :----- | :---------- |
|
906
|
-
| `app` | Constant name of your Rodauth app, which is called by the middleware. |
|
907
|
-
| `middleware` | Whether to insert the middleware into the Rails application's middleware stack. Defaults to `true`. |
|
908
|
-
|
909
|
-
```rb
|
910
|
-
# config/initializers/rodauth.rb
|
911
|
-
Rodauth::Rails.configure do |config|
|
912
|
-
config.app = "RodauthApp"
|
913
|
-
config.middleware = true
|
914
|
-
end
|
915
|
-
```
|
916
|
-
|
917
788
|
For the list of configuration methods provided by Rodauth, see the [feature
|
918
789
|
documentation].
|
919
790
|
|
@@ -926,7 +797,9 @@ auth class:
|
|
926
797
|
```rb
|
927
798
|
class RodauthMain < Rodauth::Rails::Auth
|
928
799
|
configure do
|
800
|
+
# ...
|
929
801
|
password_match? { |password| ldap_valid?(password) }
|
802
|
+
# ...
|
930
803
|
end
|
931
804
|
|
932
805
|
# Example external identities table
|
@@ -1013,6 +886,172 @@ class RodauthApp < Rodauth::Rails::App
|
|
1013
886
|
end
|
1014
887
|
```
|
1015
888
|
|
889
|
+
## How it works
|
890
|
+
|
891
|
+
### Rack middleware
|
892
|
+
|
893
|
+
The railtie inserts [`Rodauth::Rails::Middleware`](/lib/rodauth/rails/middleware.rb)
|
894
|
+
at the end of the middleware stack, which calls your Rodauth app around each request.
|
895
|
+
|
896
|
+
```sh
|
897
|
+
$ rails middleware
|
898
|
+
# ...
|
899
|
+
# use Rodauth::Rails::Middleware
|
900
|
+
# run MyApp::Application.routes
|
901
|
+
```
|
902
|
+
|
903
|
+
It can be inserted at any point in the middleware stack:
|
904
|
+
|
905
|
+
```rb
|
906
|
+
Rodauth::Rails.configure do |config|
|
907
|
+
config.middleware = false # disable auto-insertion
|
908
|
+
end
|
909
|
+
|
910
|
+
Rails.application.config.middleware.insert_before AnotherMiddleware, Rodauth::Rails::Middleware
|
911
|
+
```
|
912
|
+
|
913
|
+
The middleware retrieves the Rodauth app via `Rodauth::Rails.app`, which is
|
914
|
+
specified as a string to keep the class autoloadable and reloadable in
|
915
|
+
development.
|
916
|
+
|
917
|
+
```rb
|
918
|
+
Rodauth::Rails.configure do |config|
|
919
|
+
config.app = "RodauthApp"
|
920
|
+
end
|
921
|
+
```
|
922
|
+
|
923
|
+
In addition to Zeitwerk compatibility, this extra layer catches Rodauth redirects
|
924
|
+
that happen on the controller level (e.g. when calling
|
925
|
+
`rodauth.require_authentication` in a `before_action` filter).
|
926
|
+
|
927
|
+
### Roda app
|
928
|
+
|
929
|
+
The [`Rodauth::Rails::App`](/lib/rodauth/rails/app.rb) class is a [Roda]
|
930
|
+
subclass that provides a convenience layer for Rodauth:
|
931
|
+
|
932
|
+
* uses Action Dispatch flash messages
|
933
|
+
* provides syntax sugar for loading the rodauth plugin
|
934
|
+
* saves Rodauth object(s) to Rack env hash
|
935
|
+
* propagates edited headers to Rails responses
|
936
|
+
|
937
|
+
#### Configure block
|
938
|
+
|
939
|
+
The `configure` call loads the rodauth plugin. By convention, it receives an
|
940
|
+
auth class and configuration name as positional arguments (forwarded as
|
941
|
+
`:auth_class` and `:name` plugin options), a block for anonymous auth classes,
|
942
|
+
and also accepts any additional plugin options.
|
943
|
+
|
944
|
+
```rb
|
945
|
+
class RodauthApp < Rodauth::Rails::App
|
946
|
+
# named auth class
|
947
|
+
configure(RodauthMain)
|
948
|
+
configure(RodauthAdmin, :admin)
|
949
|
+
|
950
|
+
# anonymous auth class
|
951
|
+
configure { ... }
|
952
|
+
configure(:admin) { ... }
|
953
|
+
|
954
|
+
# plugin options
|
955
|
+
configure(RodauthMain, json: :only)
|
956
|
+
end
|
957
|
+
```
|
958
|
+
|
959
|
+
#### Route block
|
960
|
+
|
961
|
+
The `route` block is called for each request, before it reaches the Rails
|
962
|
+
router, and it's yielded the request object.
|
963
|
+
|
964
|
+
```rb
|
965
|
+
class RodauthApp < Rodauth::Rails::App
|
966
|
+
route do |r|
|
967
|
+
# called before each request
|
968
|
+
end
|
969
|
+
end
|
970
|
+
```
|
971
|
+
|
972
|
+
#### Routing prefix
|
973
|
+
|
974
|
+
If you use a routing prefix, you don't need to add a call to `r.on` like with
|
975
|
+
vanilla Rodauth, as `r.rodauth` has been modified to automatically route the
|
976
|
+
prefix.
|
977
|
+
|
978
|
+
```rb
|
979
|
+
class RodauthApp < Rodauth::Rails::App
|
980
|
+
configure do
|
981
|
+
prefix "/user"
|
982
|
+
end
|
983
|
+
|
984
|
+
route do |r|
|
985
|
+
r.rodauth # no need to wrap with `r.on("user") { ... }`
|
986
|
+
end
|
987
|
+
end
|
988
|
+
```
|
989
|
+
|
990
|
+
### Auth class
|
991
|
+
|
992
|
+
The [`Rodauth::Rails::Auth`](/lib/rodauth/rails/auth.rb) class is a subclass of
|
993
|
+
`Rodauth::Auth`, which preloads the `rails` rodauth feature, sets [HMAC] secret to
|
994
|
+
Rails' secret key base, and modifies some [configuration defaults](#rodauth-defaults).
|
995
|
+
|
996
|
+
```rb
|
997
|
+
class RodauthMain < Rodauth::Rails::Auth
|
998
|
+
configure do
|
999
|
+
# authentication configuration
|
1000
|
+
end
|
1001
|
+
end
|
1002
|
+
```
|
1003
|
+
|
1004
|
+
### Rodauth feature
|
1005
|
+
|
1006
|
+
The [`rails`](/lib/rodauth/rails/feature.rb) Rodauth feature loaded by
|
1007
|
+
`Rodauth::Rails::Auth` provides the main part of the Rails integration for Rodauth:
|
1008
|
+
|
1009
|
+
* uses Action View for template rendering
|
1010
|
+
* uses Action Dispatch for CSRF protection
|
1011
|
+
* runs Action Controller callbacks and rescue from blocks around Rodauth requests
|
1012
|
+
* uses Action Mailer to create and deliver emails
|
1013
|
+
* uses Action Controller instrumentation around Rodauth requests
|
1014
|
+
* uses Action Mailer's default URL options when calling Rodauth outside of a request
|
1015
|
+
|
1016
|
+
### Controller
|
1017
|
+
|
1018
|
+
The Rodauth app stores the `Rodauth::Rails::Auth` instances in the Rack env
|
1019
|
+
hash, which is then available in your Rails app:
|
1020
|
+
|
1021
|
+
```rb
|
1022
|
+
request.env["rodauth"] #=> #<RodauthMain>
|
1023
|
+
request.env["rodauth.admin"] #=> #<RodauthAdmin> (if using multiple configurations)
|
1024
|
+
```
|
1025
|
+
|
1026
|
+
For convenience, this object can be accessed via the `#rodauth` method in views
|
1027
|
+
and controllers:
|
1028
|
+
|
1029
|
+
```rb
|
1030
|
+
class MyController < ApplicationController
|
1031
|
+
def my_action
|
1032
|
+
rodauth #=> #<RodauthMain>
|
1033
|
+
rodauth(:admin) #=> #<RodauthAdmin> (if using multiple configurations)
|
1034
|
+
end
|
1035
|
+
end
|
1036
|
+
```
|
1037
|
+
```erb
|
1038
|
+
<% rodauth #=> #<RodauthMain> %>
|
1039
|
+
<% rodauth(:admin) #=> #<RodauthAdmin> (if using multiple configurations) %>
|
1040
|
+
```
|
1041
|
+
|
1042
|
+
### Sequel
|
1043
|
+
|
1044
|
+
Rodauth uses the [Sequel] library for database interaction, which offers
|
1045
|
+
powerful APIs for building advanced queries (it supports SQL expressions,
|
1046
|
+
database-agnostic date arithmetic, SQL function calls).
|
1047
|
+
|
1048
|
+
If you're using Active Record in your application, the `rodauth:install`
|
1049
|
+
generator automatically configures Sequel to reuse ActiveRecord's database
|
1050
|
+
connection, using the [sequel-activerecord_connection] gem.
|
1051
|
+
|
1052
|
+
This means that, from the usage perspective, Sequel can be considered just
|
1053
|
+
as an implementation detail of Rodauth.
|
1054
|
+
|
1016
1055
|
## Rodauth defaults
|
1017
1056
|
|
1018
1057
|
rodauth-rails changes some of the default Rodauth settings for easier setup:
|
@@ -12,12 +12,9 @@ class RodauthApp < Rodauth::Rails::App
|
|
12
12
|
<% end -%>
|
13
13
|
r.rodauth # route rodauth requests
|
14
14
|
|
15
|
-
# ==> Authenticating
|
15
|
+
# ==> Authenticating requests
|
16
16
|
# Call `rodauth.require_authentication` for requests that you want to
|
17
|
-
# require authentication for.
|
18
|
-
#
|
19
|
-
# next if r.path.start_with?("/docs") # skip authentication for documentation pages
|
20
|
-
# next if session[:admin] # skip authentication for admins
|
17
|
+
# require authentication for. For example:
|
21
18
|
#
|
22
19
|
# # authenticate /dashboard/* and /account/* requests
|
23
20
|
# if r.path.start_with?("/dashboard") || r.path.start_with?("/account")
|
@@ -25,14 +22,6 @@ class RodauthApp < Rodauth::Rails::App
|
|
25
22
|
# end
|
26
23
|
|
27
24
|
# ==> Secondary configurations
|
28
|
-
# r.
|
29
|
-
# r.rodauth(:admin)
|
30
|
-
#
|
31
|
-
# unless rodauth(:admin).logged_in?
|
32
|
-
# rodauth(:admin).require_http_basic_auth
|
33
|
-
# end
|
34
|
-
#
|
35
|
-
# break # allow the Rails app to handle other "/admin/*" requests
|
36
|
-
# end
|
25
|
+
# r.rodauth(:admin) # route admin rodauth requests
|
37
26
|
end
|
38
27
|
end
|
data/lib/rodauth/rails/app.rb
CHANGED
@@ -25,6 +25,8 @@ module Rodauth
|
|
25
25
|
auth_class ||= Class.new(Rodauth::Rails::Auth)
|
26
26
|
|
27
27
|
plugin :rodauth, auth_class: auth_class, name: name, csrf: false, flash: false, json: true, **options, &block
|
28
|
+
|
29
|
+
self::RodaRequest.include RequestMethods
|
28
30
|
end
|
29
31
|
|
30
32
|
before do
|
@@ -44,6 +46,21 @@ module Rodauth
|
|
44
46
|
def self.rodauth!(name)
|
45
47
|
rodauth(name) or fail ArgumentError, "unknown rodauth configuration: #{name.inspect}"
|
46
48
|
end
|
49
|
+
|
50
|
+
module RequestMethods
|
51
|
+
def rodauth(name = nil)
|
52
|
+
prefix = scope.rodauth(name).prefix
|
53
|
+
|
54
|
+
if prefix.present? && remaining_path == path_info
|
55
|
+
on prefix[1..-1] do
|
56
|
+
super
|
57
|
+
break # forward other `{prefix}/*` requests to the rails router
|
58
|
+
end
|
59
|
+
else
|
60
|
+
super
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
47
64
|
end
|
48
65
|
end
|
49
66
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodauth-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janko Marohnić
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|