Skip to content

Commit

Permalink
Separate API Key auth support generation (#124)
Browse files Browse the repository at this point in the history
## Problem

The generator `stitches:api` forces adding in API Key auth support.

## Solution

Introduce a new generator `stitches:api_migration` that can add in API Key auth support.
  • Loading branch information
benortiz authored Jun 17, 2024
1 parent b791d8e commit c98a18a
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 17 deletions.
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,20 @@ bundle install

Then, set it up:

```
```bash
> bin/rails generate stitches:api
> bundle exec rake db:migrate
> bin/rails generate stitches:api_migration # only if you're using API key authentication
> bundle exec rake db:migrate # only if you're using API key authentication
```

### Disable API Key Support

If you're not using the API Key authentication feature of the library, configure stitches:

```ruby
Stitches.configure do |config|
config.disable_api_key_support = true
end
```

### Upgrading from an older version
Expand Down
12 changes: 0 additions & 12 deletions lib/stitches/api_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@

module Stitches
class ApiGenerator < Rails::Generators::Base
include Rails::Generators::Migration

source_root(File.expand_path(File.join(File.dirname(__FILE__), "generator_files")))

def self.next_migration_number(path)
Time.now.utc.strftime("%Y%m%d%H%M%S")
end

desc "Bootstraps your API service with a basic ping controller and spec to ensure everything is setup properly"
def bootstrap_api
gem_group :development, :test do
Expand Down Expand Up @@ -44,16 +38,10 @@ def bootstrap_api
copy_file "app/controllers/api/v2.rb"
copy_file "app/controllers/api/v1/pings_controller.rb"
copy_file "app/controllers/api/v2/pings_controller.rb"
copy_file "app/models/api_client.rb"
copy_file "config/initializers/stitches.rb"
copy_file "lib/tasks/generate_api_key.rake"
template "spec/features/api_spec.rb.erb", "spec/features/api_spec.rb"
copy_file "spec/acceptance/ping_v1_spec.rb", "spec/acceptance/ping_v1_spec.rb"

migration_template "db/migrate/enable_uuid_ossp_extension.rb", "db/migrate/enable_uuid_ossp_extension.rb"
sleep 1 # allow clock to tick so we get different numbers
migration_template "db/migrate/create_api_clients.rb", "db/migrate/create_api_clients.rb"

inject_into_file 'spec/rails_helper.rb', %q{
config.include RSpec::Rails::RequestExampleGroup, type: :feature
}, before: /^end/
Expand Down
23 changes: 23 additions & 0 deletions lib/stitches/api_migration_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'rails/generators'

module Stitches
class ApiMigrationGenerator < Rails::Generators::Base
include Rails::Generators::Migration

source_root(File.expand_path(File.join(File.dirname(__FILE__), "generator_files")))

def self.next_migration_number(path)
Time.now.utc.strftime("%Y%m%d%H%M%S")
end

desc "Add a DB backed key storage system for your API service"
def bootstrap_api_migration
copy_file "app/models/api_client.rb"
copy_file "lib/tasks/generate_api_key.rake"

migration_template "db/migrate/enable_uuid_ossp_extension.rb", "db/migrate/enable_uuid_ossp_extension.rb"
sleep 1 # allow clock to tick so we get different numbers
migration_template "db/migrate/create_api_clients.rb", "db/migrate/create_api_clients.rb"
end
end
end
4 changes: 4 additions & 0 deletions lib/stitches/generator_files/config/initializers/stitches.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
# but generally should be a string with no spaces or special characters.
configuration.custom_http_auth_scheme = "CustomKeyAuth"

# Disable API Key feature. Enable it to add a database backed API Key auth scheme.
# Be sure to run `bin/rails generate stitches:api_migration` after enabling.
configuration.disable_api_key_support = true

# Env var that gets the primary key of the authenticated ApiKey
# for access in your controllers, so they don't need to re-parse the header
# configuration.env_var_to_hold_api_client_primary_key = "YOUR_ENV_VAR"
Expand Down
6 changes: 4 additions & 2 deletions lib/stitches/generator_files/spec/acceptance/ping_v1_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
response_field :status, "The status of the ping", scope: "ping", "Type" => "String"
example "ping the server to validate your client's happy path" do

header "Authorization", "CustomKeyAuth key=#{api_client.key}"
# Only needed if you're using API Key authentication
# header "Authorization", "CustomKeyAuth key=#{api_client.key}"
do_request

result = JSON.parse(response_body)
Expand All @@ -33,7 +34,8 @@

example "ping the server to validate your client's error handling" do

header "Authorization", "CustomKeyAuth key=#{api_client.key}"
# Only needed if you're using API Key authentication
# header "Authorization", "CustomKeyAuth key=#{api_client.key}"
do_request

result = JSON.parse(response_body)
Expand Down
3 changes: 3 additions & 0 deletions lib/stitches/generator_files/spec/features/api_spec.rb.erb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ feature "general API stuff" do
expect(response).to have_api_error(code: "test", message: "OH NOES!")
end

<%# Remove always false if statement to enable API Key authentication %>
<% if false %>
scenario "no auth header given" do
headers = TestHeaders.new(api_client: nil)
<% if ::Rails::VERSION::MAJOR >= 5 -%>
Expand Down Expand Up @@ -80,6 +82,7 @@ feature "general API stuff" do

expect(response).to have_auth_error
end
<% end %>

scenario "no version" do
headers = TestHeaders.new(version: nil)
Expand Down
2 changes: 1 addition & 1 deletion lib/stitches/spec/test_headers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def initialize(options={})
"Accept" => full_mimetype,
"Content-Type" => full_mimetype,
}.tap { |headers|
set_authorization_header(headers,options)
set_authorization_header(headers,options) unless Stitches.configuration.disable_api_key_support
}
end

Expand Down
1 change: 1 addition & 0 deletions lib/stitches_norailtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def self.configuration
require 'stitches/error'
require 'stitches/errors'
require 'stitches/api_generator'
require 'stitches/api_migration_generator'
require 'stitches/add_deprecation_generator'
require 'stitches/add_enabled_to_api_clients_generator'
require 'stitches/add_disabled_at_to_api_clients_generator'
Expand Down
1 change: 1 addition & 0 deletions spec/integration/add_to_rails_app_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def run(command)

it "works as described in the README" do
run "bin/rails generate stitches:api"
run "bin/rails generate stitches:api_migration"

# Yuck! So much duplication! BUT: Rails app templates have a notoriously silent failure mode, so mostly
# what this is doing is ensuring that the generator inserted stuff when asked and that the very basics of what happens
Expand Down

0 comments on commit c98a18a

Please sign in to comment.