first version of embed and auth. plan to implement rbac
authorymh <ymh.work@gmail.com>
Wed, 29 Sep 2010 10:10:07 +0200
changeset 81 97b12f5f2c7a
parent 79 674a65969a14
child 82 9202807b4cec
first version of embed and auth. plan to implement rbac
web/franceculture/settings.py
web/franceculture/templates/franceculture/partial/embed.html
web/franceculture/urls.py
web/franceculture/views.py
web/ldt/auth/__init__.py
web/ldt/ldt_utils/models.py
web/ldt/ldt_utils/views.py
web/ldt/locale/en/LC_MESSAGES/django.po
web/ldt/locale/fr/LC_MESSAGES/django.po
web/ldt/utils/path.py
web/static/js/projectscontents.js
web/static/swf/ldt/LignesDeTempsFlex.swf
--- a/web/franceculture/settings.py	Thu Sep 23 18:39:40 2010 +0200
+++ b/web/franceculture/settings.py	Wed Sep 29 10:10:07 2010 +0200
@@ -144,5 +144,5 @@
 LOGIN_REDIRECT_URL = BASE_URL + 'franceculture'
 
 GLOBAL_LOG_LEVEL = LOG_LEVEL
-GLOBAL_LOG_HANDLERS = [logging.FileHandler(LOG_FILE)]
+GLOBAL_LOG_HANDLERS = [{'handler':logging.FileHandler(LOG_FILE), 'format':"%(asctime)s - %(levelname)s : %(message)s"}]
 
--- a/web/franceculture/templates/franceculture/partial/embed.html	Thu Sep 23 18:39:40 2010 +0200
+++ b/web/franceculture/templates/franceculture/partial/embed.html	Wed Sep 29 10:10:07 2010 +0200
@@ -1,5 +1,6 @@
+{% load i18n %}
 <div style="height: 80px">&nbsp;</div>
-<div id="{{ player_id }}">
+<div id="{{ player_id }}_embed" class="iri_player_embed">
 </div>
 <script type="text/javascript">
 	var config = {
@@ -11,7 +12,7 @@
 				width:650,
 				height:1,
 				mode:'radio',
-				container:'{{ player_id }}',
+				container:'{{ player_id }}_embed',
 				debug:false,
 				css:'{{WEB_URL}}{{MEDIA_URL}}css/LdtPlayer.css'},
 			player:{
@@ -19,4 +20,18 @@
 				src:'{{WEB_URL}}{{MEDIA_URL}}swf/player.swf'}
 		};
 	__IriSP.init(config);     
-</script>
\ No newline at end of file
+</script>
+<div id="{{ player_id }}_seo" style="display: none;">
+	<ul>
+	{% for annotation in annotations %}
+		<li><span class="title">{{annotation.title}}</span><span class="desc">{{annotation.desc}}</span><span class="tags">{{annotation.tags}}</span><span class="uri">{% if annotation.uri %}<a href="{{annotation.uri}}">{{annotation.uri}}</a>{% endif %}</span></li>
+	{% endfor %}
+	</ul>
+</div>
+<div id="{{ player_id }}_link_list">
+	<ul>
+	{% for annotation in annotations %}
+		<li><span class="title">{{annotation.title}}</span>:&nbsp;<span class="uri">{% if annotation.uri %}<a href="{{annotation.uri}}">{{annotation.uri}}</a>{% endif %}</span></li>
+	{% endfor %}
+	</ul>
+</div>
\ No newline at end of file
--- a/web/franceculture/urls.py	Thu Sep 23 18:39:40 2010 +0200
+++ b/web/franceculture/urls.py	Wed Sep 29 10:10:07 2010 +0200
@@ -23,7 +23,7 @@
     (r'^accounts/', include('registration.backends.simple.urls')),
 
     url(r'^/?$', "franceculture.views.workspace", name="root-view"),
-    url(r'^filterprojects/(?P<filter>\w*)/(?P<is_owner>true|false)/(?P<status>\d)$', "franceculture.views.projectsfilter", ),
-    url(r'^filtercontents/(?P<filter>\w*)/$', "franceculture.views.contentsfilter", ),
+    url(r'^filterprojects/_(?P<filter>[\w\%\_\-\+]*?)/(?P<is_owner>true|false)/(?P<status>\d)$', "franceculture.views.projectsfilter", ),
+    url(r'^filtercontents/_(?P<filter>[\w\%\_\-\+]*?)/$', "franceculture.views.contentsfilter", ),
     (r'^embedpopup/?$', "franceculture.views.popup_embed"),
 )
--- a/web/franceculture/views.py	Thu Sep 23 18:39:40 2010 +0200
+++ b/web/franceculture/views.py	Wed Sep 29 10:10:07 2010 +0200
@@ -5,8 +5,11 @@
 from django.template.loader import render_to_string
 from ldt.ldt_utils.models import Content, Project, Owner
 from ldt.ldt_utils.utils import boolean_convert
-from django.http import HttpResponseServerError
+from django.http import HttpResponseServerError, HttpResponseForbidden
 from django.db.models import Q
+import logging
+import lxml.etree
+import ldt.auth
 
 
 @login_required
@@ -30,7 +33,7 @@
     is_owner = boolean_convert(is_owner)
     status = int(status)
     query = Q()
-    
+            
     if is_owner:
         owner = None
         try:
@@ -42,7 +45,9 @@
     if status > 0:
         query &= Q(state=status)
     
-    if filter and filter != "_":
+    if filter:
+        if len(filter) > 0 and filter[0] == '_':
+            filter = filter[1:]
         query &= Q(title__icontains=filter)
     
     project_list =  Project.objects.filter(query)
@@ -54,8 +59,10 @@
 
 @login_required
 def contentsfilter(request, filter):
-    if filter == "_":
-        filter = ""
+    
+    if filter and len(filter) > 0 and filter[0] == '_':
+            filter = filter[1:]
+    
     if filter:
         content_list = Content.objects.filter(title__icontains=filter)
     else:
@@ -71,11 +78,58 @@
     
     json_url = request.GET.get("json_url")
     player_id = request.GET.get("player_id")
+    ldt_id = request.GET.get("ldt_id")
     
     
-    embed_rendered = escape(render_to_string('franceculture/partial/embed.html', {'json_url':json_url,'player_id':player_id}, context_instance=RequestContext(request)))
+    project = Project.objects.get(ldt_id=ldt_id);
+    
+    if not ldt.auth.checkAccess(request.user, project):
+        return HttpResponseForbidden(_("You can not access this project"))
+
+    
+    doc = lxml.etree.fromstring(project.ldt)
+    
+    annotations = []
+    
+    for contentnode in doc.xpath("/iri/annotations/content"):
+        iri_id = contentnode.get("id")
+        content = Content.objects.get(iri_id=iri_id)
+        
+        for annotationnode in contentnode.xpath("ensemble/decoupage/elements/element"):
+             
+            tags = annotationnode.get('tags')
+            tags_list = []
+            tags_list.extend(annotationnode.xpath("tags/tag/text()"))
+            if tags:
+                tags_list.append(tags)
+            tags = ",".join(tags_list)
+            
+            begin = annotationnode.get('begin')
+            if begin is None:
+                begin = 0
+            else:
+                begin = int(begin)
+
+            uri = None            
+            if content.media_obj.external_publication_url:
+                uri = "%s#%d" % (content.media_obj.external_publication_url, begin)
+
+            annotations.append({
+                'begin': begin,
+                'duration':annotationnode.get('dur'),
+                'title':u"".join(annotationnode.xpath("title/text()")),
+                'desc':u"".join(annotationnode.xpath("abstract/text()")),
+                'tags': tags,
+                'id':u"".join(annotationnode.get('id')),
+                'uri':uri
+            })
+    
+    
+    embed_rendered = escape(render_to_string('franceculture/partial/embed.html', {'json_url':json_url,'player_id':player_id, 'annotations':annotations}, context_instance=RequestContext(request)))
 
     
     return render_to_response("franceculture/embed_popup.html",
                               {'json_url':json_url,'player_id':player_id, 'player_embed_rendered':embed_rendered},
                               context_instance=RequestContext(request)) 
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/ldt/auth/__init__.py	Wed Sep 29 10:10:07 2010 +0200
@@ -0,0 +1,7 @@
+
+def checkAccess(user, obj):
+    check_meth = getattr(obj, 'checkAccess', False)
+    if check_meth:
+        return check_meth(user)
+    else:
+        return False
\ No newline at end of file
--- a/web/ldt/ldt_utils/models.py	Thu Sep 23 18:39:40 2010 +0200
+++ b/web/ldt/ldt_utils/models.py	Wed Sep 29 10:10:07 2010 +0200
@@ -21,9 +21,9 @@
 
 class Media(models.Model):
     external_id = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_id'))
-    external_permalink = models.URLField(max_length=1024, null=True, blank=True, verbose_name=_('content.external_permalink'))
-    external_publication_url = models.URLField(max_length=1024, null=True, blank=True, verbose_name=_('content.external_publication_url'))
-    external_src_url = models.URLField(max_length=1024, null=True, blank=True, verbose_name=_('content.external_publication_url'))
+    external_permalink = models.URLField(max_length=1024, verify_exists=False, null=True, blank=True, verbose_name=_('media.external_permalink'))
+    external_publication_url = models.URLField(max_length=1024, verify_exists=False, null=True, blank=True, verbose_name=_('media.external_publication_url'))
+    external_src_url = models.URLField(max_length=1024, verify_exists=False, null=True, blank=True, verbose_name=_('media.external_src_url'))
     creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('media.creation_date'))
     media_creation_date = models.DateTimeField(null=True, blank=True, verbose_name=_('media.media_creation_date'))
     update_date = models.DateTimeField(auto_now=True, verbose_name=_('media.update_date'))
@@ -45,7 +45,7 @@
                     'mp3': lambda s: "%s:%s" %("mp3",res_src[:-4]),
                     'mp4': lambda s: "%s:%s" %("mp4",res_src[:-4]),
                     'f4v': lambda s: "%s:%s" %("mp4",res_src[:-4]),
-                }.get(extension, lambda s:s)(res_src)
+                }.get(extension, lambda s:s)(res_src.lower())
             return res_src
         
         return locals()
@@ -80,6 +80,9 @@
     content_creation_date = models.DateTimeField(null=True, blank=True, verbose_name=_('content.content_creation_date'))
     tags = tagging.fields.TagField(max_length=2048, null=True, blank=True )
     media_obj = models.ForeignKey('Media', blank=True, null=True )
+    
+    class Meta:
+        ordering = ["title"]
 
     def get_duration(self):
         if self.duration is None:
@@ -246,6 +249,10 @@
     changed_by = models.CharField(_("changed by"), max_length=70)
     state = models.IntegerField(choices=STATE_CHOICES, default=1)
     
+    class Meta:
+        ordering = ["title"]
+
+    
     def __unicode__(self):
         return unicode(self.id) + u": " + unicode(self.ldt_id)
     
@@ -284,6 +291,12 @@
             project.contents.add(content)
         project.save()
         return project
+    
+    def checkAccess(self, user):
+        if (user and user.is_staff) or self.state == 2: 
+            return True
+        else:
+            return False
 
 class Segment(models.Model):
     
--- a/web/ldt/ldt_utils/views.py	Thu Sep 23 18:39:40 2010 +0200
+++ b/web/ldt/ldt_utils/views.py	Wed Sep 29 10:10:07 2010 +0200
@@ -1,5 +1,5 @@
 import django.core.urlresolvers
-from django.http import HttpResponse, HttpResponseRedirect
+from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
 from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
 from django.template import RequestContext
 from django.core.urlresolvers import reverse
@@ -28,6 +28,9 @@
 import urllib2
 from urllib2 import urlparse
 from jogging import logging
+import ldt.utils.path
+import ldt.auth as ldt_auth
+from django.utils.translation import ugettext as _
 
 
     
@@ -203,7 +206,7 @@
 def project_json_id(request, id):
     
     project = get_object_or_404(Project,ldt_id=id)
-
+        
     return project_json(request, project)
 
 
@@ -216,7 +219,10 @@
 
 
 def project_json(request, project):
-
+    
+    if not ldt_auth.checkAccess(request.user, project):
+        return HttpResponseForbidden(_("You can not access this project"))
+        
     mimetype = request.REQUEST.get("mimetype")
     if mimetype is None:
         mimetype = "application/json; charset=utf-8"
@@ -401,6 +407,7 @@
                 media = None
             elif media_input_type == "link":
                 media = content_form.cleaned_data["media_obj"]
+                created = False
             elif media_input_type == "url" or  media_input_type == "upload" or  media_input_type == "create":                
                 # copy file
                 #complet src
@@ -419,12 +426,18 @@
                             source_file = request.FILES['media-media_file']
                             source_filename = source_file.name
                             
-    
+                        source_filename = ldt.utils.path.sanitize_filename(source_filename)
                         destination_filepath = os.path.join(settings.STREAM_PATH, source_filename)
                         base_source_filename = source_filename
+                        extension = base_source_filename.split(".")[-1]
+                        if extension == base_source_filename:
+                            extension = ""
+                            base_basename_filename = base_source_filename
+                        else:
+                            base_basename_filename  =  base_source_filename[:-1 *(len(extension)+1)]
                         i = 0
                         while os.path.exists(destination_filepath):
-                            base_source_filename = source_filename+"(%d)" % (i)
+                            base_source_filename = "%s.%d.%s" % (base_basename_filename,i,extension)
                             destination_filepath = os.path.join(settings.STREAM_PATH, base_source_filename)
                             i += 1
                             
@@ -455,10 +468,13 @@
                     if not cleaned_data['videopath']:
                         cleaned_data['videopath'] = settings.STREAM_URL
                     media, created = Media.objects.get_or_create(src=cleaned_data['src'], defaults=cleaned_data)
-                    if not created:                        
-                        for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title'):
-                            setattr(media, attribute, cleaned_data.get(attribute))
-                    media.save()
+                else:
+                    media = None
+
+            if media and not created:                        
+                for attribute in ('external_id', 'external_permalink', 'external_publication_url', 'external_src_url', 'media_creation_date', 'videopath', 'duration', 'description', 'title'):
+                    setattr(media, attribute, cleaned_data.get(attribute))
+                media.save()
                     #except Exception as inst:
 #                        logging.debug("write_content_base : POST error when saving media:" + str(inst))
  #                       form_status = "error"
--- a/web/ldt/locale/en/LC_MESSAGES/django.po	Thu Sep 23 18:39:40 2010 +0200
+++ b/web/ldt/locale/en/LC_MESSAGES/django.po	Wed Sep 29 10:10:07 2010 +0200
@@ -84,7 +84,7 @@
 #: ldt_utils/models.py:31
 #, fuzzy
 msgid "media.duration"
-msgstr "duration"
+msgstr "duration (ms)"
 
 #: ldt_utils/models.py:32
 msgid "media.creator"
@@ -135,7 +135,7 @@
 
 #: ldt_utils/models.py:58
 msgid "content.duration"
-msgstr "duration"
+msgstr "duration (ms)"
 
 #: ldt_utils/models.py:209
 msgid "created by"
--- a/web/ldt/locale/fr/LC_MESSAGES/django.po	Thu Sep 23 18:39:40 2010 +0200
+++ b/web/ldt/locale/fr/LC_MESSAGES/django.po	Wed Sep 29 10:10:07 2010 +0200
@@ -82,7 +82,7 @@
 
 #: ldt_utils/models.py:31
 msgid "media.duration"
-msgstr "Durée du contenu"
+msgstr "Durée du contenu (ms)"
 
 #: ldt_utils/models.py:32
 msgid "media.creator"
@@ -132,7 +132,7 @@
 
 #: ldt_utils/models.py:58
 msgid "content.duration"
-msgstr "Durée"
+msgstr "Durée (ms)"
 
 #: ldt_utils/models.py:209
 msgid "created by"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/ldt/utils/path.py	Wed Sep 29 10:10:07 2010 +0200
@@ -0,0 +1,14 @@
+"""
+Some small file related utilities
+"""
+
+import unicodedata
+import string
+
+validFilenameChars = "-_.() %s%s" % (string.ascii_letters, string.digits)
+
+
+def sanitize_filename(filename):
+    cleanedFilename = unicodedata.normalize('NFKD', filename).encode('ASCII', 'ignore').lower()
+    return ''.join(c for c in cleanedFilename if c in validFilenameChars).replace(' ','_')
+    
\ No newline at end of file
--- a/web/static/js/projectscontents.js	Thu Sep 23 18:39:40 2010 +0200
+++ b/web/static/js/projectscontents.js	Wed Sep 29 10:10:07 2010 +0200
@@ -68,6 +68,7 @@
 		var link = $(e.target);
 		var json_url = link.attr("href");
 		var player_id = link.attr("id");
+		var ldt_id = player_id.substring(15);
 		/*$.nyroModalSettings({
 		 	ajax: { data: ({ json_url:json_url, player_id:player_id }) }
 		  	});*/
@@ -79,7 +80,7 @@
                width:750,
                bgColor: 'rgb(239, 239, 239)',
                padding: 5,
-		       url: embed_url+'?json_url='+escape(json_url)+'&player_id='+escape(player_id),
+		       url: embed_url+'?json_url='+escape(json_url)+'&player_id='+escape(player_id)+'&ldt_id='+escape(ldt_id),
 		   });
 		   return false;
 	});
@@ -133,11 +134,8 @@
 	target.attr('timer',setTimeout(function() {
 		target.next(".searchajaxloader").show();
 		target.nextAll(".searchclear").hide();
-		var realVal = target.realVal();
-		if(realVal.length == 0) {
-			realVal = "_";
-		}
-		url = url.replace('__FILTER__',escape(realVal));
+		var filterVal = "_" + escape(target.realVal());
+		url = url.replace('__FILTER__',filterVal);
 		$(container_selector).load(url, null, function() {
 			target.next(".searchajaxloader").hide();
 			if(target.realVal().length > 0) {
Binary file web/static/swf/ldt/LignesDeTempsFlex.swf has changed