add api authentication
This commit is contained in:
@@ -5,12 +5,22 @@ class ApplicationController < ActionController::Base
|
|||||||
after_filter :reset_current_user
|
after_filter :reset_current_user
|
||||||
before_filter :set_title
|
before_filter :set_title
|
||||||
before_filter :set_started_at_session
|
before_filter :set_started_at_session
|
||||||
|
before_filter :api_check
|
||||||
layout "default"
|
layout "default"
|
||||||
|
|
||||||
rescue_from User::PrivilegeError, :with => :access_denied
|
rescue_from User::PrivilegeError, :with => :access_denied
|
||||||
rescue_from Danbooru::Paginator::PaginationError, :with => :render_pagination_limit
|
rescue_from Danbooru::Paginator::PaginationError, :with => :render_pagination_limit
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
def api_check
|
||||||
|
if CurrentUser.is_anonymous? && request.format.to_s =~ /json|xml/
|
||||||
|
render :text => "401 Not Authorized\n", :layout => false, :status => 401
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
def rescue_exception(exception)
|
def rescue_exception(exception)
|
||||||
@exception = exception
|
@exception = exception
|
||||||
|
|
||||||
@@ -53,7 +63,7 @@ protected
|
|||||||
end
|
end
|
||||||
|
|
||||||
def set_current_user
|
def set_current_user
|
||||||
session_loader = SessionLoader.new(session, cookies, request)
|
session_loader = SessionLoader.new(session, cookies, request, params)
|
||||||
session_loader.load
|
session_loader.load
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
class SessionLoader
|
class SessionLoader
|
||||||
attr_reader :session, :cookies, :request
|
attr_reader :session, :cookies, :request, :params
|
||||||
|
|
||||||
def initialize(session, cookies, request)
|
def initialize(session, cookies, request, params)
|
||||||
@session = session
|
@session = session
|
||||||
@cookies = cookies
|
@cookies = cookies
|
||||||
@request = request
|
@request = request
|
||||||
|
@params = params
|
||||||
end
|
end
|
||||||
|
|
||||||
def load
|
def load
|
||||||
@@ -12,8 +13,10 @@ class SessionLoader
|
|||||||
load_session_user
|
load_session_user
|
||||||
elsif cookie_password_hash_valid?
|
elsif cookie_password_hash_valid?
|
||||||
load_cookie_user
|
load_cookie_user
|
||||||
|
else
|
||||||
|
load_session_for_api
|
||||||
end
|
end
|
||||||
|
|
||||||
if CurrentUser.user
|
if CurrentUser.user
|
||||||
CurrentUser.user.unban! if ban_expired?
|
CurrentUser.user.unban! if ban_expired?
|
||||||
else
|
else
|
||||||
@@ -26,6 +29,32 @@ class SessionLoader
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def load_session_for_api
|
||||||
|
if request.authorization
|
||||||
|
authenticate_basic_auth
|
||||||
|
|
||||||
|
elsif params[:login].present? && params[:api_key].present?
|
||||||
|
authenticate_api_key(params[:login], params[:api_key])
|
||||||
|
|
||||||
|
elsif params[:login].present? && params[:password_hash].present?
|
||||||
|
authenticate_legacy_api_key(params[:login], params[:password_hash])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authenticate_basic_auth
|
||||||
|
credentials = ::Base64.decode64(request.authorization.split(' ', 2).last || '')
|
||||||
|
login, api_key = credentials.split(/:/, 2)
|
||||||
|
authenticate_api_key(login, api_key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def authenticate_api_key(name, api_key)
|
||||||
|
CurrentUser.user = User.authenticate_cookie_hash(name, api_key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def authenticate_legacy_api_key(name, password_hash)
|
||||||
|
CurrentUser.user = User.authenticate_hash(name, password_hash)
|
||||||
|
end
|
||||||
|
|
||||||
def load_session_user
|
def load_session_user
|
||||||
CurrentUser.user = User.find_by_id(session[:user_id])
|
CurrentUser.user = User.find_by_id(session[:user_id])
|
||||||
CurrentUser.ip_addr = request.remote_ip
|
CurrentUser.ip_addr = request.remote_ip
|
||||||
|
|||||||
@@ -96,5 +96,12 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<% if CurrentUser.user.id == user.id %>
|
||||||
|
<tr>
|
||||||
|
<th>API Key</th>
|
||||||
|
<td><%= CurrentUser.user.bcrypt_cookie_password_hash %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@@ -42,6 +42,8 @@ h1. Authentication
|
|||||||
|
|
||||||
All API calls must be authenticated. You can pass in two parameters: login and api_key. For legacy users, password_hash using the old salted SHA1 hashed password is also supported. Your API key is equivalent to your bcrypted password hash, which is stored in your cookies as password_hash. You can discover your API key by visiting your user profile. Your API key is intended to be a secret so you should not publicly distribute it.
|
All API calls must be authenticated. You can pass in two parameters: login and api_key. For legacy users, password_hash using the old salted SHA1 hashed password is also supported. Your API key is equivalent to your bcrypted password hash, which is stored in your cookies as password_hash. You can discover your API key by visiting your user profile. Your API key is intended to be a secret so you should not publicly distribute it.
|
||||||
|
|
||||||
|
You can also authenticate via HTTP Basic Authentication using your user name and API key.
|
||||||
|
|
||||||
Basic members can make 3,000 requests an hour. Gold members can make 10,000 requests an hour. Platinum members can make 20,000 requests an hour.
|
Basic members can make 3,000 requests an hour. Gold members can make 10,000 requests an hour. Platinum members can make 20,000 requests an hour.
|
||||||
|
|
||||||
h1. Posts
|
h1. Posts
|
||||||
|
|||||||
@@ -14,6 +14,48 @@ class PostsControllerTest < ActionController::TestCase
|
|||||||
CurrentUser.user = nil
|
CurrentUser.user = nil
|
||||||
CurrentUser.ip_addr = nil
|
CurrentUser.ip_addr = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "for api calls" do
|
||||||
|
context "using http basic auth" do
|
||||||
|
should "succeed for password matches" do
|
||||||
|
@basic_auth_string = "Basic #{ActiveSupport::Base64.encode64("#{@user.name}:#{@user.bcrypt_cookie_password_hash}")}"
|
||||||
|
@request.env['HTTP_AUTHORIZATION'] = @basic_auth_string
|
||||||
|
get :index, {:format => "json"}
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
should "fail for password mismatches" do
|
||||||
|
@basic_auth_string = "Basic #{ActiveSupport::Base64.encode64("#{@user.name}:badpassword")}"
|
||||||
|
@request.env['HTTP_AUTHORIZATION'] = @basic_auth_string
|
||||||
|
get :index, {:format => "json"}
|
||||||
|
assert_response 401
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using the api_key parameter" do
|
||||||
|
should "succeed for password matches" do
|
||||||
|
get :index, {:format => "json", :login => @user.name, :api_key => @user.bcrypt_cookie_password_hash}
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
should "fail for password mismatches" do
|
||||||
|
get :index, {:format => "json", :login => @user.name, :api_key => "bad"}
|
||||||
|
assert_response 401
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "using the password_hash parameter" do
|
||||||
|
should "succeed for password matches" do
|
||||||
|
get :index, {:format => "json", :login => @user.name, :password_hash => User.sha1("password")}
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
should "fail for password mismatches" do
|
||||||
|
get :index, {:format => "json", :login => @user.name, :password_hash => "bad"}
|
||||||
|
assert_response 401
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "index action" do
|
context "index action" do
|
||||||
should "render" do
|
should "render" do
|
||||||
|
|||||||
Reference in New Issue
Block a user