garage
garage copied to clipboard
Rails extension for RESTful Hypermedia API
Garage
Rails framework to add RESTful hypermedia API to your application.
Gem name has been changed!
We renamed gem name the_garage
from version 2.0.0. Please update your Gemfile.
What Is It?
Garage provides a simple, Hypermedia friendly RESTful API to your Rails application using its native RESTful routes. Garage provides a descriptive way to serve your ActiveRecord models, as well as plain old Ruby objects as JSON-based resources.
Garage supports OAuth 2 authorizations via Doorkeeper (more extensions to come), and provides resource-based access controls.
Quickstart
In Gemfile
:
# Notice this gem has "the_" prefix for gem name.
gem 'the_garage'
In your Rails model class:
class Employee < ActiveRecord::Base
include Garage::Representer
include Garage::Authorizable
belongs_to :division
has_many :projects
property :id
property :title
property :first_name
property :last_name
property :division, selectable: true
collection :projects, selectable: true
link(:division) { division_path(division) }
link(:projects) { employee_projects_path(self) }
def self.build_permissions(perms, other, target)
perms.permits! :read
end
end
In your controller classes:
class ApplicationController < ActionController::Base
include Garage::ControllerHelper
# ...
end
class EmployeesController < ApplicationController
include Garage::RestfulActions
def require_resources
@resources = Employee.all
end
end
Resources are rendered with respond_with (responders gem).
Additional options can be passed to respond_with by implementing respond_with_resources_options
(index action)
and respond_with_resource_options
(show, update destroy actions).
Available options
-
:paginate
- (Boolean) Enable pagination whentrue
. Paginates with theper_page
andpage
params -
:per_page
- (Integer) value for default number of resources per page when paginating -
:max_per_page
- (Integer) Maximum resources per page, irrespective of requested per_page -
:hard_limit
- (Integer) Limit of retrievable records when paginating. Also hides total records. -
:distinct_by
- (Symbol) Specify a property to count by for total page count -
:to_resource_options
- (Hash) Options to pass as argument toto_resource(options)
Create decorator for your AR models
With not small application, you may add a presentation layer to build API responses.
Define a decorator class with Resource
suffix and define #to_resource
in
your AR model.
class User < ActiveRecord::Base
def to_resource
UserResource.new(self)
end
end
class UserResource
include Garage::Representer
include Garage::Authorizable
property :id
property :name
property :email
delegate :id, :name, :email, to: :@model
def initialize(model)
@model = model
end
end
Advanced Configurations
In config/initializers/garage.rb
:
Garage.configure {}
# Optional
Rails.application.config.to_prepare do
Garage::TokenScope.configure do
register :public, desc: "accessing publicly available data" do
access :read, Recipe
end
register :read_post, desc: "reading blog post" do
access :read, Post
end
end
end
# If you want to use different authentication/authorization logic.
Garage.configuration.strategy = Garage::Strategy::AuthServer
The following authentication strategies are available.
-
Garage::Strategy::NoAuthentication
- Does not authenticate request and does not verify permission and access on resource operation. For non-public, internal-use Garage application. -
Garage::Strategy::Test
- Trust request thoroughly, and build access token from request headers. For testing or prototyping. -
Garage::Strategy::Doorkeeper
- Authenticate request with doorkeeper gem. To use this strategy, bundle garage-doorkeeper gem. -
Garage::Strategy::AuthServer
- Delegate authentication to OAuth server. This auth strategy has configurations.
Delegate Authentication/Authorization to your OAuth server
To delegate auth to your OAuth server, use Garage::Strategy::AuthServer
strategy.
Then configure auth server strategy:
-
Garage.configuration.auth_server_url
- A full url of your OAuth server's access token validation endpoint. i.e.https://example.com/token
. -
Garage.configuration.auth_server_host
- A host header value to request to your OAuth server. Can be empty. -
Garage.configuration.auth_server_timeout
- A read timeout second. Default is 1 second.
The OAuth server must response a json with following structure.
-
token
(string, null) - OAuth access token value. -
token_type
(string) - OAuth access token value. i.e.bearer
type. -
scope
(string) - OAuth scopes separated by spaces. i.e.public read_user
. -
application_id
(integer) - OAuth application id of the access token. -
resource_owner_id
(integer, null) - Resource owner id of the access token. -
expired_at
(string, null) - Expire datetime with string representation. -
revoked_at
(string, null) - Revoked datetime with string representation.
When requested access token is invalid, OAuth server must response 401.
Customize Authentication/Authorization
Garage supports customizable Authentication/Authorization strategy. The Strategy has some conventions to follow.
- Offer OAuth access token via
access_token
method. With no access token case (does not authenticate request)access_token
should returnnil
. - Register
verify_auth
hook as before filter inincluded
block if authenticate request. Or register custom authentication hook. The custom authentication hook should response unauthorized usingunauthorized_render_options
when fails to authenticate a request. - Offer whether verify permission and access in
RestfulActions
viaverify_permission
method. Returntrue
to verify them.
module MyStrategy
extend ActiveSupport::Concern
included do
# Register verify_auth hook if you want to authenticate request.
before_action :verify_auth
end
def access_token
# Fetch some `attributes` from DB or auth server API using request.
# Then returns an AccessToken with caching.
@access_token ||= Garage::Strategy::AccessToken.new(attributes)
end
# Whether verify permission and access in `RestfulActions`.
def verify_permission?
true
end
end
Distributed tracing
In case you use auth-server strategy, you can setup distributed tracing for the service communication between garage application and auth server. Currently, we support following tracers:
-
aws-xray
using aws-xray gem.- Bundle
aws-xray
gem in your application. - Configure
service
option for a logical service name of the auth server.
- Bundle
# e.g. aws-xray tracer
require 'aws/xray/hooks/net_http'
Garage::Tracer::AwsXrayTracer.service = 'your-auth-server-name'
Garage.configuration.tracer = Garage::Tracer::AwsXrayTracer
Development
See DEVELOPMENT.md.
Authors
- Tatsuhiko Miyagawa
- Taiki Ono
- Yusuke Mito
- Ryo Nakamura