Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API] Commenting through a token #1513

Merged
merged 14 commits into from
Jul 11, 2017
36 changes: 32 additions & 4 deletions app/controllers/comment_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class CommentController < ApplicationController
include CommentHelper

respond_to :html, :xml, :json
before_filter :require_user, only: %i[create update delete]

Expand All @@ -12,9 +14,11 @@ def index
# create node comments
def create
@node = Node.find params[:id]
@comment = @node.add_comment(uid: current_user.uid, body: params[:body])
if current_user && @comment.save
@comment.notify(current_user)
@body = params[:body]
@user = current_user

begin
@comment = create_comment(@node, @user, @body)
respond_with do |format|
if params[:type] && params[:type] == 'question'
@answer_id = 0
Expand All @@ -30,12 +34,36 @@ def create
end
end
end
else
rescue CommentError
flash[:error] = 'The comment could not be saved.'
render text: 'failure'
end
end

def create_by_token
@node = Node.find params[:id]
@user = User.find_by_username params[:username]
@body = params[:body]
@token = request.env['rack.session']['token']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the advantages of this over passing the token in a POST req?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will look around for the best practices regarding tokens and come back to you. AFAIK, there's an important security benefit of passing the auth token inside the header, but I totally forgot what it was. 😅

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://www.codeschool.com/blog/2014/02/03/token-based-authentication-rails/ says that there's an inbuilt Rails function for dealing Authorization tokens "the right way".

It goes like:

authenticate_or_request_with_http_token do |token, options|
  # authenticate user...
end

should we use it instead?


if @user && @user.token == @token
begin
@comment = create_comment(@node, @user, @body)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment here telling where to find this method? I think for newcomers the Rails organization can be a bit arcane and although it adds a line, this could be really helpful for some.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, will do.

respond_to do |format|
format.all { render :nothing => true, :status => :created }
end
rescue CommentError
respond_to do |format|
format.all { render :nothing => true, :status => :bad_request }
end
end
else
respond_to do |format|
format.all { render :nothing => true, :status => :unauthorized }
end
end
end

# create answer comments
def answer_create
@answer_id = params[:aid]
Expand Down
14 changes: 14 additions & 0 deletions app/helpers/comment_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module CommentHelper
class CommentError < ArgumentError
end

def create_comment(node, user, body)
@comment = node.add_comment(uid: user.uid, body: body)
if user && @comment.save
@comment.notify user
return @comment
else
raise CommentError.new()
end
end
end
4 changes: 3 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
mount JasmineRails::Engine => '/specs' if defined?(JasmineRails)
mount JasmineFixtureServer => '/spec/javascripts/fixtures' if defined?(Jasmine::Jquery::Rails::Engine)

# Manually written API functions
post '/bot/comment/id.:format', to: 'comment#create_by_token'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd prefer this to be more general -- anyone developing an API use -- could we do /comment/create/token/:id.:format maybe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely. This was a placeholder anyway, because I realized that there would be a few issues with the /api endpoint because it's already being used.


#Search RESTful endpoints
#constraints(subdomain: 'api') do
mount Srch::API => '/api'
mount GrapeSwaggerRails::Engine => '/api/d1ocs'
#end


resources :rusers
resources :user_sessions
resources :images
Expand Down
51 changes: 50 additions & 1 deletion test/functional/comment_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def teardown
end
assert_response :success
assert_not_nil :comment
#assert_template partial: 'wiki/_comment'
#assert_template partial: 'wiki/_comment'
#should uncomment above once comment displaying partial is implemented for wikis.
end

Expand Down Expand Up @@ -251,4 +251,53 @@ def teardown
assert ActionMailer::Base.deliveries.collect(&:to).include?([rusers(:moderator).email])
# tag followers can be found in tag_selection.yml
end

test 'should not post comment through invalid token successfully' do
@params = {
id: 1,
body: 'Test Comment',
username: 'Bob',
format: 'json'
}

@headers = {
'token' => 'invalid-token'
}

post :create_by_token, @params, @headers
assert_response :unauthorized
end

test 'should not post an invalid comment successfully' do
@params = {
id: 1,
body: '',
username: 'Bob',
format: 'json'
}

@headers = {
'token' => 'abcdefg12345'
}

post :create_by_token, @params, @headers
assert_response :bad_request
end

test 'should post comment through valid token successfully' do
@params = {
id: 1,
body: 'Test Comment',
username: 'Bob',
format: 'json'
}

@headers = {
'token' => 'abcdefg12345'
}

post :create_by_token, @params, @headers
assert_response :success
end

end