Skip to content

Commit bab1890

Browse files
committed
Replace api key with token per query
1 parent 1e2628a commit bab1890

File tree

8 files changed

+47
-19
lines changed

8 files changed

+47
-19
lines changed

app/controllers/blazer/queries_controller.rb

+6-5
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,12 @@ def edit
7979
end
8080

8181
def share
82-
if params[:token] && params[:query_id] && params[:token] == Blazer.sharing.query_token(params[:query_id])
83-
run
84-
else
85-
render_forbidden
86-
end
82+
return render_forbidden unless params[:token] && params[:query_id]
83+
84+
@query = Query.find_by(id: params[:query_id]) if params[:query_id]
85+
return render_forbidden unless @query.correct_token?(params[:token])
86+
87+
run
8788
end
8889

8990
def run

app/models/blazer/query.rb

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module Blazer
22
class Query < Record
3+
has_secure_token :secret_token, length: 36
4+
35
belongs_to :creator, optional: true, class_name: Blazer.user_class.to_s if Blazer.user_class
46
has_many :checks, dependent: :destroy
57
has_many :dashboard_queries, dependent: :destroy
@@ -15,6 +17,10 @@ def to_param
1517
[id, name].compact.join("-").gsub("'", "").parameterize
1618
end
1719

20+
def correct_token?(token)
21+
ActiveSupport::SecurityUtils.secure_compare(secret_token, token)
22+
end
23+
1824
def friendly_name
1925
name.to_s.sub(/\A[#\*]/, "").gsub(/\[.+\]/, "").strip
2026
end

lib/blazer/sharing.rb

+7-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
module Blazer
22
class Sharing
3-
attr_accessor :api_key, :path
3+
attr_accessor :path, :enabled
44

5-
def initialize(api_key: ENV.fetch('BLAZER_DOWNLOAD_API_KEY', nil), path: '/blazer_share')
6-
@api_key = api_key
5+
def initialize(enabled: false, path: '/blazer_share')
76
@path = path.sub(/\/$/, '') # Strip trailing /
7+
@enabled = enabled
88
end
99

1010
def route_path
@@ -15,16 +15,13 @@ def to_controller
1515
'blazer/queries#share'
1616
end
1717

18-
def query_token(query_id)
19-
Digest::SHA1.hexdigest("#{query_id}-#{api_key}")
20-
end
21-
2218
def enabled?
23-
api_key.present?
19+
enabled
2420
end
2521

26-
def share_path(query_id, format: nil)
27-
"#{path}/#{query_token(query_id)}/#{query_id}#{".#{format}" if format}"
22+
def share_path(query_id, format: nil, token: nil)
23+
query = Query.find(query_id)
24+
"#{path}/#{token}/#{query_id}#{".#{format}" if format}"
2825
end
2926

3027
def url_for(query_id, current_url, format: 'csv')

lib/generators/blazer/templates/install.rb.tt

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
55
t.string :name
66
t.text :description
77
t.text :statement
8+
t.text :secret_token
89
t.string :data_source
910
t.string :status
1011
t.timestamps null: false

test/internal/config/blazer.yml

+4
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,7 @@ uploads:
161161
url: postgres://localhost/blazer_test
162162
schema: uploads
163163
data_source: main
164+
165+
sharing:
166+
path: /blazer_share
167+
enabled: true

test/internal/config/routes.rb

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
Rails.application.routes.draw do
22
mount Blazer::Engine, at: "/"
3+
4+
get Blazer.sharing.route_path, to: Blazer.sharing.to_controller, as: :share_query if Blazer.sharing.enabled?
35
end

test/internal/db/schema.rb

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
t.string :name
55
t.text :description
66
t.text :statement
7+
t.text :secret_token
78
t.string :data_source
89
t.string :status
910
t.timestamps null: false

test/queries_test.rb

+20-4
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,22 @@ def test_variables_time_range
7676
assert_match "daterangepicker", response.body
7777
end
7878

79+
def test_correct_token
80+
query = create_query(statement: "SELECT 1")
81+
get share_query_path(query.id, token: query.secret_token, format: 'csv')
82+
83+
assert_response :success
84+
assert_equal "text/csv", response.content_type
85+
end
86+
87+
def test_incorrect_token
88+
query = create_query(statement: "SELECT 1")
89+
get share_query_path(query.id, token: "x")
90+
91+
assert_response :forbidden
92+
assert_match "Access denied", response.body
93+
end
94+
7995
def test_variable_defaults
8096
query = create_query(statement: "SELECT {default_var}")
8197
get blazer.query_path(query)
@@ -108,12 +124,12 @@ def test_csv
108124
end
109125

110126
def test_share
111-
Blazer.sharing.api_key = "123"
112127
query = create_query
113-
get blazer.query_share_path(query_id: query.id, token: Digest::SHA1.hexdigest("#{query.id}-123"), format: 'csv')
128+
assert query.secret_token
129+
130+
get blazer.query_share_path(query_id: query.id, token: query.secret_token, format: 'csv')
131+
114132
assert_response :success
115-
assert_match query.name, response.body
116-
Blazer.sharing.api_key = nil
117133
end
118134

119135
def test_url

0 commit comments

Comments
 (0)