Ver código fonte

add right management tab and related stuff: api, model

Damien Accorsi 11 anos atrás
pai
commit
63211a4482

+ 54 - 0
pboard/pboard/controllers/api.py Ver arquivo

@@ -23,6 +23,7 @@ from tg.i18n import ugettext as _, lazy_ugettext as l_
23 23
 from pboard.lib.base import BaseController
24 24
 from pboard.lib   import dbapi as pld
25 25
 from pboard.model import data as pmd
26
+from pboard.model import auth as pma
26 27
 from pboard import model as pm
27 28
 from pboard.lib.auth import can_read, can_write
28 29
 
@@ -303,3 +304,56 @@ class PODApiController(BaseController):
303 304
       # - if root node, then exception
304 305
       # - this redirect is done in order to be adapted to comment share status toggle
305 306
       redirect(lurl('/document/%s#tab-comments'%(loNode._oParent.node_id)))
307
+
308
+    @expose()
309
+    @require(can_read())
310
+    def set_access_management(self, node_id, is_shared='off', read=[0], write=[0]):
311
+
312
+      llReadAccessGroupIds = [int(liGroupId) for liGroupId in read]
313
+      llWriteAccessGroupIds = [int(liGroupId) for liGroupId in write]
314
+
315
+      # HACK - D.A. - 2015-058-20
316
+      # the 0 values are added in order to get a read and write parameters as list even if only one value is inside
317
+      # (the default behavior of TG2 is to convert it to a string value if only one value is sent
318
+      #
319
+      llReadAccessGroupIds.remove(0) # remove useless value
320
+      llWriteAccessGroupIds.remove(0) # remove useless value
321
+
322
+      loCurrentUser   = pld.PODStaticController.getCurrentUser()
323
+      loApiController = pld.PODUserFilteredApiController(loCurrentUser.user_id)
324
+
325
+      loNode = loApiController.getNode(node_id)
326
+      # loNode._lRights = list()
327
+
328
+      # SHARE IS OFF, so deactivate the document share (and do not change "shared-with" group configuration
329
+      if is_shared=='off':
330
+        loNode.is_shared = False
331
+        pm.DBSession.flush()
332
+        redirect(lurl('/document/%s#tab-accessmanagement'%(loNode.node_id)))
333
+
334
+      # SHARE IS ON, so remove all current shares and set the new ones
335
+      loNode.is_shared = True
336
+
337
+      for loRight in loNode._lRights:
338
+        pm.DBSession.delete(loRight)
339
+      pm.DBSession.flush()
340
+
341
+      ldNewRights = dict()
342
+      for liGroupId in llReadAccessGroupIds:
343
+        ldNewRights[liGroupId] = pma.Rights.READ_ACCESS
344
+
345
+      for liGroupId in llWriteAccessGroupIds:
346
+        liOldValue = 0
347
+        if liGroupId in ldNewRights:
348
+          liOldValue = ldNewRights[liGroupId]
349
+        ldNewRights[liGroupId] = liOldValue + pma.Rights.WRITE_ACCESS
350
+
351
+      for liGroupId, liRightLevel in ldNewRights.items():
352
+        loNewRight = loApiController.createRight()
353
+        loNewRight.group_id = liGroupId
354
+        loNewRight.node_id = node_id
355
+        loNewRight.rights = liRightLevel
356
+        loNode._lRights.append(loNewRight)
357
+
358
+      redirect(lurl('/document/%s#tab-accessmanagement'%(loNode.node_id)))
359
+

+ 4 - 0
pboard/pboard/lib/dbapi.py Ver arquivo

@@ -225,3 +225,7 @@ class PODUserFilteredApiController(object):
225 225
     # INFO - D.A. - 2013-11-07 - should be save as getNode should return only accessible nodes
226 226
     DBSession.delete(loNode)
227 227
     return
228
+
229
+  def createRight(self):
230
+    loRight = pbma.Rights()
231
+    return loRight

+ 27 - 5
pboard/pboard/model/auth.py Ver arquivo

@@ -11,6 +11,7 @@ though.
11 11
 import os
12 12
 from datetime import datetime
13 13
 from hashlib import sha256
14
+from sqlalchemy.sql.functions import session_user
14 15
 
15 16
 __all__ = ['User', 'Group', 'Permission']
16 17
 
@@ -42,13 +43,14 @@ user_group_table = Table('pod_user_group', metadata,
42 43
 
43 44
 
44 45
 class Rights(DeclarativeBase):
46
+
45 47
     READ_ACCESS = 1
46 48
     WRITE_ACCESS = 2
47 49
 
48 50
     __tablename__ = 'pod_group_node'
49 51
 
50
-    group_id = Column(Integer, ForeignKey('pod_group.group_id'), autoincrement=True, primary_key=True)
51
-    node_id = Column(Integer, ForeignKey('pod_nodes.node_id'), autoincrement=True, primary_key=True)
52
+    group_id = Column(Integer, ForeignKey('pod_group.group_id'), primary_key=True)
53
+    node_id = Column(Integer, ForeignKey('pod_nodes.node_id'), primary_key=True)
52 54
     rights = Column(Integer)
53 55
 
54 56
     def hasReadAccess(self):
@@ -57,6 +59,8 @@ class Rights(DeclarativeBase):
57 59
     def hasWriteAccess(self):
58 60
         return self.rights & Rights.WRITE_ACCESS
59 61
 
62
+
63
+
60 64
 class Group(DeclarativeBase):
61 65
 
62 66
     __tablename__ = 'pod_group'
@@ -68,8 +72,9 @@ class Group(DeclarativeBase):
68 72
     personnal_group = Column(Boolean)
69 73
     users = relation('User', secondary=user_group_table, backref='groups')
70 74
 
71
-    users = relation('User', secondary=user_group_table, backref='groups')
72
-    _lRights = relationship('Rights', remote_side=[Rights.group_id], backref='_oGroup')
75
+    _lRights = relationship('Rights', backref='_oGroup', cascade = "all, delete-orphan")
76
+
77
+
73 78
 
74 79
     def __repr__(self):
75 80
         return '<Group: name=%s>' % repr(self.group_name)
@@ -84,7 +89,12 @@ class Group(DeclarativeBase):
84 89
 
85 90
     def getDisplayName(self) -> str:
86 91
         if self.group_id<0:
87
-            return self.users[0].display_name
92
+            # FIXME - D.A. - 2014-05-19 - MAKE THIS CODE CLEANER,
93
+            try:
94
+                return self.users[0].getDisplayName()
95
+            except:
96
+                print('ERROR GROUP =>', self.group_id)
97
+
88 98
 
89 99
         return self.display_name
90 100
 
@@ -92,6 +102,13 @@ class Group(DeclarativeBase):
92 102
     def rights(self):
93 103
         return self._lRights
94 104
 
105
+    def hasSomeAccess(self, poNode):
106
+        for loRight in self._lRights:
107
+            if loRight.node_id == poNode.node_id and loRight.rights>0:
108
+                return True
109
+        return False
110
+
111
+
95 112
 
96 113
 class User(DeclarativeBase):
97 114
     """
@@ -181,6 +198,11 @@ class User(DeclarativeBase):
181 198
         hash.update((password + self.password[:64]).encode('utf-8'))
182 199
         return self.password[64:] == hash.hexdigest()
183 200
 
201
+    def getDisplayName(self):
202
+        if self.display_name!=None and self.display_name!='':
203
+            return self.display_name
204
+        else:
205
+            return self.email_address
184 206
 
185 207
 
186 208
 class Permission(DeclarativeBase):

+ 8 - 1
pboard/pboard/model/data.py Ver arquivo

@@ -189,7 +189,7 @@ class PBNode(DeclarativeBase):
189 189
   data_file_mime_type = Column(Unicode(255),  unique=False, nullable=False, default='')
190 190
   data_file_content   = sqlao.deferred(Column(LargeBinary(), unique=False, nullable=False, default=None))
191 191
 
192
-  rights = relation('Rights')
192
+  _lRights = relationship('Rights', backref='_oNode', cascade = "all, delete-orphan")
193 193
 
194 194
   _oParent = relationship('PBNode', remote_side=[node_id], backref='_lAllChildren')
195 195
   _oOwner = relationship('User', remote_side=[pma.User.user_id], backref='_lAllNodes')
@@ -217,6 +217,13 @@ class PBNode(DeclarativeBase):
217 217
   def getChildNb(self):
218 218
     return self.getChildNbOfType([PBNodeType.Data])
219 219
 
220
+  def getGroupsWithSomeAccess(self):
221
+    llRights = []
222
+    for loRight in self._lRights:
223
+      if loRight.rights>0:
224
+        llRights.append(loRight)
225
+    return llRights
226
+
220 227
   def getChildren(self, pbIncludeDeleted=False):
221 228
     """return all children nodes of type 'data' or 'node' or 'folder'"""
222 229
     # return self.getChildrenOfType([PBNodeType.Node, PBNodeType.Folder, PBNodeType.Data])

+ 130 - 76
pboard/pboard/templates/document-widgets-tabs.mak Ver arquivo

@@ -3,7 +3,7 @@
3 3
 <%namespace name="DOC" file="pboard.templates.document-widgets"/>
4 4
 
5 5
 <%def name="HistoryTabContent(poNode)">
6
-  <h4>History</h4>
6
+  <h4>${_('Revisions')}</h4>
7 7
   <ul>
8 8
   % for version in poNode.getHistory():
9 9
   	<li><a href="${tg.url('/document/%i/%i'%(version.node_id, version.version_id))}">${version.created_at.strftime("%a %x %X")}</a></li>
@@ -18,26 +18,14 @@
18 18
   ##
19 19
   <h4>${_('Share options')}</h4> 
20 20
   <p>
21
-    This document is
22 21
     % if poNode.is_shared==False:
23
-      <span class="label label-info">
24
-        <i class="fa fa-user"></i>
25
-        ${_('private')}
26
-      </span>
22
+      <span class="pod-grey">${_('This document is not shared')}</span>
27 23
     % else:
28
-      <span class="label label-info">
29
-        <i class="fa fa-group"></i>
30
-        ${_('collaborative')}
31
-      </span>
24
+      <span class="">${_('This document is shared.')}</span>
32 25
     % endif
33 26
   </p>
34 27
   <p>
35
-    % if poNode.is_shared==True or poNode.is_shared==False:
36
-      ${_('People working on it are:')}
37
-######
38
-##
39
-## FIXME - SHOW LIST OF GROUPS ALLOWED TO WORK ON THE DOCUMENT
40
-##
28
+    % if poNode.is_shared==True:
41 29
     <table class="table table-striped table-hover table-condensed">
42 30
       <thead>
43 31
         <tr>
@@ -46,44 +34,48 @@
46 34
         </tr>
47 35
       </thead>
48 36
       % for loCurrentGroup in real_groups:
49
-        <tr>
50
-          <td>${loCurrentGroup.getDisplayName()}</td>
51
-          <td>
52
-            % for loRight in loCurrentGroup.rights:
53
-              % if loRight.node_id==poNode.node_id:
54
-                % if loRight.hasReadAccess():
55
-                  <span class="label label-success">R</span>
56
-                % endif
57
-                % if loRight.hasWriteAccess():
58
-                  <span class="label label-warning">W</span>
37
+        % if loCurrentGroup.hasSomeAccess(poNode):
38
+          <tr>
39
+            <td>${loCurrentGroup.getDisplayName()}</td>
40
+            <td>
41
+              % for loRight in loCurrentGroup.rights:
42
+                % if loRight.node_id==poNode.node_id:
43
+                  % if loRight.hasReadAccess():
44
+                    <span class="label label-success">R</span>
45
+                  % endif
46
+                  % if loRight.hasWriteAccess():
47
+                    <span class="label label-warning">W</span>
48
+                  % endif
59 49
                 % endif
60
-              % endif
61
-            % endfor
62
-          </td>
63
-        </tr>
50
+              % endfor
51
+            </td>
52
+          </tr>
53
+        % endif
64 54
       % endfor
65 55
       <thead>
66 56
         <tr>
67
-          <th><i class="fa fa-user"></i> ${_('Users')}</th>
57
+          <th><i class="fa fa-user"></i> ${_('Individual users')}</th>
68 58
           <th></th>
69 59
         </tr>
70 60
       </thead>
71 61
       % for loCurrentGroup in user_specific_groups:
72
-        <tr>
73
-          <td>${loCurrentGroup.getDisplayName()}</td>
74
-          <td>
75
-            % for loRight in loCurrentGroup.rights:
76
-              % if loRight.node_id==poNode.node_id:
77
-                % if loRight.hasReadAccess():
78
-                  <span class="label label-success">R</span>
79
-                % endif
80
-                % if loRight.hasWriteAccess():
81
-                  <span class="label label-warning">W</span>
62
+        % if loCurrentGroup.hasSomeAccess(poNode):
63
+          <tr>
64
+            <td>${loCurrentGroup.getDisplayName()}</td>
65
+            <td>
66
+              % for loRight in loCurrentGroup.rights:
67
+                % if loRight.node_id==poNode.node_id:
68
+                  % if loRight.hasReadAccess():
69
+                    <span class="label label-success">R</span>
70
+                  % endif
71
+                  % if loRight.hasWriteAccess():
72
+                    <span class="label label-warning">W</span>
73
+                  % endif
82 74
                 % endif
83
-              % endif
84
-            % endfor
85
-          </td>
86
-        </tr>
75
+              % endfor
76
+            </td>
77
+          </tr>
78
+        % endif
87 79
       % endfor
88 80
     </table>
89 81
     
@@ -123,58 +115,101 @@
123 115
     </div>
124 116
     <div class="modal-body">
125 117
 
126
-      <form id='document-share-form' method="GET" action="${tg.url('/api/set_access_management?node_id=%d'%poNode.node_id)}">
118
+      <form id='document-share-form' method="GET" action="${tg.url('/api/set_access_management')}">
119
+        <input type="hidden" name="node_id" value="${poNode.node_id}" />
120
+        <input type="hidden" name="read" value="0" />
121
+        <input type="hidden" name="write" value="0" />
127 122
         <fieldset>
128 123
           <label class="checkbox">
129 124
             <input name="is_shared" type="checkbox" id="document-share-selector" ${('', 'checked')[poNode.is_shared]}/>
130
-            ${_('Share document with collaborators.')} <i class="fa fa-group"></i>
125
+            ${_('Share document with collaborators.')}
131 126
           </label>
132 127
           <div id="document-share-people-selector">
133
-            <p>
134
-              ${_('Select read and write access for each group or people...')}</p>
128
+            <p>${_('Select read and write access for each group or people...')}</p>
135 129
             <script>
136
-            function updateRights(psUserId) {
137
-              var ACCESS_NONE = '';
138
-              var ACCESS_READ = 'R';
139
-              var ACCESS_WRITE = 'RW';
130
+            function updateRights(psUserId, piNewValue = -1) {
131
+              var ACCESS_UNDEFINED = -1;
132
+              var ACCESS_NONE = 0;
133
+              var ACCESS_READ = 1;
134
+              var ACCESS_WRITE = 2;
140 135
               
141 136
               var nodeIdForSelectedUser = 'user-'+psUserId+'-value';
142
-              var widget = $('#'+nodeIdForSelectedUser);
143
-              var oldValue = widget.val();
144
-              var newValue = '';
145
-              if(oldValue==ACCESS_NONE) {
146
-                newValue = ACCESS_READ;
147
-                newHtml = '<span class="label label-success">R</span>';
148
-              } else if(oldValue==ACCESS_READ) {
149
-                newValue = ACCESS_WRITE;
150
-                newHtml = '<span class="label label-success">R</span> <span class="label label-warning">W</span>';
151
-              } else if (oldValue==ACCESS_WRITE) {
152
-                newValue = ACCESS_NONE;
137
+              var widgetRead = $('#'+nodeIdForSelectedUser+'-read');
138
+              var widgetWrite = $('#'+nodeIdForSelectedUser+'-write');
139
+              var oldReadValue = widgetRead.val()
140
+              var oldWriteValue = widgetWrite.val();
141
+              
142
+              if(oldReadValue=='' && oldWriteValue=='' && piNewValue==ACCESS_UNDEFINED || piNewValue==ACCESS_READ) {
143
+## SET READ ACCESS
144
+                widgetRead.val(psUserId)
145
+                widgetWrite.val('')
146
+                newHtml = '<span class="label label-success" title="${'Allow to read the item'}">R</span>';
147
+              } else if(oldReadValue==psUserId && oldWriteValue=='' && piNewValue==ACCESS_UNDEFINED || piNewValue==ACCESS_READ+ACCESS_WRITE) {
148
+## SET READ + WRITE ACCESS
149
+                widgetRead.val(psUserId)
150
+                widgetWrite.val(psUserId)
151
+                newHtml = '<span class="label label-success" title="${'Allow to read the item'}">R</span> <span class="label label-warning" title="${'Allow to modify the item'}">W</span>';
152
+              } else if (oldReadValue==psUserId && oldWriteValue==psUserId && piNewValue==ACCESS_UNDEFINED || piNewValue==ACCESS_NONE) {
153
+## SET NO ACCESS
154
+                widgetRead.val('')
155
+                widgetWrite.val('')
153 156
                 newHtml = '';
154 157
               } else {
155
-                newValue = ACCESS_READ;
156
-                newHtml = '<span class="label label-success">R</span>';
158
+## SET READ ACCESS (default)
159
+                widgetRead.val(psUserId)
160
+                widgetWrite.val('')
161
+                newHtml = '<span class="label label-success" title="${'Allow to read the item'}">R</span>';
157 162
               }
158 163
               
159
-              widget.val(newValue);
160 164
               visibleid = 'user-'+psUserId+'-rights';
161 165
               $("#"+visibleid).html(newHtml);
162 166
             }
163 167
             </script>
164 168
             
165 169
             <table class="table table-striped table-hover table-condensed">
170
+    ######
171
+    ##
172
+    ## REAL GROUPS LISTING HERE
173
+    ##
166 174
               <thead>
167 175
                 <tr>
168
-                  <th></th>
176
+                  <th><i class="fa fa-group"></i></th>
169 177
                   <th>${_('Group')}</th>
170 178
                   <th>${_('Access')}</th>
171 179
                 </tr>
172 180
               </thead>
181
+              % for loCurrentGroup in real_groups:
182
+              <tr id='user-${loCurrentGroup.group_id}-rights-row'>
183
+                <td>
184
+                  <a
185
+                    class="btn btn-mini"
186
+                    onclick="updateRights(${loCurrentGroup.group_id})"
187
+                  >
188
+                    <i class="fa fa-key"></i>
189
+                  </a>
190
+                </td>
191
+                <td class='pod-highlightable-access-management-cell'>
192
+                  ${loCurrentGroup.getDisplayName()}
193
+                  <input type="hidden" id="user-${loCurrentGroup.group_id}-value-read" name="read" value="" />
194
+                  <input type="hidden" id="user-${loCurrentGroup.group_id}-value-write" name="write" value="" />
195
+                </td>
196
+                <td id="user-${loCurrentGroup.group_id}-rights" class="pod-right-cell"></td>
197
+              </tr>
198
+              % endfor
199
+              
173 200
     ######
174 201
     ##
175
-    ## FIXME - SET A DYNAMIC SELECT LIST HERE
202
+    ## INDIVIDUAL USERS LISTING HERE
176 203
     ##
204
+              <thead>
205
+                <tr>
206
+                  <th><i class="fa fa-user"></i></th>
207
+                  <th>${_('Individual Users')}</th>
208
+                  <th>${_('Access')}</th>
209
+                </tr>
210
+              </thead>
177 211
               % for loCurrentGroup in user_specific_groups:
212
+              
178 213
               <tr id='user-${loCurrentGroup.group_id}-rights-row'>
179 214
                 <td>
180 215
                   <a
@@ -186,12 +221,8 @@
186 221
                 </td>
187 222
                 <td class='pod-highlightable-access-management-cell'>
188 223
                   ${loCurrentGroup.getDisplayName()}
189
-                  <input
190
-                    type="hidden"
191
-                    id="user-${loCurrentGroup.group_id}-value"
192
-                    name="user[${loCurrentGroup.group_id}]"
193
-                    value=""
194
-                  />
224
+                  <input type="hidden" id="user-${loCurrentGroup.group_id}-value-read" name="read" value="" />
225
+                  <input type="hidden" id="user-${loCurrentGroup.group_id}-value-write" name="write" value="" />
195 226
                 </td>
196 227
                 <td id="user-${loCurrentGroup.group_id}-rights" class="pod-right-cell"></td>
197 228
               </tr>
@@ -298,6 +329,8 @@
298 329
 
299 330
       // Submit access-management modal dialog form
300 331
       $('#document-share-form-submit-button').click(function(){
332
+        $("input[name='read'][value='']").remove();
333
+        $("input[name='write'][value='']").remove();
301 334
         $('#document-share-form')[0].submit();
302 335
       });
303 336
 
@@ -308,7 +341,28 @@
308 341
       // FIXME - 2014-05-06 - This is not working (should be done at document.ready time)
309 342
       // note: putting this in a document.ready callback does not work.
310 343
       //
311
-      $('#document-share-form')[0].reset();
344
+##
345
+## The following code is something like dirty ;)
346
+## the goal of this piece of code is to setup view
347
+## according to hidden input values
348
+## for read/write access management
349
+##
350
+
351
+      % for loCurrentGroup in real_groups + user_specific_groups:
352
+        % if loCurrentGroup.hasSomeAccess(poNode)==False:
353
+              updateRights(${loCurrentGroup.group_id}, 0);
354
+        % else:
355
+          % for loRight in loCurrentGroup.rights:
356
+            % if loRight.node_id==poNode.node_id:
357
+##
358
+## The following line should build some javascript code similar to this:
359
+## updateRights(-5, 3);
360
+              updateRights(${loCurrentGroup.group_id}, ${loRight.rights});
361
+            % endif
362
+          % endfor
363
+        % endif
364
+      % endfor
365
+
312 366
       toggleDocumentSharePeopleSelector($('#document-share-selector').prop("checked"));
313 367
 ##        toggleDocumentPublicKeyGenerator($('#document-public-selector').prop("checked"));  
314 368
 ##        

+ 2 - 2
pboard/pboard/templates/document-widgets.mak Ver arquivo

@@ -206,9 +206,9 @@
206 206
         ${_('private')}
207 207
       </sup>
208 208
     % else:
209
-      <sup class="label label-warning" title="${_('This document is collaborative')}">
209
+      <sup class="label label-warning" title="${_('This document is shared')}">
210 210
         <i class="fa fa-group"></i>
211
-        ${_('collaborative')}
211
+        ${_('shared')}
212 212
       </sup>
213 213
     % endif
214 214
 ######

+ 1 - 1
pboard/pboard/templates/document.mak Ver arquivo

@@ -123,7 +123,7 @@
123 123
                 <li>${DOC.MetadataTab('#contacts', 'tab', _('Address book'), 'fa-user', current_node.getContacts())}</li>
124 124
                 <li>${DOC.MetadataTab('#comments', 'tab', _('Comment thread'), 'fa-comments-o', current_node.getComments())}</li>
125 125
                 <li>${DOC.MetadataTab('#files', 'tab', _('Attachments'), 'fa-paperclip', current_node.getFiles())}</li>
126
-                <li class="pull-right">${DOC.MetadataTab('#accessmanagement', 'tab', _('Access Management'), 'fa-key', [])}</li>
126
+                <li class="pull-right">${DOC.MetadataTab('#accessmanagement', 'tab', _('Access Management'), 'fa-key', current_node.getGroupsWithSomeAccess())}</li>
127 127
                 <li class="pull-right">${DOC.MetadataTab('#history', 'tab', _('History'), 'fa-history', current_node.getHistory())}</li>
128 128
             </ul>
129 129
             ################################