Переглянути джерело

[core] Secure shared tag edition

Romain Rigaux 11 роки тому
батько
коміт
618672d

+ 1 - 1
desktop/core/src/desktop/api_tests.py

@@ -135,7 +135,7 @@ class TestDocModelTags():
     response = self.client.post("/desktop/api/doc/update_tags", {'data': json.dumps({'doc_id': doc.id, 'tag_ids': [tag1_id, tag2_id]})})
     content = json.loads(response.content)
 
-    assert_equal(0, content['status'])
+    assert_equal(0, content['status'], content)
     assert_equal([
         {"id": default_tag.id, "name": "default"},
         {"id": tag1_id, "name": "update_tags_1"},

+ 2 - 2
desktop/core/src/desktop/auth/backend.py

@@ -239,7 +239,7 @@ class DemoBackend(django.contrib.auth.backends.ModelBackend):
     user = super(DemoBackend, self).authenticate(username, password)
 
     if not user:
-      username = self._randome_name()
+      username = self._random_name()
 
       user = find_or_create_user(username, None)
 
@@ -258,7 +258,7 @@ class DemoBackend(django.contrib.auth.backends.ModelBackend):
     user = rewrite_user(user)
     return user
 
-  def _randome_name(self):
+  def _random_name(self):
     import string
     import random
 

+ 4 - 13
desktop/core/src/desktop/models.py

@@ -57,18 +57,7 @@ class Settings(models.Model):
 class DocumentTagManager(models.Manager):
 
   def get_tags(self, user):
-    # For now, the only shared tag is from 'sample' user and is named 'example'
-    # Tag permissions will come later.
-    # Share Tag from shared document will come later.
-    tags = self
-
-    try:
-      sample_user = auth_models.User.objects.get(username=SAMPLE_USERNAME)
-      tags = tags.filter(Q(owner=user) | Q(owner=sample_user, tag=DocumentTag.EXAMPLE))
-    except:
-      tags = tags.filter(owner=user)
-
-    return tags.distinct()
+    return self.filter(owner=user).distinct()
 
   def create_tag(self, owner, tag_name):
     if tag_name in DocumentTag.RESERVED:
@@ -120,6 +109,7 @@ class DocumentTagManager(models.Manager):
       raise Exception(_("Can't remove %s: it is a reserved tag.") % tag)
 
     doc = Document.objects.get_doc(doc_id, owner=owner)
+    doc.can_write_or_exception(owner)
     doc.remove_tag(tag)
 
   def delete_tag(self, tag_id, owner):
@@ -135,8 +125,8 @@ class DocumentTagManager(models.Manager):
       doc.add_tag(default_tag)
 
   def update_tags(self, owner, doc_id, tag_ids):
-    # TODO secu
     doc = Document.objects.get_doc(doc_id, owner)
+    doc.can_write_or_exception(owner)
 
     for tag in doc.tags.all():
       if tag.tag not in DocumentTag.RESERVED:
@@ -175,6 +165,7 @@ class DocumentTag(models.Model):
 class DocumentManager(models.Manager):
 
   def documents(self, user):
+    # Check for READ perm only, not write
     return Document.objects.filter(Q(owner=user) | Q(documentpermission__users=user) | Q(documentpermission__groups__in=user.groups.all())).distinct()
 
   def get_docs(self, user, model_class=None, extra=None):

+ 25 - 17
desktop/core/src/desktop/templates/home.mako

@@ -129,7 +129,7 @@ ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
             % for tag in tags:
               % if tag.tag not in ('trash', 'history') and tag.is_mine:
               <% has_tag = True %>
-              <li class="toggle-tag" data-tag="${ tag.tag }"><a href="javascript:void(0)"><i class="fa fa-tag"></i> ${ tag.tag }<span class="tag-counter badge pull-right">0</span></a></li>
+              <li class="toggle-tag" data-tag="${ tag.tag }" data-ismine="true"><a href="javascript:void(0)"><i class="fa fa-tag"></i> ${ tag.tag }<span class="tag-counter badge pull-right">0</span></a></li>
               % endif
             % endfor
           % endif
@@ -144,7 +144,7 @@ ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
             % for tag in tags:
               % if tag.tag not in ('trash', 'history') and not tag.is_mine:
               <% has_tag = True %>
-              <li class="toggle-tag" data-tag="${ tag.tag }" rel="tooltip" title="${_('Shared by %s' % tag.owner)}" data-placement="right"><a href="javascript:void(0)"><i class="fa fa-tag"></i> ${ tag.tag }<span class="tag-counter badge pull-right">0</span></a></li>
+              <li class="toggle-tag" data-tag="${ tag.tag }" data-ismine="false" rel="tooltip" title="${_('Shared by %s' % tag.owner)}" data-placement="right"><a href="javascript:void(0)"><i class="fa fa-tag"></i> ${ tag.tag }<span class="tag-counter badge pull-right">0</span></a></li>
               % endif
             % endfor
           % endif
@@ -355,17 +355,17 @@ $(document).ready(function () {
 
   $(".view-trash").on("click", function () {
     $(".viewHistory").removeClass("active");
-    toggleSpecificSection($(this), "trash");
+    toggleSpecificSection($(this), "trash", true);
   });
 
   $(".viewHistory").on("click", function () {
     $(".view-trash").removeClass("active");
-    toggleSpecificSection($(this), "history");
+    toggleSpecificSection($(this), "history", true);
   });
 
-  function toggleSpecificSection(section, filter){
+  function toggleSpecificSection(section, filter, isMine){
     section.siblings().removeClass("active");
-    populateTable(filter);
+    populateTable(filter, isMine);
     section.addClass("active");
   }
 
@@ -374,7 +374,7 @@ $(document).ready(function () {
     _this.siblings().removeClass("active");
     _this.blur();
     _this.addClass("active");
-    populateTable($(".toggle-tag.active").data("tag"));
+    populateTable($(".toggle-tag.active").data("tag"), $(".toggle-tag.active").data("ismine"));
   });
 
   function updateTagCounters(){
@@ -440,6 +440,7 @@ $(document).ready(function () {
       if (!JSON_TAGS[i].isTrash && !JSON_TAGS[i].isHistory) {
         var _t = $("<li>").addClass("toggle-tag");
         _t.attr("data-tag", JSON_TAGS[i].name);
+        _t.attr("data-isMine", JSON_TAGS[i].is_mine);
         _t.html('<a href="javascript:void(0)"><i class="fa fa-tag"></i> ' + JSON_TAGS[i].name + '<span class="tag-counter badge pull-right">0</span></a>');
         if (JSON_TAGS[i].isMine){
           _t.insertAfter(".tag-mine-header");
@@ -630,12 +631,12 @@ $(document).ready(function () {
     if (_doc != null) {
       if (_doc.perms != null && _doc.perms.read != null){
         if (_doc.perms.read.users != null){
-          for (var i=0; i<_doc.perms.read.users.length;i++){
+          for (var i=0; i < _doc.perms.read.users.length; i++){
             addToShareList(map[_doc.perms.read.users[i].username]);
           }
         }
         if (_doc.perms.read.groups != null){
-          for (var i=0; i<_doc.perms.read.groups.length;i++){
+          for (var i=0; i < _doc.perms.read.groups.length; i++){
             addToShareList(map[_doc.perms.read.groups[i].name]);
           }
         }
@@ -714,9 +715,9 @@ $(document).ready(function () {
     }
 
     $.post("/desktop/api/doc/update_permissions", {
-      doc_id: $("#documentShareModal").data("document-id"),
-      data: JSON.stringify(_postPerms)
-    }, function (response) {
+        doc_id: $("#documentShareModal").data("document-id"),
+        data: JSON.stringify(_postPerms)
+      }, function (response) {
       $("#documentShareModal").modal("hide");
       if (response!=null){
         if (response.status == 0){
@@ -755,15 +756,21 @@ function isInTags(doc, tag) {
   return _inTags;
 }
 
-function populateTable(tag) {
+function populateTable(tag, isMine) {
   if (tag == null || tag == "") {
-    tag = "default"; //force default tag in case of empty
+    tag = "default"; // force default tag in case of empty
+  }
+  if (isMine === undefined ) {
+    isMine = true; // default owner is current user
   }
+
   $.totalStorage("hueHomeTags", tag);
   documentsTable.fnClearTable();
   documentsTable.fnDraw();
+
   $(JSON_DOCS).each(function (cnt, doc) {
-    if (((tag == ("trash") || tag == "history") || (tag != "trash" && tag != "history" && !isInTags(doc, "trash") && !isInTags(doc, "history"))) && isInTags(doc, tag)) {
+    // Need to simplify this
+    if (isMine == doc.isMine && ((tag == ("trash") || tag == "history") || (tag != "trash" && tag != "history" && !isInTags(doc, "trash") && !isInTags(doc, "history"))) && isInTags(doc, tag)) {
       addRow(doc);
     }
   });
@@ -781,10 +788,11 @@ function addRow(doc) {
       '<img src="' + doc.icon + '" width="80%"/>',
       '<a href="' + doc.url + '" data-row-selector="true">' + doc.name + '</a>',
       emptyStringIfNull(doc.description),
-      '<div class="documentTags" data-document-id="' + doc.id + '">' + _tags + '</div>',
+      doc.isMine ? '<div class="documentTags" data-document-id="' + doc.id + '">' + _tags + '</div>' : '<div class="documentTags">' + _tags + '</div>',
       emptyStringIfNull(doc.owner),
       emptyStringIfNull(doc.lastModified),
-      '<a href="#" class="shareDocument" data-document-id="' + doc.id + '" rel="tooltip" title="${_('Share')} ' + doc.name + '" data-placement="left" style="padding-left:10px"><i class="fa fa-share-square-o"></i></a>',
+      doc.isMine ? '<a href="#" class="shareDocument" data-document-id="' + doc.id + '" rel="tooltip" title="${_('Share')} ' +
+        doc.name + '" data-placement="left" style="padding-left:10px"><i class="fa fa-share-square-o"></i></a>' : '<i class="fa fa-user"></i>',
     ], false);
     $("td", documentsTable.fnGetNodes(_addedRow[0]))[5].setAttribute("data-sort-value", doc.lastModifiedInMillis); // a bit of black magic.
   }

+ 2 - 2
desktop/core/src/desktop/views.py

@@ -40,7 +40,7 @@ from desktop.lib.django_util import login_notrequired, render_json, render
 from desktop.lib.i18n import smart_str
 from desktop.lib.paths import get_desktop_root
 from desktop.log.access import access_log_level, access_warn
-from desktop.models import UserPreferences, Settings, Document, DocumentTag
+from desktop.models import UserPreferences, Settings, Document
 from desktop import appmanager
 import desktop.conf
 import desktop.log.log_buffer
@@ -56,7 +56,7 @@ def home(request):
       Document.objects.get_docs(request.user).order_by('-last_modified').filter(tags__tag__in=['history'])[:100]
   )
   docs = list(docs)
-  tags = DocumentTag.objects.get_tags(user=request.user)
+  tags = list(set([tag for doc in docs for tag in doc.tags.all()])) # List of all personal and share tags
 
   apps = appmanager.get_apps_dict(request.user)