Added protect_from_forgery option - #210
Andrew Kane
committed Aug 23, 2016
commit 910190e3fbf194705cef02d32ab9c04f51473a4e
Showing 4
changed files with
80 additions
and 46 deletions
app/controllers/ahoy/base_controller.rb
+2
-0
| @@ | @@ -15,6 +15,8 @@ module Ahoy |
| before_filter :verify_request_size | |
| end | |
| + | protect_from_forgery with: :null_session, if: -> { Ahoy.protect_from_forgery } |
| + | |
| protected | |
| def ahoy | |
app/controllers/ahoy/events_controller.rb
+2
-0
| @@ | @@ -5,6 +5,8 @@ module Ahoy |
| if params[:name] | |
| # legacy API | |
| [params] | |
| + | elsif params[:events] |
| + | params[:events] |
| else | |
| begin | |
| ActiveSupport::JSON.decode(request.body.read) | |
ahoy.rb b/lib/ahoy.rb
+3
-0
| @@ | @@ -87,6 +87,9 @@ module Ahoy |
| mattr_accessor :api_only | |
| self.api_only = false | |
| + | mattr_accessor :protect_from_forgery |
| + | self.protect_from_forgery = false |
| + | |
| def self.ensure_uuid(id) | |
| valid = UUIDTools::UUID.parse(id) rescue nil | |
| if valid | |
vendor/assets/javascripts/ahoy.js
+73
-46
| @@ | @@ -129,34 +129,59 @@ |
| } | |
| } | |
| + | // from jquery-ujs |
| + | |
| + | function csrfToken() { |
| + | return $("meta[name=csrf-token]").attr("content"); |
| + | } |
| + | |
| + | function csrfParam() { |
| + | return $("meta[name=csrf-param]").attr("content"); |
| + | } |
| + | |
| + | function CSRFProtection(xhr) { |
| + | var token = csrfToken(); |
| + | if (token) xhr.setRequestHeader("X-CSRF-Token", token); |
| + | } |
| + | |
| + | function sendRequest(url, data, success) { |
| + | if (canStringify) { |
| + | $.ajax({ |
| + | type: "POST", |
| + | url: url, |
| + | data: JSON.stringify(data), |
| + | contentType: "application/json; charset=utf-8", |
| + | dataType: "json", |
| + | beforeSend: CSRFProtection, |
| + | success: success |
| + | }); |
| + | } |
| + | } |
| + | |
| function trackEvent(event) { | |
| ready( function () { | |
| - | // ensure JSON is defined |
| - | if (canStringify) { |
| - | $.ajax({ |
| - | type: "POST", |
| - | url: eventsUrl(), |
| - | data: JSON.stringify([event]), |
| - | contentType: "application/json; charset=utf-8", |
| - | dataType: "json", |
| - | success: function() { |
| - | // remove from queue |
| - | for (var i = 0; i < eventQueue.length; i++) { |
| - | if (eventQueue[i].id == event.id) { |
| - | eventQueue.splice(i, 1); |
| - | break; |
| - | } |
| - | } |
| - | saveEventQueue(); |
| + | sendRequest(eventsUrl(), {events: [event]}, function() { |
| + | // remove from queue |
| + | for (var i = 0; i < eventQueue.length; i++) { |
| + | if (eventQueue[i].id == event.id) { |
| + | eventQueue.splice(i, 1); |
| + | break; |
| } | |
| - | }); |
| - | } |
| + | } |
| + | saveEventQueue(); |
| + | }); |
| }); | |
| } | |
| function trackEventNow(event) { | |
| ready( function () { | |
| - | var payload = new Blob([JSON.stringify([event])], {type : "application/json; charset=utf-8"}); |
| + | var data = { |
| + | events: [event] |
| + | } |
| + | var param = csrfParam(); |
| + | var token = csrfToken(); |
| + | if (param && token) data[param] = token; |
| + | var payload = new Blob([JSON.stringify(data)], {type : "application/json; charset=utf-8"}); |
| navigator.sendBeacon(eventsUrl(), payload); | |
| }); | |
| } | |
| @@ | @@ -222,7 +247,7 @@ |
| log(data); | |
| - | $.post(visitsUrl(), data, setReady, "json"); |
| + | sendRequest(visitsUrl(), data, setReady); |
| } else { | |
| log("Cookies disabled"); | |
| setReady(); | |
| @@ | @@ -256,32 +281,34 @@ |
| }; | |
| ahoy.track = function (name, properties) { | |
| - | if (!ahoy.getVisitId()) { |
| - | createVisit(); |
| - | } |
| - | |
| - | // generate unique id |
| - | var event = { |
| - | id: generateId(), |
| - | visit_token: ahoy.getVisitId(), |
| - | visitor_token: ahoy.getVisitorId(), |
| - | name: name, |
| - | properties: properties, |
| - | time: (new Date()).getTime() / 1000.0 |
| - | }; |
| - | log(event); |
| + | ready( function () { |
| + | if (!ahoy.getVisitId()) { |
| + | createVisit(); |
| + | } |
| - | if (canTrackNow()) { |
| - | trackEventNow(event); |
| - | } else { |
| - | eventQueue.push(event); |
| - | saveEventQueue(); |
| + | // generate unique id |
| + | var event = { |
| + | id: generateId(), |
| + | visit_token: ahoy.getVisitId(), |
| + | visitor_token: ahoy.getVisitorId(), |
| + | name: name, |
| + | properties: properties, |
| + | time: (new Date()).getTime() / 1000.0 |
| + | }; |
| + | log(event); |
| + | |
| + | if (canTrackNow()) { |
| + | trackEventNow(event); |
| + | } else { |
| + | eventQueue.push(event); |
| + | saveEventQueue(); |
| - | // wait in case navigating to reduce duplicate events |
| - | setTimeout( function () { |
| - | trackEvent(event); |
| - | }, 1000); |
| - | } |
| + | // wait in case navigating to reduce duplicate events |
| + | setTimeout( function () { |
| + | trackEvent(event); |
| + | }, 1000); |
| + | } |
| + | }); |
| }; | |
| ahoy.trackView = function () { | |
| @@ | @@ -324,7 +351,7 @@ |
| ahoy.trackChanges(); | |
| }; | |
| - | createVisit(); |
| + | $(createVisit); |
| // push events from queue | |
| try { | |