PageRenderTime 27ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/indico/MaKaC/services/implementation/material.py

https://github.com/flannery/indico-flannery
Python | 397 lines | 277 code | 68 blank | 52 comment | 30 complexity | adaeffead6a1c28927a948cf8d0e1f99 MD5 | raw file
  1. """
  2. Schedule-related services
  3. """
  4. import MaKaC.conference as conference
  5. from MaKaC.common.PickleJar import DictPickler
  6. import MaKaC.webinterface.locators as locators
  7. from MaKaC.user import AvatarHolder, GroupHolder
  8. from MaKaC.services.interface.rpc.common import ServiceError, ServiceAccessError
  9. from MaKaC.services.implementation.base import ParameterManager
  10. from MaKaC.services.implementation.base import ProtectedModificationService
  11. from MaKaC.services.implementation.base import ProtectedDisplayService
  12. from MaKaC.errors import ModificationError, MaKaCError
  13. from MaKaC.common.fossilize import fossilize
  14. class UserListChange(object):
  15. def changeUserList(self, object, newList):
  16. # clone the list, to avoid problems
  17. allowedUsers = object.getAllowedToAccessList()[:]
  18. # user can be a user or group
  19. for user in allowedUsers:
  20. if not user.getId() in newList:
  21. object.revokeAccess(user)
  22. else:
  23. del newList[user.getId()]
  24. for elem in newList:
  25. if 'isGroup' in elem and elem['isGroup']:
  26. avatar = GroupHolder().getById(elem['id'])
  27. else:
  28. avatar = AvatarHolder().getById(elem['id'])
  29. object.grantAccess(avatar)
  30. class MaterialBase(object):
  31. def _checkParams( self ):
  32. try:
  33. l = locators.WebLocator()
  34. self._material = None
  35. self._conf = None
  36. l.setMaterial( self._params, 0 )
  37. self._target = l.getObject()
  38. #if isinstance(self._target, conference.Material):
  39. self._material = self._target
  40. self._conf = self._target.getConference()
  41. self._categ = self._conf.getOwner()
  42. ## TODO: remove this, since material/resource creation
  43. ## doesn't come through this method
  44. ## if isinstance(self._target, conference.Category):
  45. ## self._categ = self._target
  46. ## else:
  47. ## self._conf = self._target.getConference()
  48. ## if self._conf == None:
  49. ## self._categ=self._target.getCategory()
  50. except Exception, e:
  51. raise ServiceError("ERR-M0", str(e))
  52. class MaterialDisplayBase(ProtectedDisplayService, MaterialBase):
  53. def _checkParams(self):
  54. MaterialBase._checkParams(self)
  55. ProtectedDisplayService._checkParams(self)
  56. class MaterialModifBase(MaterialBase, ProtectedModificationService):
  57. def _checkParams(self):
  58. MaterialBase._checkParams(self)
  59. ProtectedModificationService._checkParams(self)
  60. def _checkProtection(self):
  61. owner = self._material.getOwner()
  62. # There are two exceptions to the normal permission scheme:
  63. # (sub-)contribution submitters and session coordinators
  64. # in case the owner is a (sub-)contribution, we should
  65. # allow submitters
  66. if isinstance(owner, conference.Contribution) or \
  67. isinstance(owner, conference.SubContribution):
  68. reviewingState = self._material.getReviewingState()
  69. if (reviewingState < 3 and
  70. owner.canUserSubmit(self._aw.getUser())):
  71. # Submitters have access
  72. return
  73. elif owner.getSession() and owner.getSession().canCoordinate(self._aw, "modifContribs"):
  74. # Coordinators of the parent session have access
  75. return
  76. # if it's associated with a session, coordinators
  77. # should be allowed
  78. elif self._material.getSession() != None and \
  79. self._material.getSession().canCoordinate(self._aw, "modifContribs"):
  80. # Session coordinators have access
  81. return
  82. try:
  83. ProtectedModificationService._checkProtection(self)
  84. except ModificationError:
  85. raise ServiceAccessError("ERR-P5", _("you are not authorised to manage material for this contribution"))
  86. except Exception, e:
  87. raise e
  88. class ResourceBase(object):
  89. """
  90. Base class for material resource access
  91. """
  92. def _checkParams(self):
  93. """
  94. Checks the materialId, and retrieves the material using it
  95. """
  96. self._material = None
  97. self._conf = None
  98. l = locators.WebLocator()
  99. try:
  100. l.setResource( self._params, 0 )
  101. self._target = l.getObject()
  102. if isinstance(self._target, conference.Resource):
  103. self._resource = self._target
  104. self._material = self._target.getOwner()
  105. if isinstance(self._target, conference.Material):
  106. self._material = self._target
  107. if isinstance(self._target, conference.Category):
  108. self._categ = self._target
  109. else:
  110. self._conf = self._target.getConference()
  111. if self._conf == None:
  112. self._categ=self._target.getCategory()
  113. except Exception, e:
  114. raise ServiceError("ERR-M0", str(e))
  115. class ResourceDisplayBase(ProtectedDisplayService, ResourceBase):
  116. def _checkProtection(self):
  117. ProtectedDisplayService._checkParams(self)
  118. def _checkParams(self):
  119. ResourceBase._checkParams(self)
  120. ProtectedDisplayService._checkParams(self)
  121. class ResourceModifBase(ResourceBase, MaterialModifBase):
  122. def _checkParams(self):
  123. ResourceBase._checkParams(self)
  124. #def _checkProtection(self):
  125. # MaterialModifBase._checkProtection(self)
  126. class GetMaterialClassesBase(MaterialDisplayBase):
  127. """
  128. Base class for obtaining a listing of material classes
  129. """
  130. def _checkParams( self ):
  131. l = locators.WebLocator()
  132. l.setMaterial( self._params, 0 )
  133. self._target = l.getObject()
  134. def _getAnswer(self):
  135. """
  136. Provides the list of material classes, based on the target
  137. resource (conference, session, contribution, etc...)
  138. """
  139. matList = {}
  140. for mat in self._target.getAllMaterialList():
  141. matList[mat.getId()] = DictPickler.pickle(mat)
  142. return matList
  143. class GetMaterial(MaterialDisplayBase):
  144. """
  145. Service for obtaining a material by id
  146. """
  147. def _getAnswer(self):
  148. """
  149. Provides the list of material classes, based on the target
  150. resource (conference, session, contribution, etc...)
  151. """
  152. return DictPickler.pickle(self._material)
  153. class GetMaterialAllowedUsers(MaterialModifBase):
  154. """
  155. Lists the users that allowed to access the material
  156. """
  157. def _checkParams(self):
  158. MaterialModifBase._checkParams(self)
  159. self._includeFavList = self._params.get("includeFavList", False)
  160. self._user = self._getUser() #will be None if user is not authenticated
  161. def _getAnswer(self):
  162. #will use IAvatarFossil or IGroupFossil
  163. allowedAccesList = fossilize(self._material.getAllowedToAccessList())
  164. if self._includeFavList and self._user:
  165. favList = fossilize(self._user.getPersonalInfo().getBasket().getUsers().values())
  166. return [allowedAccesList, favList]
  167. else:
  168. return allowedAccesList
  169. class GetMaterialProtection(MaterialModifBase):
  170. def _getAnswer(self):
  171. """
  172. Returns the material's protection
  173. """
  174. try:
  175. materialId = self._target.getMaterialById(self._params['matId'])
  176. except:
  177. #it's not in the material list, we return the parent's level of protection
  178. #WATCH OUT! This is the default value to inherit from parent in Editor.js, if that value is changed
  179. #for any reason this function may not work properly
  180. return 0
  181. else:
  182. return materialId.getAccessProtectionLevel()
  183. class EditMaterialClassBase(MaterialModifBase, UserListChange):
  184. """
  185. Base class for material class edition
  186. """
  187. def _checkParams(self):
  188. """
  189. Gets a reference to the material, using the
  190. id as the key, and gets the properties to change
  191. """
  192. MaterialModifBase._checkParams(self)
  193. matId = self._params.get("materialId",None)
  194. self._newProperties = self._params.get("materialInfo",None)
  195. self._newUserList = self._newProperties['userList']
  196. materialPM = ParameterManager(self._newProperties)
  197. self._title = materialPM.extract('title', pType=str, allowEmpty=True, defaultValue="NO TITLE ASSIGNED")
  198. self._description = materialPM.extract('description', pType=str, allowEmpty=True)
  199. self._protection = materialPM.extract('protection', pType=int)
  200. self._hidden = materialPM.extract('hidden', pType=int)
  201. self._accessKey = materialPM.extract('accessKey', pType=str, allowEmpty=True)
  202. def _getAnswer(self):
  203. """
  204. Updates the material with the new properties
  205. """
  206. self.changeUserList(self._material, self._newUserList)
  207. self._material.setTitle(self._title);
  208. self._material.setDescription(self._description);
  209. self._material.setProtection(self._protection);
  210. self._material.setHidden(self._hidden);
  211. self._material.setAccessKey(self._accessKey);
  212. event = self._material.getOwner()
  213. materialRegistry = event.getMaterialRegistry()
  214. return {
  215. 'material': DictPickler.pickle(self._material),
  216. 'newMaterialTypes': materialRegistry.getMaterialList(event)
  217. }
  218. class DeleteMaterialClassBase(MaterialModifBase):
  219. def _getAnswer(self):
  220. materialId = self._material.getId()
  221. event = self._material.getOwner()
  222. # actually delete it
  223. self._target.getOwner().removeMaterial(self._material)
  224. materialRegistry = event.getMaterialRegistry()
  225. return {
  226. 'deletedMaterialId': materialId,
  227. 'newMaterialTypes': materialRegistry.getMaterialList(event)
  228. }
  229. class GetResourcesBase(ResourceDisplayBase):
  230. def _getAnswer(self):
  231. resList = {}
  232. for resource in self._material.getResourceList():
  233. resList[resource.getId()] = DictPickler.pickle(resource)
  234. return resList
  235. class EditResourceBase(ResourceModifBase, UserListChange):
  236. def _checkParams(self):
  237. ResourceModifBase._checkParams(self)
  238. resId = self._params.get("resourceId",None)
  239. self._newProperties = self._params.get("resourceInfo",None)
  240. self._newUserList = self._newProperties['userList']
  241. def _getAnswer(self):
  242. self.changeUserList(self._resource, self._newUserList)
  243. DictPickler.update(self._resource, self._newProperties)
  244. return DictPickler.pickle(self._resource)
  245. class GetResourceAllowedUsers(ResourceModifBase):
  246. """
  247. Lists the users that allowed to access the resource
  248. """
  249. def _checkParams(self):
  250. ResourceModifBase._checkParams(self)
  251. self._includeFavList = self._params.get("includeFavList", False)
  252. self._user = self._getUser() #will be None if user is not authenticated
  253. def _getAnswer(self):
  254. #will use IAvatarFossil or IGroupFossil
  255. allowedAccesList = fossilize(self._resource.getAllowedToAccessList())
  256. if self._includeFavList and self._user:
  257. favList = fossilize(self._user.getPersonalInfo().getBasket().getUsers().values())
  258. return [allowedAccesList, favList]
  259. else:
  260. return allowedAccesList
  261. class DeleteResourceBase(ResourceModifBase):
  262. def _getAnswer(self):
  263. resourceId = self._resource.getId()
  264. # remove the resource
  265. self._material.removeResource(self._resource)
  266. event = self._material.getOwner()
  267. # if there are no resources left inside the material,
  268. # just delete it
  269. if len(self._material.getResourceList()) == 0:
  270. event.removeMaterial(self._material)
  271. newMaterialTypes = event.getMaterialRegistry().getMaterialList(event)
  272. return {
  273. 'deletedResourceId': resourceId,
  274. 'newMaterialTypes': newMaterialTypes
  275. }
  276. methodMap = {
  277. "list": GetMaterialClassesBase,
  278. "listAllowedUsers": GetMaterialAllowedUsers,
  279. "get": GetMaterial,
  280. "edit": EditMaterialClassBase,
  281. "delete": DeleteMaterialClassBase,
  282. "getProtection": GetMaterialProtection,
  283. # Resource add is quite hacky, and uses a normal RH, because of file upload
  284. # So, you won't find it here...
  285. "resources.listAllowedUsers": GetResourceAllowedUsers,
  286. "resources.list": GetResourcesBase,
  287. "resources.edit": EditResourceBase,
  288. "resources.delete": DeleteResourceBase
  289. }