Adding doorkeeper, adding a REST API
POST /api/statuses Params: status (text contents), in_reply_to_id (optional) GET /api/statuses/:id POST /api/statuses/:id/reblog GET /api/accounts/:id GET /api/accounts/:id/following GET /api/accounts/:id/followers POST /api/accounts/:id/follow POST /api/accounts/:id/unfollow POST /api/follows Params: uri (e.g. user@domain) OAuth authentication is currently disabled, but the API can be used with HTTP Auth.
This commit is contained in:
		
							
								
								
									
										3
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Gemfile
									
									
									
									
									
								
							| @@ -27,6 +27,9 @@ gem 'ostatus2' | ||||
| gem 'goldfinger' | ||||
| gem 'devise' | ||||
| gem 'rails_autolink' | ||||
| gem 'doorkeeper' | ||||
| gem 'rabl' | ||||
| gem 'oj' | ||||
|  | ||||
| group :development, :test do | ||||
|   gem 'rspec-rails' | ||||
|   | ||||
							
								
								
									
										12
									
								
								Gemfile.lock
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Gemfile.lock
									
									
									
									
									
								
							| @@ -74,8 +74,10 @@ GEM | ||||
|       warden (~> 1.2.3) | ||||
|     diff-lcs (1.2.5) | ||||
|     docile (1.1.5) | ||||
|     domain_name (0.5.20160128) | ||||
|     domain_name (0.5.20160216) | ||||
|       unf (>= 0.0.5, < 1.0.0) | ||||
|     doorkeeper (3.1.0) | ||||
|       railties (>= 3.2) | ||||
|     dotenv (2.1.0) | ||||
|     dotenv-rails (2.1.0) | ||||
|       dotenv (= 2.1.0) | ||||
| @@ -90,7 +92,7 @@ GEM | ||||
|       ruby-progressbar (~> 1.4) | ||||
|     globalid (0.3.6) | ||||
|       activesupport (>= 4.1.0) | ||||
|     goldfinger (1.0.1) | ||||
|     goldfinger (1.0.2) | ||||
|       addressable (~> 2.4) | ||||
|       http (~> 1.0) | ||||
|       nokogiri (~> 1.6) | ||||
| @@ -139,6 +141,7 @@ GEM | ||||
|     multi_json (1.11.2) | ||||
|     nokogiri (1.6.7.2) | ||||
|       mini_portile2 (~> 2.0.0.rc2) | ||||
|     oj (2.14.5) | ||||
|     orm_adapter (0.5.0) | ||||
|     ostatus2 (0.1.1) | ||||
|       addressable (~> 2.4) | ||||
| @@ -165,6 +168,8 @@ GEM | ||||
|     puma (2.16.0) | ||||
|     quiet_assets (1.1.0) | ||||
|       railties (>= 3.1, < 5.0) | ||||
|     rabl (0.12.0) | ||||
|       activesupport (>= 2.3.14) | ||||
|     rack (1.6.4) | ||||
|     rack-test (0.6.3) | ||||
|       rack (>= 1.0) | ||||
| @@ -300,6 +305,7 @@ DEPENDENCIES | ||||
|   binding_of_caller | ||||
|   coffee-rails (~> 4.1.0) | ||||
|   devise | ||||
|   doorkeeper | ||||
|   dotenv-rails | ||||
|   fabrication | ||||
|   font-awesome-sass | ||||
| @@ -310,6 +316,7 @@ DEPENDENCIES | ||||
|   jbuilder (~> 2.0) | ||||
|   jquery-rails | ||||
|   nokogiri | ||||
|   oj | ||||
|   ostatus2 | ||||
|   paperclip (~> 4.3) | ||||
|   paranoia (~> 2.0) | ||||
| @@ -317,6 +324,7 @@ DEPENDENCIES | ||||
|   pry-rails | ||||
|   puma | ||||
|   quiet_assets | ||||
|   rabl | ||||
|   rails (= 4.2.5.1) | ||||
|   rails_12factor | ||||
|   rails_autolink | ||||
|   | ||||
							
								
								
									
										3
									
								
								app/assets/javascripts/api/accounts.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/assets/javascripts/api/accounts.coffee
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # Place all the behaviors and hooks related to the matching controller here. | ||||
| # All this logic will automatically be available in application.js. | ||||
| # You can use CoffeeScript in this file: http://coffeescript.org/ | ||||
							
								
								
									
										3
									
								
								app/assets/javascripts/api/follows.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/assets/javascripts/api/follows.coffee
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # Place all the behaviors and hooks related to the matching controller here. | ||||
| # All this logic will automatically be available in application.js. | ||||
| # You can use CoffeeScript in this file: http://coffeescript.org/ | ||||
							
								
								
									
										3
									
								
								app/assets/javascripts/api/statuses.coffee
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/assets/javascripts/api/statuses.coffee
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # Place all the behaviors and hooks related to the matching controller here. | ||||
| # All this logic will automatically be available in application.js. | ||||
| # You can use CoffeeScript in this file: http://coffeescript.org/ | ||||
							
								
								
									
										3
									
								
								app/assets/stylesheets/api/accounts.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/assets/stylesheets/api/accounts.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| // Place all the styles related to the Api::Accounts controller here. | ||||
| // They will automatically be included in application.css. | ||||
| // You can use Sass (SCSS) here: http://sass-lang.com/ | ||||
							
								
								
									
										3
									
								
								app/assets/stylesheets/api/follows.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/assets/stylesheets/api/follows.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| // Place all the styles related to the API::Follows controller here. | ||||
| // They will automatically be included in application.css. | ||||
| // You can use Sass (SCSS) here: http://sass-lang.com/ | ||||
							
								
								
									
										3
									
								
								app/assets/stylesheets/api/statuses.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/assets/stylesheets/api/statuses.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| // Place all the styles related to the API::Statuses controller here. | ||||
| // They will automatically be included in application.css. | ||||
| // You can use Sass (SCSS) here: http://sass-lang.com/ | ||||
| @@ -3,7 +3,6 @@ class AccountsController < ApplicationController | ||||
|  | ||||
|   before_action :set_account | ||||
|   before_action :set_webfinger_header | ||||
|   before_action :authenticate_user!, only: [:follow, :unfollow] | ||||
|  | ||||
|   def show | ||||
|     @statuses = @account.statuses.order('id desc').includes(thread: [:account], reblog: [:account], stream_entry: []) | ||||
| @@ -14,16 +13,6 @@ class AccountsController < ApplicationController | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def follow | ||||
|     current_user.account.follow!(@account) | ||||
|     redirect_to root_path | ||||
|   end | ||||
|  | ||||
|   def unfollow | ||||
|     current_user.account.unfollow!(@account) | ||||
|     redirect_to root_path | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def set_account | ||||
|   | ||||
							
								
								
									
										36
									
								
								app/controllers/api/accounts_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/controllers/api/accounts_controller.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| class Api::AccountsController < ApiController | ||||
|   before_action :set_account | ||||
|   before_action :authenticate_user! | ||||
|   respond_to    :json | ||||
|  | ||||
|   def show | ||||
|   end | ||||
|  | ||||
|   def following | ||||
|     @following = @account.following | ||||
|   end | ||||
|  | ||||
|   def followers | ||||
|     @followers = @account.followers | ||||
|   end | ||||
|  | ||||
|   def statuses | ||||
|     @statuses = @account.statuses | ||||
|   end | ||||
|  | ||||
|   def follow | ||||
|     @follow = current_user.account.follow!(@account) | ||||
|     render action: :show | ||||
|   end | ||||
|  | ||||
|   def unfollow | ||||
|     @unfollow = current_user.account.unfollow!(@account) | ||||
|     render action: :show | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def set_account | ||||
|     @account = Account.find(params[:id]) | ||||
|   end | ||||
| end | ||||
							
								
								
									
										9
									
								
								app/controllers/api/follows_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/controllers/api/follows_controller.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| class Api::FollowsController < ApiController | ||||
|   before_action :authenticate_user! | ||||
|   respond_to    :json | ||||
|  | ||||
|   def create | ||||
|     @follow = FollowService.new.(current_user.account, params[:uri]) | ||||
|     render action: :show | ||||
|   end | ||||
| end | ||||
							
								
								
									
										18
									
								
								app/controllers/api/statuses_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								app/controllers/api/statuses_controller.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| class Api::StatusesController < ApiController | ||||
|   before_action :authenticate_user! | ||||
|   respond_to    :json | ||||
|  | ||||
|   def show | ||||
|     @status = Status.find(params[:id]) | ||||
|   end | ||||
|  | ||||
|   def create | ||||
|     @status = PostStatusService.new.(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id])) | ||||
|     render action: :show | ||||
|   end | ||||
|  | ||||
|   def reblog | ||||
|     @status = ReblogService.new.(current_user.account, Status.find(params[:id])) | ||||
|     render action: :show | ||||
|   end | ||||
| end | ||||
| @@ -1,3 +1,13 @@ | ||||
| class ApiController < ApplicationController | ||||
|   protect_from_forgery with: :null_session | ||||
|  | ||||
|   protected | ||||
|  | ||||
|   def current_resource_owner | ||||
|     User.find(doorkeeper_token.user_id) if doorkeeper_token | ||||
|   end | ||||
|  | ||||
|   def current_user | ||||
|     super || current_resource_owner | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -3,8 +3,6 @@ class StreamEntriesController < ApplicationController | ||||
|  | ||||
|   before_action :set_account | ||||
|   before_action :set_stream_entry | ||||
|   before_action :authenticate_user!, only: [:reblog, :favourite] | ||||
|   before_action :only_statuses!, only: [:reblog, :favourite] | ||||
|  | ||||
|   def show | ||||
|     @type = @stream_entry.activity_type.downcase | ||||
| @@ -15,16 +13,6 @@ class StreamEntriesController < ApplicationController | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def reblog | ||||
|     ReblogService.new.(current_user.account, @stream_entry.activity) | ||||
|     redirect_to root_path | ||||
|   end | ||||
|  | ||||
|   def favourite | ||||
|     FavouriteService.new.(current_user.account, @stream_entry.activity) | ||||
|     redirect_to root_path | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def set_account | ||||
| @@ -34,8 +22,4 @@ class StreamEntriesController < ApplicationController | ||||
|   def set_stream_entry | ||||
|     @stream_entry = @account.stream_entries.find(params[:id]) | ||||
|   end | ||||
|  | ||||
|   def only_statuses! | ||||
|     redirect_to root_url unless @stream_entry.activity_type == 'Status' | ||||
|   end | ||||
| end | ||||
|   | ||||
							
								
								
									
										2
									
								
								app/helpers/api/accounts_helper.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/helpers/api/accounts_helper.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| module Api::AccountsHelper | ||||
| end | ||||
							
								
								
									
										2
									
								
								app/helpers/api/follows_helper.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/helpers/api/follows_helper.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| module Api::FollowsHelper | ||||
| end | ||||
							
								
								
									
										2
									
								
								app/helpers/api/statuses_helper.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/helpers/api/statuses_helper.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| module Api::StatusesHelper | ||||
| end | ||||
| @@ -31,10 +31,10 @@ module StreamEntriesHelper | ||||
|   end | ||||
|  | ||||
|   def reblogged_by_me_class(status) | ||||
|     user_signed_in? && (status.reblog? ? status.reblog : status).reblogs.where(account: current_user.account).count == 1 ? 'reblogged' : '' | ||||
|     user_signed_in? && current_user.account.reblogged?(status) ? 'reblogged' : '' | ||||
|   end | ||||
|  | ||||
|   def favourited_by_me_class(status) | ||||
|     user_signed_in? && (status.reblog? ? status.reblog : status).favourites.where(account: current_user.account).count == 1 ? 'favourited' : '' | ||||
|     user_signed_in? && current_user.account.favourited?(status) ? 'favourited' : '' | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -24,7 +24,7 @@ class Account < ActiveRecord::Base | ||||
|   MENTION_RE = /(?:^|\W)@([a-z0-9_]+(?:@[a-z0-9\.\-]+)?)/i | ||||
|  | ||||
|   def follow!(other_account) | ||||
|     self.active_relationships.first_or_create!(target_account: other_account) | ||||
|     self.active_relationships.where(target_account: other_account).first_or_create!(target_account: other_account) | ||||
|   end | ||||
|  | ||||
|   def unfollow!(other_account) | ||||
| @@ -59,6 +59,14 @@ class Account < ActiveRecord::Base | ||||
|     !(self.secret.blank? || self.verify_token.blank?) | ||||
|   end | ||||
|  | ||||
|   def favourited?(status) | ||||
|     (status.reblog? ? status.reblog : status).favourites.where(account: self).count == 1 | ||||
|   end | ||||
|  | ||||
|   def reblogged?(status) | ||||
|     (status.reblog? ? status.reblog : status).reblogs.where(account: self).count == 1 | ||||
|   end | ||||
|  | ||||
|   def keypair | ||||
|     self.private_key.nil? ? OpenSSL::PKey::RSA.new(self.public_key) : OpenSSL::PKey::RSA.new(self.private_key) | ||||
|   end | ||||
|   | ||||
| @@ -5,11 +5,12 @@ class FollowService < BaseService | ||||
|   def call(source_account, uri) | ||||
|     target_account = follow_remote_account_service.(uri) | ||||
|  | ||||
|     return if target_account.nil? | ||||
|     return nil if target_account.nil? | ||||
|  | ||||
|     follow = source_account.follow!(target_account) | ||||
|     send_interaction_service.(follow.stream_entry, target_account) | ||||
|     source_account.ping!(account_url(account, format: 'atom'), [Rails.configuration.x.hub_url]) | ||||
|     source_account.ping!(account_url(source_account, format: 'atom'), [Rails.configuration.x.hub_url]) | ||||
|     follow | ||||
|   end | ||||
|  | ||||
|   private | ||||
|   | ||||
							
								
								
									
										2
									
								
								app/views/api/accounts/followers.rabl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/views/api/accounts/followers.rabl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| collection @followers | ||||
| extends('api/accounts/show') | ||||
							
								
								
									
										2
									
								
								app/views/api/accounts/following.rabl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/views/api/accounts/following.rabl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| collection @following | ||||
| extends('api/accounts/show') | ||||
							
								
								
									
										9
									
								
								app/views/api/accounts/show.rabl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/views/api/accounts/show.rabl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| object @account | ||||
|  | ||||
| attributes :id, :username, :acct, :display_name, :note | ||||
|  | ||||
| node(:url)       { |account| url_for_target(account) } | ||||
| node(:avatar)    { |account| asset_url(account.avatar.url(:large, false)) } | ||||
| node(:followers) { |account| account.followers.count } | ||||
| node(:following) { |account| account.following.count } | ||||
| node(:statuses)  { |account| account.statuses.count  } | ||||
							
								
								
									
										2
									
								
								app/views/api/accounts/statuses.rabl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/views/api/accounts/statuses.rabl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| collection @statuses | ||||
| extends('api/statuses/show') | ||||
							
								
								
									
										5
									
								
								app/views/api/follows/show.rabl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/views/api/follows/show.rabl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| object @follow | ||||
|  | ||||
| child :target_account => :target_account do | ||||
|   extends('api/accounts/show') | ||||
| end | ||||
							
								
								
									
										18
									
								
								app/views/api/statuses/show.rabl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								app/views/api/statuses/show.rabl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| object @status | ||||
| attributes :id, :created_at, :in_reply_to_id | ||||
|  | ||||
| node(:uri)        { |status| uri_for_target(status) } | ||||
| node(:content)    { |status| status.local? ? linkify(status) : status.content } | ||||
| node(:url)        { |status| url_for_target(status) } | ||||
| node(:reblogs)    { |status| status.reblogs.count } | ||||
| node(:favourites) { |status| status.favourites.count } | ||||
| node(:favourited) { |status| current_user.account.favourited?(status) } | ||||
| node(:reblogged)  { |status| current_user.account.reblogged?(status) } | ||||
|  | ||||
| child :reblog => :reblog do | ||||
|   extends('api/statuses/show') | ||||
| end | ||||
|  | ||||
| child :account do | ||||
|   extends('api/accounts/show') | ||||
| end | ||||
							
								
								
									
										5
									
								
								app/views/doorkeeper/applications/_delete_form.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/views/doorkeeper/applications/_delete_form.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| <%- submit_btn_css ||= 'btn btn-link' %> | ||||
| <%= form_tag oauth_application_path(application) do %> | ||||
|   <input type="hidden" name="_method" value="delete"> | ||||
|   <%= submit_tag t('doorkeeper.applications.buttons.destroy'), onclick: "return confirm('#{ t('doorkeeper.applications.confirmations.destroy') }')", class: submit_btn_css %> | ||||
| <% end %> | ||||
							
								
								
									
										47
									
								
								app/views/doorkeeper/applications/_form.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/views/doorkeeper/applications/_form.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| <%= form_for application, url: doorkeeper_submit_path(application), html: {class: 'form-horizontal', role: 'form'} do |f| %> | ||||
|   <% if application.errors.any? %> | ||||
|     <div class="alert alert-danger" data-alert><p><%= t('doorkeeper.applications.form.error') %></p></div> | ||||
|   <% end %> | ||||
|  | ||||
|   <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do %> | ||||
|     <%= f.label :name, class: 'col-sm-2 control-label' %> | ||||
|     <div class="col-sm-10"> | ||||
|       <%= f.text_field :name, class: 'form-control' %> | ||||
|       <%= doorkeeper_errors_for application, :name %> | ||||
|     </div> | ||||
|   <% end %> | ||||
|  | ||||
|   <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do %> | ||||
|     <%= f.label :redirect_uri, class: 'col-sm-2 control-label' %> | ||||
|     <div class="col-sm-10"> | ||||
|       <%= f.text_area :redirect_uri, class: 'form-control' %> | ||||
|       <%= doorkeeper_errors_for application, :redirect_uri %> | ||||
|       <span class="help-block"> | ||||
|         <%= t('doorkeeper.applications.help.redirect_uri') %> | ||||
|       </span> | ||||
|       <% if Doorkeeper.configuration.native_redirect_uri %> | ||||
|           <span class="help-block"> | ||||
|             <%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: "<code>#{ Doorkeeper.configuration.native_redirect_uri }</code>") %> | ||||
|           </span> | ||||
|       <% end %> | ||||
|     </div> | ||||
|   <% end %> | ||||
|  | ||||
|   <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:scopes].present?}" do %> | ||||
|     <%= f.label :scopes, class: 'col-sm-2 control-label' %> | ||||
|     <div class="col-sm-10"> | ||||
|       <%= f.text_field :scopes, class: 'form-control' %> | ||||
|       <%= doorkeeper_errors_for application, :scopes %> | ||||
|       <span class="help-block"> | ||||
|         <%= t('doorkeeper.applications.help.scopes') %> | ||||
|       </span> | ||||
|     </div> | ||||
|   <% end %> | ||||
|  | ||||
|   <div class="form-group"> | ||||
|     <div class="col-sm-offset-2 col-sm-10"> | ||||
|       <%= f.submit t('doorkeeper.applications.buttons.submit'), class: "btn btn-primary" %> | ||||
|       <%= link_to t('doorkeeper.applications.buttons.cancel'), oauth_applications_path, :class => "btn btn-default" %> | ||||
|     </div> | ||||
|   </div> | ||||
| <% end %> | ||||
							
								
								
									
										5
									
								
								app/views/doorkeeper/applications/edit.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/views/doorkeeper/applications/edit.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| <div class="page-header"> | ||||
|   <h1><%= t('.title') %></h1> | ||||
| </div> | ||||
|  | ||||
| <%= render 'form', application: @application %> | ||||
							
								
								
									
										26
									
								
								app/views/doorkeeper/applications/index.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/views/doorkeeper/applications/index.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <div class="page-header"> | ||||
|   <h1><%= t('.title') %></h1> | ||||
| </div> | ||||
|  | ||||
| <p><%= link_to t('.new'), new_oauth_application_path, class: 'btn btn-success' %></p> | ||||
|  | ||||
| <table class="table table-striped"> | ||||
|   <thead> | ||||
|   <tr> | ||||
|     <th><%= t('.name') %></th> | ||||
|     <th><%= t('.callback_url') %></th> | ||||
|     <th></th> | ||||
|     <th></th> | ||||
|   </tr> | ||||
|   </thead> | ||||
|   <tbody> | ||||
|   <% @applications.each do |application| %> | ||||
|     <tr id="application_<%= application.id %>"> | ||||
|       <td><%= link_to application.name, oauth_application_path(application) %></td> | ||||
|       <td><%= application.redirect_uri %></td> | ||||
|       <td><%= link_to t('doorkeeper.applications.buttons.edit'), edit_oauth_application_path(application), class: 'btn btn-link' %></td> | ||||
|       <td><%= render 'delete_form', application: application %></td> | ||||
|     </tr> | ||||
|   <% end %> | ||||
|   </tbody> | ||||
| </table> | ||||
							
								
								
									
										5
									
								
								app/views/doorkeeper/applications/new.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/views/doorkeeper/applications/new.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| <div class="page-header"> | ||||
|   <h1><%= t('.title') %></h1> | ||||
| </div> | ||||
|  | ||||
| <%= render 'form', application: @application %> | ||||
							
								
								
									
										39
									
								
								app/views/doorkeeper/applications/show.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								app/views/doorkeeper/applications/show.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| <div class="page-header"> | ||||
|   <h1><%= t('.title', name: @application.name) %></h1> | ||||
| </div> | ||||
|  | ||||
| <div class="row"> | ||||
|   <div class="col-md-8"> | ||||
|     <h4><%= t('.application_id') %>:</h4> | ||||
|     <p><code id="application_id"><%= @application.uid %></code></p> | ||||
|  | ||||
|     <h4><%= t('.secret') %>:</h4> | ||||
|     <p><code id="secret"><%= @application.secret %></code></p> | ||||
|  | ||||
|     <h4><%= t('.scopes') %>:</h4> | ||||
|     <p><code id="scopes"><%= @application.scopes %></code></p> | ||||
|  | ||||
|     <h4><%= t('.callback_urls') %>:</h4> | ||||
|  | ||||
|     <table> | ||||
|       <% @application.redirect_uri.split.each do |uri| %> | ||||
|         <tr> | ||||
|           <td> | ||||
|             <code><%= uri %></code> | ||||
|           </td> | ||||
|           <td> | ||||
|             <%= link_to t('doorkeeper.applications.buttons.authorize'), oauth_authorization_path(client_id: @application.uid, redirect_uri: uri, response_type: 'code'), class: 'btn btn-success', target: '_blank' %> | ||||
|           </td> | ||||
|         </tr> | ||||
|       <% end %> | ||||
|     </table> | ||||
|   </div> | ||||
|  | ||||
|   <div class="col-md-4"> | ||||
|     <h3><%= t('.actions') %></h3> | ||||
|  | ||||
|     <p><%= link_to t('doorkeeper.applications.buttons.edit'), edit_oauth_application_path(@application), class: 'btn btn-primary' %></p> | ||||
|  | ||||
|     <p><%= render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger' %></p> | ||||
|   </div> | ||||
| </div> | ||||
							
								
								
									
										7
									
								
								app/views/doorkeeper/authorizations/error.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/views/doorkeeper/authorizations/error.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| <div class="page-header"> | ||||
|   <h1><%= t('doorkeeper.authorizations.error.title') %></h1> | ||||
| </div> | ||||
|  | ||||
| <main role="main"> | ||||
|   <pre><%= @pre_auth.error_response.body[:error_description] %></pre> | ||||
| </main> | ||||
							
								
								
									
										40
									
								
								app/views/doorkeeper/authorizations/new.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/views/doorkeeper/authorizations/new.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <header class="page-header" role="banner"> | ||||
|   <h1><%= t('.title') %></h1> | ||||
| </header> | ||||
|  | ||||
| <main role="main"> | ||||
|   <p class="h4"> | ||||
|     <%= raw t('.prompt', client_name: "<strong class=\"text-info\">#{ @pre_auth.client.name }</strong>") %> | ||||
|   </p> | ||||
|  | ||||
|   <% if @pre_auth.scopes.count > 0 %> | ||||
|     <div id="oauth-permissions"> | ||||
|       <p><%= t('.able_to') %>:</p> | ||||
|  | ||||
|       <ul class="text-info"> | ||||
|         <% @pre_auth.scopes.each do |scope| %> | ||||
|           <li><%= t scope, scope: [:doorkeeper, :scopes] %></li> | ||||
|         <% end %> | ||||
|       </ul> | ||||
|     </div> | ||||
|   <% end %> | ||||
|  | ||||
|   <div class="actions"> | ||||
|     <%= form_tag oauth_authorization_path, method: :post do %> | ||||
|       <%= hidden_field_tag :client_id, @pre_auth.client.uid %> | ||||
|       <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %> | ||||
|       <%= hidden_field_tag :state, @pre_auth.state %> | ||||
|       <%= hidden_field_tag :response_type, @pre_auth.response_type %> | ||||
|       <%= hidden_field_tag :scope, @pre_auth.scope %> | ||||
|       <%= submit_tag t('doorkeeper.authorizations.buttons.authorize'), class: "btn btn-success btn-lg btn-block" %> | ||||
|     <% end %> | ||||
|     <%= form_tag oauth_authorization_path, method: :delete do %> | ||||
|       <%= hidden_field_tag :client_id, @pre_auth.client.uid %> | ||||
|       <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %> | ||||
|       <%= hidden_field_tag :state, @pre_auth.state %> | ||||
|       <%= hidden_field_tag :response_type, @pre_auth.response_type %> | ||||
|       <%= hidden_field_tag :scope, @pre_auth.scope %> | ||||
|       <%= submit_tag t('doorkeeper.authorizations.buttons.deny'), class: "btn btn-danger btn-lg btn-block" %> | ||||
|     <% end %> | ||||
|   </div> | ||||
| </main> | ||||
							
								
								
									
										7
									
								
								app/views/doorkeeper/authorizations/show.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/views/doorkeeper/authorizations/show.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| <header class="page-header"> | ||||
|   <h1><%= t('.title') %>:</h1> | ||||
| </header> | ||||
|  | ||||
| <main role="main"> | ||||
|   <code id="authorization_code"><%= params[:code] %></code> | ||||
| </main> | ||||
| @@ -0,0 +1,5 @@ | ||||
| <%- submit_btn_css ||= 'btn btn-link' %> | ||||
| <%= form_tag oauth_authorized_application_path(application) do %> | ||||
|   <input type="hidden" name="_method" value="delete"> | ||||
|   <%= submit_tag t('doorkeeper.authorized_applications.buttons.revoke'), onclick: "return confirm('#{ t('doorkeeper.authorized_applications.confirmations.revoke') }')", class: submit_btn_css %> | ||||
| <% end %> | ||||
							
								
								
									
										25
									
								
								app/views/doorkeeper/authorized_applications/index.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/views/doorkeeper/authorized_applications/index.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| <header class="page-header"> | ||||
|   <h1><%= t('doorkeeper.authorized_applications.index.title') %></h1> | ||||
| </header> | ||||
|  | ||||
| <main role="main"> | ||||
|   <table class="table table-striped"> | ||||
|     <thead> | ||||
|     <tr> | ||||
|       <th><%= t('doorkeeper.authorized_applications.index.application') %></th> | ||||
|       <th><%= t('doorkeeper.authorized_applications.index.created_at') %></th> | ||||
|       <th></th> | ||||
|       <th></th> | ||||
|     </tr> | ||||
|     </thead> | ||||
|     <tbody> | ||||
|     <% @applications.each do |application| %> | ||||
|       <tr> | ||||
|         <td><%= application.name %></td> | ||||
|         <td><%= application.created_at.strftime(t('doorkeeper.authorized_applications.index.date_format')) %></td> | ||||
|         <td><%= render 'delete_form', application: application %></td> | ||||
|       </tr> | ||||
|     <% end %> | ||||
|     </tbody> | ||||
|   </table> | ||||
| </main> | ||||
							
								
								
									
										37
									
								
								app/views/layouts/doorkeeper/admin.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/views/layouts/doorkeeper/admin.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| <head> | ||||
|   <meta charset="utf-8"> | ||||
|   <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||||
|   <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|   <title>Doorkeeper</title> | ||||
|   <%= stylesheet_link_tag "doorkeeper/admin/application" %> | ||||
|   <%= csrf_meta_tags %> | ||||
| </head> | ||||
| <body> | ||||
| <div class="navbar navbar-inverse navbar-static-top" role="navigation"> | ||||
|   <div class="container-fluid"> | ||||
|     <div class="navbar-header"> | ||||
|       <%= link_to t('doorkeeper.layouts.admin.nav.oauth2_provider'), oauth_applications_path, class: 'navbar-brand' %> | ||||
|     </div> | ||||
|     <ul class="nav navbar-nav"> | ||||
|       <%= content_tag :li, class: "#{'active' if request.path == oauth_applications_path}" do %> | ||||
|         <%= link_to t('doorkeeper.layouts.admin.nav.applications'), oauth_applications_path %> | ||||
|       <% end %> | ||||
|       <%= content_tag :li do %> | ||||
|         <%= link_to 'Home', root_path %> | ||||
|       <% end %> | ||||
|     </ul> | ||||
|   </div> | ||||
| </div> | ||||
| <div class="container"> | ||||
|   <%- if flash[:notice].present? %> | ||||
|     <div class="alert alert-info"> | ||||
|       <%= flash[:notice] %> | ||||
|     </div> | ||||
|   <% end -%> | ||||
|  | ||||
|   <%= yield %> | ||||
| </div> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										23
									
								
								app/views/layouts/doorkeeper/application.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/views/layouts/doorkeeper/application.html.erb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| <head> | ||||
|   <title><%= t('doorkeeper.layouts.application.title') %></title> | ||||
|   <meta charset="utf-8"> | ||||
|   <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||||
|   <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|  | ||||
|   <%= stylesheet_link_tag "doorkeeper/application" %> | ||||
|   <%= csrf_meta_tags %> | ||||
| </head> | ||||
| <body> | ||||
| <div id="container"> | ||||
|   <%- if flash[:notice].present? %> | ||||
|     <div class="alert alert-info"> | ||||
|       <%= flash[:notice] %> | ||||
|     </div> | ||||
|   <% end -%> | ||||
|  | ||||
|   <%= yield %> | ||||
| </div> | ||||
| </body> | ||||
| </html> | ||||
| @@ -27,5 +27,10 @@ module Mastodon | ||||
|  | ||||
|     config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb') | ||||
|     config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')] | ||||
|  | ||||
|     config.to_prepare do | ||||
|       Doorkeeper::AuthorizationsController.layout 'auth' | ||||
|       Doorkeeper::AuthorizedApplicationsController.layout 'auth' | ||||
|     end | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -61,7 +61,7 @@ Devise.setup do |config| | ||||
|   # given strategies, for example, `config.http_authenticatable = [:database]` will | ||||
|   # enable it only for database authentication. The supported strategies are: | ||||
|   # :database      = Support basic authentication with authentication key + password | ||||
|   # config.http_authenticatable = false | ||||
|   config.http_authenticatable = [:database] | ||||
|  | ||||
|   # If 401 status code should be returned for AJAX requests. True by default. | ||||
|   # config.http_authenticatable_on_xhr = true | ||||
|   | ||||
							
								
								
									
										104
									
								
								config/initializers/doorkeeper.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								config/initializers/doorkeeper.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| 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 | ||||
|     current_user || redirect_to(new_user_session_url) | ||||
|   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 | ||||
							
								
								
									
										3
									
								
								config/initializers/rabl_init.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								config/initializers/rabl_init.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| Rabl.configure do |config| | ||||
|   config.include_json_root = false | ||||
| end | ||||
| @@ -1,13 +0,0 @@ | ||||
| if Rails.env.development? | ||||
|   ActiveSupport::Dependencies.explicitly_unloadable_constants << 'Twitter::API' | ||||
|  | ||||
|   api_files = Dir[Rails.root.join('app', 'api', '**', '*.rb')] | ||||
|  | ||||
|   api_reloader = ActiveSupport::FileUpdateChecker.new(api_files) do | ||||
|     Rails.application.reload_routes! | ||||
|   end | ||||
|  | ||||
|   ActionDispatch::Callbacks.to_prepare do | ||||
|     api_reloader.execute_if_updated | ||||
|   end | ||||
| end | ||||
							
								
								
									
										123
									
								
								config/locales/doorkeeper.en.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								config/locales/doorkeeper.en.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| 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' | ||||
| @@ -1,4 +1,6 @@ | ||||
| Rails.application.routes.draw do | ||||
|   use_doorkeeper | ||||
|  | ||||
|   get '.well-known/host-meta', to: 'xrd#host_meta', as: :host_meta | ||||
|   get '.well-known/webfinger', to: 'xrd#webfinger', as: :webfinger | ||||
|  | ||||
| @@ -9,24 +11,37 @@ Rails.application.routes.draw do | ||||
|   } | ||||
|  | ||||
|   resources :accounts, path: 'users', only: [:show], param: :username do | ||||
|     member do | ||||
|       post :follow | ||||
|       post :unfollow | ||||
|     end | ||||
|     resources :stream_entries, path: 'updates', only: [:show] | ||||
|   end | ||||
|  | ||||
|     resources :stream_entries, path: 'updates', only: [:show] do | ||||
|   namespace :api do | ||||
|     # PubSubHubbub | ||||
|     resources :subscriptions, only: [:show] | ||||
|     post '/subscriptions/:id', to: 'subscriptions#update' | ||||
|  | ||||
|     # Salmon | ||||
|     post '/salmon/:id', to: 'salmon#update', as: :salmon | ||||
|  | ||||
|     # JSON / REST API | ||||
|     resources :statuses, only: [:create, :show] do | ||||
|       member do | ||||
|         post :reblog | ||||
|         post :favourite | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     resources :follows,  only: [:create] | ||||
|  | ||||
|     resources :accounts, only: [:show] do | ||||
|       member do | ||||
|         get :statuses | ||||
|         get :followers | ||||
|         get :following | ||||
|  | ||||
|         post :follow | ||||
|         post :unfollow | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   namespace :api do | ||||
|     resources :subscriptions, only: [:show] | ||||
|     post '/subscriptions/:id', to: 'subscriptions#update' | ||||
|     post '/salmon/:id', to: 'salmon#update', as: :salmon | ||||
|   end | ||||
|  | ||||
|   root 'home#index' | ||||
| end | ||||
|   | ||||
							
								
								
									
										50
									
								
								db/migrate/20160306172223_create_doorkeeper_tables.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								db/migrate/20160306172223_create_doorkeeper_tables.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| 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  :user_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 | ||||
|  | ||||
|       # If you use a custom token generator you may need to change this column | ||||
|       # from string to text, so that it accepts tokens larger than 255 | ||||
|       # characters. More info on custom token generators in: | ||||
|       # https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator | ||||
|       # | ||||
|       # t.text     :token,             null: false | ||||
|       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 | ||||
							
								
								
									
										42
									
								
								db/schema.rb
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								db/schema.rb
									
									
									
									
									
								
							| @@ -11,7 +11,7 @@ | ||||
| # | ||||
| # It's strongly recommended that you check this file into your version control system. | ||||
|  | ||||
| ActiveRecord::Schema.define(version: 20160305115639) do | ||||
| ActiveRecord::Schema.define(version: 20160306172223) do | ||||
|  | ||||
|   # These are extensions that must be enabled in order to support this database | ||||
|   enable_extension "plpgsql" | ||||
| @@ -67,6 +67,46 @@ ActiveRecord::Schema.define(version: 20160305115639) do | ||||
|  | ||||
|   add_index "mentions", ["account_id", "status_id"], name: "index_mentions_on_account_id_and_status_id", unique: true, using: :btree | ||||
|  | ||||
|   create_table "oauth_access_grants", force: :cascade do |t| | ||||
|     t.integer  "user_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" | ||||
|   end | ||||
|  | ||||
|   add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree | ||||
|  | ||||
|   create_table "statuses", force: :cascade do |t| | ||||
|     t.string   "uri" | ||||
|     t.integer  "account_id",                  null: false | ||||
|   | ||||
							
								
								
									
										5
									
								
								spec/controllers/api/accounts_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								spec/controllers/api/accounts_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| require 'rails_helper' | ||||
|  | ||||
| RSpec.describe Api::AccountsController, type: :controller do | ||||
|  | ||||
| end | ||||
							
								
								
									
										5
									
								
								spec/controllers/api/follows_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								spec/controllers/api/follows_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| require 'rails_helper' | ||||
|  | ||||
| RSpec.describe Api::FollowsController, type: :controller do | ||||
|  | ||||
| end | ||||
							
								
								
									
										5
									
								
								spec/controllers/api/statuses_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								spec/controllers/api/statuses_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| require 'rails_helper' | ||||
|  | ||||
| RSpec.describe Api::StatusesController, type: :controller do | ||||
|  | ||||
| end | ||||
							
								
								
									
										15
									
								
								spec/helpers/api/accounts_helper_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								spec/helpers/api/accounts_helper_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| require 'rails_helper' | ||||
|  | ||||
| # Specs in this file have access to a helper object that includes | ||||
| # the Api::AccountsHelper. For example: | ||||
| # | ||||
| # describe Api::AccountsHelper do | ||||
| #   describe "string concat" do | ||||
| #     it "concats two strings with spaces" do | ||||
| #       expect(helper.concat_strings("this","that")).to eq("this that") | ||||
| #     end | ||||
| #   end | ||||
| # end | ||||
| RSpec.describe Api::AccountsHelper, type: :helper do | ||||
|   pending "add some examples to (or delete) #{__FILE__}" | ||||
| end | ||||
							
								
								
									
										15
									
								
								spec/helpers/api/follows_helper_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								spec/helpers/api/follows_helper_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| require 'rails_helper' | ||||
|  | ||||
| # Specs in this file have access to a helper object that includes | ||||
| # the Api::FollowsHelper. For example: | ||||
| # | ||||
| # describe Api::FollowsHelper do | ||||
| #   describe "string concat" do | ||||
| #     it "concats two strings with spaces" do | ||||
| #       expect(helper.concat_strings("this","that")).to eq("this that") | ||||
| #     end | ||||
| #   end | ||||
| # end | ||||
| RSpec.describe Api::FollowsHelper, type: :helper do | ||||
|   pending "add some examples to (or delete) #{__FILE__}" | ||||
| end | ||||
							
								
								
									
										15
									
								
								spec/helpers/api/statuses_helper_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								spec/helpers/api/statuses_helper_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| require 'rails_helper' | ||||
|  | ||||
| # Specs in this file have access to a helper object that includes | ||||
| # the Api::StatusesHelper. For example: | ||||
| # | ||||
| # describe Api::StatusesHelper do | ||||
| #   describe "string concat" do | ||||
| #     it "concats two strings with spaces" do | ||||
| #       expect(helper.concat_strings("this","that")).to eq("this that") | ||||
| #     end | ||||
| #   end | ||||
| # end | ||||
| RSpec.describe Api::StatusesHelper, type: :helper do | ||||
|   pending "add some examples to (or delete) #{__FILE__}" | ||||
| end | ||||
		Reference in New Issue
	
	Block a user