dbapi.py 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  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.orm as sqlao
  12. import sqlalchemy as sqla
  13. from pod.model import data as pbmd
  14. from pod.model import auth as pbma
  15. import pod.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 createNewUser(cls, real_name, email_address, password, groups):
  29. loUser = pbma.User()
  30. new_user = pbma.User()
  31. new_user.email_address = email_address
  32. new_user.display_name = real_name if real_name!='' else email_address
  33. new_user.password = password
  34. public_group = cls.getGroupById(pbma.Group.GROUP_ID_ALL_USERS)
  35. public_group.users.append(new_user)
  36. pbm.DBSession.add(new_user)
  37. pbm.DBSession.flush()
  38. pbm.DBSession.refresh(new_user)
  39. user_dedicated_group = cls.createGroup()
  40. user_dedicated_group.group_id = 0-new_user.user_id # group id of a given user is the opposite of the user id
  41. user_dedicated_group.group_name = 'user_%d' % new_user.user_id
  42. user_dedicated_group.personnal_group = True
  43. user_dedicated_group.users.append(new_user)
  44. for group_id in groups:
  45. selected_group = cls.getGroupById(group_id)
  46. selected_group.users.append(new_user)
  47. pbm.DBSession.flush()
  48. return new_user
  49. @classmethod
  50. def updateUser(cls, user_id, real_name, email, group_ids):
  51. group_ids = list(map(int, group_ids))
  52. group_ids.append(pbma.Group.GROUP_ID_ALL_USERS)
  53. print('new group ids:', group_ids)
  54. user_to_update = pbm.DBSession.query(pbma.User).filter(pbma.User.user_id==user_id).one()
  55. user_to_update.display_name = real_name
  56. user_to_update.email_address = email
  57. merged_new_groups = []
  58. for group in user_to_update.groups:
  59. if group.group_id==pbma.Group.GROUP_ID_MANAGERS:
  60. print('adding group (3)', group.group_id)
  61. merged_new_groups.append(group)
  62. elif group.group_id==pbma.Group.GROUP_ID_ALL_USERS:
  63. print('adding group (2)', group.group_id)
  64. merged_new_groups.append(group)
  65. elif group.group_id in group_ids:
  66. print('adding group', group.group_id)
  67. merged_new_groups.append(group)
  68. else:
  69. print('remove group', group.group_id)
  70. user_to_update.groups.remove(group)
  71. for group_id in group_ids:
  72. group = cls.getGroupById(group_id)
  73. if group not in merged_new_groups:
  74. merged_new_groups.append(group)
  75. user_to_update.groups = merged_new_groups
  76. for group in merged_new_groups:
  77. print("group => ", group.group_id)
  78. pbm.DBSession.flush()
  79. @classmethod
  80. def deleteUser(cls, user_id):
  81. user_to_delete = pbm.DBSession.query(pbma.User).filter(pbma.User.user_id==user_id).one()
  82. user_dedicated_group = pbm.DBSession.query(pbma.Group).filter(pbma.Group.group_id==-user_id).one()
  83. pbm.DBSession.delete(user_to_delete)
  84. pbm.DBSession.delete(user_dedicated_group)
  85. pbm.DBSession.flush()
  86. @classmethod
  87. def getGroup(cls, psGroupName):
  88. loGroup = pbma.Group.by_group_name(psGroupName)
  89. return loGroup
  90. @classmethod
  91. def getGroupById(cls, group_id):
  92. return pbm.DBSession.query(pbma.Group).filter(pbma.Group.group_id==group_id).one()
  93. @classmethod
  94. def createGroup(cls):
  95. loGroup = pbma.Group()
  96. return loGroup
  97. @classmethod
  98. def getGroups(cls):
  99. loGroups = pbma.Group.real_groups_first()
  100. return loGroups
  101. @classmethod
  102. def getRealGroupRightsOnNode(cls, piNodeId: int) -> pbmd.DIRTY_GroupRightsOnNode:
  103. groupRightsOnNodeCustomSelect = pbm.DBSession\
  104. .query(pbmd.DIRTY_GroupRightsOnNode)\
  105. .from_statement(pbmd.DIRTY_RealGroupRightOnNodeSqlQuery)\
  106. .params(node_id=piNodeId)\
  107. .all()
  108. return groupRightsOnNodeCustomSelect
  109. @classmethod
  110. def getUserDedicatedGroupRightsOnNode(cls, node: pbmd.PBNode) -> pbmd.DIRTY_GroupRightsOnNode:
  111. group_rights_on_node = []
  112. if node:
  113. group_rights_on_node = pbm.DBSession\
  114. .query(pbmd.DIRTY_GroupRightsOnNode)\
  115. .from_statement(pbmd.DIRTY_UserDedicatedGroupRightOnNodeSqlQuery)\
  116. .params(node_id=node.node_id)\
  117. .all()
  118. return group_rights_on_node
  119. @classmethod
  120. def DIRTY_get_rights_on_node(self, user_id, node_id):
  121. rights = pbm.DBSession\
  122. .execute("""select max(rights) as rights
  123. from pod_user_group
  124. natural join pod_group_node
  125. where node_id=:node_id
  126. and user_id=:user_id""", {"node_id":node_id, "user_id":user_id})\
  127. .fetchone()
  128. r = pbmd.DIRTY_GroupRightsOnNode()
  129. r.rights = rights[0]
  130. return r
  131. class PODUserFilteredApiController(object):
  132. def __init__(self, piUserId, piExtraUserIdList=[]):
  133. self._iCurrentUserId = piUserId
  134. self._iExtraUserIdList = piExtraUserIdList
  135. self._iUserIdFilteringList = None
  136. self._cache_allowed_nodes = None
  137. def _getUserIdListForFiltering(self):
  138. if self._iUserIdFilteringList==None:
  139. self._iUserIdFilteringList = list()
  140. self._iUserIdFilteringList.append(self._iCurrentUserId)
  141. for liUserId in self._iExtraUserIdList:
  142. self._iUserIdFilteringList.append(liUserId)
  143. return self._iUserIdFilteringList
  144. def createNode(self, parent_id=0, inherit_rights=True):
  145. loNode = pbmd.PBNode()
  146. loNode.owner_id = self._iCurrentUserId
  147. if int(parent_id)!=0:
  148. loNode.parent_id = parent_id
  149. if inherit_rights:
  150. parent_node = pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.node_id==parent_id).one()
  151. self.copy_rights(parent_node, loNode)
  152. pbm.DBSession.add(loNode)
  153. return loNode
  154. def copy_rights(self, from_node: pbmd.PBNode, to_node: pbmd.PBNode, copy_also_is_shared=True):
  155. """
  156. copy rights from first node to second one
  157. """
  158. for parent_right in from_node._lRights:
  159. new_right = self.createRight()
  160. new_right.group_id = parent_right.group_id
  161. new_right.rights = parent_right.rights
  162. to_node._lRights.append(new_right)
  163. if copy_also_is_shared:
  164. to_node.is_shared = from_node.is_shared
  165. def createDummyNode(self, parent_id, inherit_rights=True):
  166. loNewNode = self.createNode(parent_id, inherit_rights)
  167. loNewNode.data_label = ''
  168. loNewNode.data_content = ''
  169. return loNewNode
  170. def getNode(self, liNodeId: int) -> pbmd.PBNode:
  171. lsSqlSelectQuery = """pod_nodes.node_id IN
  172. (SELECT
  173. pgn.node_id
  174. FROM
  175. pod_group_node AS pgn
  176. join pod_user_group AS pug ON pug.group_id = pgn.group_id
  177. join pod_user AS pu ON pug.user_id = pu.user_id
  178. WHERE
  179. rights > 0
  180. AND pu.user_id = %s)
  181. """
  182. lsNodeIdFiltering = lsSqlSelectQuery % (str(self._iCurrentUserId))
  183. if liNodeId!=None and liNodeId!=0:
  184. return pbm.DBSession.query(pbmd.PBNode).options(sqlao.joinedload_all("_oParent"), sqlao.joinedload_all("_lAllChildren"))\
  185. .filter(pbmd.PBNode.node_id==liNodeId)\
  186. .filter(
  187. sqla.or_(
  188. pbmd.PBNode.owner_id==self._iCurrentUserId,
  189. lsNodeIdFiltering
  190. )
  191. )\
  192. .one()
  193. return None
  194. def getLastModifiedNodes(self, piMaxNodeNb: int):
  195. """
  196. Returns a list of nodes order by modification time and limited to piMaxNodeNb nodes
  197. """
  198. liOwnerIdList = self._getUserIdListForFiltering()
  199. return pbm.DBSession.query(pbmd.PBNode)\
  200. .outerjoin(pbma.Rights)\
  201. .outerjoin(pbma.user_group_table, pbma.Rights.group_id==pbma.user_group_table.columns['group_id'])\
  202. .options(joinedload_all("_lAllChildren"))\
  203. .filter((pbmd.PBNode.owner_id.in_(liOwnerIdList)) | ((pbma.user_group_table.c.user_id.in_(liOwnerIdList)) & (pbmd.PBNode.is_shared == True)))\
  204. .order_by(pbmd.PBNode.updated_at.desc())\
  205. .limit(piMaxNodeNb).all()
  206. def getListOfAllowedNodes(self, reset_cache=False) -> pbmd.PBNode:
  207. if self._cache_allowed_nodes==None or reset_cache==True:
  208. lsSqlQuery = """
  209. SELECT
  210. pn.node_id,
  211. pn.parent_id,
  212. pn.node_order,
  213. pn.node_type,
  214. pn.created_at,
  215. pn.updated_at,
  216. pn.data_label,
  217. pn.data_content,
  218. pn.data_datetime,
  219. pn.node_status,
  220. pn.data_reminder_datetime,
  221. pn.parent_tree_path,
  222. pn.node_depth,
  223. pn.owner_id,
  224. pn.is_shared,
  225. pn.is_public,
  226. pn.public_url_key
  227. FROM
  228. pod_group_node AS pgn
  229. join pod_user_group AS pug ON pug.group_id = pgn.group_id
  230. join pod_nodes AS pn ON pgn.node_id=pn.node_id AND pn.is_shared='t'
  231. WHERE
  232. pn.node_type='data'
  233. AND pn.node_status NOT IN ('deleted', 'closed')
  234. AND pn.node_id=pgn.node_id
  235. AND pgn.rights > 0
  236. AND pug.user_id = :owner_id
  237. UNION
  238. SELECT
  239. pn.node_id,
  240. pn.parent_id,
  241. pn.node_order,
  242. pn.node_type,
  243. pn.created_at,
  244. pn.updated_at,
  245. pn.data_label,
  246. pn.data_content,
  247. pn.data_datetime,
  248. pn.node_status,
  249. pn.data_reminder_datetime,
  250. pn.parent_tree_path,
  251. pn.node_depth,
  252. pn.owner_id,
  253. pn.is_shared,
  254. pn.is_public,
  255. pn.public_url_key
  256. FROM
  257. pod_nodes AS pn
  258. WHERE
  259. pn.node_type = 'data'
  260. AND pn.node_status NOT IN ('deleted', 'closed')
  261. AND pn.owner_id = :owner_id
  262. ORDER BY node_id ASC
  263. """
  264. loNodeListResult = pbm.DBSession.query(pbmd.PBNode).\
  265. from_statement(lsSqlQuery).\
  266. params(owner_id=self._iCurrentUserId)
  267. allowed_nodes = loNodeListResult.all()
  268. self._cache_allowed_nodes = allowed_nodes
  269. return self._cache_allowed_nodes
  270. def searchNodesByText(self, plKeywordList: [str], piMaxNodeNb=100):
  271. """
  272. Returns a list of nodes order by type, nodes which contain at least one of the keywords
  273. """
  274. liOwnerIdList = self._getUserIdListForFiltering()
  275. loKeywordFilteringClauses = []
  276. for keyword in plKeywordList:
  277. loKeywordFilteringClauses.append(pbmd.PBNode.data_label.ilike('%'+keyword+'%'))
  278. loKeywordFilteringClauses.append(pbmd.PBNode.data_content.ilike('%'+keyword+'%'))
  279. loKeywordFilteringClauses.append(pbmd.PBNode.data_file_name.ilike('%'+keyword+'%'))
  280. loKeywordFilteringClausesAsOr = sqla.or_(*loKeywordFilteringClauses) # Combine them with or to a BooleanClauseList
  281. 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'])\
  282. .filter(loKeywordFilteringClausesAsOr)\
  283. .filter((pbmd.PBNode.owner_id.in_(liOwnerIdList)) | (pbma.user_group_table.c.user_id.in_(liOwnerIdList) & pbmd.PBNode.is_shared))\
  284. .order_by(sqla.desc(pbmd.PBNode.node_type))\
  285. .limit(piMaxNodeNb)\
  286. .all()
  287. return loResultsForSomeKeywords
  288. def getNodesByStatus(self, psNodeStatus, piMaxNodeNb=5):
  289. liOwnerIdList = self._getUserIdListForFiltering()
  290. 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()
  291. def getChildNodesForMenu(self, poParentNode: pbmd.PBNode, allowed_nodes: [pbmd.PBNode]) -> [pbmd.PBNode]:
  292. visible_child_nodes = []
  293. if poParentNode!=None:
  294. # standard case
  295. print(" -------------- BEFORE @@@@@@@@@@@@@@@@ ")
  296. all_child_nodes = poParentNode.getChildren()
  297. print("@@@@@@@@@@@@@@@@ AFTER @@@@@@@@@@@@@@@@ ")
  298. for child_node in all_child_nodes:
  299. if child_node in allowed_nodes:
  300. visible_child_nodes.append(child_node)
  301. else:
  302. # Root case
  303. parent_nodes = pbm.DBSession
  304. for allowed_node in allowed_nodes:
  305. print(" @@@@@@@@@@@@@@@@ BEFORE @@@@@@@@@@@@@@@@ ")
  306. # loParent = allowed_node._oParent
  307. # print("@@@@@@@@@@@@@@@@ AFTER @@@@@@@@@@@@@@@@ {0}".format(allowed_node._oParent.node_id if allowed_node._oParent!=None else '0'))
  308. # print("==== EXTRA {0}".format(allowed_node._oParent.node_id if allowed_node._oParent!=None else '0'))
  309. print("====> ")
  310. if allowed_node._oParent is None or allowed_node._oParent==allowed_node:
  311. # D.A. - HACK - 2014-05-27
  312. # I don't know why, but as from now (with use of sqlao.contains_eager in getListOfAllowedNodes()
  313. # the root items have at first iteration itself as parent
  314. print("==== EXTRA END")
  315. # this is a root item => add it
  316. visible_child_nodes.append(allowed_node)
  317. else:
  318. if allowed_node._oParent not in allowed_nodes:
  319. # the node is visible but not the parent => put it at the root
  320. visible_child_nodes.append(allowed_node)
  321. else:
  322. print("==== EXTRA END 2 {0}".format(allowed_node._oParent.node_id))
  323. print(" @@@@@@@@@@@@@@@@ PRE FAILURE @@@@@@@@@@@@@@@@ ")
  324. return visible_child_nodes
  325. def buildTreeListForMenu(self, current_node: pbmd.PBNode, allowed_nodes: [pbmd.PBNode]) -> [pbmd.NodeTreeItem]:
  326. # The algorithm is:
  327. # 1. build an intermediate tree containing only current node and parent path
  328. # + complete it with sibling at each level (except root)
  329. # 2. add sibling nodes at root level
  330. # 3. complete it with shared documents (which are not at root but shared with current user)
  331. node_tree = []
  332. previous_tree_item = None
  333. tmp_children_nodes = []
  334. if current_node is not None:
  335. breadcrumb_nodes = current_node.getBreadCrumbNodes()
  336. breadcrumb_nodes.append(current_node) # by default the current node is not included
  337. for breadcrumb_node in reversed(breadcrumb_nodes):
  338. if previous_tree_item is None:
  339. # First iteration. We add all current_node children
  340. for child_node in breadcrumb_node.getChildren():
  341. if child_node in allowed_nodes:
  342. child_item = pbmd.NodeTreeItem(child_node, [])
  343. tmp_children_nodes.append(child_item)
  344. previous_tree_item = pbmd.NodeTreeItem(breadcrumb_node, tmp_children_nodes)
  345. else:
  346. tmp_children_nodes = []
  347. for child_node in breadcrumb_node.getChildren():
  348. if child_node in allowed_nodes:
  349. if child_node == previous_tree_item.node:
  350. tmp_children_nodes.append(previous_tree_item)
  351. else:
  352. sibling_node = pbmd.NodeTreeItem(child_node, [])
  353. tmp_children_nodes.append(sibling_node)
  354. previous_tree_item = pbmd.NodeTreeItem(breadcrumb_node, tmp_children_nodes)
  355. for node in allowed_nodes:
  356. # This part of the algorithm insert root items
  357. if node.parent_id==0 or node.parent_id is None:
  358. if previous_tree_item is not None and node == previous_tree_item.node:
  359. assert(isinstance(previous_tree_item, pbmd.NodeTreeItem))
  360. node_tree.append(previous_tree_item)
  361. else:
  362. node_tree.append(pbmd.NodeTreeItem(node, []))
  363. else:
  364. # Try to add nodes shared with me but with a parent which is not shared
  365. if node.owner_id!=self._iCurrentUserId:
  366. # this is a node shared with me
  367. if node._oParent!=None and node._oParent not in allowed_nodes:
  368. # the node is shared but not the parent => put it in the root
  369. node_tree.append(pbmd.NodeTreeItem(node, []))
  370. return node_tree
  371. def DIRTY_OLDbuildTreeListForMenu(self, plViewableStatusId: []) -> [pbmd.PBNode]:
  372. liOwnerIdList = self._getUserIdListForFiltering()
  373. # 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()
  374. 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()
  375. loNodeList = []
  376. for loNode in loNodeListNotFiltered:
  377. if loNode.owner_id in self._getUserIdListForFiltering():
  378. loNodeList.append(loNode)
  379. else:
  380. for loRight in loNode._lRights:
  381. for loUser in loRight._oGroup.users:
  382. if loUser.user_id in self._getUserIdListForFiltering():
  383. loNodeList.append(loNode)
  384. loTreeList = []
  385. loTmpDict = {}
  386. for loNode in loNodeList:
  387. loTmpDict[loNode.node_id] = loNode
  388. if loNode.parent_id==None or loNode.parent_id==0:
  389. loTreeList.append(loNode)
  390. else:
  391. # append the node to the parent list
  392. # FIXME - D.A - 2013-10-08
  393. # The following line may raise an exception
  394. # We suppose that the parent node has already been added
  395. # this *should* be the case, but the code does not check it
  396. if loNode.parent_id not in loTmpDict.keys():
  397. try:
  398. loTmpDict[loNode.parent_id] = self.getNode(loNode.parent_id)
  399. except Exception as e:
  400. # loTreeList.append(
  401. # FIXME - D.A. - 2014-05-22 This may be wrong code:
  402. # we are in the case when the node parent is not shared with the current user
  403. # So the node should be added at the root
  404. pass
  405. if loNode.parent_id in loTmpDict.keys():
  406. # HACK- D.A. - 2014-05-22 - See FIXME upper
  407. loTmpDict[loNode.parent_id].appendStaticChild(loNode)
  408. return loTreeList
  409. def getParentNode(self, loNode):
  410. liOwnerIdList = self._getUserIdListForFiltering()
  411. return pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_id==loNode.parent_id).one()
  412. def getSiblingNodes(self, poNode, pbReverseOrder=False):
  413. liOwnerIdList = self._getUserIdListForFiltering()
  414. if pbReverseOrder:
  415. 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()
  416. else:
  417. 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()
  418. def resetNodeOrderOfSiblingNodes(self, loSiblingNodes):
  419. liNewWeight = 0
  420. for loNode in loSiblingNodes:
  421. liNewWeight = liNewWeight + 1
  422. loNode.node_order = liNewWeight
  423. # DBSession.save()
  424. def moveNodeUpper(self, loNode):
  425. # FIXME - manage errors and logging
  426. loSiblingNodes = self.getSiblingNodes(loNode)
  427. self.resetNodeOrderOfSiblingNodes(loSiblingNodes)
  428. loPreviousItem = None
  429. for loItem in loSiblingNodes:
  430. if loItem==loNode:
  431. if loPreviousItem==None:
  432. return FIXME_ERROR_CODE # FIXME - D.A. Do not use hard-coded error codes
  433. print("No previous node")
  434. else:
  435. liPreviousItemOrder = loPreviousItem.node_order
  436. loPreviousItem.node_order = loNode.node_order
  437. loNode.node_order = liPreviousItemOrder
  438. # DBSession.save()
  439. break
  440. loPreviousItem = loItem
  441. def moveNodeLower(self, loNode):
  442. # FIXME - manage errors and logging
  443. loSiblingNodes = self.getSiblingNodes(loNode)
  444. self.resetNodeOrderOfSiblingNodes(loSiblingNodes)
  445. loPreviousItem = None
  446. for loItem in reversed(loSiblingNodes):
  447. if loItem==loNode:
  448. if loPreviousItem==None:
  449. return FIXME_ERROR_CODE # FIXME - D.A. Do not use hard-coded error codes
  450. # FIXME
  451. print("No previous node")
  452. else:
  453. liPreviousItemOrder = loPreviousItem.node_order
  454. loPreviousItem.node_order = loNode.node_order
  455. loNode.node_order = liPreviousItemOrder
  456. # DBSession.save()
  457. break
  458. loPreviousItem = loItem
  459. def getNodeFileContent(self, liNodeId):
  460. liOwnerIdList = self._getUserIdListForFiltering()
  461. return pbm.DBSession.query(pbmd.PBNode).filter(pbmd.PBNode.owner_id.in_(liOwnerIdList)).filter(pbmd.PBNode.node_id==liNodeId).one().data_file_content
  462. def deleteNode(loNode):
  463. # INFO - D.A. - 2013-11-07 - should be save as getNode should return only accessible nodes
  464. pbm.DBSession.delete(loNode)
  465. return
  466. def createRight(self):
  467. loRight = pbma.Rights()
  468. return loRight