Browse Source

make user and group admin work fine

Damien Accorsi 10 years ago
parent
commit
896ec42d21

+ 38 - 76
pboard/pboard/controllers/admingroup.py View File

@@ -17,93 +17,55 @@ from formencode.validators import FieldsMatch
17 17
 
18 18
 from pboard.lib import dbapi as pld
19 19
 
20
-class GroupField(PropertyMultipleSelectField):
21
-    """ Shows a limited list of groups """
22
-
23
-    def prepare(self):
24
-        # self.entity = pma.Group
25
-        #self.__class__.entity
26
-
27
-        visible_groups = pm.DBSession.query(pma.Group).\
28
-            filter(pma.Group.group_id>0).\
29
-            filter(pma.Group.group_id!=pma.Group.GROUP_ID_ALL_USERS).all()
30
-
31
-        self.options = [(group.group_id, group.getDisplayName()) for group in visible_groups]
32
-
33
-        if not self.value:
34
-            self.value = []
35
-        self.value = [unicode_text(v) for v in self.value]
36
-
37
-        super(PropertyMultipleSelectField, self).prepare()
38
-
39
-
40
-class AdminUserController(CrudRestController):
41
-    model = pma.User
20
+class AdminGroupController(CrudRestController):
21
+    model = pma.Group
42 22
 
43 23
     class new_form_type(AddRecordForm):
44
-        __model__ = pma.User
24
+        __model__ = pma.Group
25
+        __require_fields__     = ['group_name', 'display_name', 'users', 'personnal_group']
26
+        __omit_fields__        = ['created', 'permissions', '_lRights']
27
+        __field_order__        = ['group_name', 'display_name', 'users']
28
+
29
+        __headers__ = dict(group_name='Unique name', display_name='Visible name')
45 30
 
46
-        __require_fields__     = ['display_name', 'email_address', 'password', 'verify_password', 'groups']
47
-        __omit_fields__        = ['_password', 'created', 'user_id', '_lAllNodes']
48
-        __field_order__        = ['display_name', 'email_address', 'password', 'verify_password', 'groups']
31
+        group_name = tw2f.TextField('group_name')
32
+        display_name = tw2f.TextField('display_name')
33
+        personnal_group = tw2f.HiddenField('personnal_group', value='off')
49 34
 
50
-        email_address          = tw2f.TextField('email_address')
51
-        display_name           = tw2f.TextField('display_name')
52
-        verify_password        = tw2f.PasswordField('verify_password')
53
-        groups = GroupField('groups')
54 35
 
55 36
     class edit_form_type(EditableForm):
56
-        __model__ = pma.User
37
+        __model__ = pma.Group
38
+        __require_fields__     = ['group_name', 'display_name', 'users']
39
+        __omit_fields__        = ['personnal_group', 'created', 'permissions', '_lRights']
40
+        __field_order__        = ['group_name', 'display_name']
57 41
 
58
-        __require_fields__     = ['display_name', 'email_address', 'groups']
59
-        __omit_fields__        = ['_password', 'created', 'user_id', '_lAllNodes', 'password']
60
-        __field_order__        = ['display_name', 'email_address', 'groups']
42
+        __headers__ = dict(group_name='Unique name', display_name='Visible name')
61 43
 
62
-        email_address          = tw2f.TextField('email_address')
63
-        display_name           = tw2f.TextField('display_name')
64
-        groups = GroupField('groups')
65 44
 
66 45
     class edit_filler_type(EditFormFiller):
67
-        __model__ = pma.User
46
+        __model__ = pma.Group
68 47
 
69
-    class table_type(TableBase):
70
-        __model__ = pma.User
71
-        __limit_fields__ = ['user_id', 'email_address', 'display_name', 'groups']
72
-        __field_order__ = ['user_id', 'display_name', 'email_address', 'groups']
73
-        __headers__ = dict(user_id='id', email_address='Email', display_name='Name', groups='Groups')
74
-        __xml_fields__ = ['groups']
75
-
76
-    class table_filler_type(TableFiller):
77
-        __model__ = pma.User
78
-        __limit_fields__ = ['user_id', 'email_address', 'display_name', 'groups']
79
-
80
-        def groups(self, obj):
81
-            groups = ''.join(['<li>{0}</li>'.format(group.getDisplayName()) for group in obj.groups if group.group_id>0])
82
-            return groups.join(('<ul>', '</ul>'))
83
-
84
-    @tg.expose()
85
-    #@tg.validate(new_user_validator, error_handler=CrudRestController.new)
86
-    def post(self, *args, **kw):
87
-
88
-        real_name = kw['display_name']
89
-        email = kw['email_address']
90
-        groups = kw['groups'] if 'groups' in kw else []
91
-        password = kw['password']
92
-
93
-        new_user = pld.PODStaticController.createNewUser(real_name, email, password, groups)
94
-        if tg.request.response_type == 'application/json':
95
-            if new_user is not None and self.conditional_update_field is not None:
96
-                tg.response.last_modified = getattr(new_user, self.conditional_update_field)
97
-
98
-            return dict(model=self.model.__name__,
99
-                        value=self._dictify(new_user))
100
-
101
-        return tg.redirect('./', params=self._kept_params())
102 48
 
49
+    class table_type(TableBase):
50
+        __model__ = pma.Group
51
+        __limit_fields__ = ['group_id', 'group_name', 'display_name', 'users']
52
+        __headers__ = dict(group_id='id', group_name='Unique name', display_name='Visible name', users='Users')
53
+        __xml_fields__ = ['users']
103 54
 
104
-    @tg.expose()
105
-    def post_delete(self, *args, **kw):
106
-        user_id = int(args[0])
107 55
 
108
-        pld.PODStaticController.deleteUser(user_id)
109
-        return tg.redirect('./', params=self._kept_params())
56
+    class table_filler_type(TableFiller):
57
+        __model__ = pma.Group
58
+        __limit_fields__ = ['group_id', 'group_name', 'display_name', 'users']
59
+        #__add_fields__ = {'associated_users':None}
60
+
61
+        def _do_get_provider_count_and_objs(self, groups=None, **kw):
62
+            groups = pm.DBSession.query(pma.Group).\
63
+                filter(pma.Group.group_id>0).\
64
+                filter(pma.Group.group_id != pma.Group.GROUP_ID_ALL_USERS).\
65
+                filter(pma.Group.group_id != pma.Group.GROUP_ID_MANAGERS).\
66
+                all()
67
+            return len(groups), groups
68
+
69
+        def users(self, obj):
70
+            users = ''.join(['<li>{0}</li>'.format(user.getDisplayName()) for user in obj.users])
71
+            return users.join(('<ul>', '</ul>'))

+ 1 - 20
pboard/pboard/controllers/apipublic.py View File

@@ -28,26 +28,7 @@ class PODPublicApiController(plb.BaseController):
28 28
           tg.flash(_('Account creation error: account already exist: %s') % (email), 'error')
29 29
           tg.redirect(tg.lurl('/'))
30 30
 
31
-        loNewAccount = pld.PODStaticController.createUser()
32
-        loNewAccount.email_address = email
33
-        loNewAccount.display_name  = real_name if real_name!='' else email
34
-        loNewAccount.password      = password
35
-
36
-        loUserGroup = pld.PODStaticController.getGroup('user')
37
-        loUserGroup.users.append(loNewAccount)
38
-
39
-        pm.DBSession.add(loNewAccount)
40
-        pm.DBSession.flush()
41
-        pm.DBSession.refresh(loNewAccount)
42
-
43
-        loUserSpecificGroup = pld.PODStaticController.createGroup()
44
-
45
-        loUserSpecificGroup.group_id = 0-loNewAccount.user_id # group id of a given user is the opposite of the user id
46
-        loUserSpecificGroup.group_name = 'user_%d' % loNewAccount.user_id
47
-        loUserSpecificGroup.personnal_group = True
48
-        loUserSpecificGroup.users.append(loNewAccount)
49
-
50
-        pm.DBSession.flush()
31
+        loNewAccount = pld.PODStaticController.createNewUser(real_name if real_name!='' else email, email, password, [])
51 32
 
52 33
         tg.flash(_('Account successfully created: %s') % (email), 'info')
53 34
 

+ 8 - 5
pboard/pboard/controllers/root.py View File

@@ -20,6 +20,8 @@ from pboard.lib import dbapi as pld
20 20
 from pboard.controllers import api as pca
21 21
 from pboard.controllers import apipublic as pcap
22 22
 from pboard.controllers import debug as pbcd
23
+from pboard.controllers import adminuser as pbcu
24
+from pboard.controllers import admingroup as pbcg
23 25
 
24 26
 from pboard import model as pm
25 27
 
@@ -28,6 +30,11 @@ import pboard.model.data as pbmd
28 30
 __all__ = ['RootController']
29 31
 
30 32
 
33
+class AdminController(BaseController):
34
+    users = pbcu.AdminUserController(pm.DBSession)
35
+    groups = pbcg.AdminGroupController(pm.DBSession)
36
+
37
+
31 38
 class RootController(BaseController):
32 39
     """
33 40
     The root controller for the pboard application.
@@ -43,11 +50,7 @@ class RootController(BaseController):
43 50
 
44 51
     """
45 52
 
46
-    admin = tgac.AdminController(
47
-        [pm.Group, pm.User],
48
-        pm.DBSession,
49
-        config_type = pcad.PodAdminConfig
50
-    )
53
+    admin = AdminController()
51 54
 
52 55
     api   = pca.PODApiController()
53 56
     debug = pbcd.DebugController()

+ 95 - 19
pboard/pboard/lib/dbapi.py View File

@@ -12,7 +12,6 @@ from sqlalchemy.orm import joinedload_all
12 12
 import sqlalchemy.orm as sqlao
13 13
 import sqlalchemy as sqla
14 14
 
15
-from pboard.model import DeclarativeBase, metadata, DBSession
16 15
 from pboard.model import data as pbmd
17 16
 from pboard.model import auth as pbma
18 17
 import pboard.model as pbm
@@ -34,16 +33,93 @@ class PODStaticController(object):
34 33
     return loUser
35 34
   
36 35
   @classmethod
37
-  def createUser(cls):
36
+  def createNewUser(cls, real_name, email_address, password, groups):
38 37
     loUser = pbma.User()
39
-    return loUser
40
-  
38
+    new_user = pbma.User()
39
+    new_user.email_address = email_address
40
+    new_user.display_name  = real_name if real_name!='' else email_address
41
+    new_user.password      = password
42
+
43
+    public_group = cls.getGroupById(pbma.Group.GROUP_ID_ALL_USERS)
44
+    public_group.users.append(new_user)
45
+
46
+    pbm.DBSession.add(new_user)
47
+    pbm.DBSession.flush()
48
+    pbm.DBSession.refresh(new_user)
49
+
50
+    user_dedicated_group = cls.createGroup()
51
+    user_dedicated_group.group_id = 0-new_user.user_id # group id of a given user is the opposite of the user id
52
+    user_dedicated_group.group_name = 'user_%d' % new_user.user_id
53
+    user_dedicated_group.personnal_group = True
54
+    user_dedicated_group.users.append(new_user)
55
+
56
+    for group_id in groups:
57
+        selected_group = cls.getGroupById(group_id)
58
+        selected_group.users.append(new_user)
59
+
60
+    pbm.DBSession.flush()
61
+
62
+    return new_user
63
+
64
+  @classmethod
65
+  def updateUser(cls, user_id, real_name, email, group_ids):
66
+
67
+      group_ids = list(map(int, group_ids))
68
+      group_ids.append(pbma.Group.GROUP_ID_ALL_USERS)
69
+      print('new group ids:', group_ids)
70
+      user_to_update = pbm.DBSession.query(pbma.User).filter(pbma.User.user_id==user_id).one()
71
+      user_to_update.display_name = real_name
72
+      user_to_update.email_address = email
73
+
74
+      merged_new_groups = []
75
+
76
+      for group in user_to_update.groups:
77
+          if group.group_id==pbma.Group.GROUP_ID_MANAGERS:
78
+              print('adding group (3)', group.group_id)
79
+              merged_new_groups.append(group)
80
+
81
+          elif group.group_id==pbma.Group.GROUP_ID_ALL_USERS:
82
+              print('adding group (2)', group.group_id)
83
+              merged_new_groups.append(group)
84
+
85
+          elif group.group_id in group_ids:
86
+              print('adding group', group.group_id)
87
+              merged_new_groups.append(group)
88
+
89
+          else:
90
+              print('remove group', group.group_id)
91
+              user_to_update.groups.remove(group)
92
+
93
+      for group_id in group_ids:
94
+          group = cls.getGroupById(group_id)
95
+
96
+          if group not in merged_new_groups:
97
+              merged_new_groups.append(group)
98
+
99
+      user_to_update.groups = merged_new_groups
100
+
101
+      for group in merged_new_groups:
102
+          print("group => ", group.group_id)
103
+      pbm.DBSession.flush()
104
+
105
+  @classmethod
106
+  def deleteUser(cls, user_id):
107
+      user_to_delete = pbm.DBSession.query(pbma.User).filter(pbma.User.user_id==user_id).one()
108
+      user_dedicated_group = pbm.DBSession.query(pbma.Group).filter(pbma.Group.group_id==-user_id).one()
109
+      pbm.DBSession.delete(user_to_delete)
110
+      pbm.DBSession.delete(user_dedicated_group)
111
+      pbm.DBSession.flush()
112
+
41 113
   @classmethod
42 114
   def getGroup(cls, psGroupName):
43 115
     loGroup = pbma.Group.by_group_name(psGroupName)
44 116
     return loGroup
45 117
 
46 118
   @classmethod
119
+  def getGroupById(cls, group_id):
120
+    return pbm.DBSession.query(pbma.Group).filter(pbma.Group.group_id==group_id).one()
121
+
122
+  @classmethod
47 123
   def createGroup(cls):
48 124
     loGroup = pbma.Group()
49 125
     return loGroup
@@ -56,7 +132,7 @@ class PODStaticController(object):
56 132
   @classmethod
57 133
   def getRealGroupRightsOnNode(cls, piNodeId: int) -> pbmd.DIRTY_GroupRightsOnNode:
58 134
 
59
-    groupRightsOnNodeCustomSelect = DBSession\
135
+    groupRightsOnNodeCustomSelect = pbm.DBSession\
60 136
         .query(pbmd.DIRTY_GroupRightsOnNode)\
61 137
         .from_statement(pbmd.DIRTY_RealGroupRightOnNodeSqlQuery)\
62 138
         .params(node_id=piNodeId)\
@@ -67,7 +143,7 @@ class PODStaticController(object):
67 143
   @classmethod
68 144
   def getUserDedicatedGroupRightsOnNode(cls, piNodeId: int) -> pbmd.DIRTY_GroupRightsOnNode:
69 145
 
70
-    groupRightsOnNodeCustomSelect = DBSession\
146
+    groupRightsOnNodeCustomSelect = pbm.DBSession\
71 147
         .query(pbmd.DIRTY_GroupRightsOnNode)\
72 148
         .from_statement(pbmd.DIRTY_UserDedicatedGroupRightOnNodeSqlQuery)\
73 149
         .params(node_id=piNodeId)\
@@ -101,10 +177,10 @@ class PODUserFilteredApiController(object):
101 177
         loNode.parent_id = parent_id
102 178
 
103 179
     if inherit_rights:
104
-        parent_node = DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.node_id==parent_id).one()
180
+        parent_node = pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.node_id==parent_id).one()
105 181
         self.copy_rights(parent_node, loNode)
106 182
 
107
-    DBSession.add(loNode)
183
+    pbm.DBSession.add(loNode)
108 184
 
109 185
     return loNode
110 186
 
@@ -144,7 +220,7 @@ class PODUserFilteredApiController(object):
144 220
     lsNodeIdFiltering = lsSqlSelectQuery % (str(self._iCurrentUserId))
145 221
 
146 222
     if liNodeId!=None and liNodeId!=0:
147
-      return DBSession.query(pbmd.PBNode).options(sqlao.joinedload_all("_oParent"), sqlao.joinedload_all("_lAllChildren"))\
223
+      return pbm.DBSession.query(pbmd.PBNode).options(sqlao.joinedload_all("_oParent"), sqlao.joinedload_all("_lAllChildren"))\
148 224
         .filter(pbmd.PBNode.node_id==liNodeId)\
149 225
         .filter(
150 226
           sqla.or_(
@@ -160,7 +236,7 @@ class PODUserFilteredApiController(object):
160 236
     Returns a list of nodes order by modification time and limited to piMaxNodeNb nodes
161 237
     """
162 238
     liOwnerIdList = self._getUserIdListForFiltering()
163
-    return DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren")).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).order_by(pbmd.PBNode.updated_at.desc()).limit(piMaxNodeNb).all()
239
+    return pbm.DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren")).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).order_by(pbmd.PBNode.updated_at.desc()).limit(piMaxNodeNb).all()
164 240
 
165 241
 
166 242
   def getListOfAllowedNodes(self, reset_cache=False) -> pbmd.PBNode:
@@ -224,7 +300,7 @@ class PODUserFilteredApiController(object):
224 300
             ORDER BY node_id ASC
225 301
         """
226 302
 
227
-        loNodeListResult = DBSession.query(pbmd.PBNode).\
303
+        loNodeListResult = pbm.DBSession.query(pbmd.PBNode).\
228 304
             from_statement(lsSqlQuery).\
229 305
             params(owner_id=self._iCurrentUserId)
230 306
         allowed_nodes = loNodeListResult.all()
@@ -248,7 +324,7 @@ class PODUserFilteredApiController(object):
248 324
 
249 325
     loKeywordFilteringClausesAsOr = sqla.or_(*loKeywordFilteringClauses) # Combine them with or to a BooleanClauseList
250 326
 
251
-    loResultsForSomeKeywords = DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren")).join(pbma.Rights).join(pbma.user_group_table, pbma.Rights.group_id==pbma.user_group_table.columns['group_id'])\
327
+    loResultsForSomeKeywords = pbm.DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren")).join(pbma.Rights).join(pbma.user_group_table, pbma.Rights.group_id==pbma.user_group_table.columns['group_id'])\
252 328
         .filter(loKeywordFilteringClausesAsOr)\
253 329
         .filter((pbmd.PBNode.owner_id.in_(liOwnerIdList)) | (pbma.user_group_table.c.user_id.in_(liOwnerIdList) & pbmd.PBNode.is_shared))\
254 330
         .order_by(sqla.desc(pbmd.PBNode.node_type))\
@@ -259,7 +335,7 @@ class PODUserFilteredApiController(object):
259 335
 
260 336
   def getNodesByStatus(self, psNodeStatus, piMaxNodeNb=5):
261 337
     liOwnerIdList = self._getUserIdListForFiltering()
262
-    return DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren")).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_status==psNodeStatus).order_by(pbmd.PBNode.updated_at).limit(piMaxNodeNb).all()
338
+    return pbm.DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren")).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_status==psNodeStatus).order_by(pbmd.PBNode.updated_at).limit(piMaxNodeNb).all()
263 339
 
264 340
 
265 341
   def getChildNodesForMenu(self, poParentNode: pbmd.PBNode, allowed_nodes: [pbmd.PBNode]) -> [pbmd.PBNode]:
@@ -275,7 +351,7 @@ class PODUserFilteredApiController(object):
275 351
             visible_child_nodes.append(child_node)
276 352
     else:
277 353
         # Root case
278
-        parent_nodes = DBSession
354
+        parent_nodes = pbm.DBSession
279 355
         for allowed_node in allowed_nodes:
280 356
             print("     @@@@@@@@@@@@@@@@ BEFORE @@@@@@@@@@@@@@@@ ")
281 357
             # loParent = allowed_node._oParent
@@ -410,15 +486,15 @@ class PODUserFilteredApiController(object):
410 486
 
411 487
   def getParentNode(self, loNode):
412 488
     liOwnerIdList = self._getUserIdListForFiltering()
413
-    return DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_id==loNode.parent_id).one()
489
+    return pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_id==loNode.parent_id).one()
414 490
 
415 491
   def getSiblingNodes(self, poNode, pbReverseOrder=False):
416 492
     liOwnerIdList = self._getUserIdListForFiltering()
417 493
     
418 494
     if pbReverseOrder:
419
-      return DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.parent_id==poNode.parent_id).order_by(pbmd.PBNode.node_order.desc()).all()
495
+      return pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.parent_id==poNode.parent_id).order_by(pbmd.PBNode.node_order.desc()).all()
420 496
     else:
421
-      return DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.parent_id==poNode.parent_id).order_by(pbmd.PBNode.node_order).all()
497
+      return pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.parent_id==poNode.parent_id).order_by(pbmd.PBNode.node_order).all()
422 498
 
423 499
   def resetNodeOrderOfSiblingNodes(self, loSiblingNodes):
424 500
     liNewWeight = 0
@@ -470,11 +546,11 @@ class PODUserFilteredApiController(object):
470 546
 
471 547
   def getNodeFileContent(self, liNodeId):
472 548
     liOwnerIdList = self._getUserIdListForFiltering()
473
-    return DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_id==liNodeId).one().data_file_content
549
+    return pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_id==liNodeId).one().data_file_content
474 550
 
475 551
   def deleteNode(loNode):
476 552
     # INFO - D.A. - 2013-11-07 - should be save as getNode should return only accessible nodes
477
-    DBSession.delete(loNode)
553
+    pbm.DBSession.delete(loNode)
478 554
     return
479 555
 
480 556
   def createRight(self):

+ 2 - 0
pboard/pboard/model/auth.py View File

@@ -62,6 +62,8 @@ class Rights(DeclarativeBase):
62 62
 
63 63
 
64 64
 class Group(DeclarativeBase):
65
+    GROUP_ID_ALL_USERS = 2
66
+    GROUP_ID_MANAGERS = 1
65 67
 
66 68
     __tablename__ = 'pod_group'
67 69
 

+ 2 - 2
pboard/pboard/templates/master.mak View File

@@ -155,8 +155,8 @@
155 155
                 Admin <b class="caret"></b>
156 156
               </a>
157 157
               <ul class="dropdown-menu">
158
-                <li><a href="${tg.url('/admin/users')}"><i class="fa fa-user"></i> ${_('List users')}</a></li>
159
-                <li><a href="${tg.url('/admin/groups')}"><i class="fa fa-group"></i> ${_('Manage groups')}</a></li>
158
+                <li><a href="${tg.url('/admin/users')}"><i class="fa fa-user"></i> ${_('Users')}</a></li>
159
+                <li><a href="${tg.url('/admin/groups')}"><i class="fa fa-group"></i> ${_('Groups')}</a></li>
160 160
                 % if request.identity and 'managers' in request.identity['groups']:
161 161
                   <li class="divider" role="presentation"></li>
162 162
                   <li><a href="${tg.url('/admin')}"><i class="fa fa-magic"></i> Manage all</a></li>