PageRenderTime 83ms CodeModel.GetById 55ms RepoModel.GetById 1ms app.codeStats 0ms

/graphingwiki/graphingwiki/groups.py

https://bitbucket.org/clarifiednetworks/graphingwiki/
Python | 314 lines | 278 code | 21 blank | 15 comment | 21 complexity | fef7fbb5a1fd1b51d44164bf83ac663e MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. """
  3. Graphingwiki group page editing functions
  4. - Adding, deleting and renaming group members
  5. - Supports only Wiki groups
  6. @copyright: 2014 by Juhani Eronen
  7. @license: MIT <http://www.opensource.org/licenses/mit-license.php>
  8. """
  9. import re
  10. if __name__ == '__main__':
  11. # We need to import contexts before importing User, because otherwise
  12. # the relative imports in MoinMoin will fail.
  13. import MoinMoin.web.contexts
  14. from MoinMoin.user import User
  15. from MoinMoin.wikiutil import isGroupPage, normalize_pagename
  16. from MoinMoin.PageEditor import PageEditor
  17. from MoinMoin.datastruct.backends.wiki_groups import WikiGroup
  18. from MoinMoin.datastruct.backends import GroupDoesNotExistError
  19. from editing import _test, _doctest_request
  20. user_re = re.compile('(^ +\*\s*(.+)$\n?)', re.M)
  21. class GroupException(Exception):
  22. pass
  23. def groups_by_user(request, account, recursive=False):
  24. _ = request.getText
  25. if not account:
  26. raise GroupException(_('No account specified.'))
  27. if not User(request, name=account).exists():
  28. raise GroupException(_('User not valid: ') + account)
  29. wiki_groups = set(group for group in
  30. request.groups.groups_with_member(account) if
  31. isinstance(request.groups[group], WikiGroup))
  32. if recursive:
  33. return wiki_groups
  34. else:
  35. return set(gn for gn in wiki_groups if
  36. account in request.groups[gn].members)
  37. def groups_by_user_transitive(request, account):
  38. """
  39. Returns the groups where the user is a member, as well as the
  40. groups which in turn have these groups as members.
  41. """
  42. real_groups = groups_by_user(request, account, recursive=False)
  43. recursive_groups = groups_by_user(request, account, recursive=True)
  44. return real_groups, recursive_groups - real_groups
  45. def users_by_group(request, grouppage, recursive=False):
  46. _ = request.getText
  47. success, msg = check_grouppage(request, grouppage, writecheck=False)
  48. if not success:
  49. raise GroupException(msg + "(%s)" % (grouppage))
  50. if recursive:
  51. return request.groups[grouppage]
  52. else:
  53. return request.groups[grouppage].members
  54. def check_grouppage(request, grouppage, writecheck=True, createcheck=True):
  55. _ = request.getText
  56. grouppage = normalize_pagename(grouppage, request.cfg)
  57. if not isGroupPage(grouppage, request.cfg):
  58. return False, _("Invalid group name.")
  59. if writecheck:
  60. if not request.user.may.write(grouppage):
  61. return False, _("You are not allowed to edit this page.")
  62. if createcheck:
  63. try:
  64. if not isinstance(request.groups[grouppage], WikiGroup):
  65. return False, _("Invalid group.")
  66. except GroupDoesNotExistError:
  67. return False, _("Invalid group.")
  68. return True, ''
  69. def check_users(request, accounts):
  70. _ = request.getText
  71. if not accounts:
  72. raise GroupException(_('No accounts specified.'))
  73. for uname in accounts:
  74. if not User(request, name=uname).exists():
  75. raise GroupException(_('User not valid: ') + uname)
  76. def _group_add(request, pagetext, userlist):
  77. """
  78. >>> request = _doctest_request()
  79. >>> s = u"= @PAGE@ =\\n" + \
  80. u" * [[user2]]\\n" + \
  81. u" * [[user1]]\\n"
  82. >>> _group_add(request, s, ['user3'])
  83. u'= @PAGE@ =\\n * [[user3]]\\n * [[user2]]\\n * [[user1]]\\n'
  84. >>> s = u"#acl user:read,write,delete,revert,admin All:read\\n\\n" + \
  85. u" * [[user2]]\\n" + \
  86. u" * [[user1]]\\n"
  87. >>> _group_add(request, s, ['user3'])
  88. u'#acl user:read,write,delete,revert,admin All:read\\n\\n * [[user3]]\\n * [[user2]]\\n * [[user1]]\\n'
  89. >>> s = u''
  90. >>> _group_add(request, s, ['user3', 'user2'])
  91. u' * [[user2]]\\n * [[user3]]\\n'
  92. >>> s = u'This is a group page\\n'
  93. >>> _group_add(request, s, ['user3', 'user2'])
  94. u'This is a group page\\n * [[user2]]\\n * [[user3]]\\n'
  95. """
  96. if not userlist:
  97. return pagetext
  98. # Empty pages with only whitespace
  99. if not re.sub('\s', '', pagetext):
  100. pagetext = ''
  101. #
  102. if not user_re.findall(pagetext):
  103. pagetext += u' * [[%s]]\n' % userlist[0]
  104. userlist = userlist[1:]
  105. for user in userlist:
  106. pagetext = user_re.subn(r' * [[%s]]\n\1' % user, pagetext, 1)[0]
  107. return pagetext
  108. def _group_rename(request, pagetext, userlist):
  109. """
  110. >>> request = _doctest_request()
  111. >>> s = u"= @PAGE@ =\\n" + \
  112. u" * [[user2]]\\n" + \
  113. u" * [[user1]]\\n"
  114. Rename needs even-sized lists
  115. >>> _group_rename(request, s, ['user2'])
  116. u'= @PAGE@ =\\n * [[user2]]\\n * [[user1]]\\n'
  117. >>> _group_rename(request, s, ['user2', 'user3'])
  118. u'= @PAGE@ =\\n * [[user3]]\\n * [[user1]]\\n'
  119. >>> _group_rename(request, s, ['user1', 'user3'])
  120. u'= @PAGE@ =\\n * [[user3]]\\n * [[user2]]\\n'
  121. >>> _group_rename(request, s, ['user1', 'user3', 'user2', 'user4'])
  122. u'= @PAGE@ =\\n * [[user4]]\\n * [[user3]]\\n'
  123. >>> s = u"= @PAGE@ =\\n * [[user2]]\\n * [[user1]]\\n * [[user1]]\\n"
  124. >>> _group_rename(request, s, ['user1', 'user3'])
  125. u'= @PAGE@ =\\n * [[user3]]\\n * [[user2]]\\n'
  126. >>> s = u" * [[user2]]\\n"
  127. >>> _group_rename(request, s, ['user2', 'user3'])
  128. u' * [[user3]]\\n'
  129. """
  130. if not len(userlist) % 2:
  131. for user1, user2 in zip(userlist[::2], userlist[1::2]):
  132. pagetext = _group_del(request, pagetext, [user1])
  133. pagetext = _group_add(request, pagetext, [user2])
  134. return pagetext
  135. def _group_del(request, pagetext, userlist):
  136. """
  137. >>> request = _doctest_request()
  138. >>> s = u"= @PAGE@ =\\n" + \
  139. u" * [[user2]]\\n" + \
  140. u" * [[user1]]\\n"
  141. Basic functions
  142. >>> _group_del(request, s, ['user2'])
  143. u'= @PAGE@ =\\n * [[user1]]\\n'
  144. >>> _group_del(request, s, ['user3'])
  145. u'= @PAGE@ =\\n * [[user2]]\\n * [[user1]]\\n'
  146. Double users might cause problems
  147. >>> s += u" * [[user1]]\\n"
  148. >>> _group_del(request, s, ['user1'])
  149. u'= @PAGE@ =\\n * [[user2]]\\n'
  150. >>> s = u" * [[user1]]\\n"
  151. >>> _group_del(request, s, ['user1'])
  152. u'\\n'
  153. """
  154. for user in userlist:
  155. pagetext = re.sub('(?m)(^\s+\*\s*(\[\[%s\]\])$\n?)' % user, '',
  156. pagetext)
  157. # empty group pages cannot be saved
  158. if not pagetext:
  159. pagetext = u'\n'
  160. return pagetext
  161. def group_add(request, grouppage, accounts, create=False, usercheck=True):
  162. _ = request.getText
  163. success, msg = check_grouppage(request, grouppage, createcheck=not create)
  164. if not success:
  165. raise GroupException(msg + "(%s)" % (grouppage))
  166. if usercheck:
  167. check_users(request, accounts)
  168. page = PageEditor(request, grouppage)
  169. if page.exists():
  170. members = request.groups[grouppage].members | request.groups[grouppage].member_groups
  171. elif create:
  172. members = set([])
  173. else:
  174. raise GroupException(_('Group does not exist: ') + grouppage)
  175. for item in accounts:
  176. if item in members:
  177. raise GroupException(item + _(' already in group: ') + grouppage)
  178. pagetext = page.get_raw_body()
  179. if not pagetext:
  180. pagetext = ''
  181. newtext = _group_add(request, pagetext, accounts)
  182. msg = page.saveText(newtext, 0,
  183. comment="Added to group: " + ', '.join(accounts))
  184. newmembers = request.groups[grouppage].members | request.groups[grouppage].member_groups
  185. if not newmembers == members | set(accounts):
  186. msg = page.saveText(pagetext, 0,
  187. comment="Reverting due to problems in group operation.")
  188. raise GroupException(_('Add unsuccessful for unknown reasons.'))
  189. return True, msg
  190. def group_del(request, grouppage, accounts):
  191. _ = request.getText
  192. success, msg = check_grouppage(request, grouppage)
  193. if not success:
  194. raise GroupException(msg + "(%s)" % (grouppage))
  195. members = request.groups[grouppage].members | request.groups[grouppage].member_groups
  196. for name in accounts:
  197. if name not in members:
  198. raise GroupException(name + _(' not in group: ') + grouppage)
  199. page = PageEditor(request, grouppage)
  200. pagetext = page.get_raw_body()
  201. newtext = _group_del(request, pagetext, accounts)
  202. msg = page.saveText(newtext, 0,
  203. comment="Deleted from group: " +
  204. ', '.join(accounts))
  205. newmembers = request.groups[grouppage].members | request.groups[grouppage].member_groups
  206. if not newmembers == members - set(accounts):
  207. msg = page.saveText(pagetext, 0,
  208. comment="Reverting due to problems in group operation.")
  209. raise GroupException(_('Delete unsuccessful for unknown reasons.'))
  210. return True, msg
  211. def group_rename(request, grouppage, accounts):
  212. _ = request.getText
  213. success, msg = check_grouppage(request, grouppage)
  214. if not success:
  215. raise GroupException(msg + "(%s)" % (grouppage))
  216. check_users(request, accounts[::2])
  217. if len(accounts) % 2:
  218. raise ValueError(_('Wrong number of arguments for rename.'))
  219. page = PageEditor(request, grouppage)
  220. if page.exists():
  221. members = request.groups[grouppage].members
  222. else:
  223. raise GroupException(_('Group does not exist: ') + grouppage)
  224. for uname in accounts[::2]:
  225. if uname not in members:
  226. raise GroupException(_('User not in group: ') + uname)
  227. page = PageEditor(request, grouppage)
  228. pagetext = page.get_raw_body()
  229. newtext = _group_rename(request, pagetext, accounts)
  230. msg = page.saveText(newtext, 0,
  231. comment="Changed group members: " +
  232. ' -> '.join(accounts))
  233. newmembers = request.groups[grouppage].members
  234. testmembers = members.copy()
  235. for user1, user2 in zip(accounts[::2], accounts[1::2]):
  236. testmembers.remove(user1)
  237. testmembers.add(user2)
  238. if testmembers != newmembers:
  239. msg = page.saveText(pagetext, 0,
  240. comment="Reverting due to problems in group operation.")
  241. raise GroupException(_('Rename unsuccessful for unknown reasons.'))
  242. return True, msg
  243. if __name__ == "__main__":
  244. _test()