Permalink
Browse files

Fix a variety of issues related to session handling & csrf. Closes #851

…. Closes #853.
  • Loading branch information...
1 parent d4153d9 commit b6f26fb9630993557a1b03520ac4d87bdbd113eb @onyxfish onyxfish committed Aug 8, 2012
@@ -1,4 +1,9 @@
/**
+ *
+ * NOTE WELL:
+ * This module has been modified for PANDA. Do NOT upgrade
+ * without assessing changes!
+ *
* Backbone-tastypie.js 0.1
* (c) 2011 Paul Uithol
*
@@ -27,15 +32,6 @@
*/
Backbone.oldSync = Backbone.sync;
Backbone.sync = function( method, model, options ) {
- var headers = '';
-
- if ( Backbone.Tastypie.apiKey && Backbone.Tastypie.apiKey.username.length ) {
- headers = _.extend( {
- 'Authorization': 'ApiKey ' + Backbone.Tastypie.apiKey.username + ':' + Backbone.Tastypie.apiKey.key
- }, options.headers );
- options.headers = headers;
- }
-
if ( ( method === 'create' && Backbone.Tastypie.doGetOnEmptyPostResponse ) ||
( method === 'update' && Backbone.Tastypie.doGetOnEmptyPutResponse ) ) {
var dfd = new $.Deferred();
@@ -47,9 +43,13 @@
// Otherwise, resolve the deferred (which triggers the original 'success' callbacks).
if ( !resp && ( xhr.status === 201 || xhr.status === 202 || xhr.status === 204 ) ) { // 201 CREATED, 202 ACCEPTED or 204 NO CONTENT; response null or empty.
var location = xhr.getResponseHeader( 'Location' ) || model.id;
+
return $.ajax( {
url: location,
- headers: headers,
+ // PANDA HACK
+ // modified to reuse original headers so CSRF persists
+ headers: options.headers,
+ // END PANDA HACK
success: dfd.resolve,
error: dfd.reject
});
@@ -1,4 +1,9 @@
/**
+ *
+ * NOTE WELL:
+ * This module has been modified for PANDA. Do NOT upgrade
+ * without assessing changes!
+ *
* http://github.com/valums/file-uploader
*
* Multiple file upload component with progress-bar, drag-and-drop.
@@ -1005,6 +1010,10 @@ qq.extend(qq.UploadHandlerForm.prototype, {
var form = this._createForm(iframe, params);
form.appendChild(input);
+ // PANDA HACK
+ form.appendChild('<input type="hidden" value="' + $.cookie('csrftoken') + '" />');
+ // END PANDA :HACK
+
var self = this;
this._attachLoadEvent(iframe, function(){
self.log('iframe loaded');
@@ -1201,6 +1210,9 @@ qq.extend(qq.UploadHandlerXhr.prototype, {
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
xhr.setRequestHeader("Content-Type", "application/octet-stream");
+ // PANDA HACK
+ xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
+ // END PANDA HACK
xhr.send(file);
},
_onComplete: function(id, xhr){
@@ -39,7 +39,7 @@ PANDA.views.DataUpload = Backbone.View.extend({
this.file_uploader = null;
this.upload = null;
- $.ajax({
+ Redd.ajax({
url: '/check_available_space/',
dataType: 'json',
type: 'GET',
@@ -60,29 +60,12 @@ PANDA.views.Root = Backbone.View.extend({
},
configure_csrf_handling: function() {
- // Always attach the CSRF token to requests
- // Cribbed from http://stackoverflow.com/a/7093862/24608
+ /*
+ * Always attach CSRF token to requests.
+ */
$.ajaxSetup({
beforeSend: function(xhr, settings) {
- function getCookie(name) {
- var cookieValue = null;
- if (document.cookie && document.cookie != '') {
- var cookies = document.cookie.split(';');
- for (var i = 0; i < cookies.length; i++) {
- var cookie = jQuery.trim(cookies[i]);
- // Does this cookie string begin with the name we want?
- if (cookie.substring(0, name.length + 1) == (name + '=')) {
- cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
- break;
- }
- }
- }
- return cookieValue;
- }
- if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
- // Only send the token to relative URLs i.e. locally.
- xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
- }
+ xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
}
});
},
@@ -7,7 +7,7 @@
from panda.api.utils import PandaAuthentication, PandaModelResource, PandaSerializer
from django.db import IntegrityError
-from panda.models import ActivityLog
+from panda.models import ActivityLog, UserProxy
class ActivityLogResource(PandaModelResource):
"""
@@ -30,8 +30,12 @@ def obj_create(self, bundle, request=None, **kwargs):
"""
Create an activity log for the accessing user.
"""
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
try:
- bundle = super(ActivityLogResource, self).obj_create(bundle, request=request, user=request.user, **kwargs)
+ bundle = super(ActivityLogResource, self).obj_create(bundle, request=request, user=user, **kwargs)
except IntegrityError:
raise ImmediateHttpResponse(response=HttpConflict('Activity has already been recorded.'))
View
@@ -17,7 +17,7 @@
from panda.api.datasets import DatasetResource
from panda.exceptions import DatasetLockedError
from panda.api.utils import PandaAuthentication, PandaPaginator, PandaResource, PandaSerializer
-from panda.models import Category, Dataset, SearchLog, TaskStatus
+from panda.models import Category, Dataset, SearchLog, TaskStatus, UserProxy
from panda.tasks import ExportSearchTask, PurgeDataTask
class SolrObject(object):
@@ -237,8 +237,12 @@ def obj_create(self, bundle, request=None, **kwargs):
else:
external_id = None
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
try:
- row = dataset.add_row(request.user, bundle.data['data'], external_id=external_id)
+ row = dataset.add_row(user, bundle.data['data'], external_id=external_id)
except DatasetLockedError:
raise ImmediateHttpResponse(response=http.HttpForbidden('Dataset is currently locked by another process.'))
@@ -264,8 +268,12 @@ def obj_delete(self, request=None, **kwargs):
"""
dataset = Dataset.objects.get(slug=kwargs['dataset_slug'])
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
try:
- dataset.delete_row(request.user, kwargs['external_id'])
+ dataset.delete_row(user, kwargs['external_id'])
except DatasetLockedError:
raise ImmediateHttpResponse(response=http.HttpForbidden('Dataset is currently locked by another process.'))
@@ -329,9 +337,13 @@ def put_list(self, request, **kwargs):
))
self.validate_bundle_data(bundle, request, dataset)
+
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
try:
- solr_rows = dataset.add_many_rows(request.user, data)
+ solr_rows = dataset.add_many_rows(user, data)
except DatasetLockedError:
raise ImmediateHttpResponse(response=http.HttpForbidden('Dataset is currently locked by another process.'))
@@ -377,9 +389,13 @@ def delete_list(self, request, **kwargs):
not supported.
"""
dataset = Dataset.objects.get(slug=kwargs['dataset_slug'])
+
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
try:
- dataset.delete_all_rows(request.user)
+ dataset.delete_all_rows(user)
except DatasetLockedError:
raise ImmediateHttpResponse(response=http.HttpForbidden('Dataset is currently locked by another process.'))
@@ -419,13 +435,17 @@ def search_all_data(self, request, **kwargs):
if since:
query = 'last_modified:[' + since + 'Z TO *] AND (%s)' % query
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
if export:
task_type = ExportSearchTask
task = TaskStatus.objects.create(
task_name=task_type.name,
task_description='Export search results for "%s".' % query,
- creator=request.user
+ creator=user
)
task_type.apply_async(
@@ -500,7 +520,7 @@ def search_all_data(self, request, **kwargs):
page['objects'] = datasets
# Log query
- SearchLog.objects.create(user=request.user, dataset=None, query=query)
+ SearchLog.objects.create(user=user, dataset=None, query=query)
self.log_throttled_access(request)
@@ -558,8 +578,12 @@ def search_dataset_data(self, request, **kwargs):
bundle = self.build_bundle(obj=obj, request=request)
bundle = self.full_dehydrate(bundle)
dataset_bundle.data['objects'].append(bundle.data)
+
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
- SearchLog.objects.create(user=request.user, dataset=dataset, query=query)
+ SearchLog.objects.create(user=user, dataset=dataset, query=query)
return dataset_bundle
View
@@ -12,7 +12,7 @@
from panda import solr
from panda.api.utils import PandaAuthentication, PandaPaginator, JSONApiField, SluggedModelResource, PandaSerializer
from panda.exceptions import DataImportError, DatasetLockedError
-from panda.models import Category, Dataset, DataUpload
+from panda.models import Category, Dataset, DataUpload, UserProxy
from panda.utils.column_schema import make_column_schema
class DatasetValidation(Validation):
@@ -165,7 +165,11 @@ def obj_create(self, bundle, request=None, **kwargs):
"""
Set creator and update full text.
"""
- bundle = super(DatasetResource, self).obj_create(bundle, request=request, creator=request.user, **kwargs)
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
+ bundle = super(DatasetResource, self).obj_create(bundle, request=request, creator=user, **kwargs)
if 'columns' in request.GET:
columns = request.GET['columns'].split(',')
@@ -230,8 +234,12 @@ def import_data(self, request, **kwargs):
dataset = Dataset.objects.get(slug=slug)
upload = DataUpload.objects.get(id=kwargs['upload_id'])
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
try:
- dataset.import_data(request.user, upload)
+ dataset.import_data(user, upload)
except DatasetLockedError:
raise ImmediateHttpResponse(response=http.HttpForbidden('Dataset is currently locked by another process.'))
except DataImportError, e:
@@ -280,8 +288,12 @@ def reindex_data(self, request, **kwargs):
else:
column_types = None
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
try:
- dataset.reindex_data(request.user, typed_columns=typed_columns, column_types=column_types)
+ dataset.reindex_data(user, typed_columns=typed_columns, column_types=column_types)
except DatasetLockedError:
raise ImmediateHttpResponse(response=http.HttpForbidden('Dataset is currently locked by another process.'))
@@ -319,8 +331,12 @@ def export_data(self, request, **kwargs):
if since:
query = 'last_modified:[' + since + 'Z TO *] AND (%s)' % query
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
try:
- dataset.export_data(request.user, query=query)
+ dataset.export_data(user, query=query)
except DatasetLockedError:
raise ImmediateHttpResponse(response=http.HttpForbidden('Dataset is currently locked by another process.'))
@@ -3,7 +3,7 @@
from tastypie.authorization import DjangoAuthorization
from panda.api.utils import PandaAuthentication, PandaSerializer, PandaModelResource
-from panda.models import Notification
+from panda.models import Notification, UserProxy
class NotificationResource(PandaModelResource):
"""
@@ -22,10 +22,18 @@ class Meta:
}
def obj_create(self, bundle, request=None, **kwargs):
- return super(NotificationResource, self).obj_create(bundle, request, recipient=request.user)
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
+ return super(NotificationResource, self).obj_create(bundle, request, recipient=user)
def apply_authorization_limits(self, request, object_list):
- return object_list.filter(recipient=request.user)
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
+ return object_list.filter(recipient=user)
def save_related(self, bundle):
"""
@@ -4,7 +4,7 @@
from tastypie.authorization import DjangoAuthorization
from panda.api.utils import PandaAuthentication, PandaSerializer, PandaModelResource
-from panda.models import SearchSubscription
+from panda.models import SearchSubscription, UserProxy
class SearchSubscriptionResource(PandaModelResource):
"""
@@ -26,10 +26,18 @@ class Meta:
serializer = PandaSerializer()
def obj_create(self, bundle, request=None, **kwargs):
- return super(SearchSubscriptionResource, self).obj_create(bundle, request, user=request.user)
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
+ return super(SearchSubscriptionResource, self).obj_create(bundle, request, user=user)
def apply_authorization_limits(self, request, object_list):
- return object_list.filter(user=request.user)
+ # Because users may have authenticated via headers the request.user may
+ # not be a full User instance. To be sure, we fetch one.
+ user = UserProxy.objects.get(id=request.user.id)
+
+ return object_list.filter(user=user)
def save_related(self, bundle):
"""
Oops, something went wrong.

0 comments on commit b6f26fb

Please sign in to comment.