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 {