From 8d2b5c043fb74e4e1275807071017dc60a64fd07 Mon Sep 17 00:00:00 2001 From: Charles Connell Date: Thu, 23 Jan 2014 15:44:27 -0500 Subject: [PATCH] Reliably associate users with notes and give karma points #305 --- karmaworld/apps/document_upload/models.py | 5 +- karmaworld/apps/document_upload/tasks.py | 4 +- karmaworld/apps/document_upload/tests.py | 55 +++--- karmaworld/apps/document_upload/views.py | 11 +- karmaworld/apps/notes/gdrive.py | 41 ++--- ...d_unique_useruploadmapping_user_fp_file.py | 159 ++++++++++++++++++ karmaworld/apps/notes/models.py | 32 +++- karmaworld/apps/users/models.py | 2 +- 8 files changed, 234 insertions(+), 75 deletions(-) create mode 100644 karmaworld/apps/notes/migrations/0015_auto__add_useruploadmapping__add_unique_useruploadmapping_user_fp_file.py diff --git a/karmaworld/apps/document_upload/models.py b/karmaworld/apps/document_upload/models.py index ab2bd9a..8d26b24 100644 --- a/karmaworld/apps/document_upload/models.py +++ b/karmaworld/apps/document_upload/models.py @@ -65,9 +65,10 @@ class RawDocument(Document): note.tags.add(tag) return note - def save(self, user=None, session=None, *args, **kwargs): + def save(self, user=None, *args, **kwargs): super(RawDocument, self).save(*args, **kwargs) if not self.is_processed: - tasks.process_raw_document.delay(self, user, session) + tasks.process_raw_document.delay(self, user) + auto_add_check_unique_together(RawDocument) diff --git a/karmaworld/apps/document_upload/tasks.py b/karmaworld/apps/document_upload/tasks.py index f4e31d0..e871388 100644 --- a/karmaworld/apps/document_upload/tasks.py +++ b/karmaworld/apps/document_upload/tasks.py @@ -10,10 +10,10 @@ from karmaworld.apps.notes.gdrive import convert_raw_document logger = get_task_logger(__name__) @task() -def process_raw_document(raw_document, user, session): +def process_raw_document(raw_document, user): """ Process a RawDocument instance in to a Note instance """ try: - convert_raw_document(raw_document, user=user, session=session) + convert_raw_document(raw_document, user=user) except: logger.error(traceback.format_exc()) diff --git a/karmaworld/apps/document_upload/tests.py b/karmaworld/apps/document_upload/tests.py index b5d3ca7..88600f0 100644 --- a/karmaworld/apps/document_upload/tests.py +++ b/karmaworld/apps/document_upload/tests.py @@ -4,13 +4,15 @@ when you run "manage.py test". Replace this with more appropriate tests for your application. """ +from django.contrib.sessions.backends.db import SessionStore from django.test import TestCase, Client from karmaworld.apps.courses.models import Course from karmaworld.apps.courses.models import School from karmaworld.apps.document_upload.forms import RawDocumentForm from karmaworld.apps.notes.gdrive import * -from karmaworld.apps.notes.models import Note, find_orphan_notes +from karmaworld.apps.notes.models import Note, ANONYMOUS_UPLOAD_URLS +from karmaworld.apps.notes.models import find_orphan_notes TEST_USERNAME = 'alice' @@ -33,7 +35,7 @@ class ConversionTest(TestCase): self.assertTrue(r_d_f.is_valid()) raw_document = r_d_f.save(commit=False) raw_document.fp_file = post['fp_file'] - convert_raw_document(raw_document, user=user, session_key=session) + convert_raw_document(raw_document, user=user) self.assertEqual(Note.objects.count(), 1) def testPlaintextConversion(self): @@ -70,8 +72,8 @@ class ConversionTest(TestCase): 'mimetype': 'application/octet-stream'}) def testSessionUserAssociation1(self): - """Test setting the user of an uploaded document to a known - user in our database""" + """If the user is already logged in when they + upload a note, it should set note.user correctly.""" user = User(username=TEST_USERNAME) user.save() self.doConversionForPost({'fp_file': 'https://www.filepicker.io/api/file/S2lhT3INSFCVFURR2RV7', @@ -82,51 +84,44 @@ class ConversionTest(TestCase): user=user) note = Note.objects.all()[0] self.assertEqual(note.user, user) + karma_event = NoteKarmaEvent.objects.all()[0] + self.assertEqual(karma_event.user, user) def testSessionUserAssociation2(self): - """Test setting the user of an uploaded document - to an existing user in the database, finding them - through a session key.""" - user = User(username=TEST_USERNAME) - user.save() + """If a user logs in after convert_raw_document has finished, + we should associate them with the note they uploaded anonymously""" s = SessionStore() - s['_auth_user_id'] = user.pk + s[ANONYMOUS_UPLOAD_URLS] = ['https://www.filepicker.io/api/file/S2lhT3INSFCVFURR2RV7'] s.save() self.doConversionForPost({'fp_file': 'https://www.filepicker.io/api/file/S2lhT3INSFCVFURR2RV7', 'course': str(self.course.id), 'name': 'graph3.txt', 'tags': '', - 'mimetype': 'text/plain'}, - session=s) + 'mimetype': 'text/plain'}) + user = User(username=TEST_USERNAME) + user.save() + find_orphan_notes(None, user=user, request=_FakeRequest(s)) note = Note.objects.all()[0] self.assertEqual(note.user, user) - - + karma_event = NoteKarmaEvent.objects.all()[0] + self.assertEqual(karma_event.user, user) def testSessionUserAssociation3(self): - """Test setting the user of an uploaded document - to an existing user in the database, finding them - through a session key.""" + """If a user logs in WHILE convert_raw_document is running, + make sure they are associated with that note by the time it finishes.""" s = SessionStore() + s[ANONYMOUS_UPLOAD_URLS] = ['https://www.filepicker.io/api/file/S2lhT3INSFCVFURR2RV7'] s.save() + user = User(username=TEST_USERNAME) + user.save() + find_orphan_notes(None, user=user, request=_FakeRequest(s)) self.doConversionForPost({'fp_file': 'https://www.filepicker.io/api/file/S2lhT3INSFCVFURR2RV7', 'course': str(self.course.id), 'name': 'graph3.txt', 'tags': '', 'mimetype': 'text/plain'}, session=s) - user = User(username=TEST_USERNAME) - user.save() - - # Normally this next bit is called automatically, but - # in testing we need to call it manually - note = Note.objects.all()[0] - s = SessionStore(session_key=s.session_key) - find_orphan_notes(note, user=user, request=_FakeRequest(s)) - note = Note.objects.all()[0] self.assertEqual(note.user, user) - - - - + karma_event = NoteKarmaEvent.objects.all()[0] + self.assertEqual(karma_event.user, user) diff --git a/karmaworld/apps/document_upload/views.py b/karmaworld/apps/document_upload/views.py index 6032e0f..792118f 100644 --- a/karmaworld/apps/document_upload/views.py +++ b/karmaworld/apps/document_upload/views.py @@ -6,6 +6,7 @@ import datetime from django.http import HttpResponse from karmaworld.apps.document_upload.forms import RawDocumentForm +from karmaworld.apps.notes.models import ANONYMOUS_UPLOAD_URLS def save_fp_upload(request): @@ -24,11 +25,11 @@ def save_fp_upload(request): if request.user.is_authenticated(): raw_document.save(user=request.user) else: - # Generate session key if it doesn't exist - if not request.session.get('has_session'): - request.session['has_session'] = True - request.session.save() - raw_document.save(session=request.session) + anonymous_upload_urls = request.session.get(ANONYMOUS_UPLOAD_URLS, []) + anonymous_upload_urls.append(request.POST['fp_file']) + request.session.modified = True + request.session.save() + raw_document.save() # save the tags to the database, too. don't forget those guys. r_d_f.save_m2m() diff --git a/karmaworld/apps/notes/gdrive.py b/karmaworld/apps/notes/gdrive.py index db39265..24af3d0 100644 --- a/karmaworld/apps/notes/gdrive.py +++ b/karmaworld/apps/notes/gdrive.py @@ -3,8 +3,10 @@ # Copyright (C) 2012 FinalsClub Foundation import datetime +import logging from django.contrib.auth.models import User -from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned +from karmaworld.apps.notes.models import UserUploadMapping from karmaworld.apps.users.models import NoteKarmaEvent import os import subprocess @@ -14,7 +16,6 @@ import magic import re import json import time -from django.contrib.auth import SESSION_KEY import httplib2 from apiclient.discovery import build @@ -23,12 +24,11 @@ from oauth2client.client import SignedJwtAssertionCredentials import karmaworld.secret.drive as drive +logger = logging.getLogger(__name__) PDF_MIMETYPE = 'application/pdf' PPT_MIMETYPES = ['application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation'] -UPLOADED_NOTES_SESSION_KEY = 'uploaded_notes' - def extract_file_details(fileobj): details = None @@ -178,7 +178,7 @@ def upload_to_gdrive(service, media, filename, extension=None, mimetype=None): return file_dict -def convert_raw_document(raw_document, user=None, session=None): +def convert_raw_document(raw_document, user=None): """ Upload a raw document to google drive and get a Note back""" fp_file = raw_document.get_file() @@ -244,30 +244,19 @@ def convert_raw_document(raw_document, user=None, session=None): if user: note.user = user NoteKarmaEvent.create_event(user, note, NoteKarmaEvent.UPLOAD) + else: + try: + mapping = UserUploadMapping.objects.get(fp_file=raw_document.fp_file) + note.user = mapping.user + note.save() + NoteKarmaEvent.create_event(mapping.user, note, NoteKarmaEvent.UPLOAD) + except (ObjectDoesNotExist, MultipleObjectsReturned): + logger.info("Zero or multiple mappings found with fp_file " + raw_document.fp_file.url) # Finally, save whatever data we got back from google note.save() - if session and not user: - # If the person who uploaded this made an - # account or signed in while convert_raw_document - # was running, associate their account with this note - try: - uid = session[SESSION_KEY] - user = User.objects.get(pk=uid) - note.user = user - NoteKarmaEvent.create_event(user, note, NoteKarmaEvent.UPLOAD) - note.save() - # If we don't know the user who uploaded - # this, then we should have a session key - # instead. Associate this note with the session - # so if the uploader later creates an account, - # we can find notes they uploaded - except (KeyError, ObjectDoesNotExist): - uploaded_notes = session.get(UPLOADED_NOTES_SESSION_KEY, []) - uploaded_notes.append(note.id) - session[UPLOADED_NOTES_SESSION_KEY] = uploaded_notes - session.modified = True - session.save() + + diff --git a/karmaworld/apps/notes/migrations/0015_auto__add_useruploadmapping__add_unique_useruploadmapping_user_fp_file.py b/karmaworld/apps/notes/migrations/0015_auto__add_useruploadmapping__add_unique_useruploadmapping_user_fp_file.py new file mode 100644 index 0000000..e646466 --- /dev/null +++ b/karmaworld/apps/notes/migrations/0015_auto__add_useruploadmapping__add_unique_useruploadmapping_user_fp_file.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'UserUploadMapping' + db.create_table(u'notes_useruploadmapping', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), + ('fp_file', self.gf('django.db.models.fields.CharField')(max_length=255)), + )) + db.send_create_signal(u'notes', ['UserUploadMapping']) + + # Adding unique constraint on 'UserUploadMapping', fields ['user', 'fp_file'] + db.create_unique(u'notes_useruploadmapping', ['user_id', 'fp_file']) + + + def backwards(self, orm): + # Removing unique constraint on 'UserUploadMapping', fields ['user', 'fp_file'] + db.delete_unique(u'notes_useruploadmapping', ['user_id', 'fp_file']) + + # Deleting model 'UserUploadMapping' + db.delete_table(u'notes_useruploadmapping') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'courses.course': { + 'Meta': {'ordering': "['-file_count', 'school', 'name']", 'unique_together': "(('name', 'department'),)", 'object_name': 'Course'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'department': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.Department']", 'null': 'True', 'blank': 'True'}), + 'desc': ('django.db.models.fields.TextField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'}), + 'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'instructor_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'instructor_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'school': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.School']", 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'}) + }, + u'courses.department': { + 'Meta': {'unique_together': "(('name', 'school'),)", 'object_name': 'Department'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'school': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.School']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'}) + }, + u'courses.school': { + 'Meta': {'ordering': "['-file_count', '-priority', 'name']", 'object_name': 'School'}, + 'alias': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'facebook_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'hashtag': ('django.db.models.fields.CharField', [], {'max_length': '16', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'priority': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'blank': 'True'}), + 'usde_id': ('django.db.models.fields.BigIntegerField', [], {'unique': 'True', 'null': 'True', 'blank': 'True'}) + }, + u'licenses.license': { + 'Meta': {'object_name': 'License'}, + 'html': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}) + }, + u'notes.note': { + 'Meta': {'ordering': "['-uploaded_at']", 'unique_together': "(('fp_file', 'upstream_link'),)", 'object_name': 'Note'}, + 'course': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.Course']"}), + 'file_type': ('django.db.models.fields.CharField', [], {'default': "'???'", 'max_length': '15', 'null': 'True', 'blank': 'True'}), + 'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'fp_file': ('django_filepicker.models.FPFileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'gdrive_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), + 'is_hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'license': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['licenses.License']", 'null': 'True', 'blank': 'True'}), + 'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'pdf_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}), + 'static_html': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'thanks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'tweeted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow', 'null': 'True'}), + 'upstream_link': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'year': ('django.db.models.fields.IntegerField', [], {'default': '2014', 'null': 'True', 'blank': 'True'}) + }, + u'notes.useruploadmapping': { + 'Meta': {'unique_together': "(('user', 'fp_file'),)", 'object_name': 'UserUploadMapping'}, + 'fp_file': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + u'taggit.tag': { + 'Meta': {'ordering': "['namespace', 'name']", 'object_name': 'Tag'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'namespace': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + u'taggit.taggeditem': { + 'Meta': {'object_name': 'TaggedItem'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"}) + } + } + + complete_apps = ['notes'] \ No newline at end of file diff --git a/karmaworld/apps/notes/models.py b/karmaworld/apps/notes/models.py index 4a58f75..309d202 100644 --- a/karmaworld/apps/notes/models.py +++ b/karmaworld/apps/notes/models.py @@ -11,12 +11,11 @@ import traceback import logging from allauth.account.signals import user_logged_in from django.contrib.auth.models import User -from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.core.files.storage import default_storage from django.db.models import SET_NULL from django.db.models.signals import post_save, post_delete, pre_save from django.dispatch import receiver -from karmaworld.apps.notes.gdrive import UPLOADED_NOTES_SESSION_KEY from karmaworld.apps.users.models import NoteKarmaEvent, GenericKarmaEvent import os import urllib @@ -35,6 +34,7 @@ from karmaworld.apps.licenses.models import License from karmaworld.apps.notes.search import SearchIndex from karmaworld.settings.manual_unique_together import auto_add_check_unique_together +ANONYMOUS_UPLOAD_URLS = 'anonymous_upload_urls' logger = logging.getLogger(__name__) fs = FileSystemStorage(location=settings.MEDIA_ROOT) @@ -387,15 +387,29 @@ def note_delete_receiver(sender, **kwargs): index = SearchIndex() index.remove_note(note) - delete_message = 'Your note "{n}" was deleted'.format(n=note.name) - GenericKarmaEvent.create_event(note.user, delete_message, -5) + GenericKarmaEvent.create_event(note.user, note.name, GenericKarmaEvent.NOTE_DELETED) + + +class UserUploadMapping(models.Model): + user = models.ForeignKey(User) + fp_file = models.CharField(max_length=255) + + class Meta: + unique_together = ('user', 'fp_file') + @receiver(user_logged_in, weak=True) def find_orphan_notes(sender, **kwargs): user = kwargs['user'] s = kwargs['request'].session - uploaded_note_ids = s.get(UPLOADED_NOTES_SESSION_KEY, []) - notes = Note.objects.filter(id__in=uploaded_note_ids) - for note in notes: - note.user = user - note.save() + uploaded_note_urls = s.get(ANONYMOUS_UPLOAD_URLS, []) + for uploaded_note_url in uploaded_note_urls: + try: + note = Note.objects.get(fp_file=uploaded_note_url) + note.user = user + note.save() + NoteKarmaEvent.create_event(user, note, NoteKarmaEvent.UPLOAD) + except (ObjectDoesNotExist, MultipleObjectsReturned): + mapping = UserUploadMapping.objects.create(fp_file=uploaded_note_url, user=user) + mapping.save() + diff --git a/karmaworld/apps/users/models.py b/karmaworld/apps/users/models.py index 3ea4f5f..9fcbb64 100644 --- a/karmaworld/apps/users/models.py +++ b/karmaworld/apps/users/models.py @@ -3,7 +3,7 @@ # Copyright (C) 2013 FinalsClub Foundation import logging import datetime -from allauth.account.signals import email_confirmed, email_added +from allauth.account.signals import email_confirmed from django.contrib.auth.models import User from django.db.models import Sum from django.db.models.signals import post_save -- 2.25.1