From c964ffaa712605a0aff96385bf727f5c905ff64d Mon Sep 17 00:00:00 2001 From: j <0x006A@0x2620.org> Date: Sat, 6 Feb 2010 13:54:39 +0530 Subject: [PATCH] recover account, email in preferences --- oxdb/backend/encoder.py | 1 + oxdb/backend/models.py | 88 +++++++++++++++++++++++++++++++++++------ oxdb/backend/views.py | 33 ++++++---------- oxdb/oxuser/models.py | 30 +++++++++----- oxdb/oxuser/views.py | 23 +++++++++-- oxdb/settings.py | 8 +++- oxdb/urls.py | 1 + 7 files changed, 136 insertions(+), 48 deletions(-) diff --git a/oxdb/backend/encoder.py b/oxdb/backend/encoder.py index d588e6a..1835e31 100644 --- a/oxdb/backend/encoder.py +++ b/oxdb/backend/encoder.py @@ -5,6 +5,7 @@ from django.conf import settings import load import models + def send_encoder_message(msg): conn = DjangoBrokerConnection() publisher = Publisher(connection=conn, exchange="oxdb-encoder", diff --git a/oxdb/backend/models.py b/oxdb/backend/models.py index 059922d..43c580e 100644 --- a/oxdb/backend/models.py +++ b/oxdb/backend/models.py @@ -964,6 +964,8 @@ class List(models.Model): def editable(self, user): #FIXME: make permissions work + if self.user == user or user.has_perm('Ox.admin'): + return True return False class ListItem(models.Model): @@ -978,12 +980,18 @@ 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], url_hash, name) + return os.path.join(url_hash[:2], url_hash[2:4], url_hash[4:6], url_hash, name) -def still_path(f, still): - name = "%s.%s" % (still, 'png') +def timeline_path(f): + name = "timeline.png" url_hash = f.oshash - return os.path.join('still', url_hash[:2], url_hash[2:4], url_hash[4:6], name) + return os.path.join(url_hash[:2], url_hash[2:4], url_hash[4:6], url_hash, name) + +def frame_path(f): + position = oxlib.formatTime(f.position*1000).replace(':', '.') + name = "%s.%s" % (position, 'png') + url_hash = f.file.oshash + return os.path.join(url_hash[:2], url_hash[2:4], url_hash[4:6], url_hash, name) FILE_TYPES = ( (0, 'unknown'), @@ -1039,7 +1047,7 @@ class File(models.Model): stream320 = models.FileField(default=None, upload_to=lambda f, x: stream_path(f, '320')) stream640 = models.FileField(default=None, upload_to=lambda f, x: stream_path(f, '640')) - timeline = models.ImageField(default=None, null=True, upload_to=lambda f, x: still_path(f, '0')) + timeline = models.ImageField(default=None, null=True, upload_to=lambda f, x: timeline_path(f)) def save_chunk(self, chunk, name='video.ogv'): if not self.available: @@ -1105,24 +1113,69 @@ class File(models.Model): self.movie = getMovie(info) self.save() + def extract_timeline(self): + if self.stream640: + video = self.stream640.path + elif stream320: + video = self.stream320.path + elif stream128: + video = self.stream128.path + else: + return False + prefix = os.path.join(os.path.dirname(video), 'timeline') + cmd = ['oxtimeline', '-i', video, '-o', prefix] + p = subprocess.Popen(cmd) + p.wait() + return p.returncode == 0 + + def extract_video(self): + ogg = Firefogg() + if self.stream640: + #320 stream + self.stream320.name = stream_path(self, '320') + self.stream320.save() + ogg.encode(self.stream640.path, self.stream320.path, settings.VIDEO320) + #128 stream + self.stream128.name = stream_path(self, '128') + self.stream128.save() + ogg.encode(self.stream640.path, self.stream128.path, settings.VIDEO128) + elif self.stream320: + self.stream128.name = stream_path(self, '128') + self.stream128.save() + ogg.encode(self.stream320.path, self.stream128.path, settings.VIDEO128) + def extract(self): #FIXME: do stuff, like create timeline or create smaller videos etc + self.extract_video() + self.extract_timeline() return def editable(self, user): - #FIXME: make permissions work - return True + ''' + #FIXME: this should use a queryset!!! + archives = [] + for a in self.archive_files.all(): + archives.append(a.archive) + users = [] + for a in archives: + users += a.users.all() + return user in users + ''' + return self.archive_files.filter(archive__users__id=user.id).count() > 0 -class Still(models.Model): +class Frame(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) - file = models.ForeignKey(File, related_name="stills") + file = models.ForeignKey(File, related_name="frames") position = models.FloatField() - still = models.ImageField(default=None, null=True, upload_to=lambda f, x: still_path(f, '0')) + frame = models.ImageField(default=None, null=True, upload_to=lambda f, x: frame_path(f)) + + #FIXME: frame path should be renamed on save to match current position def __unicode__(self): return '%s at %s' % (self.file, self.position) + class Layer(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) @@ -1140,10 +1193,13 @@ class Layer(models.Model): #location = models.ForeignKey('Location', default=None) def editable(self, user): - #FIXME: make permissions work + if user.is_authenticated(): + if obj.user == user.id or user.has_perm('0x.admin'): + return True + if user.groups.filter(id__in=obj.groups.all()).count() > 0: + return True return False - class Archive(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) @@ -1162,7 +1218,7 @@ class ArchiveFile(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) archive = models.ForeignKey(Archive, related_name='files') - file = models.ForeignKey(File) + file = models.ForeignKey(File, related_name='archive_files') path = models.CharField(blank=True, max_length=2048) objects = managers.ArchiveFileManager() @@ -1189,10 +1245,16 @@ class ArchiveFile(models.Model): def __unicode__(self): return '%s (%s)' % (self.path, unicode(self.archive)) + def editable(self, user): + return self.archive.editable(user) class Collection(models.Model): created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) + users = models.ManyToManyField(User, related_name='collections') name = models.CharField(blank=True, max_length=2048) subdomain = models.CharField(unique=True, max_length=2048) movies = models.ForeignKey(Movie) + + def editable(self, user): + return self.users.filter(id=user.id).count() > 0 diff --git a/oxdb/backend/views.py b/oxdb/backend/views.py index e5be67c..80bae70 100644 --- a/oxdb/backend/views.py +++ b/oxdb/backend/views.py @@ -484,7 +484,18 @@ def api_upload(request): #video, timeline, frame ''' form = UploadForm(request.POST, request.FILES) if form.is_valid(): - data = json.loads(request.POST['data']) + data = json.loads(form.cleaned_data['data']) + oshash = data['oshash'] + f = get_object_or_404(models.File, oshash=oshash) + if data['item'] == 'frame': + ff = form.cleaned_data['file'] + position = data['position'] + frame = models.Frame.objects.get_or_create(file=f, position=position) + frame.frame.save(ff.name, ff) + frame.save() + response = {'status': {'code': 200, 'text': 'ok'}} + response['url'] = still.url() + return render_to_json_response(response) if data['item'] == 'timeline': pass #print "not implemented" @@ -652,26 +663,6 @@ def find_files(request): response['files'][f.movie_file.oshash] = {'path': f.path, 'size': f.movie_file.size} return render_to_json_response(response) -class StillForm(forms.Form): - still = forms.FileField() - position = forms.FloatField() - -#@login_required_json -def add_still(request, oshash): - response = {'status': 500} - f = get_object_or_404(models.File, oshash=oshash) - - form = TimelineForm(request.POST, request.FILES) - if form.is_valid(): - ff = form.cleaned_data['still'] - position = form.cleaned_data['position'] - - still = models.Still(file=f, position=position) - still.save() - still.still.save(ff, ff.name) - response = {'status': 200} - response['url'] = still.url() - return render_to_json_response(response) class TimelineForm(forms.Form): timeline = forms.FileField() diff --git a/oxdb/oxuser/models.py b/oxdb/oxuser/models.py index 1675696..abd252f 100644 --- a/oxdb/oxuser/models.py +++ b/oxdb/oxuser/models.py @@ -26,7 +26,7 @@ class Preference(models.Model): def getUserJSON(user): json = {} - for key in ('username', 'email'): + for key in ('username', ): json[key] = getattr(user, key) json['preferences'] = getPreferences(user) return json @@ -35,19 +35,29 @@ def getPreferences(user): prefs = {} for p in Preference.objects.filter(user=user): prefs[p.key] = json.loads(p.value) + prefs['email'] = user.email return prefs def getPreference(user, key, value=None): - q = Preference.objects.filter(user=user, key=key) - if q.count() > 0: - value = json.loads(q[0].value) + if key in ('email', ): + value = getattr(user, key) + else: + q = Preference.objects.filter(user=user, key=key) + if q.count() > 0: + value = json.loads(q[0].value) return value def setPreference(user, key, value): - value = json.dumps(value) - q = Preference.objects.filter(user=user, key=key) - if q.count() > 0: - q[0].value = value + if key in ('email', ): + setattr(user, key, value) + user.save() else: - p = Preference(user=user, key=key, value=value) - p.save() + value = json.dumps(value) + q = Preference.objects.filter(user=user, key=key) + if q.count() > 0: + p = q[0] + p.value = value + p.save() + else: + p = Preference(user=user, key=key, value=value) + p.save() diff --git a/oxdb/oxuser/views.py b/oxdb/oxuser/views.py index 1ee6161..1c45e5a 100644 --- a/oxdb/oxuser/views.py +++ b/oxdb/oxuser/views.py @@ -6,9 +6,10 @@ import hashlib from django import forms 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.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect from django.template import RequestContext, loader, Context from django.utils import simplejson as json +from django.conf import settings from oxdjango.shortcuts import render_to_json_response from oxdjango.decorators import login_required_json @@ -116,8 +117,8 @@ def api_recover(request): user_profile.recover_key = key user_profile.save() - template = loader.get_template('recover_mail.txt') - context = RequestContext({ + template = loader.get_template('recover_email.txt') + context = RequestContext(request, { 'recover_url': request.build_absolute_uri("/r/%s" % key), 'sitename': settings.SITENAME, }) @@ -131,6 +132,22 @@ def api_recover(request): response = {'status': {'code': 400, 'text': 'username exists'}} return render_to_json_response(response) +def recover(request, key): + qs = models.UserProfile.objects.filter(recover_key=key) + if qs.count() == 1: + user = qs[0].user + user.set_password(key) + user.save() + user_profile = user.get_profile() + user_profile.recover_key = '' + user_profile.save() + user = authenticate(username=user.username, password=key) + login(request, user) + + #FIXME: set message to notify user to update password + return redirect('/#settings') + return redirect('/') + @login_required_json def api_preferences(request): ''' diff --git a/oxdb/settings.py b/oxdb/settings.py index f964db4..8d8422a 100644 --- a/oxdb/settings.py +++ b/oxdb/settings.py @@ -12,9 +12,11 @@ TEMPLATE_DEBUG = DEBUG JSON_DEBUG = False ADMINS = ( - # ('Your Name', 'your_email@domain.com'), + ('j', 'j@mailb.org'), ) +DEFAULT_FROM_EMAIL='bot@0xdb.org' + MANAGERS = ADMINS DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. @@ -106,6 +108,10 @@ BROKER_USER = "oxdb" BROKER_PASSWORD = "0xdb" BROKER_VHOST = "/oxdb" +#Video encoding settings +VIDEO128 = {'profile': 'padma-stream', 'samplerate': 44100, 'noUpscaling': True} +VIDEO320 = {'maxSize': 320, 'samplerate': 44100, 'videoBitrate': 500, 'audioQuality': 0, 'channels': 1, 'noUpscaling': True} +VIDEO640 = {'profile': 'padma'} #overwrite default settings with local settings try: diff --git a/oxdb/urls.py b/oxdb/urls.py index ccffe58..ef55bd9 100644 --- a/oxdb/urls.py +++ b/oxdb/urls.py @@ -12,6 +12,7 @@ urlpatterns = patterns('', (r'^ajax_filtered_fields/', include('ajax_filtered_fields.urls')), (r'^api/', include('backend.urls')), (r'^$', 'app.views.index'), + (r'^r/(?P.*)$', 'oxuser.views.recover'), # Uncomment the admin/doc line below and add 'django.contrib.admindocs' # to INSTALLED_APPS to enable admin documentation: