diff --git a/oxdb/backend/models.py b/oxdb/backend/models.py index 8f59f7ad8..92423cef8 100644 --- a/oxdb/backend/models.py +++ b/oxdb/backend/models.py @@ -993,7 +993,7 @@ class ListItem(models.Model): def stream_path(f, size): name = "%s.%s" % (size, 'ogv') url_hash = f.oshash - return os.path.join('stream', url_hash[:2], url_hash[2:4], url_hash[4:6], name) + return os.path.join('stream', url_hash[:2], url_hash[2:4], url_hash[4:6], url_hash, name) def still_path(f, still): name = "%s.%s" % (still, 'png') @@ -1061,13 +1061,14 @@ class File(models.Model): #FIXME: this should use stream128 or stream640 depending on configuration video = getattr(self, 'stream128') if not video: - video.save(name, ContentFile(chunk)) + video.save(name, chunk) self.save() else: f = open(video.path, 'a') - f.write(chunk) + f.write(chunk.read()) f.close() return True + print "somehing failed, not sure what?" return False objects = managers.FileManager() @@ -1134,7 +1135,7 @@ class File(models.Model): def editable(self, user): #FIXME: make permissions work - return False + return True class Still(models.Model): created = models.DateTimeField(auto_now_add=True) @@ -1213,3 +1214,9 @@ class ArchiveFile(models.Model): return '%s (%s)' % (self.path, unicode(self.archive)) +class Collection(models.Model): + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + name = models.CharField(blank=True, max_length=2048) + subdomain = models.CharField(unique=True, max_length=2048) + movies = models.ForeignKey(Movie) diff --git a/oxdb/backend/urls.py b/oxdb/backend/urls.py new file mode 100644 index 000000000..13c0237b5 --- /dev/null +++ b/oxdb/backend/urls.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 + +from django.conf.urls.defaults import * + + +urlpatterns = patterns("backend.views", + (r'^upload/', 'firefogg_upload'), + (r'^$', 'api'), +) + diff --git a/oxdb/backend/views.py b/oxdb/backend/views.py index 6530cf485..611c03ed1 100644 --- a/oxdb/backend/views.py +++ b/oxdb/backend/views.py @@ -356,7 +356,7 @@ def api_removeList(request): @login_required_json def api_addArchive(request): ''' - ARCHIVE API NEED CLEANUP + ARCHIVE API NEEDS CLEANUP param data {name: string} return {'status': {'code': int, 'text': string}, @@ -376,7 +376,7 @@ def api_addArchive(request): @login_required_json def api_editArchive(request): ''' - ARCHIVE API NEED CLEANUP + ARCHIVE API NEEDS CLEANUP param data {id: string, key: value,..} return {'status': {'code': int, 'text': string}, @@ -394,7 +394,7 @@ def api_editArchive(request): @login_required_json def api_removeArchive(request): ''' - ARCHIVE API NEED CLEANUP + ARCHIVE API NEEDS CLEANUP param data string id @@ -454,10 +454,24 @@ def api_update(request): response = {'status': {'code': 403, 'text': 'permission denied'}} return render_to_json_response(response) +def api_encodingSettings(request): + ''' + returns Firefogg encoding settings as specified by site + return {'status': {'code': int, 'text': string}, + 'data': {'options': {'videoQuality':...}}} + ''' + response = {'status': {'code': 200, 'text': 'ok'}} + response['data'] = {'options': {'preset': 'padma'}} + return render_to_json_response(response) + class UploadForm(forms.Form): data = forms.TextInput() file = forms.FileField() +class VideoChunkForm(forms.Form): + chunk = forms.FileField() + done = forms.IntegerField(required=False) + def api_upload(request): #video, timeline, frame ''' upload video, timeline or frame @@ -466,16 +480,59 @@ def api_upload(request): #video, timeline, frame return {'status': {'code': int, 'text': string}, 'data': {}} ''' - form = LoginForm(request.POST, request.FILES) + form = UploadForm(request.POST, request.FILES) if form.is_valid(): data = json.loads(request.POST['data']) if data['item'] == 'timeline': pass #print "not implemented" - + response = {'status': {'code': 501, 'text': 'not implemented'}} return render_to_json_response(response) +@login_required_json +def firefogg_upload(request): + #handle video upload + if request.method == 'POST': + #init upload + if 'oshash' in request.POST: + #FIXME: what to do if requested oshash is not in db? + #FIXME: should existing data be reset here? or better, should this fail if an upload was there + f = get_object_or_404(models.File, oshash=request.POST['oshash']) + if f.stream128: + f.stream128.delete() + f.available = False + f.save() + response = { + 'uploadUrl': request.build_absolute_uri('/api/upload/?oshash=%s' % f.oshash), + 'result': 1 + } + return render_to_json_response(response) + #post next chunk + if 'chunk' in request.FILES and 'oshash' in request.GET: + print "all chunk now" + f = get_object_or_404(models.File, oshash=request.GET['oshash']) + form = VideoChunkForm(request.POST, request.FILES) + #FIXME: + if form.is_valid() and f.editable(request.user): + c = form.cleaned_data['chunk'] + response = { + 'result': 1, + 'resultUrl': request.build_absolute_uri('/') + } + if not f.save_chunk(c, c.name): + response['result'] = -1 + elif form.cleaned_data['done']: + #FIXME: send message to encode deamon to create derivates instead + f.available = True + f.save() + response['result'] = 1 + response['done'] = 1 + return render_to_json_response(response) + print request.GET, request.POST + response = {'status': {'code': 400, 'text': 'this request requires POST'}} + return render_to_json_response(response) + @login_required_json def api_editFile(request): #FIXME: should this be file.files. or part of update ''' diff --git a/oxdb/oxuser/models.py b/oxdb/oxuser/models.py index 662a4a398..cdf0419f1 100644 --- a/oxdb/oxuser/models.py +++ b/oxdb/oxuser/models.py @@ -5,7 +5,20 @@ from django.db import models from django.contrib.auth.models import User from django.utils import simplejson as json +from django.contrib.auth.models import User +from django.db.models import signals +from django.dispatch import dispatcher + +class UserProfile(models.Model): + recover_key = models.TextField() + user = models.ForeignKey(User, unique=True) + +def user_post_save(sender, instance, **kwargs): + profile, new = UserProfile.objects.get_or_create(user=instance) + +models.signals.post_save.connect(user_post_save, sender=User) + class Preference(models.Model): user = models.ForeignKey(User, related_name='preferences') created = models.DateTimeField(auto_now_add=True) diff --git a/oxdb/oxuser/views.py b/oxdb/oxuser/views.py index 532e6e203..e8bebec3a 100644 --- a/oxdb/oxuser/views.py +++ b/oxdb/oxuser/views.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- # vi:si:et:sw=4:sts=4:ts=4 +import uuid +import hashlib from django.contrib.auth.models import User from django.contrib.auth import authenticate, login, logout from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404 -from django.template import RequestContext +from django.template import RequestContext, loader, Context from django.utils import simplejson as json from django import forms @@ -109,8 +111,19 @@ def api_recover(request): if q.count() > 0: user = q[0] if user: - user.email_user('recovert','not yest, but soon you will be able to recover') - #user.sendmail(...) #FIXME: send recovery mail + key = hashlib.sha1(str(uuid.uuid4())).hexdigest() + user_profile = user.get_profile() + user_profile.recover_key = key + user_profile.save() + + template = loader.get_template('recover_mail.txt') + context = RequestContext({ + 'recover_url': request.build_absolute_uri("/r/%s" % key), + 'sitename': settings.SITENAME, + }) + message = template.render(context) + subject = '%s account recovery' % settings.SITENAME + user.email_user(subject, message) response = {'status': {'code': 200, 'text': 'recover email sent.'}} else: response = {'status': {'code': 404, 'text': 'user or email not found.'}} diff --git a/oxdb/settings.py b/oxdb/settings.py index 60ad3d645..f964db449 100644 --- a/oxdb/settings.py +++ b/oxdb/settings.py @@ -4,6 +4,7 @@ import os from os.path import join +SITENAME = 'Pad.ma' PROJECT_ROOT = os.path.normpath(os.path.dirname(__file__)) DEBUG = True @@ -42,6 +43,7 @@ SITE_ID = 1 # If you set this to False, Django will make some optimizations so as not # to load the internationalization machinery. USE_I18N = True +APPEND_SLASH = False # Absolute path to the directory that holds media. # Example: "/home/media/media.lawrence.com/" @@ -95,6 +97,8 @@ INSTALLED_APPS = ( 'oxuser', ) +AUTH_PROFILE_MODULE = 'oxuser.UserProfile' + #rabbitmq connection settings BROKER_HOST = "127.0.0.1" BROKER_PORT = 5672 diff --git a/oxdb/urls.py b/oxdb/urls.py index 28c477802..ccffe5834 100644 --- a/oxdb/urls.py +++ b/oxdb/urls.py @@ -10,7 +10,7 @@ admin.autodiscover() urlpatterns = patterns('', # Example: (r'^ajax_filtered_fields/', include('ajax_filtered_fields.urls')), - (r'^api/', 'backend.views.api'), + (r'^api/', include('backend.urls')), (r'^$', 'app.views.index'), # Uncomment the admin/doc line below and add 'django.contrib.admindocs'