upload, recovery
This commit is contained in:
parent
56ae83cb5b
commit
57fad37643
7 changed files with 118 additions and 13 deletions
|
@ -993,7 +993,7 @@ class ListItem(models.Model):
|
||||||
def stream_path(f, size):
|
def stream_path(f, size):
|
||||||
name = "%s.%s" % (size, 'ogv')
|
name = "%s.%s" % (size, 'ogv')
|
||||||
url_hash = f.oshash
|
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):
|
def still_path(f, still):
|
||||||
name = "%s.%s" % (still, 'png')
|
name = "%s.%s" % (still, 'png')
|
||||||
|
@ -1061,13 +1061,14 @@ class File(models.Model):
|
||||||
#FIXME: this should use stream128 or stream640 depending on configuration
|
#FIXME: this should use stream128 or stream640 depending on configuration
|
||||||
video = getattr(self, 'stream128')
|
video = getattr(self, 'stream128')
|
||||||
if not video:
|
if not video:
|
||||||
video.save(name, ContentFile(chunk))
|
video.save(name, chunk)
|
||||||
self.save()
|
self.save()
|
||||||
else:
|
else:
|
||||||
f = open(video.path, 'a')
|
f = open(video.path, 'a')
|
||||||
f.write(chunk)
|
f.write(chunk.read())
|
||||||
f.close()
|
f.close()
|
||||||
return True
|
return True
|
||||||
|
print "somehing failed, not sure what?"
|
||||||
return False
|
return False
|
||||||
|
|
||||||
objects = managers.FileManager()
|
objects = managers.FileManager()
|
||||||
|
@ -1134,7 +1135,7 @@ class File(models.Model):
|
||||||
|
|
||||||
def editable(self, user):
|
def editable(self, user):
|
||||||
#FIXME: make permissions work
|
#FIXME: make permissions work
|
||||||
return False
|
return True
|
||||||
|
|
||||||
class Still(models.Model):
|
class Still(models.Model):
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
@ -1213,3 +1214,9 @@ class ArchiveFile(models.Model):
|
||||||
return '%s (%s)' % (self.path, unicode(self.archive))
|
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)
|
||||||
|
|
11
oxdb/backend/urls.py
Normal file
11
oxdb/backend/urls.py
Normal file
|
@ -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'),
|
||||||
|
)
|
||||||
|
|
|
@ -356,7 +356,7 @@ def api_removeList(request):
|
||||||
@login_required_json
|
@login_required_json
|
||||||
def api_addArchive(request):
|
def api_addArchive(request):
|
||||||
'''
|
'''
|
||||||
ARCHIVE API NEED CLEANUP
|
ARCHIVE API NEEDS CLEANUP
|
||||||
param data
|
param data
|
||||||
{name: string}
|
{name: string}
|
||||||
return {'status': {'code': int, 'text': string},
|
return {'status': {'code': int, 'text': string},
|
||||||
|
@ -376,7 +376,7 @@ def api_addArchive(request):
|
||||||
@login_required_json
|
@login_required_json
|
||||||
def api_editArchive(request):
|
def api_editArchive(request):
|
||||||
'''
|
'''
|
||||||
ARCHIVE API NEED CLEANUP
|
ARCHIVE API NEEDS CLEANUP
|
||||||
param data
|
param data
|
||||||
{id: string, key: value,..}
|
{id: string, key: value,..}
|
||||||
return {'status': {'code': int, 'text': string},
|
return {'status': {'code': int, 'text': string},
|
||||||
|
@ -394,7 +394,7 @@ def api_editArchive(request):
|
||||||
@login_required_json
|
@login_required_json
|
||||||
def api_removeArchive(request):
|
def api_removeArchive(request):
|
||||||
'''
|
'''
|
||||||
ARCHIVE API NEED CLEANUP
|
ARCHIVE API NEEDS CLEANUP
|
||||||
param data
|
param data
|
||||||
string id
|
string id
|
||||||
|
|
||||||
|
@ -454,10 +454,24 @@ def api_update(request):
|
||||||
response = {'status': {'code': 403, 'text': 'permission denied'}}
|
response = {'status': {'code': 403, 'text': 'permission denied'}}
|
||||||
return render_to_json_response(response)
|
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):
|
class UploadForm(forms.Form):
|
||||||
data = forms.TextInput()
|
data = forms.TextInput()
|
||||||
file = forms.FileField()
|
file = forms.FileField()
|
||||||
|
|
||||||
|
class VideoChunkForm(forms.Form):
|
||||||
|
chunk = forms.FileField()
|
||||||
|
done = forms.IntegerField(required=False)
|
||||||
|
|
||||||
def api_upload(request): #video, timeline, frame
|
def api_upload(request): #video, timeline, frame
|
||||||
'''
|
'''
|
||||||
upload video, timeline or frame
|
upload video, timeline or frame
|
||||||
|
@ -466,16 +480,59 @@ def api_upload(request): #video, timeline, frame
|
||||||
return {'status': {'code': int, 'text': string},
|
return {'status': {'code': int, 'text': string},
|
||||||
'data': {}}
|
'data': {}}
|
||||||
'''
|
'''
|
||||||
form = LoginForm(request.POST, request.FILES)
|
form = UploadForm(request.POST, request.FILES)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
data = json.loads(request.POST['data'])
|
data = json.loads(request.POST['data'])
|
||||||
if data['item'] == 'timeline':
|
if data['item'] == 'timeline':
|
||||||
pass
|
pass
|
||||||
#print "not implemented"
|
#print "not implemented"
|
||||||
|
|
||||||
response = {'status': {'code': 501, 'text': 'not implemented'}}
|
response = {'status': {'code': 501, 'text': 'not implemented'}}
|
||||||
return render_to_json_response(response)
|
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
|
@login_required_json
|
||||||
def api_editFile(request): #FIXME: should this be file.files. or part of update
|
def api_editFile(request): #FIXME: should this be file.files. or part of update
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -5,7 +5,20 @@ from django.db import models
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.utils import simplejson as json
|
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):
|
class Preference(models.Model):
|
||||||
user = models.ForeignKey(User, related_name='preferences')
|
user = models.ForeignKey(User, related_name='preferences')
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# vi:si:et:sw=4:sts=4:ts=4
|
# vi:si:et:sw=4:sts=4:ts=4
|
||||||
|
import uuid
|
||||||
|
import hashlib
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.auth import authenticate, login, logout
|
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.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.utils import simplejson as json
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
|
@ -109,8 +111,19 @@ def api_recover(request):
|
||||||
if q.count() > 0:
|
if q.count() > 0:
|
||||||
user = q[0]
|
user = q[0]
|
||||||
if user:
|
if user:
|
||||||
user.email_user('recovert','not yest, but soon you will be able to recover')
|
key = hashlib.sha1(str(uuid.uuid4())).hexdigest()
|
||||||
#user.sendmail(...) #FIXME: send recovery mail
|
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.'}}
|
response = {'status': {'code': 200, 'text': 'recover email sent.'}}
|
||||||
else:
|
else:
|
||||||
response = {'status': {'code': 404, 'text': 'user or email not found.'}}
|
response = {'status': {'code': 404, 'text': 'user or email not found.'}}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import os
|
import os
|
||||||
from os.path import join
|
from os.path import join
|
||||||
|
|
||||||
|
SITENAME = 'Pad.ma'
|
||||||
PROJECT_ROOT = os.path.normpath(os.path.dirname(__file__))
|
PROJECT_ROOT = os.path.normpath(os.path.dirname(__file__))
|
||||||
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
@ -42,6 +43,7 @@ SITE_ID = 1
|
||||||
# If you set this to False, Django will make some optimizations so as not
|
# If you set this to False, Django will make some optimizations so as not
|
||||||
# to load the internationalization machinery.
|
# to load the internationalization machinery.
|
||||||
USE_I18N = True
|
USE_I18N = True
|
||||||
|
APPEND_SLASH = False
|
||||||
|
|
||||||
# Absolute path to the directory that holds media.
|
# Absolute path to the directory that holds media.
|
||||||
# Example: "/home/media/media.lawrence.com/"
|
# Example: "/home/media/media.lawrence.com/"
|
||||||
|
@ -95,6 +97,8 @@ INSTALLED_APPS = (
|
||||||
'oxuser',
|
'oxuser',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AUTH_PROFILE_MODULE = 'oxuser.UserProfile'
|
||||||
|
|
||||||
#rabbitmq connection settings
|
#rabbitmq connection settings
|
||||||
BROKER_HOST = "127.0.0.1"
|
BROKER_HOST = "127.0.0.1"
|
||||||
BROKER_PORT = 5672
|
BROKER_PORT = 5672
|
||||||
|
|
|
@ -10,7 +10,7 @@ admin.autodiscover()
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
# Example:
|
# Example:
|
||||||
(r'^ajax_filtered_fields/', include('ajax_filtered_fields.urls')),
|
(r'^ajax_filtered_fields/', include('ajax_filtered_fields.urls')),
|
||||||
(r'^api/', 'backend.views.api'),
|
(r'^api/', include('backend.urls')),
|
||||||
(r'^$', 'app.views.index'),
|
(r'^$', 'app.views.index'),
|
||||||
|
|
||||||
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
|
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
|
||||||
|
|
Loading…
Reference in a new issue