diff --git a/app/controllers/api/users_controller.rb b/app/controllers/api/users_controller.rb
index 533b995..da058f9 100644
--- a/app/controllers/api/users_controller.rb
+++ b/app/controllers/api/users_controller.rb
@@ -7,7 +7,9 @@ def index
end
def show
- @user = scope.find(params[:id])
+ @user = scope.all.to_a.find do |user|
+ user.id == params[:id]
+ end
render json: serialize(resource: @user)
end
diff --git a/prompt.md b/prompt.md
new file mode 100644
index 0000000..e5fde75
--- /dev/null
+++ b/prompt.md
@@ -0,0 +1,2621 @@
+Project Path: backend
+
+Source Tree:
+
+```txt
+backend
+├── Gemfile
+├── Gemfile.lock
+├── README.md
+├── Rakefile
+├── app
+│ ├── assets
+│ │ ├── config
+│ │ │ └── manifest.js
+│ │ ├── images
+│ │ └── stylesheets
+│ │ └── application.css
+│ ├── channels
+│ │ └── application_cable
+│ │ ├── channel.rb
+│ │ └── connection.rb
+│ ├── controllers
+│ │ ├── api
+│ │ │ ├── oauth_applications_controller.rb
+│ │ │ └── users_controller.rb
+│ │ ├── application_controller.rb
+│ │ └── concerns
+│ ├── helpers
+│ │ └── application_helper.rb
+│ ├── jobs
+│ │ └── application_job.rb
+│ ├── mailers
+│ │ └── application_mailer.rb
+│ ├── models
+│ │ ├── application_record.rb
+│ │ ├── concerns
+│ │ ├── oauth_application.rb
+│ │ └── user.rb
+│ ├── serializers
+│ │ ├── application_serializer.rb
+│ │ ├── oauth_application_serializer.rb
+│ │ └── user_serializer.rb
+│ └── views
+│ └── layouts
+│ ├── application.html.erb
+│ ├── mailer.html.erb
+│ └── mailer.text.erb
+├── bin
+│ ├── bundle
+│ ├── rails
+│ ├── rake
+│ ├── setup
+│ ├── spring
+│ └── update
+├── config
+│ ├── application.rb
+│ ├── boot.rb
+│ ├── cable.yml
+│ ├── database.yml
+│ ├── environment.rb
+│ ├── environments
+│ │ ├── development.rb
+│ │ ├── production.rb
+│ │ └── test.rb
+│ ├── initializers
+│ │ ├── active_record_belongs_to_required_by_default.rb
+│ │ ├── application_controller_renderer.rb
+│ │ ├── backtrace_silencers.rb
+│ │ ├── callback_terminator.rb
+│ │ ├── cookies_serializer.rb
+│ │ ├── doorkeeper.rb
+│ │ ├── filter_parameter_logging.rb
+│ │ ├── inflections.rb
+│ │ ├── mime_types.rb
+│ │ ├── per_form_csrf_tokens.rb
+│ │ ├── request_forgery_protection.rb
+│ │ ├── session_store.rb
+│ │ ├── version.rb
+│ │ └── wrap_parameters.rb
+│ ├── locales
+│ │ ├── doorkeeper.en.yml
+│ │ └── en.yml
+│ ├── puma.rb
+│ ├── routes.rb
+│ └── secrets.yml
+├── config.ru
+├── db
+│ ├── migrate
+│ │ ├── 20160403175438_create_users.rb
+│ │ ├── 20160405123119_create_doorkeeper_tables.rb
+│ │ └── 20160410194053_add_owner_to_oauth_applications.rb
+│ ├── schema.rb
+│ └── seeds.rb
+├── lib
+│ ├── assets
+│ ├── metal.rb
+│ └── tasks
+├── log
+│ └── .keep
+├── public
+│ ├── 404.html
+│ ├── 422.html
+│ ├── 500.html
+│ ├── apple-touch-icon-precomposed.png
+│ ├── apple-touch-icon.png
+│ ├── favicon.ico
+│ └── robots.txt
+├── spec
+│ ├── controllers
+│ │ └── api
+│ │ ├── oauth_applications_controller_spec.rb
+│ │ └── users_controller_spec.rb
+│ ├── factories
+│ │ ├── doorkeeper_token.rb
+│ │ ├── oauth_application.rb
+│ │ └── user.rb
+│ ├── json_helper.rb
+│ ├── models
+│ │ └── user_spec.rb
+│ ├── rails_helper.rb
+│ └── spec_helper.rb
+├── tmp
+│ └── .keep
+└── vendor
+ └── assets
+ └── stylesheets
+
+```
+
+`backend/Gemfile`:
+
+```
+source "https://rubygems.org"
+
+ruby "2.3.3"
+
+gem "rails", "5.1.1"
+gem "pg", "~> 0.18"
+gem "puma"
+gem "oj"
+gem "redis", "~> 3.0"
+gem "bcrypt", "~> 3.1.7"
+
+gem "doorkeeper", "4.2.6"
+gem "jsonapi-serializers"
+
+group :development, :test do
+ gem "byebug"
+ gem "pry"
+end
+
+group :test do
+ gem "rspec"
+ gem "rspec-rails"
+ gem "database_cleaner"
+ gem "factory_girl"
+end
+
+group :development do
+ # Access an IRB console on exception pages or by using <%= console %> in views
+ gem "web-console", "~> 3.0"
+ gem "listen", "~> 3.0.5"
+ gem "spring"
+ gem "spring-watcher-listen", "~> 2.0.0"
+end
+
+gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
+
+```
+
+`backend/Gemfile.lock`:
+
+```lock
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actioncable (5.1.1)
+ actionpack (= 5.1.1)
+ nio4r (~> 2.0)
+ websocket-driver (~> 0.6.1)
+ actionmailer (5.1.1)
+ actionpack (= 5.1.1)
+ actionview (= 5.1.1)
+ activejob (= 5.1.1)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 2.0)
+ actionpack (5.1.1)
+ actionview (= 5.1.1)
+ activesupport (= 5.1.1)
+ rack (~> 2.0)
+ rack-test (~> 0.6.3)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (5.1.1)
+ activesupport (= 5.1.1)
+ builder (~> 3.1)
+ erubi (~> 1.4)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
+ activejob (5.1.1)
+ activesupport (= 5.1.1)
+ globalid (>= 0.3.6)
+ activemodel (5.1.1)
+ activesupport (= 5.1.1)
+ activerecord (5.1.1)
+ activemodel (= 5.1.1)
+ activesupport (= 5.1.1)
+ arel (~> 8.0)
+ activesupport (5.1.1)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (~> 0.7)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ arel (8.0.0)
+ bcrypt (3.1.11)
+ bindex (0.5.0)
+ builder (3.2.3)
+ byebug (9.0.6)
+ coderay (1.1.1)
+ concurrent-ruby (1.0.5)
+ database_cleaner (1.6.1)
+ diff-lcs (1.3)
+ doorkeeper (4.2.6)
+ railties (>= 4.2)
+ erubi (1.6.0)
+ factory_girl (4.8.0)
+ activesupport (>= 3.0.0)
+ ffi (1.9.18)
+ globalid (0.4.0)
+ activesupport (>= 4.2.0)
+ i18n (0.8.4)
+ jsonapi-serializers (1.0.0)
+ activesupport
+ listen (3.0.8)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+ loofah (2.0.3)
+ nokogiri (>= 1.5.9)
+ mail (2.6.5)
+ mime-types (>= 1.16, < 4)
+ method_source (0.8.2)
+ mime-types (3.1)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2016.0521)
+ mini_portile2 (2.1.0)
+ minitest (5.10.2)
+ nio4r (2.1.0)
+ nokogiri (1.7.2)
+ mini_portile2 (~> 2.1.0)
+ oj (3.0.10)
+ pg (0.20.0)
+ pry (0.10.4)
+ coderay (~> 1.1.0)
+ method_source (~> 0.8.1)
+ slop (~> 3.4)
+ puma (3.8.2)
+ rack (2.0.3)
+ rack-test (0.6.3)
+ rack (>= 1.0)
+ rails (5.1.1)
+ actioncable (= 5.1.1)
+ actionmailer (= 5.1.1)
+ actionpack (= 5.1.1)
+ actionview (= 5.1.1)
+ activejob (= 5.1.1)
+ activemodel (= 5.1.1)
+ activerecord (= 5.1.1)
+ activesupport (= 5.1.1)
+ bundler (>= 1.3.0, < 2.0)
+ railties (= 5.1.1)
+ sprockets-rails (>= 2.0.0)
+ rails-dom-testing (2.0.3)
+ activesupport (>= 4.2.0)
+ nokogiri (>= 1.6)
+ rails-html-sanitizer (1.0.3)
+ loofah (~> 2.0)
+ railties (5.1.1)
+ actionpack (= 5.1.1)
+ activesupport (= 5.1.1)
+ method_source
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rake (12.0.0)
+ rb-fsevent (0.9.8)
+ rb-inotify (0.9.8)
+ ffi (>= 0.5.0)
+ redis (3.3.3)
+ rspec (3.6.0)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-core (3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-expectations (3.6.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.6.0)
+ rspec-mocks (3.6.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.6.0)
+ rspec-rails (3.6.0)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ railties (>= 3.0)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-support (3.6.0)
+ slop (3.6.0)
+ spring (2.0.2)
+ activesupport (>= 4.2)
+ spring-watcher-listen (2.0.1)
+ listen (>= 2.7, < 4.0)
+ spring (>= 1.2, < 3.0)
+ sprockets (3.7.1)
+ concurrent-ruby (~> 1.0)
+ rack (> 1, < 3)
+ sprockets-rails (3.2.0)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ thor (0.19.4)
+ thread_safe (0.3.6)
+ tzinfo (1.2.3)
+ thread_safe (~> 0.1)
+ web-console (3.5.1)
+ actionview (>= 5.0)
+ activemodel (>= 5.0)
+ bindex (>= 0.4.0)
+ railties (>= 5.0)
+ websocket-driver (0.6.5)
+ websocket-extensions (>= 0.1.0)
+ websocket-extensions (0.1.2)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ bcrypt (~> 3.1.7)
+ byebug
+ database_cleaner
+ doorkeeper (= 4.2.6)
+ factory_girl
+ jsonapi-serializers
+ listen (~> 3.0.5)
+ oj
+ pg (~> 0.18)
+ pry
+ puma
+ rails (= 5.1.1)
+ redis (~> 3.0)
+ rspec
+ rspec-rails
+ spring
+ spring-watcher-listen (~> 2.0.0)
+ tzinfo-data
+ web-console (~> 3.0)
+
+RUBY VERSION
+ ruby 2.3.3p222
+
+BUNDLED WITH
+ 1.15.0
+
+```
+
+`backend/README.md`:
+
+```md
+
+
+# Backend [](https://travis-ci.org/mariogintili/backend) [](https://codeclimate.com/github/mariogintili/backend)
+
+A Rails starter app, [JSON-API](http://jsonapi.org/) compliant + [OAUTH 2](http://oauth.net/2/) based authentication :monkey_face: Always riding the latest edge :light_rail:
+
+## Caveats
+
+Due to a Rails bug, in order to correctly serve it for the [client counterpart](https://github.com/mariogintili/ember-oauth-client) Ember app, run the server like so
+
+```shell
+$ bin/rails s --binding 127.0.0.1
+```
+
+```
+
+`backend/Rakefile`:
+
+```
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+Rails.application.load_tasks
+
+```
+
+`backend/app/assets/config/manifest.js`:
+
+```js
+//= link_tree ../images
+//= link_directory ../stylesheets .css
+
+```
+
+`backend/app/assets/stylesheets/application.css`:
+
+```css
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
+ * files in this directory. Styles in this file should be added after the last require_* statement.
+ * It is generally better to create a new file per style scope.
+ *
+ *= require_tree .
+ *= require_self
+ */
+
+```
+
+`backend/app/channels/application_cable/channel.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
+module ApplicationCable
+ class Channel < ActionCable::Channel::Base
+ end
+end
+
+```
+
+`backend/app/channels/application_cable/connection.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
+module ApplicationCable
+ class Connection < ActionCable::Connection::Base
+ end
+end
+
+```
+
+`backend/app/controllers/api/oauth_applications_controller.rb`:
+
+```rb
+class Api::OauthApplicationsController < ApplicationController
+ before_action :doorkeeper_authorize!, except: [:create]
+ def index
+ @oauth_applications = scope
+ render json: serialize(resource: @oauth_applications, options: { is_collection: true })
+ end
+
+ def show
+ @oauth_application = OauthApplication.find(params[:id])
+ render json: serialize(resource: @oauth_application)
+ end
+
+ def create
+ @oauth_application = OauthApplication.new(oauth_application_params)
+ if @oauth_application.save
+ render json: serialize(resource: @oauth_application), status: :created
+ else
+ render json: { errors: @oauth_application.errors }, status: :unprocessable_entity
+ end
+ end
+
+ private
+
+ def oauth_application_params
+ @oauth_application_params ||= begin
+ data = params.require(:data)
+ hash = data.require(:attributes).permit(:name, :"redirect-uri")
+ hash["redirect_uri"] = hash.delete(:"redirect-uri")
+ hash["owner_id"] = data.require(:relationships).require(:owner).require(:data).require(:id)
+ hash
+ end
+ end
+
+ def scope
+ current_user.oauth_applications
+ end
+end
+
+```
+
+`backend/app/controllers/api/users_controller.rb`:
+
+```rb
+class Api::UsersController < ApplicationController
+ before_action :authenticate_user!, only: [:update]
+
+ def index
+ @users = scope.find(params[:ids])
+ render json: serialize(resource: @users, options: { is_collection: true })
+ end
+
+ def show
+ @user = scope.all.to_a.find do |user|
+ user.id == params[:id]
+ end
+ render json: serialize(resource: @user)
+ end
+
+ def create
+ @user = User.new(user_params)
+ if @user.save
+ render json: serialize(resource: @user), status: :created
+ else
+ render json: { errors: @user.errors }, status: :unprocessable_entity
+ end
+ end
+
+ def update
+ @user = User.find(params.require(:id))
+ return head(:forbidden) unless @user.id == current_user.id
+ if @user.update_attributes(user_params)
+ render json: serialize(resource: @user)
+ else
+ render json: { errors: @user.errors }, status: :unprocessable_entity
+ end
+ end
+
+ private
+
+ def user_params
+ params.require(:data).require(:attributes).permit(:email, :password, :password_confirmation)
+ end
+
+ def scope
+ User
+ end
+end
+
+```
+
+`backend/app/controllers/application_controller.rb`:
+
+```rb
+class ApplicationController < ActionController::Base
+ JSON_API_REQUIRED_REQUEST_HEADER = "application/vnd.api+json"
+ BAD_REQUEST = -> do
+ render nothing: true, status: 400
+ end
+ NOT_FOUND = -> do
+ head :not_found
+ end
+
+ # Prevent CSRF attacks by raising an exception.
+ # For APIs, you may want to use :null_session instead.
+ protect_from_forgery with: :null_session
+ before_action :check_request_headers!
+
+
+ rescue_from ActiveRecord::RecordNotFound, &NOT_FOUND
+ rescue_from ActionController::BadRequest, &BAD_REQUEST
+ rescue_from ActionController::ParameterMissing, &BAD_REQUEST
+
+ def authenticate_user!
+ return @current_user if @current_user.present?
+ if doorkeeper_token
+ found_user = User.find(doorkeeper_token.resource_owner_id)
+ Thread.current[:current_user] = found_user
+ @current_user = found_user
+ found_user
+ else
+ head :forbidden
+ end
+ end
+
+ private
+
+ def check_request_headers!
+ return if request.headers["Content-Type"] == JSON_API_REQUIRED_REQUEST_HEADER
+ fail ActionController::BadRequest
+ end
+
+ def serialize(resource:, options: {})
+ JSONAPI::Serializer.serialize(resource, options)
+ end
+
+ def current_user
+ @current_user ||= authenticate_user!
+ end
+end
+
+```
+
+`backend/app/helpers/application_helper.rb`:
+
+```rb
+module ApplicationHelper
+end
+
+```
+
+`backend/app/jobs/application_job.rb`:
+
+```rb
+class ApplicationJob < ActiveJob::Base
+end
+
+```
+
+`backend/app/mailers/application_mailer.rb`:
+
+```rb
+class ApplicationMailer < ActionMailer::Base
+ default from: 'from@example.com'
+ layout 'mailer'
+end
+
+```
+
+`backend/app/models/application_record.rb`:
+
+```rb
+class ApplicationRecord < ActiveRecord::Base
+ self.abstract_class = true
+end
+
+```
+
+`backend/app/models/oauth_application.rb`:
+
+```rb
+OauthApplication = Doorkeeper::Application
+
+class OauthApplication
+ belongs_to :owner, required: true, dependent: :destroy, class_name: "User"
+end
+
+```
+
+`backend/app/models/user.rb`:
+
+```rb
+class User < ApplicationRecord
+ VALID_EMAIL_REGEX = /\A([\w+\-]\.?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
+
+ has_secure_password
+ validates_format_of :email, with: VALID_EMAIL_REGEX
+ validates :email, { presence: true, uniqueness: true }
+ validates :password_digest, { presence: true }
+
+ has_many :oauth_applications, class_name: "Doorkeeper::Application", as: :owner
+end
+
+```
+
+`backend/app/serializers/application_serializer.rb`:
+
+```rb
+require "jsonapi-serializers"
+
+class ApplicationSerializer
+ include JSONAPI::Serializer
+end
+
+```
+
+`backend/app/serializers/oauth_application_serializer.rb`:
+
+```rb
+class OauthApplicationSerializer < ApplicationSerializer
+ attributes :name, :redirect_uri, :owner_id
+
+ def type
+ "oauth-applications"
+ end
+end
+
+```
+
+`backend/app/serializers/user_serializer.rb`:
+
+```rb
+class UserSerializer < ApplicationSerializer
+ attributes :id, :email
+end
+
+```
+
+`backend/app/views/layouts/application.html.erb`:
+
+```erb
+
+
+
+ Backend
+ <%= csrf_meta_tags %>
+ <%= action_cable_meta_tag %>
+
+ <%= stylesheet_link_tag 'application', media: 'all' %>
+
+
+
+ <%= yield %>
+
+
+
+```
+
+`backend/app/views/layouts/mailer.html.erb`:
+
+```erb
+
+
+
+
+
+
+
+
+ <%= yield %>
+
+
+
+```
+
+`backend/app/views/layouts/mailer.text.erb`:
+
+```erb
+<%= yield %>
+
+```
+
+`backend/bin/bundle`:
+
+```
+#!/usr/bin/env ruby
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+load Gem.bin_path('bundler', 'bundle')
+
+```
+
+`backend/bin/rails`:
+
+```
+#!/usr/bin/env ruby
+begin
+ load File.expand_path('../spring', __FILE__)
+rescue LoadError => e
+ raise unless e.message.include?('spring')
+end
+APP_PATH = File.expand_path('../../config/application', __FILE__)
+require_relative '../config/boot'
+require 'rails/commands'
+
+```
+
+`backend/bin/rake`:
+
+```
+#!/usr/bin/env ruby
+begin
+ load File.expand_path('../spring', __FILE__)
+rescue LoadError => e
+ raise unless e.message.include?('spring')
+end
+require_relative '../config/boot'
+require 'rake'
+Rake.application.run
+
+```
+
+`backend/bin/setup`:
+
+```
+#!/usr/bin/env ruby
+require 'pathname'
+require 'fileutils'
+include FileUtils
+
+# path to your application root.
+APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
+
+def system!(*args)
+ system(*args) || abort("\n== Command #{args} failed ==")
+end
+
+chdir APP_ROOT do
+ # This script is a starting point to setup your application.
+ # Add necessary setup steps to this file.
+
+ puts '== Installing dependencies =='
+ system! 'gem install bundler --conservative'
+ system('bundle check') or system!('bundle install')
+
+ # puts "\n== Copying sample files =="
+ # unless File.exist?('config/database.yml')
+ # cp 'config/database.yml.sample', 'config/database.yml'
+ # end
+
+ puts "\n== Preparing database =="
+ system! 'bin/rails db:setup'
+
+ puts "\n== Removing old logs and tempfiles =="
+ system! 'bin/rails log:clear tmp:clear'
+
+ puts "\n== Restarting application server =="
+ system! 'bin/rails restart'
+end
+
+```
+
+`backend/bin/spring`:
+
+```
+#!/usr/bin/env ruby
+
+# This file loads spring without using Bundler, in order to be fast.
+# It gets overwritten when you run the `spring binstub` command.
+
+unless defined?(Spring)
+ require 'rubygems'
+ require 'bundler'
+
+ if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m))
+ Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) }
+ gem 'spring', match[1]
+ require 'spring/binstub'
+ end
+end
+
+```
+
+`backend/bin/update`:
+
+```
+#!/usr/bin/env ruby
+require 'pathname'
+require 'fileutils'
+include FileUtils
+
+# path to your application root.
+APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
+
+def system!(*args)
+ system(*args) || abort("\n== Command #{args} failed ==")
+end
+
+chdir APP_ROOT do
+ # This script is a way to update your development environment automatically.
+ # Add necessary update steps to this file.
+
+ puts '== Installing dependencies =='
+ system! 'gem install bundler --conservative'
+ system 'bundle check' or system! 'bundle install'
+
+ puts "\n== Updating database =="
+ system! 'bin/rails db:migrate'
+
+ puts "\n== Removing old logs and tempfiles =="
+ system! 'bin/rails log:clear tmp:clear'
+
+ puts "\n== Restarting application server =="
+ system! 'bin/rails restart'
+end
+
+```
+
+`backend/config.ru`:
+
+```ru
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment', __FILE__)
+
+# Action Cable requires that all classes are loaded in advance
+Rails.application.eager_load!
+
+run Rails.application
+
+```
+
+`backend/config/application.rb`:
+
+```rb
+require File.expand_path('../boot', __FILE__)
+
+require "rails"
+# Pick the frameworks you want:
+require "active_model/railtie"
+require "active_job/railtie"
+require "active_record/railtie"
+require "action_controller/railtie"
+require "action_mailer/railtie"
+require "action_view/railtie"
+require "action_cable/engine"
+# require "sprockets/railtie"
+# require "rails/test_unit/railtie"
+
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(*Rails.groups)
+
+module BackendEmberTraining
+ class Application < Rails::Application
+ config.autoload_paths << Rails.root.join("lib")
+ # Settings in config/environments/* take precedence over those specified here.
+ # Application configuration should go into files in config/initializers
+ # -- all .rb files in that directory are automatically loaded.
+ end
+end
+
+```
+
+`backend/config/boot.rb`:
+
+```rb
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' # Set up gems listed in the Gemfile.
+
+```
+
+`backend/config/cable.yml`:
+
+```yml
+# Action Cable uses Redis by default to administer connections, channels, and sending/receiving messages over the WebSocket.
+production:
+ adapter: redis
+ url: redis://localhost:6379/1
+
+development:
+ adapter: async
+
+test:
+ adapter: async
+
+```
+
+`backend/config/database.yml`:
+
+```yml
+# PostgreSQL. Versions 9.1 and up are supported.
+#
+# Install the pg driver:
+# gem install pg
+# On OS X with Homebrew:
+# gem install pg -- --with-pg-config=/usr/local/bin/pg_config
+# On OS X with MacPorts:
+# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
+# On Windows:
+# gem install pg
+# Choose the win32 build.
+# Install PostgreSQL and put its /bin directory on your path.
+#
+# Configure Using Gemfile
+# gem 'pg'
+#
+default: &default
+ adapter: postgresql
+ encoding: unicode
+ # For details on connection pooling, see rails configuration guide
+ # http://guides.rubyonrails.org/configuring.html#database-pooling
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
+
+development:
+ <<: *default
+ database: backend_development
+
+ # The specified database role being used to connect to postgres.
+ # To create additional roles in postgres see `$ createuser --help`.
+ # When left blank, postgres will use the default role. This is
+ # the same name as the operating system user that initialized the database.
+ #username: backend
+
+ # The password associated with the postgres role (username).
+ #password:
+
+ # Connect on a TCP socket. Omitted by default since the client uses a
+ # domain socket that doesn't need configuration. Windows does not have
+ # domain sockets, so uncomment these lines.
+ #host: localhost
+
+ # The TCP port the server listens on. Defaults to 5432.
+ # If your server runs on a different port number, change accordingly.
+ #port: 5432
+
+ # Schema search path. The server defaults to $user,public
+ #schema_search_path: myapp,sharedapp,public
+
+ # Minimum log levels, in increasing order:
+ # debug5, debug4, debug3, debug2, debug1,
+ # log, notice, warning, error, fatal, and panic
+ # Defaults to warning.
+ #min_messages: notice
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ <<: *default
+ database: backend_test
+
+# As with config/secrets.yml, you never want to store sensitive information,
+# like your database password, in your source code. If your source code is
+# ever seen by anyone, they now have access to your database.
+#
+# Instead, provide the password as a unix environment variable when you boot
+# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
+# for a full rundown on how to provide these environment variables in a
+# production deployment.
+#
+# On Heroku and other platform providers, you may have a full connection URL
+# available as an environment variable. For example:
+#
+# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
+#
+# You can use this database configuration with:
+#
+# production:
+# url: <%= ENV['DATABASE_URL'] %>
+#
+production:
+ <<: *default
+ database: backend_production
+ username: backend
+ password: <%= ENV['backend_DATABASE_PASSWORD'] %>
+
+```
+
+`backend/config/environment.rb`:
+
+```rb
+# Load the Rails application.
+require File.expand_path('../application', __FILE__)
+
+# Initialize the Rails application.
+Rails.application.initialize!
+
+```
+
+`backend/config/environments/development.rb`:
+
+```rb
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = false
+
+ # Do not eager load code on boot.
+ config.eager_load = false
+
+ # Show full error reports.
+ config.consider_all_requests_local = true
+
+ # Enable/disable caching. By default caching is disabled.
+ if Rails.root.join('tmp/caching-dev.txt').exist?
+ config.action_controller.perform_caching = true
+
+ config.action_mailer.perform_caching = false
+
+ config.cache_store = :memory_store
+ config.public_file_server.headers = {
+ 'Cache-Control' => 'public, max-age=172800'
+ }
+ else
+ config.action_controller.perform_caching = false
+
+ config.action_mailer.perform_caching = false
+
+ config.cache_store = :null_store
+ end
+
+ # Don't care if the mailer can't send.
+ config.action_mailer.raise_delivery_errors = false
+
+ # Print deprecation notices to the Rails logger.
+ config.active_support.deprecation = :log
+
+ # Raise an error on page load if there are pending migrations.
+ config.active_record.migration_error = :page_load
+
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+
+ # Use an evented file watcher to asynchronously detect changes in source code,
+ # routes, locales, etc. This feature depends on the listen gem.
+ config.file_watcher = ActiveSupport::EventedFileUpdateChecker
+end
+
+```
+
+`backend/config/environments/production.rb`:
+
+```rb
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # Code is not reloaded between requests.
+ config.cache_classes = true
+
+ # Eager load code on boot. This eager loads most of Rails and
+ # your application in memory, allowing both threaded web servers
+ # and those relying on copy on write to perform better.
+ # Rake tasks automatically ignore this option for performance.
+ config.eager_load = true
+
+ # Full error reports are disabled and caching is turned on.
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Disable serving static files from the `/public` folder by default since
+ # Apache or NGINX already handles this.
+ config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
+
+
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server.
+ # config.action_controller.asset_host = 'http://assets.example.com'
+
+ # Specifies the header that your server uses for sending files.
+ # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
+
+ # Action Cable endpoint configuration
+ # config.action_cable.url = 'wss://example.com/cable'
+ # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
+
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
+
+ # Use the lowest log level to ensure availability of diagnostic information
+ # when problems arise.
+ config.log_level = :debug
+
+ # Prepend all log lines with the following tags.
+ config.log_tags = [ :request_id ]
+
+ # Use a different logger for distributed setups.
+ # require 'syslog/logger'
+ # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
+
+ if ENV["RAILS_LOG_TO_STDOUT"].present?
+ config.logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
+ end
+
+ # Use a different cache store in production.
+ # config.cache_store = :mem_cache_store
+
+ # Use a real queuing backend for Active Job (and separate queues per environment)
+ # config.active_job.queue_adapter = :resque
+ # config.active_job.queue_name_prefix = "backend_#{Rails.env}"
+ config.action_mailer.perform_caching = false
+
+ # Ignore bad email addresses and do not raise email delivery errors.
+ # Set this to true and configure the email server for immediate delivery to raise delivery errors.
+ # config.action_mailer.raise_delivery_errors = false
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation cannot be found).
+ config.i18n.fallbacks = true
+
+ # Send deprecation notices to registered listeners.
+ config.active_support.deprecation = :notify
+
+ # Use default logging formatter so that PID and timestamp are not suppressed.
+ config.log_formatter = ::Logger::Formatter.new
+
+ # Do not dump schema after migrations.
+ config.active_record.dump_schema_after_migration = false
+end
+
+```
+
+`backend/config/environments/test.rb`:
+
+```rb
+Rails.application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # The test environment is used exclusively to run your application's
+ # test suite. You never need to work with it otherwise. Remember that
+ # your test database is "scratch space" for the test suite and is wiped
+ # and recreated between test runs. Don't rely on the data there!
+ config.cache_classes = true
+
+ # Do not eager load code on boot. This avoids loading your whole application
+ # just for the purpose of running a single test. If you are using a tool that
+ # preloads Rails for running tests, you may have to set it to true.
+ config.eager_load = false
+
+ # Configure public file server for tests with Cache-Control for performance.
+ config.public_file_server.enabled = true
+ config.public_file_server.headers = {
+ 'Cache-Control' => 'public, max-age=3600'
+ }
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Raise exceptions instead of rendering exception templates.
+ config.action_dispatch.show_exceptions = false
+
+ # Disable request forgery protection in test environment.
+ config.action_controller.allow_forgery_protection = false
+ config.action_mailer.perform_caching = false
+
+ # Tell Action Mailer not to deliver emails to the real world.
+ # The :test delivery method accumulates sent emails in the
+ # ActionMailer::Base.deliveries array.
+ config.action_mailer.delivery_method = :test
+
+ # Print deprecation notices to the stderr.
+ config.active_support.deprecation = :stderr
+
+ # Raises error for missing translations
+ # config.action_view.raise_on_missing_translations = true
+end
+
+```
+
+`backend/config/initializers/active_record_belongs_to_required_by_default.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# Require `belongs_to` associations by default. This is a new Rails 5.0
+# default, so it is introduced as a configuration option to ensure that apps
+# made on earlier versions of Rails are not affected when upgrading.
+Rails.application.config.active_record.belongs_to_required_by_default = true
+
+```
+
+`backend/config/initializers/application_controller_renderer.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# ApplicationController.renderer.defaults.merge!(
+# http_host: 'example.org',
+# https: false
+# )
+
+```
+
+`backend/config/initializers/backtrace_silencers.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
+
+```
+
+`backend/config/initializers/callback_terminator.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# Do not halt callback chains when a callback returns false. This is a new
+# Rails 5.0 default, so it is introduced as a configuration option to ensure
+# that apps made with earlier versions of Rails are not affected when upgrading.
+ActiveSupport.halt_callback_chains_on_return_false = false
+
+```
+
+`backend/config/initializers/cookies_serializer.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# Specify a serializer for the signed and encrypted cookie jars.
+# Valid options are :json, :marshal, and :hybrid.
+Rails.application.config.action_dispatch.cookies_serializer = :json
+
+```
+
+`backend/config/initializers/doorkeeper.rb`:
+
+```rb
+Doorkeeper.configure do
+ # Change the ORM that doorkeeper will use (needs plugins)
+ orm :active_record
+
+ # This block will be called to check whether the resource owner is authenticated or not.
+ resource_owner_authenticator do |*args|
+ fail NotImplementError, "needs to be implemented"
+ # Put your resource owner authentication logic here.
+ # Example implementation:
+ # User.find_by_id(session[:user_id]) || redirect_to(new_user_session_url)
+ end
+
+ resource_owner_from_credentials do |controller|
+ user = User.find_by(email: controller.params.fetch(:username))
+
+ user.authenticate(controller.params.fetch(:password))
+ end
+
+ # If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below.
+ # admin_authenticator do
+ # # Put your admin authentication logic here.
+ # # Example implementation:
+ # Admin.find_by_id(session[:admin_id]) || redirect_to(new_admin_session_url)
+ # end
+
+ # Authorization Code expiration time (default 10 minutes).
+ # authorization_code_expires_in 10.minutes
+
+ # Access token expiration time (default 2 hours).
+ # If you want to disable expiration, set this to nil.
+ # access_token_expires_in 2.hours
+
+ # Assign a custom TTL for implicit grants.
+ # custom_access_token_expires_in do |oauth_client|
+ # oauth_client.application.additional_settings.implicit_oauth_expiration
+ # end
+
+ # Use a custom class for generating the access token.
+ # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
+ # access_token_generator "::Doorkeeper::JWT"
+
+ # Reuse access token for the same resource owner within an application (disabled by default)
+ # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
+ # reuse_access_token
+
+ # Issue access tokens with refresh token (disabled by default)
+ use_refresh_token
+
+ # Provide support for an owner to be assigned to each registered application (disabled by default)
+ # Optional parameter :confirmation => true (default false) if you want to enforce ownership of
+ # a registered application
+ # Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
+ # enable_application_owner :confirmation => false
+
+ # Define access token scopes for your provider
+ # For more information go to
+ # https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
+ # default_scopes :public
+ # optional_scopes :write, :update
+
+ # Change the way client credentials are retrieved from the request object.
+ # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
+ # falls back to the `:client_id` and `:client_secret` params from the `params` object.
+ # Check out the wiki for more information on customization
+ # client_credentials :from_basic, :from_params
+
+ # Change the way access token is authenticated from the request object.
+ # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
+ # falls back to the `:access_token` or `:bearer_token` params from the `params` object.
+ # Check out the wiki for more information on customization
+ # access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
+
+ # Change the native redirect uri for client apps
+ # When clients register with the following redirect uri, they won't be redirected to any server and the authorization code will be displayed within the provider
+ # The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
+ # (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
+ #
+ # native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
+
+ # Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
+ # by default in non-development environments). OAuth2 delegates security in
+ # communication to the HTTPS protocol so it is wise to keep this enabled.
+ #
+ # force_ssl_in_redirect_uri !Rails.env.development?
+
+ # Specify what grant flows are enabled in array of Strings. The valid
+ # strings and the flows they enable are:
+ #
+ # "authorization_code" => Authorization Code Grant Flow
+ # "implicit" => Implicit Grant Flow
+ # "password" => Resource Owner Password Credentials Grant Flow
+ # "client_credentials" => Client Credentials Grant Flow
+ #
+ # If not specified, Doorkeeper enables authorization_code and
+ # client_credentials.
+ #
+ # implicit and password grant flows have risks that you should understand
+ # before enabling:
+ # http://tools.ietf.org/html/rfc6819#section-4.4.2
+ # http://tools.ietf.org/html/rfc6819#section-4.4.3
+ #
+ # grant_flows %w(authorization_code client_credentials)
+
+ # Under some circumstances you might want to have applications auto-approved,
+ # so that the user skips the authorization step.
+ # For example if dealing with a trusted application.
+ # skip_authorization do |resource_owner, client|
+ # client.superapp? or resource_owner.admin?
+ # end
+
+ # WWW-Authenticate Realm (default "Doorkeeper").
+ # realm "Doorkeeper"
+end
+
+# https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Resource-Owner-Password-Credentials-flow
+Doorkeeper.configuration.token_grant_types << "password"
+
+Doorkeeper::Application.class_eval do
+ def jsonapi_serializer_class_name
+ "OauthApplicationSerializer"
+ end
+end
+
+```
+
+`backend/config/initializers/filter_parameter_logging.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# Configure sensitive parameters which will be filtered from the log file.
+Rails.application.config.filter_parameters += [:password]
+
+```
+
+`backend/config/initializers/inflections.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format. Inflections
+# are locale specific, and you may define rules for as many different
+# locales as you wish. All of these examples are active by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.acronym 'RESTful'
+# end
+
+```
+
+`backend/config/initializers/mime_types.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+# https://github.com/rails-api/active_model_serializers/issues/1027#issuecomment-126543577
+mime_types = [
+ "application/vnd.api+json",
+ "text/x-json",
+ "application/json"
+]
+
+Mime::Type.unregister :json
+Mime::Type.register "application/json", :json, mime_types
+
+```
+
+`backend/config/initializers/per_form_csrf_tokens.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# Enable per-form CSRF tokens.
+Rails.application.config.action_controller.per_form_csrf_tokens = true
+
+```
+
+`backend/config/initializers/request_forgery_protection.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# Enable origin-checking CSRF mitigation.
+Rails.application.config.action_controller.forgery_protection_origin_check = true
+
+```
+
+`backend/config/initializers/session_store.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+Rails.application.config.session_store :cookie_store, key: '_backend_session'
+
+```
+
+`backend/config/initializers/version.rb`:
+
+```rb
+Rails::Application::VERSION = "0.1.4"
+
+```
+
+`backend/config/initializers/wrap_parameters.rb`:
+
+```rb
+# Be sure to restart your server when you modify this file.
+
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+ wrap_parameters format: [:json]
+end
+
+# To enable root element in JSON for ActiveRecord objects.
+# ActiveSupport.on_load(:active_record) do
+# self.include_root_in_json = true
+# end
+
+```
+
+`backend/config/locales/doorkeeper.en.yml`:
+
+```yml
+en:
+ activerecord:
+ attributes:
+ doorkeeper/application:
+ name: 'Name'
+ redirect_uri: 'Redirect URI'
+ errors:
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: 'cannot contain a fragment.'
+ invalid_uri: 'must be a valid URI.'
+ relative_uri: 'must be an absolute URI.'
+ secured_uri: 'must be an HTTPS/SSL URI.'
+
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: 'Are you sure?'
+ buttons:
+ edit: 'Edit'
+ destroy: 'Destroy'
+ submit: 'Submit'
+ cancel: 'Cancel'
+ authorize: 'Authorize'
+ form:
+ error: 'Whoops! Check your form for possible errors'
+ help:
+ redirect_uri: 'Use one line per URI'
+ native_redirect_uri: 'Use %{native_redirect_uri} for local tests'
+ scopes: 'Separate scopes with spaces. Leave blank to use the default scopes.'
+ edit:
+ title: 'Edit application'
+ index:
+ title: 'Your applications'
+ new: 'New Application'
+ name: 'Name'
+ callback_url: 'Callback URL'
+ new:
+ title: 'New Application'
+ show:
+ title: 'Application: %{name}'
+ application_id: 'Application Id'
+ secret: 'Secret'
+ scopes: 'Scopes'
+ callback_urls: 'Callback urls'
+ actions: 'Actions'
+
+ authorizations:
+ buttons:
+ authorize: 'Authorize'
+ deny: 'Deny'
+ error:
+ title: 'An error has occurred'
+ new:
+ title: 'Authorization required'
+ prompt: 'Authorize %{client_name} to use your account?'
+ able_to: 'This application will be able to'
+ show:
+ title: 'Authorization code'
+
+ authorized_applications:
+ confirmations:
+ revoke: 'Are you sure?'
+ buttons:
+ revoke: 'Revoke'
+ index:
+ title: 'Your authorized applications'
+ application: 'Application'
+ created_at: 'Created At'
+ date_format: '%Y-%m-%d %H:%M:%S'
+
+ errors:
+ messages:
+ # Common error messages
+ invalid_request: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
+ invalid_redirect_uri: 'The redirect uri included is not valid.'
+ unauthorized_client: 'The client is not authorized to perform this request using this method.'
+ access_denied: 'The resource owner or authorization server denied the request.'
+ invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
+ server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
+ temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
+
+ #configuration error messages
+ credential_flow_not_configured: 'Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.'
+ resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfiged.'
+
+ # Access grant errors
+ unsupported_response_type: 'The authorization server does not support this response type.'
+
+ # Access token errors
+ invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
+ invalid_grant: 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'
+ unsupported_grant_type: 'The authorization grant type is not supported by the authorization server.'
+
+ # Password Access token errors
+ invalid_resource_owner: 'The provided resource owner credentials are not valid, or resource owner cannot be found'
+
+ invalid_token:
+ revoked: "The access token was revoked"
+ expired: "The access token expired"
+ unknown: "The access token is invalid"
+
+ flash:
+ applications:
+ create:
+ notice: 'Application created.'
+ destroy:
+ notice: 'Application deleted.'
+ update:
+ notice: 'Application updated.'
+ authorized_applications:
+ destroy:
+ notice: 'Application revoked.'
+
+ layouts:
+ admin:
+ nav:
+ oauth2_provider: 'OAuth2 Provider'
+ applications: 'Applications'
+ application:
+ title: 'OAuth authorization required'
+
+```
+
+`backend/config/locales/en.yml`:
+
+```yml
+# Files in the config/locales directory are used for internationalization
+# and are automatically loaded by Rails. If you want to use locales other
+# than English, add the necessary files in this directory.
+#
+# To use the locales, use `I18n.t`:
+#
+# I18n.t 'hello'
+#
+# In views, this is aliased to just `t`:
+#
+# <%= t('hello') %>
+#
+# To use a different locale, set it with `I18n.locale`:
+#
+# I18n.locale = :es
+#
+# This would use the information in config/locales/es.yml.
+#
+# To learn more, please read the Rails Internationalization guide
+# available at http://guides.rubyonrails.org/i18n.html.
+
+en:
+ hello: "Hello world"
+
+```
+
+`backend/config/puma.rb`:
+
+```rb
+# Puma can serve each request in a thread from an internal thread pool.
+# The `threads` method setting takes two numbers a minimum and maximum.
+# Any libraries that use thread pools should be configured to match
+# the maximum value specified for Puma. Default is set to 5 threads for minimum
+# and maximum, this matches the default thread size of Active Record.
+#
+threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
+threads threads_count, threads_count
+
+# Specifies the `port` that Puma will listen on to receive requests, default is 3000.
+#
+port ENV.fetch("PORT") { 3000 }
+
+# Specifies the `environment` that Puma will run in.
+#
+environment ENV.fetch("RAILS_ENV") { "development" }
+
+# Specifies the number of `workers` to boot in clustered mode.
+# Workers are forked webserver processes. If using threads and workers together
+# the concurrency of the application would be max `threads` * `workers`.
+# Workers do not work on JRuby or Windows (both of which do not support
+# processes).
+#
+# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
+
+# Use the `preload_app!` method when specifying a `workers` number.
+# This directive tells Puma to first boot the application and load code
+# before forking the application. This takes advantage of Copy On Write
+# process behavior so workers use less memory. If you use this option
+# you need to make sure to reconnect any threads in the `on_worker_boot`
+# block.
+#
+# preload_app!
+
+# The code in the `on_worker_boot` will be called if you are using
+# clustered mode by specifying a number of `workers`. After each worker
+# process is booted this block will be run, if you are using `preload_app!`
+# option you will want to use this block to reconnect to any threads
+# or connections that may have been created at application boot, Ruby
+# cannot share connections between processes.
+#
+# on_worker_boot do
+# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
+# end
+
+# Allow puma to be restarted by `rails restart` command.
+plugin :tmp_restart
+
+```
+
+`backend/config/routes.rb`:
+
+```rb
+Rails.application.routes.draw do
+ use_doorkeeper scope: "/api/oauth"
+ root to: "api/users#index"
+
+ namespace :api do
+ resources :users, only: [:index, :show, :create, :update]
+ resources :oauth_applications, path: "/oauth-applications", only: [:index, :show, :create]
+ end
+
+ # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
+ # Serve websocket cable requests in-process
+ # mount ActionCable.server => '/cable'
+end
+
+```
+
+`backend/config/secrets.yml`:
+
+```yml
+# Be sure to restart your server when you modify this file.
+
+# Your secret key is used for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+# You can use `rails secret` to generate a secure secret key.
+
+# Make sure the secrets in this file are kept private
+# if you're sharing your code publicly.
+
+development:
+ secret_key_base: a7592c0579655b88d0a0bc93efb90270053b04815743eeb47657a7e023cb7fb25b754c422299184e4c3a1e011dea757ac7a9e35986c2c7720a41807da694aace
+ doorkeeper:
+ name: "oauth_application"
+ redirect_uri: "http://localhost:4200/"
+test:
+ secret_key_base: e8bd7a87364aa33c48ae99669b33c538c1359437a1c45fd67407169ce212428dad777dc70e059e34766f466ffc6d77d32ca9d1b62041dec7a7014bd3375cb8ab
+ name: "oauth_application"
+ redirect_uri: "http://test:4200/"
+# Do not keep production secrets in the repository,
+# instead read values from the environment.
+production:
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
+
+```
+
+`backend/db/migrate/20160403175438_create_users.rb`:
+
+```rb
+class CreateUsers < ActiveRecord::Migration[5.0]
+ def change
+ create_table :users do |t|
+ t.string :email
+ t.string :password_digest
+
+ t.timestamps
+ end
+ end
+end
+
+```
+
+`backend/db/migrate/20160405123119_create_doorkeeper_tables.rb`:
+
+```rb
+class CreateDoorkeeperTables < ActiveRecord::Migration
+ def change
+ create_table :oauth_applications do |t|
+ t.string :name, null: false
+ t.string :uid, null: false
+ t.string :secret, null: false
+ t.text :redirect_uri, null: false
+ t.string :scopes, null: false, default: ''
+ t.timestamps
+ end
+
+ add_index :oauth_applications, :uid, unique: true
+
+ create_table :oauth_access_grants do |t|
+ t.integer :resource_owner_id, null: false
+ t.integer :application_id, null: false
+ t.string :token, null: false
+ t.integer :expires_in, null: false
+ t.text :redirect_uri, null: false
+ t.datetime :created_at, null: false
+ t.datetime :revoked_at
+ t.string :scopes
+ end
+
+ add_index :oauth_access_grants, :token, unique: true
+
+ create_table :oauth_access_tokens do |t|
+ t.integer :resource_owner_id
+ t.integer :application_id
+ t.string :token, null: false
+ t.string :refresh_token
+ t.integer :expires_in
+ t.datetime :revoked_at
+ t.datetime :created_at, null: false
+ t.string :scopes
+ end
+
+ add_index :oauth_access_tokens, :token, unique: true
+ add_index :oauth_access_tokens, :resource_owner_id
+ add_index :oauth_access_tokens, :refresh_token, unique: true
+ end
+end
+
+```
+
+`backend/db/migrate/20160410194053_add_owner_to_oauth_applications.rb`:
+
+```rb
+class AddOwnerToOauthApplications < ActiveRecord::Migration[5.0]
+ def change
+ add_column :oauth_applications, :owner_id, :integer, null: true
+ add_index :oauth_applications, [:owner_id]
+ end
+end
+
+```
+
+`backend/db/schema.rb`:
+
+```rb
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema.define(version: 20160410194053) do
+
+ # These are extensions that must be enabled in order to support this database
+ enable_extension "plpgsql"
+
+ create_table "oauth_access_grants", force: :cascade do |t|
+ t.integer "resource_owner_id", null: false
+ t.integer "application_id", null: false
+ t.string "token", null: false
+ t.integer "expires_in", null: false
+ t.text "redirect_uri", null: false
+ t.datetime "created_at", null: false
+ t.datetime "revoked_at"
+ t.string "scopes"
+ end
+
+ add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree
+
+ create_table "oauth_access_tokens", force: :cascade do |t|
+ t.integer "resource_owner_id"
+ t.integer "application_id"
+ t.string "token", null: false
+ t.string "refresh_token"
+ t.integer "expires_in"
+ t.datetime "revoked_at"
+ t.datetime "created_at", null: false
+ t.string "scopes"
+ end
+
+ add_index "oauth_access_tokens", ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true, using: :btree
+ add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id", using: :btree
+ add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree
+
+ create_table "oauth_applications", force: :cascade do |t|
+ t.string "name", null: false
+ t.string "uid", null: false
+ t.string "secret", null: false
+ t.text "redirect_uri", null: false
+ t.string "scopes", default: "", null: false
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.integer "owner_id"
+ end
+
+ add_index "oauth_applications", ["owner_id"], name: "index_oauth_applications_on_owner_id", using: :btree
+ add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree
+
+ create_table "users", force: :cascade do |t|
+ t.string "email"
+ t.string "password_digest"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
+end
+
+```
+
+`backend/db/seeds.rb`:
+
+```rb
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
+#
+# Examples:
+#
+# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
+# Character.create(name: 'Luke', movie: movies.first)
+
+```
+
+`backend/lib/metal.rb`:
+
+```rb
+module Metal
+ autoload :EncryptedPassword, "metal/encrypted_password"
+end
+
+```
+
+`backend/public/404.html`:
+
+```html
+
+
+
+ The page you were looking for doesn't exist (404)
+
+
+
+
+
+
+
+
+
The page you were looking for doesn't exist.
+
You may have mistyped the address or the page may have moved.
+
+
If you are the application owner check the logs for more information.
+
+
+
+
+```
+
+`backend/public/422.html`:
+
+```html
+
+
+
+ The change you wanted was rejected (422)
+
+
+
+
+
+
+
+
+
The change you wanted was rejected.
+
Maybe you tried to change something you didn't have access to.
+
+
If you are the application owner check the logs for more information.
+
+
+
+
+```
+
+`backend/public/500.html`:
+
+```html
+
+
+
+ We're sorry, but something went wrong (500)
+
+
+
+
+
+
+
+
+
We're sorry, but something went wrong.
+
+
If you are the application owner check the logs for more information.
+
+
+
+
+```
+
+`backend/public/robots.txt`:
+
+```txt
+# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-agent: *
+# Disallow: /
+
+```
+
+`backend/spec/controllers/api/oauth_applications_controller_spec.rb`:
+
+```rb
+require "rails_helper"
+
+RSpec.describe Api::OauthApplicationsController, type: :controller do
+ let(:token) { double(:token, acceptable?: true) }
+ let(:user) { build(:user) }
+ let(:oauth_application_name) { "Chrome Web broswer" }
+ let(:oauth_application) do
+ build(:oauth_application, name: oauth_application_name)
+ end
+ before do
+ allow(controller).to receive(:check_request_headers!) { nil }
+ end
+
+ describe "GET api/oauth_applications" do
+ context "without authentication" do
+ before do
+ get :index
+ end
+
+ it "401 - Unauthorized" do
+ expect(response.status).to eq(401)
+ end
+ end
+
+ context "with authentication" do
+ before do
+ allow(controller).to receive(:doorkeeper_token) { token }
+ allow(controller).to receive(:current_user) { user }
+ get :index
+ end
+
+ it "200 - Ok" do
+ expect(response.status).to eq(200)
+ end
+
+ it "returns that users oauth applications" do
+ expect(json_body.fetch(:data)).to be_empty
+ end
+ end
+ end
+
+ describe "GET api/oauth_applications/:id" do
+ context "without authentication" do
+ before do
+ get :show, params: { id: 1 }
+ end
+
+ it "401 - Unauthorized" do
+ expect(response.status).to eq(401)
+ end
+ end
+
+ context "with authentication" do
+ let(:parsed_oauth_application) do
+ json_body.fetch("data")
+ end
+ before do
+ allow(controller).to receive(:doorkeeper_token) { token }
+ allow(controller).to receive(:current_user) { user }
+ allow(OauthApplication).to receive(:find).and_return(oauth_application)
+ get :show, params: { id: 1 }
+ end
+
+ it "200 - Ok" do
+ expect(response.status).to eq(200)
+ end
+
+ it "returns a serialized oauth application" do
+ expect(parsed_oauth_application["type"]).to eq("oauth-applications")
+ expect(parsed_oauth_application["attributes"]["name"]).to eq(oauth_application_name)
+ end
+ end
+ end
+
+ describe "POST api/oauth_applications" do
+ context "with valid parameters" do
+ let!(:user) { create(:user) }
+ let(:params) do
+ {
+ data: {
+ type: "oauth-applications",
+ attributes: {
+ name: oauth_application_name,
+ "redirect-uri": "https://localhost:4200/"
+ },
+ relationships: {
+ owner: {
+ data: {
+ type: "users",
+ id: user.id
+ }
+ }
+ }
+ }
+ }
+ end
+
+ before do
+ post :create, params: params
+ end
+
+ it "201 - Created" do
+ expect(response.status).to eq(201)
+ end
+
+ it "returns the serialized oauth-application" do
+ payload = json_body.fetch(:data)
+ expect(payload.fetch(:attributes).fetch(:name)).to eq(oauth_application_name)
+ end
+ end
+
+ context "without valid parameters" do
+ let(:invalid_params) do
+ {
+ data: {
+ type: "oauth-applications",
+ attributes: {
+ name: nil
+ },
+ relationships: {
+ owner: {
+ data: {
+ id: 100
+ }
+ }
+ }
+ }
+ }
+ end
+ before do
+ post :create, params: invalid_params
+ end
+
+ it "422 - Unprocessable entity" do
+ expect(response.status).to eq(422)
+ end
+
+ it "Responds with errors" do
+ errors = json_body.fetch(:errors)
+ expect(errors.fetch(:name)).not_to be_empty
+ expect(errors.fetch(:redirect_uri)).not_to be_empty
+ expect(errors.fetch(:owner)).not_to be_empty
+ end
+ end
+ end
+end
+
+```
+
+`backend/spec/controllers/api/users_controller_spec.rb`:
+
+```rb
+require "rails_helper"
+
+RSpec.describe Api::UsersController, type: :controller do
+ before do
+ allow(controller).to receive(:check_request_headers!) { nil }
+ end
+ describe "GET /api/users" do
+ let(:users) { [build(:user), build(:user)] }
+ before do
+ allow(controller.send(:scope)).to receive(:find) { users }
+ get :index, params: { ids: [1,2] }
+ end
+
+ it "200 - OK" do
+ expect(response.status).to eq(200)
+ end
+
+ it "returns a collection of users" do
+ expect(json_body.fetch(:data).length).to eq(users.length)
+ end
+ end
+
+ describe "POST /api/users" do
+ context "with valid parameters" do
+ let(:email) { "foo@bar.com" }
+ let(:password) { "password12345" }
+ let(:payload) do
+ {
+ data: {
+ attributes: {
+ email: email,
+ password: password,
+ password_confirmation: password
+ },
+ type: "users"
+ }
+ }
+ end
+
+ it "201 - Created" do
+ post :create, params: payload
+ expect(response.status).to eq(201)
+ end
+
+ it "creates a user" do
+ expect { post :create, params: payload }.to change { User.count }.from(0).to(1)
+ end
+ end
+
+ context "with invalid parameters" do
+ let(:payload) do
+ {
+ data: {
+ attributes: {
+ email: "foo@?@.com",
+ password: "123",
+ password_confirmation: "123456"
+ },
+ type: "users"
+ }
+ }
+ end
+
+ before do
+ post :create, params: payload
+ end
+
+ it "422 - Unprocessable entity" do
+ expect(response.status).to eq(422)
+ end
+
+ it "returns errors" do
+ expect(json_body.key?(:errors)).to be_truthy
+ expect(json_body[:errors][:password_confirmation]).not_to be_empty
+ end
+ end
+ end
+
+ describe "GET /api/users/:id" do
+ let(:email) { "foo@bar.com" }
+ let(:user) { build(:user, email: email) }
+
+ before do
+ allow(controller.send(:scope)).to receive(:find) { user }
+ get :show, params: { id: 1 }
+ end
+
+ it "200 - OK" do
+ expect(response.status).to eq(200)
+ end
+
+ it "returns a user's attributes in the payload" do
+ expect(json_body.fetch(:data).fetch(:attributes).fetch(:email)).to eq(email)
+ end
+ end
+
+ describe "PUT /api/users/:id" do
+ context "with an authenticated user" do
+ context "who is the same as the target to update" do
+ let(:valid_token) do
+ create(:doorkeeper_token).tap do |token|
+ allow(token).to receive(:acceptable?).and_return(true)
+ end
+ end
+ let(:new_email) { "foobars@barbar.com" }
+ let(:payload) do
+ {
+ data: {
+ attributes: {
+ email: new_email
+ },
+ type: "users"
+ }
+ }
+ end
+
+ before do
+ allow(controller).to receive(:doorkeeper_token) { valid_token }
+ put :update, params: payload.merge(id: valid_token.resource_owner_id)
+ end
+
+ context "with valid parameters" do
+ it "200 - OK" do
+ expect(response.status).to eq(200)
+ end
+
+ it "updates the attributes for the user" do
+ expect(json_body.fetch(:data).fetch(:attributes).fetch(:email)).to eq(new_email)
+ end
+ end
+ end
+
+ context "who is different from the target to update" do
+ let(:target) { create(:user) }
+ let(:valid_token) do
+ create(:doorkeeper_token).tap do |token|
+ allow(token).to receive(:acceptable?).and_return(true)
+ end
+ end
+
+ before do
+ allow(controller).to receive(:doorkeeper_token) { valid_token }
+ put :update, params: { id: target.id }
+ end
+
+ it "403 - Forbidden" do
+ expect(response.status).to eq(403)
+ end
+ end
+ end
+ end
+end
+
+```
+
+`backend/spec/factories/doorkeeper_token.rb`:
+
+```rb
+FactoryGirl.define do
+ factory :doorkeeper_token, class: "Doorkeeper::AccessToken" do
+ resource_owner_id { create(:user).id }
+ end
+end
+
+```
+
+`backend/spec/factories/oauth_application.rb`:
+
+```rb
+FactoryGirl.define do
+ factory :oauth_application, class: "Doorkeeper::Application" do
+ end
+end
+
+```
+
+`backend/spec/factories/user.rb`:
+
+```rb
+FactoryGirl.define do
+ factory :user do
+ email { "user-#{SecureRandom.hex(3)}@foo.com" }
+ password "foobar12345"
+ end
+end
+
+```
+
+`backend/spec/json_helper.rb`:
+
+```rb
+module JSONHelper
+ def json_body
+ JSON.parse(response.body).with_indifferent_access
+ end
+end
+
+```
+
+`backend/spec/models/user_spec.rb`:
+
+```rb
+require "rails_helper"
+
+RSpec.describe User, type: :model do
+ let(:email) { "foo@bar.com" }
+ let(:password) { "mario123456" }
+ subject do
+ described_class.new(email: email,
+ password: password,
+ password_confirmation: password)
+ end
+
+ describe "attributes" do
+ it "#email" do
+ expect(subject.email).to eq(email)
+ end
+
+ it "#password" do
+ expect(subject.password).to eq(password)
+ end
+ end
+end
+
+```
+
+`backend/spec/rails_helper.rb`:
+
+```rb
+ENV["RAILS_ENV"] ||= 'test'
+require "spec_helper"
+require File.expand_path("../../config/environment", __FILE__)
+require "rspec/rails"
+require "database_cleaner"
+# Add additional requires below this line. Rails is not loaded until this point!
+
+ActiveRecord::Migration.maintain_test_schema!
+
+RSpec.configure do |config|
+ config.infer_spec_type_from_file_location!
+
+ config.before(:suite) do
+ DatabaseCleaner.strategy = :transaction
+ DatabaseCleaner.clean_with(:truncation)
+ end
+
+ config.around(:each) do |example|
+ DatabaseCleaner.cleaning do
+ example.run
+ end
+ end
+end
+
+```
+
+`backend/spec/spec_helper.rb`:
+
+```rb
+require "pry"
+require "securerandom"
+require "factory_girl"
+require_relative "./json_helper"
+# load lib folder for tests, even when rails is not loaded
+Dir[Dir.pwd + "/lib/**"].each { |f| require(f) if f.match(/.rb/) }
+
+RSpec.configure do |config|
+
+ config.expect_with :rspec do |expectations|
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+
+ # mocks
+ config.mock_with :rspec do |mocks|
+ mocks.verify_partial_doubles = true
+ end
+
+ config.include JSONHelper, type: :controller
+
+ # factory girl
+ config.include FactoryGirl::Syntax::Methods
+ config.before(:suite) do
+ FactoryGirl.find_definitions
+ end
+end
+
+```