├── .gitignore ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── grape-devise.gemspec └── lib ├── grape-devise.rb └── grape ├── devise.rb └── devise ├── endpoints.rb ├── endpoints ├── all.rb └── authentication.rb ├── helpers.rb └── version.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | *.bundle 19 | *.so 20 | *.o 21 | *.a 22 | mkmf.log 23 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in grape-devise.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Pavel Shutsin 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Grape::Devise 2 | 3 | This gem attempts to integrate Devise into Grape in native Grape fashion. 4 | Devise has great model modules, warden strategies etc so it's really tempts to use it when building APIs. 5 | However devise controller layer doesn't fit well with Grape. Here where `grape-devise` comes to the rescue. 6 | 7 | Gem benifits: 8 | 9 | * native Grape integration 10 | * ready-to-use set of helpers as well-known `current_user` 11 | 12 | ## Installation 13 | 14 | Add this line to your application's Gemfile: 15 | 16 | gem 'grape-devise' 17 | 18 | And then execute: 19 | 20 | $ bundle 21 | 22 | Or install it yourself as: 23 | 24 | $ gem install grape-devise 25 | 26 | ## Usage 27 | 28 | 1. First of all you need to setup devise as usual. See ( https://github.com/plataformatec/devise#getting-started ) 29 | 1. Add `Grape::Devise::Helpers` helpers and include `Grape::Devise::Endpoints` module into your API endpoints class e.g. 30 | 31 | ``` 32 | class MyApi < Grape::API 33 | helpers Grape::Devise::Helpers 34 | include Grape::Devise::Endpoints 35 | end 36 | ``` 37 | 38 | 1. Remove Devise routes from `routes.rb` file. We will use Grape-styled endpoints for our API, not default Rails routes. 39 | 1. Add `Devise.add_mapping(:users, {})` to your `devise.rb` initializer. Consider replacing `:users` with appropriate symbol of your devise resource. 40 | 1. Restart your server 41 | 42 | ## TODO 43 | 44 | * Add support for every Devise module. Currently we have endpoints only for `:database_authenticatable` 45 | * Create Rails generator 46 | * Improve test coverage 47 | 48 | ## Contributing 49 | 50 | 1. Fork it ( https://github.com/pluff/grape-devise/fork ) 51 | 2. Create your feature branch (`git checkout -b my-new-feature`) 52 | 3. Commit your changes (`git commit -am 'Add some feature'`) 53 | 4. Push to the branch (`git push origin my-new-feature`) 54 | 5. Create a new Pull Request 55 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | 3 | -------------------------------------------------------------------------------- /grape-devise.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'grape/devise/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "grape-devise" 8 | spec.version = Grape::Devise::VERSION 9 | spec.authors = ["Pavel Shutsin"] 10 | spec.email = ["publicshady@gmail.com"] 11 | spec.summary = %q{This gem attempts to integrate Devise into Grape.} 12 | spec.description = %q{This gem attempts to provide Devise integration into Grape in native Grape way} 13 | spec.homepage = "https://github.com/pluff/grape-devise" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files -z`.split("\x0") 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_dependency "grape", "> 0.7" 22 | spec.add_dependency "devise", "> 3.2" 23 | spec.add_dependency "activesupport", ">= 3.2.6", "< 5" 24 | 25 | spec.add_development_dependency "bundler", "~> 1.6" 26 | spec.add_development_dependency "rake" 27 | end 28 | -------------------------------------------------------------------------------- /lib/grape-devise.rb: -------------------------------------------------------------------------------- 1 | require 'grape/devise' 2 | -------------------------------------------------------------------------------- /lib/grape/devise.rb: -------------------------------------------------------------------------------- 1 | require "grape/devise/version" 2 | 3 | require "grape/devise/helpers" 4 | require "grape/devise/endpoints" 5 | 6 | module Grape 7 | module Devise 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/grape/devise/endpoints.rb: -------------------------------------------------------------------------------- 1 | require "grape/devise/endpoints/all" 2 | require "active_support/concern" 3 | 4 | module Grape 5 | module Devise 6 | module Endpoints 7 | extend ActiveSupport::Concern 8 | 9 | included do 10 | include Grape::Devise::Endpoints::Authentication 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/grape/devise/endpoints/all.rb: -------------------------------------------------------------------------------- 1 | require 'grape/devise/endpoints/authentication' 2 | -------------------------------------------------------------------------------- /lib/grape/devise/endpoints/authentication.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/concern' 2 | 3 | module Grape 4 | module Devise 5 | module Endpoints 6 | module Authentication 7 | extend ActiveSupport::Concern 8 | included do 9 | before do 10 | env['devise.mapping'] = ::Devise::Mapping.find_by_path!(request.path) 11 | end 12 | 13 | helpers do 14 | delegate :session, to: :request 15 | 16 | def auth_options 17 | {scope: resource_name} 18 | end 19 | 20 | # Gets the actual resource stored in the instance variable 21 | def resource 22 | instance_variable_get(:"@#{resource_name}") 23 | end 24 | 25 | # Proxy to devise map name 26 | def resource_name 27 | devise_mapping.name 28 | end 29 | 30 | alias :scope_name :resource_name 31 | 32 | # Proxy to devise map class 33 | def resource_class 34 | devise_mapping.to 35 | end 36 | 37 | # Attempt to find the mapped route for devise based on request path 38 | def devise_mapping 39 | @devise_mapping ||= env['devise.mapping'] 40 | end 41 | 42 | include ::Devise::Controllers::SignInOut 43 | end 44 | 45 | ::Devise.mappings.keys.each do |mapping_name| 46 | resource mapping_name.to_s.pluralize do 47 | desc "Signs in #{mapping_name}" 48 | post 'sign_in' do 49 | env["devise.allow_params_authentication"] = true 50 | @resource = warden.authenticate auth_options 51 | if @resource 52 | sign_in(resource_name, @resource) 53 | @resource 54 | else 55 | {error: warden.message} 56 | end 57 | end 58 | 59 | desc "Signs out current #{mapping_name}" 60 | delete 'sign_out' do 61 | signed_out = (::Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)) 62 | true 63 | end 64 | end 65 | end 66 | end 67 | end 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /lib/grape/devise/helpers.rb: -------------------------------------------------------------------------------- 1 | module Grape 2 | module Devise 3 | module Helpers 4 | def warden 5 | env['warden'] 6 | end 7 | 8 | def current_user 9 | warden.user 10 | end 11 | 12 | def authenticate! 13 | handle_not_authenticated unless warden.authenticated? 14 | end 15 | 16 | def handle_not_authenticated 17 | error!('401 Unauthorized!', 401) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/grape/devise/version.rb: -------------------------------------------------------------------------------- 1 | module Grape 2 | module Devise 3 | VERSION = "0.0.1" 4 | end 5 | end 6 | --------------------------------------------------------------------------------