Skip to content

Commit

Permalink
Merge pull request #4 from kobaltz/remove-action-auth-namespace
Browse files Browse the repository at this point in the history
Remove ActionAuth Namespace

- the user, session and webauthn_credential tables have had their ActionAuth namespace removed
- tests updated to reflect the new tables
- updated the models to use the table_name
- updated README
  • Loading branch information
kobaltz committed Aug 6, 2024
2 parents 4bd78f6 + 12ce803 commit c668a4d
Show file tree
Hide file tree
Showing 26 changed files with 108 additions and 87 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:
action_auth (0.3.0)
action_auth (1.0.0)
bcrypt (~> 3.1.0)
rails (~> 7.1)

Expand Down
57 changes: 38 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,43 @@ user experience akin to that offered by the well-regarded Devise gem.
7. [License](#license)
8. [Credits](#credits)

## Breaking Changes

With the release of v1.0.0, there are some breaking changes that have been introduced. The
biggest change is that the `ActionAuth::User` model now uses the table name of `users` instead
of `action_auth_users`. This was done to make it easier to integrate with your application
without having to worry about the table name. If you have an existing application that is
using ActionAuth, you will need to rename the table to `users` with a migration like

```ruby
rename_table :action_auth_users, :users
```

Coming from `v0.3.0` to `v1.0.0`, you will need to create a migration to rename the table and foreign keys.

```ruby
class UpgradeActionAuth < ActiveRecord::Migration[7.1]
def change
rename_table :action_auth_users, :users

rename_table :action_auth_sessions, :sessions
rename_column :sessions, :action_auth_user_id, :user_id

rename_table :action_auth_webauthn_credentials, :webauthn_credentials
rename_column :webauthn_credentials, :action_auth_user_id, :user_id
end
end
```

You will then need to undo the migrations where the foreign keys were added in cases where `foreign_key: true` was
changed to `foreign_key: { to_table: 'action_auth_users' }`. You can do this for each table with a migration like:

```ruby
add_foreign_key :user_settings, :users, column: :user_id unless foreign_key_exists?(:user_settings, :users)
add_foreign_key :profiles, :users, column: :user_id unless foreign_key_exists?(:profiles, :users)
add_foreign_key :nfcs, :users, column: :user_id unless foreign_key_exists?(:nfcs, :users)
```

## Installation
Add this line to your application's Gemfile:

Expand Down Expand Up @@ -242,30 +279,12 @@ end

#### Generating an association

There's one little gotcha when generating the associations. We are using `user:belongs_to` instead of
`action_auth_user:belongs_to`. However, when the foreign key is generated, it will look for the users table
instead of the action_auth_users table. To get around this, we'll need to modify the migration.
We are using `user:belongs_to` instead of `action_auth_user:belongs_to`.

```bash
bin/rails g scaffold posts user:belongs_to title
```

We can update the `foreign_key` from `true` to `{ to_table: :action_auth_users }` to get around this.

```ruby
# db/migrate/XXXXXXXXXXX_create_posts.rb
class CreatePosts < ActiveRecord::Migration[7.1]
def change
create_table :posts do |t|
t.belongs_to :user, null: false, foreign_key: { to_table: :action_auth_users }
t.string :title

t.timestamps
end
end
end
```

And the post model doesn't need anything special to ActionAuth.

```ruby
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/action_auth/registrations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def create
send_email_verification
redirect_to sign_in_path, notice: "Welcome! You have signed up successfully. Please check your email to verify your account."
else
session_record = @user.action_auth_sessions.create!
session_record = @user.sessions.create!
cookies.signed.permanent[:session_token] = { value: session_record.id, httponly: true }

redirect_to sign_in_path, notice: "Welcome! You have signed up successfully"
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/action_auth/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class SessionsController < ApplicationController

def index
@action_auth_wide = true
@sessions = Current.user.action_auth_sessions.order(created_at: :desc)
@sessions = Current.user.sessions.order(created_at: :desc)
end

def new
Expand All @@ -18,7 +18,7 @@ def create
redirect_to new_webauthn_credential_authentications_path
else
return if check_if_email_is_verified(user)
@session = user.action_auth_sessions.create
@session = user.sessions.create
cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true }
redirect_to main_app.root_path, notice: "Signed in successfully"
end
Expand All @@ -28,7 +28,7 @@ def create
end

def destroy
session = Current.user.action_auth_sessions.find(params[:id])
session = Current.user.sessions.find(params[:id])
session.destroy
redirect_to main_app.root_path, notice: "That session has been logged out"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ class ActionAuth::WebauthnCredentialAuthenticationsController < ApplicationContr
layout "action_auth/application"

def new
get_options = WebAuthn::Credential.options_for_get(allow: user.action_auth_webauthn_credentials.pluck(:external_id))
get_options = WebAuthn::Credential.options_for_get(allow: user.webauthn_credentials.pluck(:external_id))
session[:current_challenge] = get_options.challenge
@options = get_options
end

def create
webauthn_credential = WebAuthn::Credential.from_get(params)

credential = user.action_auth_webauthn_credentials.find_by(external_id: webauthn_credential.id)
credential = user.webauthn_credentials.find_by(external_id: webauthn_credential.id)

begin
webauthn_credential.verify(
Expand All @@ -23,7 +23,7 @@ def create

credential.update!(sign_count: webauthn_credential.sign_count)
session.delete(:webauthn_user_id)
session = user.action_auth_sessions.create
session = user.sessions.create
cookies.signed.permanent[:session_token] = { value: session.id, httponly: true }
render json: { status: "ok" }, status: :ok
rescue WebAuthn::Error => e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def options
id: current_user.webauthn_id,
name: current_user.email
},
exclude: current_user.action_auth_webauthn_credentials.pluck(:external_id)
exclude: current_user.webauthn_credentials.pluck(:external_id)
)

session[:current_challenge] = create_options.challenge
Expand All @@ -34,7 +34,7 @@ def create
begin
webauthn_credential.verify(session[:current_challenge])

credential = current_user.action_auth_webauthn_credentials.build(
credential = current_user.webauthn_credentials.build(
external_id: webauthn_credential.id,
nickname: params[:credential_nickname],
public_key: webauthn_credential.public_key,
Expand All @@ -53,7 +53,7 @@ def create
end

def destroy
current_user.action_auth_webauthn_credentials.destroy(params[:id])
current_user.webauthn_credentials.destroy(params[:id])

redirect_to sessions_path
end
Expand Down
6 changes: 1 addition & 5 deletions app/models/action_auth/current.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ class Current < ActiveSupport::CurrentAttributes
attribute :session
attribute :user_agent, :ip_address

delegate :action_auth_user, to: :session, allow_nil: true

def user
action_auth_user
end
delegate :user, to: :session, allow_nil: true
end
end
4 changes: 3 additions & 1 deletion app/models/action_auth/session.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module ActionAuth
class Session < ApplicationRecord
belongs_to :action_auth_user, class_name: "ActionAuth::User", foreign_key: "action_auth_user_id"
self.table_name = "sessions"

belongs_to :user, class_name: "ActionAuth::User", foreign_key: "user_id"

before_create do
self.user_agent = Current.user_agent
Expand Down
14 changes: 8 additions & 6 deletions app/models/action_auth/user.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
module ActionAuth
class User < ApplicationRecord
self.table_name = "users"

has_secure_password

has_many :action_auth_sessions, dependent: :destroy,
class_name: "ActionAuth::Session", foreign_key: "action_auth_user_id"
has_many :sessions, dependent: :destroy,
class_name: "ActionAuth::Session", foreign_key: "user_id"

if ActionAuth.configuration.webauthn_enabled?
has_many :action_auth_webauthn_credentials, dependent: :destroy,
class_name: "ActionAuth::WebauthnCredential", foreign_key: "action_auth_user_id"
has_many :webauthn_credentials, dependent: :destroy,
class_name: "ActionAuth::WebauthnCredential", foreign_key: "user_id"
end

generates_token_for :email_verification, expires_in: 2.days do
Expand All @@ -28,12 +30,12 @@ class User < ApplicationRecord
end

after_update if: :password_digest_previously_changed? do
action_auth_sessions.where.not(id: Current.session).delete_all
sessions.where.not(id: Current.session).delete_all
end

def second_factor_enabled?
return false unless ActionAuth.configuration.webauthn_enabled?
action_auth_webauthn_credentials.any?
webauthn_credentials.any?
end
end
end
2 changes: 2 additions & 0 deletions app/models/action_auth/webauthn_credential.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module ActionAuth
class WebauthnCredential < ApplicationRecord
self.table_name = "webauthn_credentials"

validates :external_id, :public_key, :nickname, :sign_count, presence: true
validates :external_id, uniqueness: true
validates :sign_count,
Expand Down
2 changes: 1 addition & 1 deletion app/views/action_auth/sessions/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
</tr>
</thead>
<tbody>
<% current_user.action_auth_webauthn_credentials.each do |credential| %>
<% current_user.webauthn_credentials.each do |credential| %>
<%= content_tag :tr, id: dom_id(credential) do %>
<td><%= credential.nickname %></td>
<td nowrap><%= credential.created_at.strftime('%B %d, %Y') %></td>
Expand Down
4 changes: 2 additions & 2 deletions db/migrate/20231107165548_create_action_auth_users.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
class CreateActionAuthUsers < ActiveRecord::Migration[7.1]
def change
create_table :action_auth_users do |t|
create_table :users do |t|
t.string :email
t.string :password_digest
t.boolean :verified

t.timestamps
end
add_index :action_auth_users, :email, unique: true
add_index :users, :email, unique: true
end
end
4 changes: 2 additions & 2 deletions db/migrate/20231107170349_create_action_auth_sessions.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class CreateActionAuthSessions < ActiveRecord::Migration[7.1]
def change
create_table :action_auth_sessions do |t|
t.references :action_auth_user, null: false, foreign_key: true
create_table :sessions do |t|
t.references :user, null: false, foreign_key: true
t.string :user_agent
t.string :ip_address

Expand Down
4 changes: 2 additions & 2 deletions db/migrate/20240111125859_add_webauthn_credentials.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
class AddWebauthnCredentials < ActiveRecord::Migration[7.1]
def change
create_table :action_auth_webauthn_credentials do |t|
create_table :webauthn_credentials do |t|
t.string :external_id, null: false
t.string :public_key, null: false
t.string :nickname, null: false
t.bigint :sign_count, null: false, default: 0

t.index :external_id, unique: true

t.references :action_auth_user, foreign_key: true
t.references :user, foreign_key: true

t.timestamps
end
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/20240111142545_add_webauthn_id_to_users.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class AddWebauthnIdToUsers < ActiveRecord::Migration[7.1]
def change
add_column :action_auth_users, :webauthn_id, :string
add_column :users, :webauthn_id, :string
end
end
2 changes: 1 addition & 1 deletion lib/action_auth/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module ActionAuth
VERSION = "0.3.0"
VERSION = "1.0.0"
end
2 changes: 1 addition & 1 deletion test/controllers/action_auth/sessions_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class SessionsControllerTest < ActionDispatch::IntegrationTest
test "should sign out" do
sign_in_as(@user)

delete session_url(@user.action_auth_sessions.last)
delete session_url(@user.sessions.last)
assert_response :redirect
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ class WebauthnCredentialsControllerTest < ActionDispatch::IntegrationTest

public_key_credential = fake_client.get(challenge: authentication_challenge)
post(action_auth.webauthn_credential_authentications_path, params: public_key_credential)
delete action_auth.webauthn_credential_path(user.action_auth_webauthn_credentials.first.id)
delete action_auth.webauthn_credential_path(user.webauthn_credentials.first.id)

assert_redirected_to action_auth.sessions_path
assert_empty user.reload.action_auth_webauthn_credentials
assert_empty user.reload.webauthn_credentials
end

private
Expand Down
6 changes: 3 additions & 3 deletions test/dummy/app/controllers/posts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def show

# GET /posts/new
def new
@post = Post.new
@post = Current.user.posts.new
end

# GET /posts/1/edit
Expand All @@ -21,7 +21,7 @@ def edit

# POST /posts
def create
@post = Post.new(post_params)
@post = Current.user.posts.new(post_params)

if @post.save
redirect_to @post, notice: "Post was successfully created."
Expand Down Expand Up @@ -53,6 +53,6 @@ def set_post

# Only allow a list of trusted parameters through.
def post_params
params.require(:post).permit(:user_id, :title)
params.require(:post).permit(:title)
end
end
2 changes: 1 addition & 1 deletion test/dummy/db/migrate/20240114051355_create_posts.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class CreatePosts < ActiveRecord::Migration[7.1]
def change
create_table :posts do |t|
t.belongs_to :user, null: false, foreign_key: { to_table: :action_auth_users }
t.belongs_to :user, null: false, foreign_key: true
t.string :title

t.timestamps
Expand Down
Loading

0 comments on commit c668a4d

Please sign in to comment.