dbapi.py 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. # -*- coding: utf-8 -*-
  2. """
  3. """
  4. import os
  5. from datetime import datetime
  6. from hashlib import sha256
  7. from sqlalchemy import Table, ForeignKey, Column
  8. from sqlalchemy.types import Unicode, Integer, DateTime, Text
  9. from sqlalchemy.orm import relation, synonym
  10. from sqlalchemy.orm import joinedload_all
  11. import sqlalchemy as sqla
  12. from pboard.model import DeclarativeBase, metadata, DBSession
  13. from pboard.model import data as pbmd
  14. from pboard.model import auth as pbma
  15. import pboard.model as pbm
  16. import tg
  17. FIXME_ERROR_CODE=-1
  18. class PODStaticController(object):
  19. @classmethod
  20. def getCurrentUser(cls):
  21. loCurrentUser = pbma.User.by_email_address(tg.request.identity['repoze.who.userid'])
  22. return loCurrentUser
  23. @classmethod
  24. def getUserByEmailAddress(cls, psEmailAddress):
  25. loUser = pbma.User.by_email_address(psEmailAddress)
  26. return loUser
  27. @classmethod
  28. def createUser(cls):
  29. loUser = pbma.User()
  30. return loUser
  31. @classmethod
  32. def getGroup(cls, psGroupName):
  33. loGroup = pbma.Group.by_group_name(psGroupName)
  34. return loGroup
  35. @classmethod
  36. def createGroup(cls):
  37. loGroup = pbma.Group()
  38. return loGroup
  39. @classmethod
  40. def getGroups(cls):
  41. loGroups = pbma.Group.real_groups_first()
  42. return loGroups
  43. @classmethod
  44. def getRealGroupRightsOnNode(cls, piNodeId: int) -> pbmd.DIRTY_GroupRightsOnNode:
  45. groupRightsOnNodeCustomSelect = DBSession\
  46. .query(pbmd.DIRTY_GroupRightsOnNode)\
  47. .from_statement(pbmd.DIRTY_RealGroupRightOnNodeSqlQuery)\
  48. .params(node_id=piNodeId)\
  49. .all()
  50. return groupRightsOnNodeCustomSelect
  51. @classmethod
  52. def getUserDedicatedGroupRightsOnNode(cls, piNodeId: int) -> pbmd.DIRTY_GroupRightsOnNode:
  53. groupRightsOnNodeCustomSelect = DBSession\
  54. .query(pbmd.DIRTY_GroupRightsOnNode)\
  55. .from_statement(pbmd.DIRTY_UserDedicatedGroupRightOnNodeSqlQuery)\
  56. .params(node_id=piNodeId)\
  57. .all()
  58. return groupRightsOnNodeCustomSelect
  59. class PODUserFilteredApiController(object):
  60. def __init__(self, piUserId, piExtraUserIdList=[]):
  61. self._iCurrentUserId = piUserId
  62. self._iExtraUserIdList = piExtraUserIdList
  63. self._iUserIdFilteringList = None
  64. def _getUserIdListForFiltering(self):
  65. if self._iUserIdFilteringList==None:
  66. self._iUserIdFilteringList = list()
  67. self._iUserIdFilteringList.append(self._iCurrentUserId)
  68. for liUserId in self._iExtraUserIdList:
  69. self._iUserIdFilteringList.append(liUserId)
  70. return self._iUserIdFilteringList
  71. def createNode(self, parent_id=0):
  72. loNode = pbmd.PBNode()
  73. loNode.owner_id = self._iCurrentUserId
  74. if int(parent_id)!=0:
  75. loNode.parent_id = parent_id
  76. parent_rights = DBSession.query(pbma.Rights).filter(pbma.Rights.node_id==parent_id).all()
  77. loNode.rights = parent_rights
  78. loNode.rights = [pbma.Rights(group_id=r.group_id, rights=r.rights) for r in parent_rights]
  79. DBSession.add(loNode)
  80. return loNode
  81. def createDummyNode(self, parent_id):
  82. loNewNode = self.createNode(parent_id)
  83. loNewNode.data_label = ''
  84. loNewNode.data_content = ''
  85. return loNewNode
  86. def getNode(self, liNodeId: int) -> pbmd.PBNode:
  87. lsSqlSelectQuery = """pod_nodes.node_id IN
  88. (SELECT
  89. pgn.node_id
  90. FROM
  91. pod_group_node AS pgn
  92. join pod_user_group AS pug ON pug.group_id = pgn.group_id
  93. join pod_user AS pu ON pug.user_id = pu.user_id
  94. WHERE
  95. rights > 0
  96. AND pu.user_id = %s)
  97. """
  98. lsNodeIdFiltering = lsSqlSelectQuery % (str(self._iCurrentUserId))
  99. if liNodeId!=None and liNodeId!=0:
  100. return DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren"))\
  101. .filter(pbmd.PBNode.node_id==liNodeId)\
  102. .filter(
  103. sqla.or_(
  104. pbmd.PBNode.owner_id==self._iCurrentUserId,
  105. lsNodeIdFiltering
  106. )
  107. )\
  108. .one()
  109. return None
  110. def getLastModifiedNodes(self, piMaxNodeNb: int):
  111. """
  112. Returns a list of nodes order by modification time and limited to piMaxNodeNb nodes
  113. """
  114. liOwnerIdList = self._getUserIdListForFiltering()
  115. 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()
  116. def searchNodesByText(self, plKeywordList: [str], piMaxNodeNb=100):
  117. """
  118. Returns a list of nodes order by type, nodes which contain at least one of the keywords
  119. """
  120. liOwnerIdList = self._getUserIdListForFiltering()
  121. loKeywordFilteringClauses = []
  122. for keyword in plKeywordList:
  123. loKeywordFilteringClauses.append(pbmd.PBNode.data_label.ilike('%'+keyword+'%'))
  124. loKeywordFilteringClauses.append(pbmd.PBNode.data_content.ilike('%'+keyword+'%'))
  125. loKeywordFilteringClausesAsOr = sqla.or_(*loKeywordFilteringClauses) # Combine them with or to a BooleanClauseList
  126. loResultsForSomeKeywords = DBSession.query(pbmd.PBNode).options(joinedload_all("_lAllChildren"))\
  127. .filter(loKeywordFilteringClausesAsOr)\
  128. .filter(pbmd.PBNode.owner_id.in_(liOwnerIdList))\
  129. .order_by(sqla.desc(pbmd.PBNode.node_type))\
  130. .limit(piMaxNodeNb)\
  131. .all()
  132. return loResultsForSomeKeywords
  133. def getNodesByStatus(self, psNodeStatus, piMaxNodeNb=5):
  134. liOwnerIdList = self._getUserIdListForFiltering()
  135. 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()
  136. def buildTreeListForMenu(self, plViewableStatusId):
  137. liOwnerIdList = self._getUserIdListForFiltering()
  138. # loNodeList = pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_type==pbmd.PBNodeType.Data).filter(pbmd.PBNode.node_status.in_(plViewableStatusId)).order_by(pbmd.PBNode.parent_tree_path).order_by(pbmd.PBNode.node_order).order_by(pbmd.PBNode.node_id).all()
  139. loNodeListNotFiltered = pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.node_type==pbmd.PBNodeType.Data).filter(pbmd.PBNode.node_status.in_(plViewableStatusId)).order_by(pbmd.PBNode.parent_tree_path).order_by(pbmd.PBNode.node_order).order_by(pbmd.PBNode.node_id).all()
  140. loNodeList = []
  141. for loNode in loNodeListNotFiltered:
  142. if loNode.owner_id in self._getUserIdListForFiltering():
  143. loNodeList.append(loNode)
  144. else:
  145. for loRight in loNode._lRights:
  146. for loUser in loRight._oGroup.users:
  147. if loUser.user_id in self._getUserIdListForFiltering():
  148. loNodeList.append(loNode)
  149. loTreeList = []
  150. loTmpDict = {}
  151. for loNode in loNodeList:
  152. loTmpDict[loNode.node_id] = loNode
  153. if loNode.parent_id==None:
  154. loTreeList.append(loNode)
  155. else:
  156. # append the node to the parent list
  157. # FIXME - D.A - 2013-10-08
  158. # The following line may raise an exception
  159. # We suppose that the parent node has already been added
  160. # this *should* be the case, but the code does not check it
  161. if loNode.parent_id not in loTmpDict.keys():
  162. print('THE NODE =========',loNode.parent_id)
  163. try:
  164. loTmpDict[loNode.parent_id] = self.getNode(loNode.parent_id)
  165. except Exception as e:
  166. # loTreeList.append(
  167. # FIXME - D.A. - 2014-05-22 This may be wrong code:
  168. # we are in the case when the node parent is not shared with the current user
  169. # So the node should be added at the root
  170. pass
  171. if loNode.parent_id in loTmpDict.keys():
  172. # HACK- D.A. - 2014-05-22 - See FIXME upper
  173. loTmpDict[loNode.parent_id].appendStaticChild(loNode)
  174. return loTreeList
  175. def getParentNode(self, loNode):
  176. liOwnerIdList = self._getUserIdListForFiltering()
  177. return DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_id==loNode.parent_id).one()
  178. def getSiblingNodes(self, poNode, pbReverseOrder=False):
  179. liOwnerIdList = self._getUserIdListForFiltering()
  180. if pbReverseOrder:
  181. 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()
  182. else:
  183. 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()
  184. def resetNodeOrderOfSiblingNodes(self, loSiblingNodes):
  185. liNewWeight = 0
  186. for loNode in loSiblingNodes:
  187. liNewWeight = liNewWeight + 1
  188. loNode.node_order = liNewWeight
  189. # DBSession.save()
  190. def moveNodeUpper(self, loNode):
  191. # FIXME - manage errors and logging
  192. loSiblingNodes = self.getSiblingNodes(loNode)
  193. self.resetNodeOrderOfSiblingNodes(loSiblingNodes)
  194. loPreviousItem = None
  195. for loItem in loSiblingNodes:
  196. if loItem==loNode:
  197. if loPreviousItem==None:
  198. return FIXME_ERROR_CODE # FIXME - D.A. Do not use hard-coded error codes
  199. print("No previous node")
  200. else:
  201. liPreviousItemOrder = loPreviousItem.node_order
  202. loPreviousItem.node_order = loNode.node_order
  203. loNode.node_order = liPreviousItemOrder
  204. # DBSession.save()
  205. break
  206. loPreviousItem = loItem
  207. def moveNodeLower(self, loNode):
  208. # FIXME - manage errors and logging
  209. loSiblingNodes = self.getSiblingNodes(loNode)
  210. self.resetNodeOrderOfSiblingNodes(loSiblingNodes)
  211. loPreviousItem = None
  212. for loItem in reversed(loSiblingNodes):
  213. if loItem==loNode:
  214. if loPreviousItem==None:
  215. return FIXME_ERROR_CODE # FIXME - D.A. Do not use hard-coded error codes
  216. # FIXME
  217. print("No previous node")
  218. else:
  219. liPreviousItemOrder = loPreviousItem.node_order
  220. loPreviousItem.node_order = loNode.node_order
  221. loNode.node_order = liPreviousItemOrder
  222. # DBSession.save()
  223. break
  224. loPreviousItem = loItem
  225. def getNodeFileContent(self, liNodeId):
  226. liOwnerIdList = self._getUserIdListForFiltering()
  227. return DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_id==liNodeId).one().data_file_content
  228. def deleteNode(loNode):
  229. # INFO - D.A. - 2013-11-07 - should be save as getNode should return only accessible nodes
  230. DBSession.delete(loNode)
  231. return
  232. def createRight(self):
  233. loRight = pbma.Rights()
  234. return loRight