stitchfix / stitches Goto Github PK
View Code? Open in Web Editor NEWCreate a Microservice in Rails with minimal ceremony
License: MIT License
Create a Microservice in Rails with minimal ceremony
License: MIT License
(missing from repo and gemspec)
Having a generator option alone makes it hard to take advantage of future updates without squashing any changes you may have made to the generated files in the meantime. A Rails engine pattern could help give this and still allow for a generator for non-Rails apps. It would also mean that we could set up a dummy app for CI to actually run the bundled tests.
Another option or baby step could be to vendor the generated files to discourage changes being made to them directly.
When rotating keys, you can't necessarily delete old api keys, for example if you have foreign key constraints to them from your domain objects.
The default api_clients
table should have an active
field, defaulting to true
, or maybe an active_til
field? It would probably be handy to have some rake tasks to help with rotation as well.
This will be brittle, but might be worth doing, if we had a test that:
rails new
bundle install
rails g stitches:api
rails rspec:install
rails apitome:install
bundle exec rake
And fails the build if any of that fails.
Getting a deprecation warning when running this gem in Rails 6.
DEPRECATION WARNING: `Module#parent` has been renamed to `module_parent`. `parent` is deprecated and will be removed in Rails 6.1. (called from <top (required)> at /Users/chris/galley/api_playground/config/environment.rb:5)
Looks like it is the result of rails/rails#34051. Not critical at all as it is just a warning, but wanted to flag!
rails new APP_NAME
[error]
uninitialized constant RSpec::Rails (NameError)
I have various routes whitelisted, docs for example, but I need to whitelist a route such as users/abc12379xyz_asdf/activate
I have tried this regex but it is still throwing an error:
configuration.whitelist_regexp = %r{\A/(sidekiq|resque|docs|assets)(users\/.*\/activate)(\Z|/.*\Z)}
error:
Unauthorized - no authorization header
Is it possible to use an alternative header for authentication?
I use stitches to protect the API routes from unauthorized requests based on the API key, but I use devise-jwt to authenticate/authorize user access.
Devise-jwt uses a Bearer token in the Authorization header, so being able to override the header used by stitches to almost anything else would let these two gems play nice together.
The pain of #61 highlights that this regex is cumbersome to maintain. In referrals, we have an entry that looks like this:
configuration.allowlist_regexp = %r{\A/(referrals\/api\/contacts|referrals\/api\/referrals|assets|client|referrals\/api\/docs|referrals\/proof_of_life|referrals\/resque|referrals\/teaspoon)}
It turns out that there was an overly permissive entry in there which essentially white listed all of the referrals API - not desirable and tests are being back filled.
I'd like to add something that's a bit easier to read/maintain. I spent some time trying to replace the middleware by creating a Rails custom constraint. Constraints have a handle on the request, but not on the response and so I ran into trouble when trying to replicate these lines:
stitches/lib/stitches/api_key.rb
Lines 44 to 45 in 80231b3
Is there a) still a need for these lines, and b) a way to move them out of the middleware? Or maybe some third way to make it more obvious in routes.rb what does/does not require the api_key? A less desirable option would be to add a before_filter in the controllers but I'm guessing that choice was avoided on purpose?
Since this is an API, we don't want sessions or cookie support. Let's remove the middleware for these.
# No sessions. This removes the need for CSRF protection.
config.middleware.delete "ActionDispatch::Cookies"
config.middleware.delete "ActionDispatch::Session::CookieStore"
config.middleware.delete "ActionDispatch::Flash"
Discussed in https://github.com/stitchfix/app-template/pull/60
Problem:
ApiVersionConstraint
requires clients to send Accept
request headers that specify the API version, for example: Accept: "application/json; version=2"
. However, the API response does not match this expected behavior.
Solution:
Add a default header to Api::ApiController
that responds with the correct version.
For example: Content-Type: "application/json; version=2"
Currently the generator assumes you only have a spec_helper.rb
but the new convention is to keep that barebones and use an enhanced rails_helper.rb
when you need the Rails stack. The generator should take advantage of this, unless we invalidate that with #1
For example:
https://github.com/basecamp/easymon looks interesting. Would be nice if stitches provided an easy way to have your API service expose monitoring details.
Need tasks to bump to a new version of the gem and release it to RubyGems.org
Problem:
I get ActionController::RoutingError (uninitialized constant Api::V1)
in debug mode using Fast Debugger in IntelliJ IDEA (ruby-debug-ide
0.8.0.beta8 with debase
0.3.0.beta8).
Steps to reproduce:
Create new Rails 6 API app and setup stitches.
Create a Controller
, e.g. RestaurantsController
with Rails scaffold:
My example rails app has following routes then:
namespace :api do
scope module: :v1, constraints: Stitches::ApiVersionConstraint.new(1) do
resource :ping, only: [:create]
# Add your V1 resources here
resources :restaurants
end
end
end
...
Controller looks like:
class Api::V1::RestaurantsController < Api::ApiController
...
# POST /restaurants
def create
@restaurant = Restaurant.new(restaurant_params)
if @restaurant.save
render json: { restaurant: @restaurant }, status: :created,
location: @restaurant
else
render json: Stitches::Errors.from_active_record(@restaurant),
status: :unprocessable_entity
end
end
...
end
Now start Server with rails s
and send proper POST to localhost:3000/api/restaurants/1
.
It works just fine for now.
Now start Server with debug and you will see the error: ActionController::RoutingError (uninitialized constant Api::V1)
with the same POST request.
how can I allow the root route? Or what am I setting incorrectly?
My stitches.rb:
require 'stitches'
Stitches.configure do |configuration|
# Regexp of urls that do not require ApiKeys or valid, versioned mime types
configuration.allowlist_regexp = %r{
admin|dashboard|root|password_resets|login|logout|activate|sessions|
sms_events|sidekiq|resque|docs|assets|temp_athletes|temp_commit_offers|
commit-offers|co_email_recipients|co_email_groupings|conferences|
rails\/mailers|forest
}
# Name of the custom Authorization scheme. See http://www.ietf.org/rfc/rfc2617.txt for details,
# but generally should be a string with no spaces or special characters.
configuration.custom_http_auth_scheme = 'My_Key'
end
My routes.rb:
Rails.application.routes.draw do
...
root to: 'user_sessions#new'
...
end
My application_controller.rb:
class ApplicationController < ActionController::Base
include Sorcery::Controller
def authenticate
current_user || not_authenticated
end
def not_authenticated
respond_to do |type|
type.html { redirect_to login_path, alert: 'Please login first' }
type.json { render json: { errors: 'Unable to authenticate' }, status: :unauthorized }
end
end
def unable_to_activate
render json: { errors: 'User already activated or not found' }, status: :unprocessable_entity
end
end
My user_sessions_controller.rb:
class UserSessionsController < ApplicationController
skip_before_action :require_login # , except: %i[destroy]
def new
if logged_in?
if current_user.is_admin?
redirect_to(admin_path) && return
else
redirect_to(athletes_path) && return
end
end
@user = User.new
end
...
end
When I start my server locally and attempt to go to the root all I get rendered is:
Unauthorized - no authorization header
and the only request I see come through is for:
Started GET "/" for 127.0.0.1 at 2018-12-10 10:16:15 -0600
I was reviewing the details from the Error Handling page, but it does seem to indicate the best way to implement validations in the model.
I have a model that contains a file attachment called :object. I have a validation that checks the file size based on file type:
def ojbect_size_valid
errors.add(:object, 'should be less than or equal to 5MB for images') if object_file_size > 5.megabytes && image_type?
errors.add(:object, 'should be less than or equal to 15MB for gifs and videos') if object_file_size > 15.megabytes && (gif_type? || video_type?)
end
This validation is catching files correctly but in the create method of the controller it is throwing an error:
def create
mp = medium_params
@medium = Medium.create(mp)
if @medium.valid?
...
else
render json: {
errors: Stitches::Errors.from_active_record_object(@medium)
}, status: :unprocessable_entity
end
end
undefined method `full_messages' for {}:Hash
103 )
104 else
105
106
107 render json: {
> 108 errors: Stitches::Errors.from_active_record_object(@medium)
109 }, status: :unprocessable_entity
110 end
111 end
112
What am I doing wrong here to get the errors to render?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.