forked from 0x2620/pandora
recover account, email in preferences
This commit is contained in:
parent
76368153ba
commit
c964ffaa71
7 changed files with 136 additions and 48 deletions
|
@ -5,6 +5,7 @@ from django.conf import settings
|
||||||
import load
|
import load
|
||||||
import models
|
import models
|
||||||
|
|
||||||
|
|
||||||
def send_encoder_message(msg):
|
def send_encoder_message(msg):
|
||||||
conn = DjangoBrokerConnection()
|
conn = DjangoBrokerConnection()
|
||||||
publisher = Publisher(connection=conn, exchange="oxdb-encoder",
|
publisher = Publisher(connection=conn, exchange="oxdb-encoder",
|
||||||
|
|
|
@ -964,6 +964,8 @@ class List(models.Model):
|
||||||
|
|
||||||
def editable(self, user):
|
def editable(self, user):
|
||||||
#FIXME: make permissions work
|
#FIXME: make permissions work
|
||||||
|
if self.user == user or user.has_perm('Ox.admin'):
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class ListItem(models.Model):
|
class ListItem(models.Model):
|
||||||
|
@ -978,12 +980,18 @@ 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], 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):
|
def timeline_path(f):
|
||||||
name = "%s.%s" % (still, 'png')
|
name = "timeline.png"
|
||||||
url_hash = f.oshash
|
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 = (
|
FILE_TYPES = (
|
||||||
(0, 'unknown'),
|
(0, 'unknown'),
|
||||||
|
@ -1039,7 +1047,7 @@ class File(models.Model):
|
||||||
stream320 = models.FileField(default=None, upload_to=lambda f, x: stream_path(f, '320'))
|
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'))
|
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'):
|
def save_chunk(self, chunk, name='video.ogv'):
|
||||||
if not self.available:
|
if not self.available:
|
||||||
|
@ -1105,24 +1113,69 @@ class File(models.Model):
|
||||||
self.movie = getMovie(info)
|
self.movie = getMovie(info)
|
||||||
self.save()
|
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):
|
def extract(self):
|
||||||
#FIXME: do stuff, like create timeline or create smaller videos etc
|
#FIXME: do stuff, like create timeline or create smaller videos etc
|
||||||
|
self.extract_video()
|
||||||
|
self.extract_timeline()
|
||||||
return
|
return
|
||||||
|
|
||||||
def editable(self, user):
|
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)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
modified = models.DateTimeField(auto_now=True)
|
modified = models.DateTimeField(auto_now=True)
|
||||||
file = models.ForeignKey(File, related_name="stills")
|
file = models.ForeignKey(File, related_name="frames")
|
||||||
position = models.FloatField()
|
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):
|
def __unicode__(self):
|
||||||
return '%s at %s' % (self.file, self.position)
|
return '%s at %s' % (self.file, self.position)
|
||||||
|
|
||||||
|
|
||||||
class Layer(models.Model):
|
class Layer(models.Model):
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
modified = models.DateTimeField(auto_now=True)
|
modified = models.DateTimeField(auto_now=True)
|
||||||
|
@ -1140,10 +1193,13 @@ class Layer(models.Model):
|
||||||
#location = models.ForeignKey('Location', default=None)
|
#location = models.ForeignKey('Location', default=None)
|
||||||
|
|
||||||
def editable(self, user):
|
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
|
return False
|
||||||
|
|
||||||
|
|
||||||
class Archive(models.Model):
|
class Archive(models.Model):
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
modified = models.DateTimeField(auto_now=True)
|
modified = models.DateTimeField(auto_now=True)
|
||||||
|
@ -1162,7 +1218,7 @@ class ArchiveFile(models.Model):
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
modified = models.DateTimeField(auto_now=True)
|
modified = models.DateTimeField(auto_now=True)
|
||||||
archive = models.ForeignKey(Archive, related_name='files')
|
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)
|
path = models.CharField(blank=True, max_length=2048)
|
||||||
|
|
||||||
objects = managers.ArchiveFileManager()
|
objects = managers.ArchiveFileManager()
|
||||||
|
@ -1189,10 +1245,16 @@ class ArchiveFile(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return '%s (%s)' % (self.path, unicode(self.archive))
|
return '%s (%s)' % (self.path, unicode(self.archive))
|
||||||
|
|
||||||
|
def editable(self, user):
|
||||||
|
return self.archive.editable(user)
|
||||||
|
|
||||||
class Collection(models.Model):
|
class Collection(models.Model):
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
modified = models.DateTimeField(auto_now=True)
|
modified = models.DateTimeField(auto_now=True)
|
||||||
|
users = models.ManyToManyField(User, related_name='collections')
|
||||||
name = models.CharField(blank=True, max_length=2048)
|
name = models.CharField(blank=True, max_length=2048)
|
||||||
subdomain = models.CharField(unique=True, max_length=2048)
|
subdomain = models.CharField(unique=True, max_length=2048)
|
||||||
movies = models.ForeignKey(Movie)
|
movies = models.ForeignKey(Movie)
|
||||||
|
|
||||||
|
def editable(self, user):
|
||||||
|
return self.users.filter(id=user.id).count() > 0
|
||||||
|
|
|
@ -484,7 +484,18 @@ def api_upload(request): #video, timeline, frame
|
||||||
'''
|
'''
|
||||||
form = UploadForm(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(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':
|
if data['item'] == 'timeline':
|
||||||
pass
|
pass
|
||||||
#print "not implemented"
|
#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}
|
response['files'][f.movie_file.oshash] = {'path': f.path, 'size': f.movie_file.size}
|
||||||
return render_to_json_response(response)
|
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):
|
class TimelineForm(forms.Form):
|
||||||
timeline = forms.FileField()
|
timeline = forms.FileField()
|
||||||
|
|
|
@ -26,7 +26,7 @@ class Preference(models.Model):
|
||||||
|
|
||||||
def getUserJSON(user):
|
def getUserJSON(user):
|
||||||
json = {}
|
json = {}
|
||||||
for key in ('username', 'email'):
|
for key in ('username', ):
|
||||||
json[key] = getattr(user, key)
|
json[key] = getattr(user, key)
|
||||||
json['preferences'] = getPreferences(user)
|
json['preferences'] = getPreferences(user)
|
||||||
return json
|
return json
|
||||||
|
@ -35,19 +35,29 @@ def getPreferences(user):
|
||||||
prefs = {}
|
prefs = {}
|
||||||
for p in Preference.objects.filter(user=user):
|
for p in Preference.objects.filter(user=user):
|
||||||
prefs[p.key] = json.loads(p.value)
|
prefs[p.key] = json.loads(p.value)
|
||||||
|
prefs['email'] = user.email
|
||||||
return prefs
|
return prefs
|
||||||
|
|
||||||
def getPreference(user, key, value=None):
|
def getPreference(user, key, value=None):
|
||||||
q = Preference.objects.filter(user=user, key=key)
|
if key in ('email', ):
|
||||||
if q.count() > 0:
|
value = getattr(user, key)
|
||||||
value = json.loads(q[0].value)
|
else:
|
||||||
|
q = Preference.objects.filter(user=user, key=key)
|
||||||
|
if q.count() > 0:
|
||||||
|
value = json.loads(q[0].value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def setPreference(user, key, value):
|
def setPreference(user, key, value):
|
||||||
value = json.dumps(value)
|
if key in ('email', ):
|
||||||
q = Preference.objects.filter(user=user, key=key)
|
setattr(user, key, value)
|
||||||
if q.count() > 0:
|
user.save()
|
||||||
q[0].value = value
|
|
||||||
else:
|
else:
|
||||||
p = Preference(user=user, key=key, value=value)
|
value = json.dumps(value)
|
||||||
p.save()
|
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()
|
||||||
|
|
|
@ -6,9 +6,10 @@ import hashlib
|
||||||
from django import forms
|
from django import forms
|
||||||
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, redirect
|
||||||
from django.template import RequestContext, loader, Context
|
from django.template import RequestContext, loader, Context
|
||||||
from django.utils import simplejson as json
|
from django.utils import simplejson as json
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
from oxdjango.shortcuts import render_to_json_response
|
from oxdjango.shortcuts import render_to_json_response
|
||||||
from oxdjango.decorators import login_required_json
|
from oxdjango.decorators import login_required_json
|
||||||
|
@ -116,8 +117,8 @@ def api_recover(request):
|
||||||
user_profile.recover_key = key
|
user_profile.recover_key = key
|
||||||
user_profile.save()
|
user_profile.save()
|
||||||
|
|
||||||
template = loader.get_template('recover_mail.txt')
|
template = loader.get_template('recover_email.txt')
|
||||||
context = RequestContext({
|
context = RequestContext(request, {
|
||||||
'recover_url': request.build_absolute_uri("/r/%s" % key),
|
'recover_url': request.build_absolute_uri("/r/%s" % key),
|
||||||
'sitename': settings.SITENAME,
|
'sitename': settings.SITENAME,
|
||||||
})
|
})
|
||||||
|
@ -131,6 +132,22 @@ def api_recover(request):
|
||||||
response = {'status': {'code': 400, 'text': 'username exists'}}
|
response = {'status': {'code': 400, 'text': 'username exists'}}
|
||||||
return render_to_json_response(response)
|
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
|
@login_required_json
|
||||||
def api_preferences(request):
|
def api_preferences(request):
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -12,9 +12,11 @@ TEMPLATE_DEBUG = DEBUG
|
||||||
JSON_DEBUG = False
|
JSON_DEBUG = False
|
||||||
|
|
||||||
ADMINS = (
|
ADMINS = (
|
||||||
# ('Your Name', 'your_email@domain.com'),
|
('j', 'j@mailb.org'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
DEFAULT_FROM_EMAIL='bot@0xdb.org'
|
||||||
|
|
||||||
MANAGERS = ADMINS
|
MANAGERS = ADMINS
|
||||||
|
|
||||||
DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
|
DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
|
||||||
|
@ -106,6 +108,10 @@ BROKER_USER = "oxdb"
|
||||||
BROKER_PASSWORD = "0xdb"
|
BROKER_PASSWORD = "0xdb"
|
||||||
BROKER_VHOST = "/oxdb"
|
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
|
#overwrite default settings with local settings
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -12,6 +12,7 @@ urlpatterns = patterns('',
|
||||||
(r'^ajax_filtered_fields/', include('ajax_filtered_fields.urls')),
|
(r'^ajax_filtered_fields/', include('ajax_filtered_fields.urls')),
|
||||||
(r'^api/', include('backend.urls')),
|
(r'^api/', include('backend.urls')),
|
||||||
(r'^$', 'app.views.index'),
|
(r'^$', 'app.views.index'),
|
||||||
|
(r'^r/(?P<key>.*)$', 'oxuser.views.recover'),
|
||||||
|
|
||||||
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
|
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
|
||||||
# to INSTALLED_APPS to enable admin documentation:
|
# to INSTALLED_APPS to enable admin documentation:
|
||||||
|
|
Loading…
Reference in a new issue