Ralfp 12 лет назад
Родитель
Сommit
80a019e2b6
336 измененных файлов с 0 добавлено и 18698 удалено
  1. 0 0
      notrefactored/acl/__init__.py
  2. 0 92
      notrefactored/acl/builder.py
  3. 0 7
      notrefactored/acl/context_processors.py
  4. 0 9
      notrefactored/acl/fixtures.py
  5. 0 13
      notrefactored/acl/middleware.py
  6. 0 30
      notrefactored/acl/panels.py
  7. 0 17
      notrefactored/acl/utils.py
  8. 0 0
      notrefactored/activation/__init__.py
  9. 0 34
      notrefactored/activation/forms.py
  10. 0 6
      notrefactored/activation/urls.py
  11. 0 92
      notrefactored/activation/views.py
  12. 0 280
      notrefactored/admin/__init__.py
  13. 0 29
      notrefactored/admin/acl.py
  14. 0 4
      notrefactored/admin/context_processors.py
  15. 0 0
      notrefactored/admin/layout/__init__.py
  16. 0 96
      notrefactored/admin/layout/forums.py
  17. 0 72
      notrefactored/admin/layout/overview.py
  18. 0 70
      notrefactored/admin/layout/perms.py
  19. 0 30
      notrefactored/admin/layout/sections.py
  20. 0 49
      notrefactored/admin/layout/system.py
  21. 0 162
      notrefactored/admin/layout/users.py
  22. 0 15
      notrefactored/admin/views.py
  23. 0 552
      notrefactored/admin/widgets.py
  24. 0 0
      notrefactored/alerts/__init__.py
  25. 0 0
      notrefactored/alerts/management/__init__.py
  26. 0 0
      notrefactored/alerts/management/commands/__init__.py
  27. 0 13
      notrefactored/alerts/management/commands/clearalerts.py
  28. 0 119
      notrefactored/alerts/migrations/0001_initial.py
  29. 0 0
      notrefactored/alerts/migrations/__init__.py
  30. 0 74
      notrefactored/alerts/models.py
  31. 0 51
      notrefactored/alerts/views.py
  32. 0 0
      notrefactored/authn/__init__.py
  33. 0 20
      notrefactored/authn/decorators.py
  34. 0 51
      notrefactored/authn/fixtures.py
  35. 0 30
      notrefactored/authn/forms.py
  36. 0 125
      notrefactored/authn/methods.py
  37. 0 13
      notrefactored/authn/urls.py
  38. 0 113
      notrefactored/authn/views.py
  39. 0 0
      notrefactored/banning/__init__.py
  40. 0 7
      notrefactored/banning/context_processors.py
  41. 0 12
      notrefactored/banning/decorators.py
  42. 0 4
      notrefactored/banning/fixtures.py
  43. 0 56
      notrefactored/banning/forms.py
  44. 0 17
      notrefactored/banning/middleware.py
  45. 0 40
      notrefactored/banning/migrations/0001_initial.py
  46. 0 0
      notrefactored/banning/migrations/__init__.py
  47. 0 84
      notrefactored/banning/models.py
  48. 0 169
      notrefactored/banning/views.py
  49. 0 0
      notrefactored/bruteforce/__init__.py
  50. 0 7
      notrefactored/bruteforce/context_processors.py
  51. 0 13
      notrefactored/bruteforce/decorators.py
  52. 0 46
      notrefactored/bruteforce/fixtures.py
  53. 0 0
      notrefactored/bruteforce/management/__init__.py
  54. 0 0
      notrefactored/bruteforce/management/commands/__init__.py
  55. 0 12
      notrefactored/bruteforce/management/commands/clearattempts.py
  56. 0 13
      notrefactored/bruteforce/middleware.py
  57. 0 34
      notrefactored/bruteforce/migrations/0001_initial.py
  58. 0 0
      notrefactored/bruteforce/migrations/__init__.py
  59. 0 54
      notrefactored/bruteforce/models.py
  60. 0 30
      notrefactored/captcha/__init__.py
  61. 0 69
      notrefactored/captcha/fixtures.py
  62. 0 10
      notrefactored/context_processors.py
  63. 0 0
      notrefactored/cookie_jar/__init__.py
  64. 0 41
      notrefactored/cookie_jar/cookie_jar.py
  65. 0 12
      notrefactored/cookie_jar/middleware.py
  66. 0 0
      notrefactored/crawlers/__init__.py
  67. 0 23
      notrefactored/crawlers/crawler.py
  68. 0 16
      notrefactored/crawlers/database.py
  69. 0 9
      notrefactored/crawlers/decorators.py
  70. 0 15
      notrefactored/crawlers/middleware.py
  71. 0 7
      notrefactored/csrf/__init__.py
  72. 0 8
      notrefactored/csrf/context_processors.py
  73. 0 10
      notrefactored/csrf/decorators.py
  74. 0 13
      notrefactored/csrf/middleware.py
  75. 0 0
      notrefactored/firewalls/__init__.py
  76. 0 39
      notrefactored/firewalls/firewalls.py
  77. 0 17
      notrefactored/firewalls/middleware.py
  78. 0 175
      notrefactored/forms/__init__.py
  79. 0 299
      notrefactored/forms/layouts.py
  80. 0 0
      notrefactored/forumroles/__init__.py
  81. 0 114
      notrefactored/forumroles/fixtures.py
  82. 0 20
      notrefactored/forumroles/forms.py
  83. 0 34
      notrefactored/forumroles/migrations/0001_initial.py
  84. 0 0
      notrefactored/forumroles/migrations/__init__.py
  85. 0 36
      notrefactored/forumroles/models.py
  86. 0 143
      notrefactored/forumroles/views.py
  87. 0 0
      notrefactored/forums/__init__.py
  88. 0 77
      notrefactored/forums/acl.py
  89. 0 58
      notrefactored/forums/fixtures.py
  90. 0 180
      notrefactored/forums/forms.py
  91. 0 0
      notrefactored/forums/management/__init__.py
  92. 0 0
      notrefactored/forums/management/commands/__init__.py
  93. 0 12
      notrefactored/forums/management/commands/syncdeltas.py
  94. 0 235
      notrefactored/forums/migrations/0001_initial.py
  95. 0 0
      notrefactored/forums/migrations/__init__.py
  96. 0 220
      notrefactored/forums/models.py
  97. 0 4
      notrefactored/forums/signals.py
  98. 0 347
      notrefactored/forums/views.py
  99. 0 0
      notrefactored/heartbeat/__init__.py
  100. 0 8
      notrefactored/heartbeat/middleware.py
  101. 0 60
      notrefactored/markdown/__init__.py
  102. 0 0
      notrefactored/markdown/extensions/__init__.py
  103. 0 45
      notrefactored/markdown/extensions/magiclinks.py
  104. 0 58
      notrefactored/markdown/extensions/mentions.py
  105. 0 58
      notrefactored/markdown/extensions/quotes.py
  106. 0 115
      notrefactored/markdown/factory.py
  107. 0 39
      notrefactored/messages/__init__.py
  108. 0 7
      notrefactored/messages/context_processors.py
  109. 0 5
      notrefactored/messages/middleware.py
  110. 0 0
      notrefactored/monitor/__init__.py
  111. 0 7
      notrefactored/monitor/context_processors.py
  112. 0 11
      notrefactored/monitor/fixtures.py
  113. 0 5
      notrefactored/monitor/middleware.py
  114. 0 34
      notrefactored/monitor/migrations/0001_initial.py
  115. 0 0
      notrefactored/monitor/migrations/__init__.py
  116. 0 6
      notrefactored/monitor/models.py
  117. 0 65
      notrefactored/monitor/monitor.py
  118. 0 0
      notrefactored/newsfeed/__init__.py
  119. 0 22
      notrefactored/newsfeed/views.py
  120. 0 0
      notrefactored/newsletters/__init__.py
  121. 0 55
      notrefactored/newsletters/forms.py
  122. 0 70
      notrefactored/newsletters/migrations/0001_initial.py
  123. 0 0
      notrefactored/newsletters/migrations/__init__.py
  124. 0 33
      notrefactored/newsletters/models.py
  125. 0 200
      notrefactored/newsletters/views.py
  126. 0 0
      notrefactored/profiles/__init__.py
  127. 0 37
      notrefactored/profiles/decorators.py
  128. 0 0
      notrefactored/profiles/details/__init__.py
  129. 0 4
      notrefactored/profiles/details/profile.py
  130. 0 14
      notrefactored/profiles/details/urls.py
  131. 0 10
      notrefactored/profiles/details/views.py
  132. 0 0
      notrefactored/profiles/followers/__init__.py
  133. 0 4
      notrefactored/profiles/followers/profile.py
  134. 0 16
      notrefactored/profiles/followers/urls.py
  135. 0 17
      notrefactored/profiles/followers/views.py
  136. 0 0
      notrefactored/profiles/follows/__init__.py
  137. 0 4
      notrefactored/profiles/follows/profile.py
  138. 0 16
      notrefactored/profiles/follows/urls.py
  139. 0 17
      notrefactored/profiles/follows/views.py
  140. 0 6
      notrefactored/profiles/forms.py
  141. 0 0
      notrefactored/profiles/posts/__init__.py
  142. 0 4
      notrefactored/profiles/posts/profile.py
  143. 0 16
      notrefactored/profiles/posts/urls.py
  144. 0 17
      notrefactored/profiles/posts/views.py
  145. 0 55
      notrefactored/profiles/template.py
  146. 0 0
      notrefactored/profiles/threads/__init__.py
  147. 0 4
      notrefactored/profiles/threads/profile.py
  148. 0 16
      notrefactored/profiles/threads/urls.py
  149. 0 17
      notrefactored/profiles/threads/views.py
  150. 0 25
      notrefactored/profiles/urls.py
  151. 0 87
      notrefactored/profiles/views.py
  152. 0 0
      notrefactored/prune/__init__.py
  153. 0 32
      notrefactored/prune/forms.py
  154. 0 40
      notrefactored/prune/migrations/0001_initial.py
  155. 0 0
      notrefactored/prune/migrations/__init__.py
  156. 0 52
      notrefactored/prune/models.py
  157. 0 212
      notrefactored/prune/views.py
  158. 0 0
      notrefactored/ranks/__init__.py
  159. 0 129
      notrefactored/ranks/fixtures.py
  160. 0 44
      notrefactored/ranks/forms.py
  161. 0 0
      notrefactored/ranks/management/__init__.py
  162. 0 0
      notrefactored/ranks/management/commands/__init__.py
  163. 0 37
      notrefactored/ranks/management/commands/updateranking.py
  164. 0 50
      notrefactored/ranks/migrations/0001_initial.py
  165. 0 0
      notrefactored/ranks/migrations/__init__.py
  166. 0 91
      notrefactored/ranks/models.py
  167. 0 150
      notrefactored/ranks/views.py
  168. 0 0
      notrefactored/readstracker/__init__.py
  169. 0 0
      notrefactored/readstracker/management/__init__.py
  170. 0 0
      notrefactored/readstracker/management/commands/__init__.py
  171. 0 15
      notrefactored/readstracker/management/commands/cleartracker.py
  172. 0 217
      notrefactored/readstracker/migrations/0001_initial.py
  173. 0 234
      notrefactored/readstracker/migrations/0002_auto__add_threadrecord__del_field_record_threads.py
  174. 0 221
      notrefactored/readstracker/migrations/0003_auto__del_record__add_forumrecord.py
  175. 0 0
      notrefactored/readstracker/migrations/__init__.py
  176. 0 37
      notrefactored/readstracker/models.py
  177. 0 99
      notrefactored/readstracker/trackers.py
  178. 0 0
      notrefactored/register/__init__.py
  179. 0 102
      notrefactored/register/fixtures.py
  180. 0 81
      notrefactored/register/forms.py
  181. 0 5
      notrefactored/register/urls.py
  182. 0 88
      notrefactored/register/views.py
  183. 0 0
      notrefactored/resetpswd/__init__.py
  184. 0 34
      notrefactored/resetpswd/forms.py
  185. 0 6
      notrefactored/resetpswd/urls.py
  186. 0 94
      notrefactored/resetpswd/views.py
  187. 0 0
      notrefactored/roles/__init__.py
  188. 0 50
      notrefactored/roles/fixtures.py
  189. 0 26
      notrefactored/roles/forms.py
  190. 0 38
      notrefactored/roles/migrations/0001_initial.py
  191. 0 0
      notrefactored/roles/migrations/__init__.py
  192. 0 40
      notrefactored/roles/models.py
  193. 0 261
      notrefactored/roles/views.py
  194. 0 85
      notrefactored/search/__init__.py
  195. 0 0
      notrefactored/sessions/__init__.py
  196. 0 27
      notrefactored/sessions/forms.py
  197. 0 0
      notrefactored/sessions/management/__init__.py
  198. 0 0
      notrefactored/sessions/management/commands/__init__.py
  199. 0 14
      notrefactored/sessions/management/commands/clearsessions.py
  200. 0 13
      notrefactored/sessions/management/commands/cleartokens.py
  201. 0 30
      notrefactored/sessions/middleware.py
  202. 0 154
      notrefactored/sessions/migrations/0001_initial.py
  203. 0 0
      notrefactored/sessions/migrations/__init__.py
  204. 0 22
      notrefactored/sessions/models.py
  205. 0 247
      notrefactored/sessions/sessions.py
  206. 0 45
      notrefactored/sessions/views.py
  207. 0 0
      notrefactored/settings/__init__.py
  208. 0 7
      notrefactored/settings/context_processors.py
  209. 0 146
      notrefactored/settings/fixtures.py
  210. 0 5
      notrefactored/settings/forms.py
  211. 0 5
      notrefactored/settings/middleware.py
  212. 0 69
      notrefactored/settings/migrations/0001_initial.py
  213. 0 0
      notrefactored/settings/migrations/__init__.py
  214. 0 144
      notrefactored/settings/models.py
  215. 0 71
      notrefactored/settings/settings.py
  216. 0 115
      notrefactored/settings/views.py
  217. 0 0
      notrefactored/setup/__init__.py
  218. 0 34
      notrefactored/setup/fixtures.py
  219. 0 0
      notrefactored/setup/management/__init__.py
  220. 0 0
      notrefactored/setup/management/commands/__init__.py
  221. 0 37
      notrefactored/setup/management/commands/about.py
  222. 0 47
      notrefactored/setup/management/commands/initdata.py
  223. 0 15
      notrefactored/setup/management/commands/initmisago.py
  224. 0 14
      notrefactored/setup/management/commands/updmisago.py
  225. 0 32
      notrefactored/setup/migrations/0001_initial.py
  226. 0 0
      notrefactored/setup/migrations/__init__.py
  227. 0 4
      notrefactored/setup/models.py
  228. 0 0
      notrefactored/stats/__init__.py
  229. 0 28
      notrefactored/stats/forms.py
  230. 0 170
      notrefactored/stats/views.py
  231. 0 7
      notrefactored/stopwatch/__init__.py
  232. 0 16
      notrefactored/stopwatch/middleware.py
  233. 0 0
      notrefactored/team/__init__.py
  234. 0 16
      notrefactored/team/views.py
  235. 0 0
      notrefactored/template/__init__.py
  236. 0 0
      notrefactored/template/templatetags/__init__.py
  237. 0 168
      notrefactored/template/templatetags/django2jinja.py
  238. 0 0
      notrefactored/themes/__init__.py
  239. 0 51
      notrefactored/themes/forms.py
  240. 0 24
      notrefactored/themes/middleware.py
  241. 0 34
      notrefactored/themes/migrations/0001_initial.py
  242. 0 0
      notrefactored/themes/migrations/__init__.py
  243. 0 25
      notrefactored/themes/models.py
  244. 0 55
      notrefactored/themes/theme.py
  245. 0 109
      notrefactored/themes/views.py
  246. 0 0
      notrefactored/threads/__init__.py
  247. 0 587
      notrefactored/threads/acl.py
  248. 0 127
      notrefactored/threads/fixtures.py
  249. 0 226
      notrefactored/threads/forms.py
  250. 0 0
      notrefactored/threads/management/__init__.py
  251. 0 0
      notrefactored/threads/management/commands/__init__.py
  252. 0 18
      notrefactored/threads/management/commands/updatethreadranking.py
  253. 0 382
      notrefactored/threads/migrations/0001_initial.py
  254. 0 0
      notrefactored/threads/migrations/__init__.py
  255. 0 392
      notrefactored/threads/models.py
  256. 0 6
      notrefactored/threads/signals.py
  257. 0 161
      notrefactored/threads/tests.py
  258. 0 40
      notrefactored/threads/testutils.py
  259. 0 34
      notrefactored/threads/urls.py
  260. 0 9
      notrefactored/threads/views/__init__.py
  261. 0 14
      notrefactored/threads/views/base.py
  262. 0 125
      notrefactored/threads/views/changelog.py
  263. 0 106
      notrefactored/threads/views/delete.py
  264. 0 41
      notrefactored/threads/views/details.py
  265. 0 242
      notrefactored/threads/views/jumps.py
  266. 0 43
      notrefactored/threads/views/karmas.py
  267. 0 392
      notrefactored/threads/views/list.py
  268. 0 435
      notrefactored/threads/views/posting.py
  269. 0 566
      notrefactored/threads/views/thread.py
  270. 0 87
      notrefactored/timezones/__init__.py
  271. 0 0
      notrefactored/tos/__init__.py
  272. 0 43
      notrefactored/tos/fixtures.py
  273. 0 8
      notrefactored/tos/views.py
  274. 0 0
      notrefactored/usercp/__init__.py
  275. 0 81
      notrefactored/usercp/acl.py
  276. 0 0
      notrefactored/usercp/avatar/__init__.py
  277. 0 32
      notrefactored/usercp/avatar/forms.py
  278. 0 21
      notrefactored/usercp/avatar/urls.py
  279. 0 4
      notrefactored/usercp/avatar/usercp.py
  280. 0 228
      notrefactored/usercp/avatar/views.py
  281. 0 0
      notrefactored/usercp/credentials/__init__.py
  282. 0 52
      notrefactored/usercp/credentials/forms.py
  283. 0 17
      notrefactored/usercp/credentials/urls.py
  284. 0 4
      notrefactored/usercp/credentials/usercp.py
  285. 0 72
      notrefactored/usercp/credentials/views.py
  286. 0 47
      notrefactored/usercp/fixtures.py
  287. 0 117
      notrefactored/usercp/migrations/0001_initial.py
  288. 0 0
      notrefactored/usercp/migrations/__init__.py
  289. 0 6
      notrefactored/usercp/models.py
  290. 0 0
      notrefactored/usercp/options/__init__.py
  291. 0 42
      notrefactored/usercp/options/forms.py
  292. 0 11
      notrefactored/usercp/options/urls.py
  293. 0 4
      notrefactored/usercp/options/usercp.py
  294. 0 40
      notrefactored/usercp/options/views.py
  295. 0 0
      notrefactored/usercp/signature/__init__.py
  296. 0 16
      notrefactored/usercp/signature/forms.py
  297. 0 11
      notrefactored/usercp/signature/urls.py
  298. 0 5
      notrefactored/usercp/signature/usercp.py
  299. 0 47
      notrefactored/usercp/signature/views.py
  300. 0 25
      notrefactored/usercp/template.py
  301. 0 22
      notrefactored/usercp/urls.py
  302. 0 0
      notrefactored/usercp/username/__init__.py
  303. 0 31
      notrefactored/usercp/username/forms.py
  304. 0 11
      notrefactored/usercp/username/urls.py
  305. 0 5
      notrefactored/usercp/username/usercp.py
  306. 0 73
      notrefactored/usercp/username/views.py
  307. 0 76
      notrefactored/usercp/views.py
  308. 0 0
      notrefactored/users/__init__.py
  309. 0 60
      notrefactored/users/acl.py
  310. 0 7
      notrefactored/users/context_processors.py
  311. 0 13
      notrefactored/users/fixtures.py
  312. 0 209
      notrefactored/users/forms.py
  313. 0 0
      notrefactored/users/management/__init__.py
  314. 0 0
      notrefactored/users/management/commands/__init__.py
  315. 0 39
      notrefactored/users/management/commands/adduser.py
  316. 0 67
      notrefactored/users/management/commands/genavatars.py
  317. 0 12
      notrefactored/users/management/commands/syncusermonitor.py
  318. 0 28
      notrefactored/users/middleware.py
  319. 0 192
      notrefactored/users/migrations/0001_initial.py
  320. 0 0
      notrefactored/users/migrations/__init__.py
  321. 0 537
      notrefactored/users/models.py
  322. 0 4
      notrefactored/users/signals.py
  323. 0 64
      notrefactored/users/validators.py
  324. 0 374
      notrefactored/users/views.py
  325. 0 94
      notrefactored/utils/__init__.py
  326. 0 46
      notrefactored/utils/avatars.py
  327. 0 11
      notrefactored/utils/slugify.py
  328. 0 15
      notrefactored/utils/validators.py
  329. 0 203
      notrefactored/views.py
  330. 0 0
      notrefactored/watcher/__init__.py
  331. 0 217
      notrefactored/watcher/migrations/0001_initial.py
  332. 0 0
      notrefactored/watcher/migrations/__init__.py
  333. 0 33
      notrefactored/watcher/models.py
  334. 0 8
      notrefactored/watcher/urls.py
  335. 0 40
      notrefactored/watcher/views.py
  336. 0 273
      refactoring.md

+ 0 - 0
notrefactored/acl/__init__.py


+ 0 - 92
notrefactored/acl/builder.py

@@ -1,92 +0,0 @@
-from django.conf import settings
-from django.core.cache import cache, InvalidCacheBackendError
-from django.utils.importlib import import_module
-from misago.forms import Form
-from misago.forums.models import Forum
-from misago.forumroles.models import ForumRole
-
-def build_form(request, role):
-    form_type = type('ACLForm', (Form,), dict(layout=[]))
-    for provider in settings.PERMISSION_PROVIDERS:
-        app_module = import_module(provider)
-        try:
-            app_module.make_form(request, role, form_type)
-        except AttributeError:
-            pass
-    return form_type
-
-
-def build_forum_form(request, role):
-    form_type = type('ACLForm', (Form,), dict(layout=[]))
-    for provider in settings.PERMISSION_PROVIDERS:
-        app_module = import_module(provider)
-        try:
-            app_module.make_forum_form(request, role, form_type)
-        except AttributeError:
-            pass
-    return form_type
-
-
-class BaseACL(object):
-    def __init__(self):
-        self.acl = {}
-
-    def __repr__(self):
-        return '%s (%s)' % (self.__class__.__name__[0:-3],
-                            self.__class__.__module__)
-
-
-class ACL(object):
-    def __init__(self, version):
-        self.version = version
-        self.team = False
-
-    def __iter__(self):
-        for attr in dir(self):
-            if not attr.startswith("__") and attr not in ['team', 'version']:
-                yield self.__dict__[attr]
-
-
-def get_acl(request, user):
-    acl_key = user.make_acl_key()
-    try:
-        user_acl = cache.get(acl_key)
-        if user_acl.version != request.monitor['acl_version']:
-            raise InvalidCacheBackendError()
-    except (AttributeError, InvalidCacheBackendError):
-        user_acl = build_acl(request, request.user.get_roles())
-        cache.set(acl_key, user_acl, 2592000)
-    return user_acl
-
-
-def build_acl(request, roles):
-    acl = ACL(request.monitor['acl_version'])
-    forums = Forum.objects.get(token='root').get_descendants().order_by('lft')
-    perms = []
-    forum_roles = {}
-
-    for role in roles:
-        perms.append(role.get_permissions())
-
-    for role in ForumRole.objects.all():
-        forum_roles[role.pk] = role.get_permissions()
-
-    for provider in settings.PERMISSION_PROVIDERS:
-        app_module = import_module(provider)
-        try:
-            app_module.build(acl, perms)
-        except AttributeError:
-            pass
-        try:
-            app_module.build_forums(acl, perms, forums, forum_roles)
-        except AttributeError:
-            pass
-
-    for provider in settings.PERMISSION_PROVIDERS:
-        app_module = import_module(provider)
-        try:
-            app_module.cleanup(acl, perms, forums)
-        except AttributeError:
-            pass
-
-    return acl

+ 0 - 7
notrefactored/acl/context_processors.py

@@ -1,7 +0,0 @@
-def acl(request):
-    try:
-        return {
-            'acl': request.acl,
-        }
-    except AttributeError:
-        pass

+ 0 - 9
notrefactored/acl/fixtures.py

@@ -1,9 +0,0 @@
-from misago.monitor.fixtures import load_monitor_fixture
-
-monitor_fixtures = {
-                  'acl_version': 0,
-                  }
-
-
-def load_fixtures():
-    load_monitor_fixture(monitor_fixtures)

+ 0 - 13
notrefactored/acl/middleware.py

@@ -1,13 +0,0 @@
-from misago.acl.builder import get_acl
-
-class ACLMiddleware(object):
-    def process_request(self, request):
-        request.acl = get_acl(request, request.user)
-        
-        if (request.user.is_authenticated() and
-            (request.acl.team or request.user.is_god()) != request.user.is_team):
-            request.user.is_team = (request.acl.team or request.user.is_god())
-            request.user.save(force_update=True)
-        if request.session.team != request.user.is_team:
-            request.session.team = request.user.is_team
-            request.session.save()

+ 0 - 30
notrefactored/acl/panels.py

@@ -1,30 +0,0 @@
-from debug_toolbar.panels import DebugPanel
-from django.template.loader import render_to_string
-from django.utils.translation import ugettext_lazy as _
-
-class MisagoACLDebugPanel(DebugPanel):
-    name = 'MisagoACL'
-    has_content = True
-
-    def nav_title(self):
-        return _('Misago ACL')
-
-    def title(self):
-        return _('Misago User ACL')
-
-    def url(self):
-        return ''
-
-    def process_request(self, request):
-        self.request = request
-
-    def content(self):
-        if self.request.heartbeat:
-            self.has_content = False
-        else:
-            context = self.context.copy()
-            try:
-                context['acl'] = self.request.acl
-            except AttributeError:
-                context['acl'] = {}
-            return render_to_string('debug_toolbar/panels/acl.html', context)

+ 0 - 17
notrefactored/acl/utils.py

@@ -1,17 +0,0 @@
-from misago.views import error403, error404
-
-class ACLError403(Exception):
-    pass
-
-class ACLError404(Exception):
-    pass
-
-def acl_errors(f):
-    def decorator(*args, **kwargs):
-        try:
-            return f(*args, **kwargs)
-        except ACLError403 as e:
-            return error403(args[0], e.message)
-        except ACLError404 as e:
-            return error404(args[0], e.message)
-    return decorator

+ 0 - 0
notrefactored/activation/__init__.py


+ 0 - 34
notrefactored/activation/forms.py

@@ -1,34 +0,0 @@
-import hashlib
-from django import forms
-from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-from misago import captcha
-from misago.users.models import User
-
-
-class UserSendActivationMailForm(Form):
-    email = forms.EmailField(max_length=255)
-    captcha_qa = captcha.QACaptchaField()
-    recaptcha = captcha.ReCaptchaField()
-    error_source = 'email'
-
-    layout = [
-              (
-               None,
-               [('email', {'label': _("Your E-mail Address"), 'help_text': _("Enter email address send activation e-mail to. It must be valid e-mail you used to register on forums."), 'attrs': {'placeholder': _("Enter your e-mail address.")}})]
-               ),
-              (
-               None,
-               ['captcha_qa', 'recaptcha']
-               ),
-              ]
-
-    def clean_email(self):
-        try:
-            email = self.cleaned_data['email'].lower()
-            email_hash = hashlib.md5(email).hexdigest()
-            self.found_user = User.objects.get(email_hash=email_hash)
-        except User.DoesNotExist:
-            raise ValidationError(_("There is no user with such e-mail address."))
-        return email

+ 0 - 6
notrefactored/activation/urls.py

@@ -1,6 +0,0 @@
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns('misago.activation.views',
-    url(r'^request/$', 'form', name="send_activation"),
-    url(r'^(?P<username>[a-z0-9]+)-(?P<user>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'activate', name="activate"),
-)

+ 0 - 92
notrefactored/activation/views.py

@@ -1,92 +0,0 @@
-from django.template import RequestContext
-from django.utils.translation import ugettext as _
-from misago.banning.models import check_ban
-from misago.banning.decorators import block_banned
-from misago.banning.views import error_banned
-from misago.crawlers.decorators import block_crawlers
-from misago.forms.layouts import FormLayout
-from misago.authn.methods import sign_user_in
-from misago.authn.decorators import block_authenticated
-from misago.activation.forms import UserSendActivationMailForm
-from misago.bruteforce.decorators import block_jammed
-from misago.messages import Message
-from misago.users.models import User
-from misago.views import redirect_message, error404
-
-
-@block_crawlers
-@block_banned
-@block_authenticated
-@block_jammed
-def form(request):
-    message = None
-    if request.method == 'POST':
-        form = UserSendActivationMailForm(request.POST, request=request)
-        if form.is_valid():
-            user = form.found_user
-            user_ban = check_ban(username=user.username, email=user.email)
-
-            if user_ban:
-                return error_banned(request, user, user_ban)
-
-            if user.activation == User.ACTIVATION_NONE:
-                return redirect_message(request, Message(_("%(username)s, your account is already active.") % {'username': user.username}), 'info')
-
-            if user.activation == User.ACTIVATION_ADMIN:
-                return redirect_message(request, Message(_("%(username)s, only board administrator can activate your account.") % {'username': user.username}), 'info')
-
-            user.email_user(
-                            request,
-                            'users/activation/resend',
-                            _("Account Activation"),
-                            )
-            return redirect_message(request, Message(_("%(username)s, e-mail containing new activation link has been sent to %(email)s.") % {'username': user.username, 'email': user.email}), 'success')
-        else:
-            message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = UserSendActivationMailForm(request=request)
-    return request.theme.render_to_response('resend_activation.html',
-                                            {
-                                             'message': message,
-                                             'form': FormLayout(form),
-                                            },
-                                            context_instance=RequestContext(request));
-
-
-@block_banned
-@block_authenticated
-@block_jammed
-def activate(request, username="", user="0", token=""):
-    user = int(user)
-
-    try:
-        user = User.objects.get(pk=user)
-        current_activation = user.activation
-
-        # Run checks
-        user_ban = check_ban(username=user.username, email=user.email)
-        if user_ban:
-            return error_banned(request, user, user_ban)
-
-        if user.activation == User.ACTIVATION_NONE:
-            return redirect_message(request, Message(_("%(username)s, your account is already active.") % {'username': user.username}), 'info')
-
-        if user.activation == User.ACTIVATION_ADMIN:
-            return redirect_message(request, Message(_("%(username)s, only board administrator can activate your account.") % {'username': user.username}), 'info')
-
-        if not token or not user.token or user.token != token:
-            return redirect_message(request, Message(_("%(username)s, your activation link is invalid. Try again or request new activation e-mail.") % {'username': user.username}), 'error')
-
-        # Activate and sign in our member
-        user.activation = User.ACTIVATION_NONE
-        sign_user_in(request, user)
-
-        # Update monitor
-        User.objects.resync_monitor(request.monitor)
-
-        if current_activation == User.ACTIVATION_CREDENTIALS:
-            return redirect_message(request, Message(_("%(username)s, your account has been successfully reactivated after change of sign-in credentials.") % {'username': user.username}), 'success')
-        else:
-            return redirect_message(request, Message(_("%(username)s, your account has been successfully activated. Welcome aboard!") % {'username': user.username}), 'success')
-    except User.DoesNotExist:
-        return error404(request)

+ 0 - 280
notrefactored/admin/__init__.py

@@ -1,280 +0,0 @@
-from django.conf import settings
-from django.conf.urls import patterns, include, url
-from django.core.urlresolvers import resolve
-from django.utils.importlib import import_module
-
-"""
-Clean admin path if it was defined, or leave variable empty if ACP is turned off.
-"""
-ADMIN_PATH = ''
-if settings.ADMIN_PATH:
-    ADMIN_PATH = settings.ADMIN_PATH
-    while ADMIN_PATH[:1] == '/':
-        ADMIN_PATH = ADMIN_PATH[1:]
-    while ADMIN_PATH[-1:] == '/':
-        ADMIN_PATH = ADMIN_PATH[:-1]
-    ADMIN_PATH += '/'
-
-
-"""
-Admin lists sorter for admin sections and actions
-"""
-class SortList(object):
-    def __init__(self, unsorted):
-        self.unsorted = unsorted
-
-    def sort(self):
-        # Sort and return sorted list
-        order = []
-        cache = {}
-        for item in self.unsorted:
-            if item.after:
-                try:
-                    cache[item.after].append(item.id)
-                except KeyError:
-                    cache[item.after] = []
-                    cache[item.after].append(item.id)
-            else:
-                order.append(item.id)
-        while cache:
-            for item in cache.keys():
-                try:
-                    target_index = order.index(item)
-                    for new_item in cache[item]:
-                        target_index += 1
-                        order.insert(target_index, new_item)
-                    del cache[item]
-                except ValueError:
-                    pass
-        sorted = []
-        for item in order:
-            for object in self.unsorted:
-                if item == object.id:
-                    sorted.append(object)
-                    break
-        return sorted
-
-
-"""
-Admin site section
-"""
-class AdminSiteItem(object):
-    def __init__(self, id, name, icon, target=None, route=None, help=None, after=None):
-        self.id = id
-        self.name = name
-        self.help = help
-        self.after = after
-        self.icon = icon
-        self.target = target
-        self.route = route
-        self.sorted = False
-
-
-"""
-Admin site action
-"""
-class AdminAction(AdminSiteItem):
-    def __init__(self, section=None, actions=[], model=None, messages={}, urlpatterns=None, **kwargs):
-        self.actions = actions
-        self.section = section
-        self.model = model
-        self.messages = messages
-        self.urlpatterns = urlpatterns
-        super(AdminAction, self).__init__(**kwargs)
-
-    def get_action_attr(self, id, attr):
-        for action in self.actions:
-            if action['id'] == id:
-                return action[attr]
-        return None
-
-    def is_active(self, full_path, section=None):
-        if section:
-            action_path = '/%s%s/%s/' % (ADMIN_PATH, section, self.id)
-        else:
-            action_path = '/%s%s/' % (ADMIN_PATH, self.id)
-        # Paths overlap = active action
-        return len(action_path) <= full_path and full_path[:len(action_path)] == action_path
-
-
-"""
-Admin site section
-"""
-class AdminSection(AdminSiteItem):
-    def __init__(self, section=None, **kwargs):
-        self.actions = []
-        self.last = None
-        super(AdminSection, self).__init__(**kwargs)
-
-    def get_routes(self):
-        routes = []
-        first_action = True
-        for action in self.actions:
-            if first_action:
-                routes += patterns('', url('^', include(action.urlpatterns)))
-                first_action = False
-            else:
-                routes += patterns('', url(('^%s/' % action.id), include(action.urlpatterns)))
-        return routes
-
-    def is_active(self, full_path):
-        action_path = '/%s%s/' % (ADMIN_PATH, self.id)
-        # Paths overlap = active action
-        return len(action_path) <= full_path and full_path[:len(action_path)] == action_path
-
-
-"""
-Admin site class that knows ACP structure
-"""
-class AdminSite(object):
-    actions_index = {}
-    routes = []
-    sections = []
-    sections_index = {}
-
-    def discover(self):
-        """
-        Build admin site structure
-        """
-        # Return discovered admin routes, so we dont repeat ourself
-        if self.routes:
-            return self.routes
-
-        # Found actions
-        actions = []
-
-        # Orphan actions that have no section yet
-        late_actions = []
-
-        # Load default admin site
-        from misago.admin.layout.sections import ADMIN_SECTIONS
-        for section in ADMIN_SECTIONS:
-            self.sections.append(section)
-            self.sections_index[section.id] = section
-
-            # Loop section actions
-            section_actions = import_module('misago.admin.layout.%s' % section.id)
-            for action in section_actions.ADMIN_ACTIONS:
-                self.actions_index[action.id] = action
-                if not action.after:
-                     action.after = self.sections_index[section.id].last
-                actions.append(action)
-                self.sections_index[section.id].last = action.after
-
-        # Iterate over installed applications
-        for app_name in settings.INSTALLED_APPS:
-            try:
-                app = import_module(app_name + '.admin')
-
-                # Attempt to import sections
-                try:
-                    for section in app.ADMIN_SECTIONS:
-                        self.sections.append(section)
-                        self.sections_index[section.id] = section
-                except AttributeError:
-                    pass
-
-                # Attempt to import actions
-                try:
-                    for action in app.ADMIN_ACTIONS:
-                        self.actions_index[action.id] = action
-                        if action.section in self.sections_index:
-                            if not action.after:
-                                 action.after = self.sections_index[action.section].last
-                            actions.append(action)
-                            self.sections_index[action.section].last = action.after
-                        else:
-                            late_actions.append(action)
-                except AttributeError:
-                    pass
-            except ImportError:
-                pass
-
-        # So actions and late actions
-        actions += late_actions
-
-        # Sorth sections and actions
-        sort_sections = SortList(self.sections)
-        sort_actions = SortList(actions)
-        self.sections = sort_sections.sort()
-        actions = sort_actions.sort()
-
-        # Put actions in sections
-        for action in actions:
-            self.sections_index[action.section].actions.append(action)
-
-        # Return ready admin routing
-        first_section = True
-        for section in self.sections:
-            if first_section:
-                self.routes += patterns('', url('^', include(section.get_routes())))
-                first_section = False
-            else:
-                self.routes += patterns('', url(('^%s/' % section.id), include(section.get_routes())))
-        return self.routes
-
-    def get_action(self, action):
-        """
-        Get admin action
-        """
-        return self.actions_index.get(action)
-
-    def get_admin_index(self):
-        """
-        Return admin index route - first action of first section
-        """
-        return self.sections[0].actions[0].route
-
-    def get_admin_navigation(self, request):
-        """
-        Find and return current admin navigation
-        """
-        sections = []
-        actions = []
-        active_section = False
-        active_action = False
-
-        # Loop sections, build list of sections and find active section
-        for section in self.sections:
-            is_active = section.is_active(request.path)
-            sections.append({
-                             'is_active': is_active,
-                             'name': section.name,
-                             'icon': section.icon,
-                             'route': section.actions[0].route
-                             })
-            if is_active:
-                active_section = section
-
-        # If no section was found to be active, default to first one
-        if not active_section:
-            active_section = self.sections[0]
-            sections[0]['is_active'] = True
-
-        # Loop active section actions
-        for action in active_section.actions:
-            is_active = action.is_active(request.path, active_section.id if active_section != self.sections[0] else None)
-            actions.append({
-                             'is_active': is_active,
-                             'name': action.name,
-                             'icon': action.icon,
-                             'help': action.help,
-                             'route': action.route
-                             })
-            if is_active:
-                active_action = action
-
-        # If no action was found to be active, default to first one
-        if not active_action:
-            active_action = active_section.actions[0]
-            actions[0]['is_active'] = True
-
-        # Return admin navigation for this location
-        return {
-                'sections': sections,
-                'actions': actions,
-                'admin_index': self.get_admin_index(),
-                }
-
-
-site = AdminSite();

+ 0 - 29
notrefactored/admin/acl.py

@@ -1,29 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.acl.builder import BaseACL
-from misago.forms import YesNoSwitch
-
-def make_form(request, role, form):
-    if not role.token and request.user.is_god():
-        form.base_fields['can_use_acp'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-        form.layout.append((
-                            _("Admin Control Panel"),
-                            (('can_use_acp', {'label': _("Can use Admin Control Panel"), 'help_text': _("Change this permission to yes to grant admin access for users with this role.")}),),
-                            ))
-
-
-class AdminACL(BaseACL):
-    def is_admin(self):
-        return self.acl['can_use_acp']
-
-
-def build(acl, roles):
-    acl.admin = AdminACL()
-    acl.admin.acl['can_use_acp'] = False
-
-    for role in roles:
-        if 'can_use_acp' in role and role['can_use_acp'] > acl.admin.acl['can_use_acp']:
-            acl.admin.acl['can_use_acp'] = role['can_use_acp']
-
-    if acl.admin.acl['can_use_acp']:
-        acl.team = True

+ 0 - 4
notrefactored/admin/context_processors.py

@@ -1,4 +0,0 @@
-from misago.admin import site
-
-def admin(request):
-    return site.get_admin_navigation(request)

+ 0 - 0
notrefactored/admin/layout/__init__.py


+ 0 - 96
notrefactored/admin/layout/forums.py

@@ -1,96 +0,0 @@
-from django.conf.urls import patterns, include, url
-from django.utils.translation import ugettext_lazy as _
-from misago.admin import AdminAction
-from misago.forums.models import Forum
-
-ADMIN_ACTIONS = (
-   AdminAction(
-               section='forums',
-               id='forums',
-               name=_("Forums List"),
-               help=_("Create, edit and delete forums."),
-               icon='comment',
-               model=Forum,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Forums List"),
-                         'help': _("All existing forums"),
-                         'route': 'admin_forums'
-                         },
-                        {
-                         'id': 'new_category',
-                         'name': _("New Category"),
-                         'help': _("Create new category"),
-                         'route': 'admin_forums_new_category'
-                         },
-                        {
-                         'id': 'new_forum',
-                         'name': _("New Forum"),
-                         'help': _("Create new forum"),
-                         'route': 'admin_forums_new_forum'
-                         },
-                        {
-                         'id': 'new_redirect',
-                         'name': _("New Redirect"),
-                         'help': _("Create new redirect"),
-                         'route': 'admin_forums_new_redirect'
-                         },
-                        ],
-               route='admin_forums',
-               urlpatterns=patterns('misago.forums.views',
-                        url(r'^$', 'List', name='admin_forums'),
-                        url(r'^new/category/$', 'NewCategory', name='admin_forums_new_category'),
-                        url(r'^new/forum/$', 'NewForum', name='admin_forums_new_forum'),
-                        url(r'^new/redirect/$', 'NewRedirect', name='admin_forums_new_redirect'),
-                        url(r'^up/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Up', name='admin_forums_up'),
-                        url(r'^down/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Down', name='admin_forums_down'),
-                        url(r'^edit/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Edit', name='admin_forums_edit'),
-                        url(r'^delete/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Delete', name='admin_forums_delete'),
-                    ),
-               ),
-   AdminAction(
-               section='forums',
-               id='labels',
-               name=_("Thread Labels"),
-               help=_("Thread Labels allow you to group threads together within forums."),
-               icon='tags',
-               route='admin_forums_labels',
-               urlpatterns=patterns('misago.admin.views',
-                        url(r'^$', 'todo', name='admin_forums_labels'),
-                    ),
-               ),
-   AdminAction(
-               section='forums',
-               id='badwords',
-               name=_("Words Filter"),
-               help=_("Forbid usage of words in messages"),
-               icon='volume-off',
-               route='admin_forums_badwords',
-               urlpatterns=patterns('misago.admin.views',
-                        url(r'^$', 'todo', name='admin_forums_badwords'),
-                    ),
-               ),
-   AdminAction(
-               section='forums',
-               id='tests',
-               name=_("Tests"),
-               help=_("Tests that new messages have to pass"),
-               icon='filter',
-               route='admin_forums_tests',
-               urlpatterns=patterns('misago.admin.views',
-                        url(r'^$', 'todo', name='admin_forums_tests'),
-                    ),
-               ),
-   AdminAction(
-               section='forums',
-               id='attachments',
-               name=_("Attachments"),
-               help=_("Manage allowed attachment types."),
-               icon='download-alt',
-               route='admin_forums_attachments',
-               urlpatterns=patterns('misago.admin.views',
-                        url(r'^$', 'todo', name='admin_forums_attachments'),
-                    ),
-               ),
-)

+ 0 - 72
notrefactored/admin/layout/overview.py

@@ -1,72 +0,0 @@
-from django.conf.urls import patterns, include, url
-from django.utils.translation import ugettext_lazy as _
-from misago.admin import AdminAction
-from misago.sessions.models import Session
-from misago.users.models import User
-
-ADMIN_ACTIONS = (
-   AdminAction(
-               section='overview',
-               id='home',
-               name=_("Home"),
-               help=_("Your forums right now"),
-               icon='home',
-               route='admin_home',
-               urlpatterns=patterns('misago.admin.views',
-                        url(r'^$', 'home', name='admin_home'),
-                    ),
-               ),
-   AdminAction(
-               section='overview',
-               id='stats',
-               name=_("Stats"),
-               help=_("Create Statistics Reports"),
-               icon='signal',
-               route='admin_stats',
-               urlpatterns=patterns('misago.stats.views',
-                        url(r'^$', 'form', name='admin_stats'),
-                        url(r'^(?P<model>[a-z0-9]+)/(?P<date_start>[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])/(?P<date_end>[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])/(?P<precision>\w+)$', 'graph', name='admin_stats_graph'),
-                    ),
-               ),
-   AdminAction(
-               section='overview',
-               id='online',
-               name=_("Online"),
-               help=_("See who is currently online on forums."),
-               icon='fire',
-               model=Session,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Browse Users"),
-                         'help': _("Browse all registered user accounts"),
-                         'route': 'admin_online'
-                         },
-                        ],
-               route='admin_online',
-               urlpatterns=patterns('misago.sessions.views',
-                        url(r'^$', 'List', name='admin_online'),
-                        url(r'^(?P<page>\d+)/$', 'List', name='admin_online'),
-                    ),
-               ),
-   AdminAction(
-               section='overview',
-               id='team',
-               name=_("Forum Team"),
-               help=_("List of all forum team members"),
-               icon='user',
-               model=User,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Forum Team Members"),
-                         'help': _("List of all forum team members"),
-                         'route': 'admin_team'
-                         },
-                        ],
-               route='admin_team',
-               urlpatterns=patterns('misago.team.views',
-                        url(r'^$', 'List', name='admin_team'),
-                    ),
-               ),
-)

+ 0 - 70
notrefactored/admin/layout/perms.py

@@ -1,70 +0,0 @@
-from django.conf.urls import patterns, include, url
-from django.utils.translation import ugettext_lazy as _
-from misago.admin import AdminAction
-from misago.roles.models import Role
-from misago.forumroles.models import ForumRole
-
-
-ADMIN_ACTIONS = (
-   AdminAction(
-               section='perms',
-               id='roles',
-               name=_("User Roles"),
-               help=_("Manage User Roles"),
-               icon='th-large',
-               model=Role,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Browse Roles"),
-                         'help': _("Browse all existing roles"),
-                         'route': 'admin_roles'
-                         },
-                        {
-                         'id': 'new',
-                         'name': _("Add Role"),
-                         'help': _("Create new role"),
-                         'route': 'admin_roles_new'
-                         },
-                        ],
-               route='admin_roles',
-               urlpatterns=patterns('misago.roles.views',
-                        url(r'^$', 'List', name='admin_roles'),
-                        url(r'^new/$', 'New', name='admin_roles_new'),
-                        url(r'^forums/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Forums', name='admin_roles_masks'),
-                        url(r'^acl/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'ACL', name='admin_roles_acl'),
-                        url(r'^edit/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Edit', name='admin_roles_edit'),
-                        url(r'^delete/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Delete', name='admin_roles_delete'),
-                    ),
-               ),
-   AdminAction(
-               section='perms',
-               id='roles_forums',
-               name=_("Forum Roles"),
-               help=_("Manage Forum Roles"),
-               icon='th-list',
-               model=ForumRole,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Browse Roles"),
-                         'help': _("Browse all existing roles"),
-                         'route': 'admin_roles_forums'
-                         },
-                        {
-                         'id': 'new',
-                         'name': _("Add Role"),
-                         'help': _("Create new role"),
-                         'route': 'admin_roles_forums_new'
-                         },
-                        ],
-               route='admin_roles_forums',
-               urlpatterns=patterns('misago.forumroles.views',
-                        url(r'^$', 'List', name='admin_roles_forums'),
-                        url(r'^new/$', 'New', name='admin_roles_forums_new'),
-                        url(r'^acl/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'ACL', name='admin_roles_forums_acl'),
-                        url(r'^edit/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Edit', name='admin_roles_forums_edit'),
-                        url(r'^delete/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Delete', name='admin_roles_forums_delete'),
-                    ),
-               ),
-)

+ 0 - 30
notrefactored/admin/layout/sections.py

@@ -1,30 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-from misago.admin import AdminSection
-
-ADMIN_SECTIONS = (
-    AdminSection(
-                 id='overview',
-                 name=_("Overview"),
-                 icon='signal',
-                 ),
-    AdminSection(
-                 id='users',
-                 name=_("Users"),
-                 icon='user',
-                 ),
-    AdminSection(
-                 id='forums',
-                 name=_("Forums"),
-                 icon='comment',
-                 ),
-    AdminSection(
-                 id='perms',
-                 name=_("Permissions"),
-                 icon='adjust',
-                 ),
-    AdminSection(
-                 id='system',
-                 name=_("System"),
-                 icon='cog',
-                 ),
-)

+ 0 - 49
notrefactored/admin/layout/system.py

@@ -1,49 +0,0 @@
-from django.conf.urls import patterns, include, url
-from django.utils.translation import ugettext_lazy as _
-from misago.admin import AdminAction
-from misago.themes.models import ThemeAdjustment
-
-ADMIN_ACTIONS = (
-   AdminAction(
-               section='system',
-               id='settings',
-               name=_("Settings"),
-               help=_("Change your forum configuration"),
-               icon='wrench',
-               route='admin_settings',
-               urlpatterns=patterns('misago.settings.views',
-                        url(r'^$', 'settings', name='admin_settings'),
-                        url(r'^search/$', 'settings_search', name='admin_settings_search'),
-                        url(r'^(?P<group_slug>([a-z0-9]|-)+)-(?P<group_id>\d+)/$', 'settings', name='admin_settings')
-                    ),
-               ),
-   AdminAction(
-               section='system',
-               id='clients',
-               name=_("Clients"),
-               help=_("Adjust presentation layer to clients"),
-               icon='tint',
-               model=ThemeAdjustment,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Browse Clients"),
-                         'help': _("Browse all existing clients"),
-                         'route': 'admin_clients'
-                         },
-                        {
-                         'id': 'new',
-                         'name': _("Add New Adjustment"),
-                         'help': _("Create new client adjustment"),
-                         'route': 'admin_clients_new'
-                         },
-                        ],
-               route='admin_clients',
-               urlpatterns=patterns('misago.themes.views',
-                        url(r'^$', 'List', name='admin_clients'),
-                        url(r'^new/$', 'New', name='admin_clients_new'),
-                        url(r'^edit/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Edit', name='admin_clients_edit'),
-                        url(r'^delete/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Delete', name='admin_clients_delete'),
-                    ),
-               ),
-)

+ 0 - 162
notrefactored/admin/layout/users.py

@@ -1,162 +0,0 @@
-from django.conf.urls import patterns, include, url
-from django.utils.translation import ugettext_lazy as _
-from misago.admin import AdminAction
-from misago.banning.models import Ban
-from misago.newsletters.models import Newsletter
-from misago.prune.models import Policy
-from misago.ranks.models import Rank
-from misago.users.models import User
-
-ADMIN_ACTIONS = (
-   AdminAction(
-               section='users',
-               id='users',
-               name=_("Users List"),
-               help=_("Search and browse users"),
-               icon='user',
-               model=User,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Browse Users"),
-                         'help': _("Browse all registered user accounts"),
-                         'route': 'admin_users'
-                         },
-                        {
-                         'id': 'new',
-                         'name': _("Add User"),
-                         'help': _("Create new user account"),
-                         'route': 'admin_users_new'
-                         },
-                        ],
-               route='admin_users',
-               urlpatterns=patterns('misago.users.views',
-                        url(r'^$', 'List', name='admin_users'),
-                        url(r'^(?P<page>\d+)/$', 'List', name='admin_users'),
-                        url(r'^inactive/$', 'inactive', name='admin_users_inactive'),
-                        url(r'^new/$', 'New', name='admin_users_new'),
-                        url(r'^edit/(?P<slug>[a-z0-9]+)-(?P<target>\d+)/$', 'Edit', name='admin_users_edit'),
-                        url(r'^delete/(?P<slug>[a-z0-9]+)-(?P<target>\d+)/$', 'Delete', name='admin_users_delete'),
-                    ),
-               ),
-   AdminAction(
-               section='users',
-               id='ranks',
-               name=_("Ranks"),
-               help=_("Administrate User Ranks"),
-               icon='star',
-               model=Rank,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Browse Ranks"),
-                         'help': _("Browse all existing ranks"),
-                         'route': 'admin_ranks'
-                         },
-                        {
-                         'id': 'new',
-                         'name': _("Add Rank"),
-                         'help': _("Create new rank"),
-                         'route': 'admin_ranks_new'
-                         },
-                        ],
-               route='admin_ranks',
-               urlpatterns=patterns('misago.ranks.views',
-                        url(r'^$', 'List', name='admin_ranks'),
-                        url(r'^new/$', 'New', name='admin_ranks_new'),
-                        url(r'^edit/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Edit', name='admin_ranks_edit'),
-                        url(r'^delete/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Delete', name='admin_ranks_delete'),
-                    ),
-               ),
-   AdminAction(
-               section='users',
-               id='bans',
-               name=_("Banning"),
-               help=_("Ban or unban users from forums."),
-               icon='lock',
-               model=Ban,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Browse Bans"),
-                         'help': _("Browse all existing bans"),
-                         'route': 'admin_bans'
-                         },
-                        {
-                         'id': 'new',
-                         'name': _("Set Ban"),
-                         'help': _("Set new Ban"),
-                         'route': 'admin_bans_new'
-                         },
-                        ],
-               route='admin_bans',
-               urlpatterns=patterns('misago.banning.views',
-                        url(r'^$', 'List', name='admin_bans'),
-                        url(r'^(?P<page>\d+)/$', 'List', name='admin_bans'),
-                        url(r'^new/$', 'New', name='admin_bans_new'),
-                        url(r'^edit/(?P<target>\d+)/$', 'Edit', name='admin_bans_edit'),
-                        url(r'^delete/(?P<target>\d+)/$', 'Delete', name='admin_bans_delete'),
-                    ),
-               ),
-   AdminAction(
-               section='users',
-               id='prune_users',
-               name=_("Prune Users"),
-               help=_("Delete multiple Users"),
-               icon='remove',
-               model=Policy,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Pruning Policies"),
-                         'help': _("Browse all existing pruning policies"),
-                         'route': 'admin_prune_users'
-                         },
-                        {
-                         'id': 'new',
-                         'name': _("Set New Policy"),
-                         'help': _("Set new pruning policy"),
-                         'route': 'admin_prune_users_new'
-                         },
-                        ],
-               route='admin_prune_users',
-               urlpatterns=patterns('misago.prune.views',
-                        url(r'^$', 'List', name='admin_prune_users'),
-                        url(r'^new/$', 'New', name='admin_prune_users_new'),
-                        url(r'^edit/(?P<target>\d+)/$', 'Edit', name='admin_prune_users_edit'),
-                        url(r'^delete/(?P<target>\d+)/$', 'Delete', name='admin_prune_users_delete'),
-                        url(r'^apply/(?P<target>\d+)/$', 'Apply', name='admin_prune_users_apply'),
-                    ),
-               ),
-   AdminAction(
-               section='users',
-               id='newsletters',
-               name=_("Newsletters"),
-               help=_("Manage and send Newsletters"),
-               icon='envelope',
-               model=Newsletter,
-               actions=[
-                        {
-                         'id': 'list',
-                         'name': _("Browse Newsletters"),
-                         'help': _("Browse all existing Newsletters"),
-                         'route': 'admin_newsletters'
-                         },
-                        {
-                         'id': 'new',
-                         'name': _("New Newsletter"),
-                         'help': _("Create new Newsletter"),
-                         'route': 'admin_newsletters_new'
-                         },
-                        ],
-               route='admin_newsletters',
-               urlpatterns=patterns('misago.newsletters.views',
-                        url(r'^$', 'List', name='admin_newsletters'),
-                        url(r'^(?P<page>\d+)/$', 'List', name='admin_newsletters'),
-                        url(r'^new/$', 'New', name='admin_newsletters_new'),
-                        url(r'^send/(?P<target>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'send', name='admin_newsletters_send'),
-                        url(r'^edit/(?P<target>\d+)/$', 'Edit', name='admin_newsletters_edit'),
-                        url(r'^delete/(?P<target>\d+)/$', 'Delete', name='admin_newsletters_delete'),
-                    ),
-               ),
-)

+ 0 - 15
notrefactored/admin/views.py

@@ -1,15 +0,0 @@
-from django.template import RequestContext
-from misago.sessions.models import Session
-
-def home(request):
-    return request.theme.render_to_response('home.html', {
-        'users': request.monitor['users'],
-        'users_inactive': request.monitor['users_inactive'],
-        'threads': request.monitor['threads'],
-        'posts': request.monitor['posts'],
-        'admins': Session.objects.filter(user__isnull=False).filter(admin=1).order_by('user__username_slug').select_related('user'),
-        }, context_instance=RequestContext(request));
-
-
-def todo(request):
-    return request.theme.render_to_response('todo.html', context_instance=RequestContext(request));

+ 0 - 552
notrefactored/admin/widgets.py

@@ -1,552 +0,0 @@
-from django import forms
-from django.core.exceptions import ValidationError
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils.translation import ugettext_lazy as _
-from jinja2 import TemplateNotFound
-import math
-from misago.forms import Form
-from misago.forms.layouts import *
-from misago.messages import Message
-from misago.search import SearchException
-
-"""
-Class widgets
-"""
-class BaseWidget(object):
-    """
-    Admin Widget abstract class, providing widgets with common or shared functionality
-    """
-    admin = None
-    id = None
-    fallback = None
-    name = None
-    help = None
-    notfound_message = None
-
-    def __new__(cls, request, **kwargs):
-        obj = super(BaseWidget, cls).__new__(cls)
-        if not obj.name:
-            obj.name = obj.get_name()
-        if not obj.help:
-            obj.help = obj.get_help()
-        return obj(request, **kwargs)
-
-    def get_token(self, token):
-        return '%s_%s_%s' % (self.id, token, str('%s.%s' % (self.admin.id, self.admin.model.__name__)))
-
-    def get_url(self):
-        return reverse(self.admin.get_action_attr(self.id, 'route'))
-
-    def get_name(self):
-        return self.admin.get_action_attr(self.id, 'name')
-
-    def get_help(self):
-        return self.admin.get_action_attr(self.id, 'help')
-
-    def get_id(self):
-        return 'admin_%s' % self.id
-
-    def get_template(self):
-        return ('%s/%s.html' % (self.admin.id, self.template),
-                'admin/%s.html' % self.template)
-
-    def add_template_variables(self, variables):
-        return variables
-
-    def get_fallback_url(self):
-        return reverse(self.fallback)
-
-    def get_target(self, model):
-        pass
-
-    def get_target_name(self, model):
-        try:
-            if self.translate_target_name:
-                return _(model.__dict__[self.target_name])
-            return model.__dict__[self.target_name]
-        except AttributeError:
-            return None
-
-    def get_and_validate_target(self, target):
-        try:
-            model = self.admin.model.objects.select_related().get(pk=target)
-            self.get_target(model)
-            return model
-        except self.admin.model.DoesNotExist:
-            self.request.messages.set_flash(Message(self.notfound_message), 'error', self.admin.id)
-        except ValueError as e:
-            self.request.messages.set_flash(Message(e.args[0]), 'error', self.admin.id)
-        return None
-
-
-class ListWidget(BaseWidget):
-    """
-    Items list widget
-    """
-    actions = []
-    columns = []
-    sortables = {}
-    default_sorting = None
-    search_form = None
-    is_filtering = False
-    pagination = None
-    template = 'list'
-    hide_actions = False
-    table_form_button = _('Go')
-    empty_message = _('There are no items to display')
-    empty_search_message = _('Search has returned no items')
-    nothing_checked_message = _('You have to select at least one item.')
-    prompt_select = False
-
-    def get_item_actions(self, item):
-        """
-        Provides request and item, should return list of tuples with item actions in following format:
-        (id, name, help, icon, link)
-        """
-        return []
-
-    def action(self, icon=None, name=None, url=None, post=False, prompt=None):
-        """
-        Function call to make hash with item actions
-        """
-        if prompt:
-            self.prompt_select = True
-        return {
-                'icon': icon,
-                'name': name,
-                'url': url,
-                'post': post,
-                'prompt': prompt,
-                }
-
-    def get_search_form(self):
-        """
-        Build a form object with items search
-        """
-        return self.search_form
-
-    def set_filters(self, model, filters):
-        """
-        Set filters on model using filters from session
-        """
-        return None
-
-    def get_table_form(self, page_items):
-        """
-        Build a form object with list of all items fields
-        """
-        return None
-
-    def table_action(self, page_items, cleaned_data):
-        """
-        Handle table form submission, return tuple containing message and redirect link/false
-        """
-        return None
-
-    def get_actions_form(self, page_items):
-        """
-        Build a form object with list of all items actions
-        """
-        if not self.actions:
-            return None # Dont build form
-        form_fields = {}
-        list_choices = []
-        for action in self.actions:
-            list_choices.append((action[0], action[1]))
-        form_fields['list_action'] = forms.ChoiceField(choices=list_choices)
-        list_choices = []
-        for item in page_items:
-            list_choices.append((item.pk, None))
-        form_fields['list_items'] = forms.MultipleChoiceField(choices=list_choices, widget=forms.CheckboxSelectMultiple)
-        return type('AdminListForm', (Form,), form_fields)
-
-    def get_sorting(self):
-        """
-        Return list sorting method.
-        A list with three values:
-        - Field we use to sort over
-        - Sorting direction
-        - order_by() argument
-        """
-        sorting_method = None
-        if self.request.session.get(self.get_token('sort')) and self.request.session.get(self.get_token('sort'))[0] in self.sortables:
-            sorting_method = self.request.session.get(self.get_token('sort'))
-
-        if self.request.GET.get('sort') and self.request.GET.get('sort') in self.sortables:
-            new_sorting = self.request.GET.get('sort')
-            sorting_dir = int(self.request.GET.get('dir')) == 1
-            sorting_method = [
-                    new_sorting,
-                    sorting_dir,
-                    new_sorting if sorting_dir else '-%s' % new_sorting
-                   ]
-            self.request.session[self.get_token('sort')] = sorting_method
-
-        if not sorting_method:
-            if self.sortables:
-                new_sorting = self.sortables.keys()[0]
-                if self.default_sorting in self.sortables:
-                    new_sorting = self.default_sorting
-                sorting_method = [
-                        new_sorting,
-                        self.sortables[new_sorting] == True,
-                        new_sorting if self.sortables[new_sorting] else '-%s' % new_sorting
-                       ]
-            else:
-                sorting_method = [
-                        id,
-                        True,
-                        '-id'
-                       ]
-        return sorting_method
-
-    def sort_items(self, page_items, sorting_method):
-        return page_items.order_by(sorting_method[2])
-
-    def get_pagination_url(self, page):
-        return reverse(self.admin.get_action_attr(self.id, 'route'), kwargs={'page': page})
-
-    def get_pagination(self, total, page):
-        """
-        Return list pagination.
-        A list with three values:
-        - Offset for ORM slicing
-        - Length of slice
-        - no. of prev page (or -1 for first page)
-        - no. of next page (or -1 for last page)
-        - Current page
-        - Pages total
-        """
-        if not self.pagination or total < 0:
-            # Dont do anything if we are not paging
-            return None
-
-        # Set basic pagination, use either Session cache or new page value
-        pagination = {'start': 0, 'stop': 0, 'prev':-1, 'next':-1}
-        if self.request.session.get(self.get_token('pagination')):
-            pagination['start'] = self.request.session.get(self.get_token('pagination'))
-        page = int(page)
-        if page > 0:
-            pagination['start'] = (page - 1) * self.pagination
-
-        # Set page and total stat
-        pagination['page'] = int(pagination['start'] / self.pagination) + 1
-        pagination['total'] = int(math.ceil(total / float(self.pagination)))
-
-        # Fix too large offset
-        if pagination['start'] > total:
-            pagination['start'] = 0
-
-        # Allow prev/next?
-        if total > self.pagination:
-            if pagination['page'] > 1:
-                pagination['prev'] = pagination['page'] - 1
-            if pagination['page'] < pagination['total']:
-                pagination['next'] = pagination['page'] + 1
-
-        # Set stop offset
-        pagination['stop'] = pagination['start'] + self.pagination
-        return pagination
-
-    def get_items(self):
-        if self.request.session.get(self.get_token('filter')):
-            self.is_filtering = True
-            return self.set_filters(self.admin.model.objects, self.request.session.get(self.get_token('filter')))
-        return self.admin.model.objects
-
-    def __call__(self, request, page=0):
-        """
-        Use widget as view
-        """
-        self.request = request
-
-        # Get basic list items
-        items_total = self.get_items()
-
-        # Set extra filters?
-        try:
-            items_total = self.select_items(items_total).count()
-        except AttributeError:
-            items_total = items_total.count()
-
-        # Set sorting and paginating
-        sorting_method = self.get_sorting()
-        paginating_method = self.get_pagination(items_total, page)
-
-        # List items
-        items = self.get_items()
-        if not request.session.get(self.get_token('filter')):
-            items = items.all()
-
-        # Set extra filters?
-        try:
-            items = self.select_items(items)
-        except AttributeError:
-            pass
-
-        # Sort them
-        items = self.sort_items(items, sorting_method);
-
-        # Set pagination
-        if self.pagination:
-            items = items[paginating_method['start']:paginating_method['stop']]
-
-        # Prefetch related?
-        try:
-            items = self.prefetch_related(items)
-        except AttributeError:
-            pass
-
-        # Default message
-        message = None
-
-        # See if we should make and handle search form
-        search_form = None
-        SearchForm = self.get_search_form()
-        if SearchForm:
-            if request.method == 'POST':
-                # New search
-                if request.POST.get('origin') == 'search':
-                    search_form = SearchForm(request.POST, request=request)
-                    if search_form.is_valid():
-                        search_criteria = {}
-                        for field, criteria in search_form.cleaned_data.items():
-                            if len(criteria) > 0:
-                                search_criteria[field] = criteria
-                        if not search_criteria:
-                            message = Message(_("No search criteria have been defined."))
-                        else:
-                            request.session[self.get_token('filter')] = search_criteria
-                            return redirect(self.get_url())
-                    else:
-                        message = Message(_("Search form contains errors."))
-                    message.type = 'error'
-                else:
-                    search_form = SearchForm(request=request)
-
-                # Kill search
-                if request.POST.get('origin') == 'clear' and self.is_filtering and request.csrf.request_secure(request):
-                    request.session[self.get_token('filter')] = None
-                    request.messages.set_flash(Message(_("Search criteria have been cleared.")), 'info', self.admin.id)
-                    return redirect(self.get_url())
-            else:
-                if self.is_filtering:
-                    search_form = SearchForm(request=request, initial=request.session.get(self.get_token('filter')))
-                else:
-                    search_form = SearchForm(request=request)
-
-        # See if we sould make and handle tab form
-        table_form = None
-        TableForm = self.get_table_form(items)
-        if TableForm:
-            if request.method == 'POST' and request.POST.get('origin') == 'table':
-                table_form = TableForm(request.POST, request=request)
-                if table_form.is_valid():
-                    message, redirect_url = self.table_action(items, table_form.cleaned_data)
-                    if redirect_url:
-                        request.messages.set_flash(message, message.type, self.admin.id)
-                        return redirect(redirect_url)
-                else:
-                    message = Message(table_form.non_field_errors()[0], 'error')
-            else:
-                table_form = TableForm(request=request)
-
-        # See if we should make and handle list form
-        list_form = None
-        ListForm = self.get_actions_form(items)
-        if ListForm:
-            if request.method == 'POST' and request.POST.get('origin') == 'list':
-                list_form = ListForm(request.POST, request=request)
-                if list_form.is_valid():
-                    try:
-                        form_action = getattr(self, 'action_' + list_form.cleaned_data['list_action'])
-                        message, redirect_url = form_action(items, list_form.cleaned_data['list_items'])
-                        if redirect_url:
-                            request.messages.set_flash(message, message.type, self.admin.id)
-                            return redirect(redirect_url)
-                    except AttributeError:
-                        message = Message(_("Action requested is incorrect."))
-                else:
-                    if 'list_items' in list_form.errors:
-                        message = Message(self.nothing_checked_message)
-                    elif 'list_action' in list_form.errors:
-                        message = Message(_("Action requested is incorrect."))
-                    else:
-                        message = Message(list_form.non_field_errors()[0])
-                message.type = 'error'
-            else:
-                list_form = ListForm(request=request)
-
-        # Little hax to keep counters correct 
-        items_shown = len(items)
-        if items_total < items_shown:
-            items_total = items_shown
-
-        # Render list
-        return request.theme.render_to_response(self.get_template(),
-                                                self.add_template_variables({
-                                                 'admin': self.admin,
-                                                 'action': self,
-                                                 'request': request,
-                                                 'url': self.get_url(),
-                                                 'messages_log': request.messages.get_messages(self.admin.id),
-                                                 'message': message,
-                                                 'sorting': self.sortables,
-                                                 'sorting_method': sorting_method,
-                                                 'pagination': paginating_method,
-                                                 'list_form': FormLayout(list_form) if list_form else None,
-                                                 'search_form': FormLayout(search_form) if search_form else None,
-                                                 'table_form': FormFields(table_form).fields if table_form else None,
-                                                 'items': items,
-                                                 'items_total': items_total,
-                                                 'items_shown': items_shown,
-                                                }),
-                                                context_instance=RequestContext(request));
-
-
-class FormWidget(BaseWidget):
-    """
-    Form page widget
-    """
-    template = 'form'
-    submit_button = _("Save Changes")
-    form = None
-    layout = None
-    tabbed = False
-    target_name = None
-    translate_target_name = False
-    original_name = None
-    submit_fallback = False
-
-    def get_url(self, model):
-        return reverse(self.admin.get_action_attr(self.id, 'route'))
-
-    def get_form(self, target):
-        return self.form
-
-    def get_form_instance(self, form, target, initial, post=False):
-        if post:
-            return form(self.request.POST, request=self.request, initial=self.get_initial_data(target))
-        return form(request=self.request, initial=self.get_initial_data(target))
-
-    def get_layout(self, form, model):
-        if self.layout:
-            return self.layout
-        return form.layout
-
-    def get_initial_data(self, model):
-        return {}
-
-    def submit_form(self, form, model):
-        """
-        Handle form submission, ALWAYS return tuple with model and message
-        """
-        pass
-
-    def __call__(self, request, target=None, slug=None):
-        self.request = request
-
-        # Fetch target?
-        model = None
-        if target:
-            model = self.get_and_validate_target(target)
-            self.original_name = self.get_target_name(model)
-            if not model:
-                return redirect(self.get_fallback_url())
-        original_model = model
-
-        # Get form type to instantiate
-        FormType = self.get_form(model)
-
-        #Submit form
-        message = None
-        if request.method == 'POST':
-            form = self.get_form_instance(FormType, model, self.get_initial_data(model), True)
-            if form.is_valid():
-                try:
-                    model, message = self.submit_form(form, model)
-                    if message.type != 'error':
-                        request.messages.set_flash(message, message.type, self.admin.id)
-                        # Redirect back to right page
-                        try:
-                            if 'save_new' in request.POST and self.get_new_url:
-                                return redirect(self.get_new_url(model))
-                        except AttributeError:
-                            pass
-                        try:
-                            if 'save_edit' in request.POST and self.get_edit_url:
-                                return redirect(self.get_edit_url(model))
-                        except AttributeError:
-                            pass
-                        try:
-                            if self.get_submit_url:
-                                return redirect(self.get_submit_url(model))
-                        except AttributeError:
-                            pass
-                        return redirect(self.get_fallback_url())
-                except ValidationError as e:
-                    message = Message(e.messages[0], 'error')
-            else:
-                message = Message(form.non_field_errors()[0], 'error')
-        else:
-            form = self.get_form_instance(FormType, model, self.get_initial_data(model))
-
-        # Render form
-        return request.theme.render_to_response(self.get_template(),
-                                                self.add_template_variables({
-                                                 'admin': self.admin,
-                                                 'action': self,
-                                                 'request': request,
-                                                 'url': self.get_url(model),
-                                                 'fallback': self.get_fallback_url(),
-                                                 'messages_log': request.messages.get_messages(self.admin.id),
-                                                 'message': message,
-                                                 'tabbed': self.tabbed,
-                                                 'target': self.get_target_name(original_model),
-                                                 'target_model': original_model,
-                                                 'form': FormLayout(form, self.get_layout(form, target)),
-                                                }),
-                                                context_instance=RequestContext(request));
-
-
-class ButtonWidget(BaseWidget):
-    """
-    Button Action Widget
-    This widget handles most basic and common type of admin action - button press:
-    - User presses button on list (for example "delete this user!")
-    - Widget checks if request is CSRF-valid and POST
-    - Widget optionally chcecks if target has been provided and action is allowed at all
-    - Widget does action and redirects us back to fallback url
-    """
-    def __call__(self, request, target=None, slug=None):
-        self.request = request
-
-        # Fetch target?
-        model = None
-        if target:
-            model = self.get_and_validate_target(target)
-            if not model:
-                return redirect(self.get_fallback_url())
-        original_model = model
-
-        # Crash if this is invalid request
-        if not request.csrf.request_secure(request):
-            request.messages.set_flash(Message(_("Action authorization is invalid.")), 'error', self.admin.id)
-            return redirect(self.get_fallback_url())
-
-        # Do something
-        message, url = self.action(model)
-        request.messages.set_flash(message, message.type, self.admin.id)
-        if url:
-            return redirect(url)
-        return redirect(self.get_fallback_url())
-
-    def action(self, target):
-        """
-        Action to be executed when button is pressed
-        Define custom one in your Admin action.
-        It should return response and message objects 
-        """
-        pass

+ 0 - 0
notrefactored/alerts/__init__.py


+ 0 - 0
notrefactored/alerts/management/__init__.py


+ 0 - 0
notrefactored/alerts/management/commands/__init__.py


+ 0 - 13
notrefactored/alerts/management/commands/clearalerts.py

@@ -1,13 +0,0 @@
-from datetime import timedelta
-from django.core.management.base import BaseCommand
-from django.utils import timezone
-from misago.alerts.models import Alert
-
-class Command(BaseCommand):
-    """
-    This command is intended to work as CRON job fired every few days to delete old alerts
-    """
-    help = 'Clears old alerts'
-    def handle(self, *args, **options):
-        Alert.objects.filter(date__lte=timezone.now() - timedelta(days=14)).delete()
-        self.stdout.write('Old Alerts have been cleared.\n')

+ 0 - 119
notrefactored/alerts/migrations/0001_initial.py

@@ -1,119 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Alert'
-        db.create_table(u'alerts_alert', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['users.User'])),
-            ('date', self.gf('django.db.models.fields.DateTimeField')()),
-            ('message', self.gf('django.db.models.fields.TextField')()),
-            ('variables', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-        ))
-        db.send_create_signal(u'alerts', ['Alert'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Alert'
-        db.delete_table(u'alerts_alert')
-
-
-    models = {
-        u'alerts.alert': {
-            'Meta': {'object_name': 'Alert'},
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'message': ('django.db.models.fields.TextField', [], {}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']"}),
-            'variables': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
-        },
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['alerts']

+ 0 - 0
notrefactored/alerts/migrations/__init__.py


+ 0 - 74
notrefactored/alerts/models.py

@@ -1,74 +0,0 @@
-from django.db import models
-import base64
-import cgi
-try:
-    import cPickle as pickle
-except ImportError:
-    import pickle
-
-class Alert(models.Model):
-    user = models.ForeignKey('users.User')
-    date = models.DateTimeField()
-    message = models.TextField()
-    variables = models.TextField(null=True, blank=True)
-
-    def vars(self):
-        try:
-            return pickle.loads(base64.decodestring(self.variables))
-        except Exception:
-            return {}
-
-    def text(self, var, value):
-        value = cgi.escape(value, True)
-        try:
-            self.vars_raw[var] = value
-        except AttributeError:
-            self.vars_raw = {var: value}
-        return self
-    
-    def strong(self, var, value):
-        try:
-            self.vars_raw[var] = '<strong>%s</strong>' % cgi.escape(value, True)
-        except AttributeError:
-            self.vars_raw = {var: '<strong>%s</strong>' % cgi.escape(value, True)}
-        return self
-
-    def url(self, var, value, href, attrs=None):
-        url = '<a href="%s"' % cgi.escape(href, True)
-        if attrs:
-            for k, v in attrs.iterator():
-                url += ' %s="%s"' % (k, cgi.escape(v, True))
-        url += '>%s</a>' % value
-        try:
-            self.vars_raw[var] = url
-        except AttributeError:
-            self.vars_raw = {var: url}
-        return self
-
-    def profile(self, var, user):
-        from django.core.urlresolvers import reverse
-        return self.url(var, user.username, reverse('user', kwargs={'user': user.pk, 'username': user.username_slug}))
-
-    def thread(self, var, thread):
-        from django.core.urlresolvers import reverse
-        return self.url(var, thread.name, reverse('thread', kwargs={'thread': thread.pk, 'slug': thread.slug}))
-
-    def post(self, var, thread, post):
-        from django.core.urlresolvers import reverse
-        return self.url(var, thread.name, reverse('thread_find', kwargs={'thread': thread.pk, 'slug': thread.slug, 'post': post.pk}))
-
-    def save_all(self, *args, **kwargs):
-        self.save(force_insert=True)
-        self.user.save(force_update=True)
-
-    def hydrate(self):
-        try:
-            self.variables = base64.encodestring(pickle.dumps(self.vars_raw, pickle.HIGHEST_PROTOCOL))
-        except AttributeError:
-            self.variables = base64.encodestring(pickle.dumps({}, pickle.HIGHEST_PROTOCOL))
-        return self
-
-    def save(self, *args, **kwargs):
-        self.hydrate()
-        super(Alert, self).save(*args, **kwargs)
-        return self.user

+ 0 - 51
notrefactored/alerts/views.py

@@ -1,51 +0,0 @@
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.authn.decorators import block_guest
-from misago.views import error404
-
-@block_guest
-def show_alerts(request):
-    now = timezone.now()
-    alerts = {}
-    if not request.user.alerts_date:
-        request.user.alerts_date = request.user.join_date
-    for alert in request.user.alert_set.order_by('-id'):
-        alert.new = alert.date > request.user.alerts_date
-        diff = now - alert.date
-        if diff.days <= 0:
-            try:
-                alerts['today'].append(alert)
-            except KeyError:
-                alerts['today'] = [alert]
-        elif diff.days <= 1:
-            try:
-                alerts['yesterday'].append(alert)
-            except KeyError:
-                alerts['yesterday'] = [alert]
-        elif diff.days <= 7:
-            try:
-                alerts['week'].append(alert)
-            except KeyError:
-                alerts['week'] = [alert]
-        elif diff.days <= 30:
-            try:
-                alerts['month'].append(alert)
-            except KeyError:
-                alerts['month'] = [alert]
-        else:
-            try:
-                alerts['older'].append(alert)
-            except KeyError:
-                alerts['older'] = [alert]
-
-    new_alerts = request.user.alerts
-    request.user.alerts = 0
-    request.user.alerts_date = now
-    request.user.save(force_update=True)
-    return request.theme.render_to_response('alerts.html',
-                                            {
-                                             'new_alerts': new_alerts,
-                                             'alerts': alerts,
-                                             },
-                                            context_instance=RequestContext(request))

+ 0 - 0
notrefactored/authn/__init__.py


+ 0 - 20
notrefactored/authn/decorators.py

@@ -1,20 +0,0 @@
-from django.utils.translation import ugettext as _
-
-def block_authenticated(f):
-    def decorator(*args, **kwargs):
-        request = args[0]
-        if not request.firewall.admin and request.user.is_authenticated():
-            from misago.views import error403
-            return error403(request, _("%(username)s, this page is not available to signed in users.") % {'username': request.user.username})
-        return f(*args, **kwargs)
-    return decorator
-
-
-def block_guest(f):
-    def decorator(*args, **kwargs):
-        request = args[0]
-        if not request.user.is_authenticated():
-            from misago.views import error403
-            return error403(request, _("Dear Guest, only signed in members are allowed to access this page. Please sign in or register and try again."))
-        return f(*args, **kwargs)
-    return decorator

+ 0 - 51
notrefactored/authn/fixtures.py

@@ -1,51 +0,0 @@
-from misago.settings.fixtures import load_settings_fixture, update_settings_fixture
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-settings_fixtures = (
-    # Register and Sign-In Settings
-    ('signin', {
-        'name': _("Sign-In and Sessions Settings"),
-        'description': _("Those settings control behaviour of signed-in accounts."),
-        'settings': (
-            ('sessions_validate_ip', {
-                'value':        True,
-                'type':         "boolean",
-                'input':        "yesno",
-                'separator':    _("Sessions Settings"),
-                'name':         _("Check IP on session authorization"),
-                'description':  _("Makes sessions more secure, but can cause problems with proxies and VPN's."),
-            }),
-            ('remember_me_allow', {
-                'value':        True,
-                'type':         "boolean",
-                'input':        "yesno",
-                'separator':    _('"Remember Me" Feature'),
-                'name':         _('Enable "Remember Me" feature'),
-                'description':  _("Turning this option on allows users to sign in on to your board using cookie-based tokens. This may result in account compromisation when user fails to sign out on shared computer or his cookie is stolen."),
-            }),
-            ('remember_me_lifetime', {
-                'value':        90,
-                'type':         "integer",
-                'input':        "text",
-                'name':         _('"Remember Me" token lifetime'),
-                'description':  _('Number of days since either last use or creation of "Remember Me" token to its expiration.'),
-            }),
-            ('remember_me_extensible', {
-                'value':        1,
-                'type':         "boolean",
-                'input':        "yesno",
-                'name':         _('Allow "Remember Me" tokens refreshing'),
-                'description':  _('Set this setting to off if you want to force your users to periodically update their "Remember Me" tokens by signing in. If this option is on, Tokens are updated when they are used to open new session.'),
-            }),
-        ),
-    }),
-)
-
-
-def load_fixtures():
-    load_settings_fixture(settings_fixtures)
-
-
-def update_fixtures():
-    update_settings_fixture(settings_fixtures)

+ 0 - 30
notrefactored/authn/forms.py

@@ -1,30 +0,0 @@
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-
-class SignInForm(Form):
-    user_email = forms.EmailField(max_length=255, label=_("Your email"))
-    user_password = forms.CharField(widget=forms.PasswordInput, max_length=255, label=_("Your password"))
-    user_remember_me = forms.BooleanField(label=_("Stay Signed In"), help_text=_("Sign me In automatically next time"), required=False)
-
-    layout = [
-              (
-               None,
-               (
-                ('user_email', {'attrs': {'placeholder': _("Enter your e-mail")}}),
-                ('user_password', {'has_value': False, 'placeholder': _("Enter your password")}),
-                )
-               ),
-              (
-               None,
-               ['user_remember_me'],
-               ),
-              ]
-
-    def __init__(self, *args, **kwargs):
-        show_remember_me = kwargs['show_remember_me']
-        del kwargs['show_remember_me']
-
-        super(SignInForm, self).__init__(*args, **kwargs)
-        if not show_remember_me:
-            del self.fields['user_remember_me']

+ 0 - 125
notrefactored/authn/methods.py

@@ -1,125 +0,0 @@
-from datetime import timedelta
-from django.conf import settings
-from django.utils import timezone
-from django.utils.translation import ugettext_lazy as _
-from misago.banning.models import check_ban
-from misago.bruteforce.models import SignInAttempt
-from misago.sessions.models import Token
-from misago.users.models import User
-
-"""
-Exception constants
-"""
-CREDENTIALS = 0
-ACTIVATION_USER = 1
-ACTIVATION_ADMIN = 2
-BANNED = 3
-NOT_ADMIN = 4
-
-
-class AuthException(Exception):
-    """
-    Auth Exception is thrown when auth_* method finds problem with allowing user to sign-in
-    """
-    def __init__(self, type=None, error=None, password=False, activation=False, ban=False):
-        self.type = type
-        self.error = error
-        self.password = password
-        self.activation = activation
-        self.ban = ban
-
-    def __str__(self):
-        return self.error
-
-
-def get_user(email, password, admin=False):
-    """
-    Fetch user from DB using email/pass pair, scream if either of data is incorrect
-    """
-    try:
-        user = User.objects.get_by_email(email)
-        if not user.check_password(password):
-            raise AuthException(CREDENTIALS, _("Your e-mail address or password is incorrect. Please try again."), password=True)
-        if not admin:
-            if user.activation == User.ACTIVATION_ADMIN:
-                # Only admin can activate your account.
-                raise AuthException(ACTIVATION_ADMIN, _("Board Administrator has not yet accepted your account."))
-            if user.activation != User.ACTIVATION_NONE:
-                # You have to activate your account - new member
-                raise AuthException(ACTIVATION_USER, _("You have to activate your account before you will be able to sign-in."), activation=True)
-
-    except User.DoesNotExist:
-        raise AuthException(CREDENTIALS, _("Your e-mail address or password is incorrect. Please try again."), password=True)
-    return user;
-
-
-def auth_forum(request, email, password):
-    """
-    Forum auth - check bans and if we are in maintenance - maintenance access
-    """
-    user = get_user(email, password)
-    user_ban = check_ban(username=user.username, email=user.email)
-    if user_ban:
-        if user_ban.reason_user:
-            raise AuthException(BANNED, _("Your account has been banned for following reason:"), ban=user_ban)
-        raise AuthException(BANNED, _("Your account has been banned."), ban=user_ban)
-    return user;
-
-
-def auth_remember(request, ip):
-    """
-    Remember-me auth - check if token is valid
-    Dont worry about AuthException being empty, it doesnt have to have anything
-    """
-    if request.firewall.admin:
-        raise AuthException()
-    if SignInAttempt.objects.is_jammed(request.settings, ip):
-        raise AuthException()
-    cookie_token = settings.COOKIES_PREFIX + 'TOKEN'
-    try:
-        cookie_token = request.COOKIES[cookie_token]
-        if len(cookie_token) != 42:
-            raise AuthException()
-        try:
-            token_rk = Token.objects.select_related().get(pk=cookie_token)
-        except Token.DoesNotExist:
-            request.cookie_jar.delete('TOKEN')
-            raise AuthException()
-
-        # See if token is not expired
-        token_expires = timezone.now() - timedelta(days=request.settings['remember_me_lifetime'])
-        if request.settings['remember_me_extensible'] and token_rk.accessed < token_expires:
-            # Token expired because it's last use is smaller than expiration date
-            raise AuthException()
-
-        if not request.settings['remember_me_extensible'] and token_rk.created < token_expires:
-            # Token expired because it was created before expiration date
-            raise AuthException()
-
-        # Update token date
-        token_rk.accessed = timezone.now()
-        token_rk.save(force_update=True)
-        request.cookie_jar.set('TOKEN', token_rk.id, True)
-    except (AttributeError, KeyError):
-        raise AuthException()
-    return token_rk
-
-
-def auth_admin(request, email, password):
-    """
-    Admin auth - check ACP permissions
-    """
-    user = get_user(email, password, True)
-    if not user.is_god() and not user.get_acl(request).admin.is_admin():
-        raise AuthException(NOT_ADMIN, _("Your account does not have admin privileges."))
-    return user;
-
-
-def sign_user_in(request, user):
-    user.set_last_visit(
-                        request.session.get_ip(request),
-                        request.META.get('HTTP_USER_AGENT', ''),
-                        )
-    user.save(force_update=True)
-    request.session.set_user(user)
-    request.session.set_hidden(user.hide_activity > 0)

+ 0 - 13
notrefactored/authn/urls.py

@@ -1,13 +0,0 @@
-from django.conf.urls import patterns, url
-from misago.admin import ADMIN_PATH
-
-urlpatterns = patterns('misago.authn.views',
-    url(r'^signin/$', 'signin', name="sign_in"),
-    url(r'^signout/$', 'signout', name="sign_out"),
-)
-
-# Include admin patterns
-if ADMIN_PATH:
-    urlpatterns += patterns('misago.authn.views',
-        url(r'^' + ADMIN_PATH + 'signout/$', 'signout', name="admin_sign_out"),
-    )

+ 0 - 113
notrefactored/authn/views.py

@@ -1,113 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.admin import site
-from misago.crawlers.decorators import block_crawlers
-from misago.csrf.decorators import check_csrf
-from misago.banning.decorators import block_banned
-from misago.forms.layouts import FormLayout
-from misago.messages import Message
-import misago.authn.methods as auth
-from misago.authn.decorators import block_authenticated, block_guest
-from misago.authn.forms import SignInForm
-from misago.authn.methods import AuthException, auth_admin, auth_forum, sign_user_in
-from misago.bruteforce.decorators import block_jammed
-from misago.bruteforce.models import SignInAttempt
-from misago.sessions.models import Token
-from misago.utils import get_random_string
-
-@block_crawlers
-@block_banned
-@block_authenticated
-@block_jammed
-def signin(request):
-    message = request.messages.get_message('security')
-    bad_password = False
-    not_active = False
-    banned_account = False
-
-    if request.method == 'POST':
-        form = SignInForm(
-                          request.POST,
-                          show_remember_me=not request.firewall.admin and request.settings['remember_me_allow'],
-                          request=request
-                          )
-
-        if form.is_valid():
-            try:
-                # Configure correct auth and redirect links
-                if request.firewall.admin:
-                    auth_method = auth_admin
-                    success_redirect = reverse(site.get_admin_index())
-                else:
-                    auth_method = auth_forum
-                    success_redirect = reverse('index')
-
-                # Authenticate user
-                user = auth_method(
-                                  request,
-                                  form.cleaned_data['user_email'],
-                                  form.cleaned_data['user_password'],
-                                  )
-
-                sign_user_in(request, user)
-                remember_me_token = False
-
-                if not request.firewall.admin and request.settings['remember_me_allow'] and form.cleaned_data['user_remember_me']:
-                    remember_me_token = get_random_string(42)
-                    remember_me = Token(
-                                        id=remember_me_token,
-                                        user=user,
-                                        created=timezone.now(),
-                                        accessed=timezone.now(),
-                                        )
-                    remember_me.save()
-                if remember_me_token:
-                    request.cookie_jar.set('TOKEN', remember_me_token, True)
-                request.messages.set_flash(Message(_("Welcome back, %(username)s!") % {'username': user.username}), 'success', 'security')
-                return redirect(success_redirect)
-            except AuthException as e:
-                message = Message(e.error, 'error')
-                bad_password = e.password
-                banned_account = e.ban
-                not_active = e.activation
-
-                # If not in Admin, register failed attempt
-                if not request.firewall.admin and e.type == auth.CREDENTIALS:
-                    SignInAttempt.objects.register_attempt(request.session.get_ip(request))
-
-                    # Have we jammed our account?
-                    if SignInAttempt.objects.is_jammed(request.settings, request.session.get_ip(request)):
-                        request.jam.expires = timezone.now()
-                        return redirect(reverse('sign_in'))
-        else:
-            message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = SignInForm(
-                          show_remember_me=not request.firewall.admin and request.settings['remember_me_allow'],
-                          request=request
-                          )
-    return request.theme.render_to_response('signin.html',
-                                            {
-                                             'message': message,
-                                             'bad_password': bad_password,
-                                             'banned_account': banned_account,
-                                             'not_active': not_active,
-                                             'form': FormLayout(form),
-                                             'hide_signin': True,
-                                             },
-                                            context_instance=RequestContext(request));
-
-
-@block_crawlers
-@block_guest
-@check_csrf
-def signout(request):
-    user = request.user
-    request.session.sign_out(request)
-    request.messages.set_flash(Message(_("You have been signed out.")), 'info', 'security')
-    if request.firewall.admin:
-        return redirect(reverse(site.get_admin_index()))
-    return redirect(reverse('index'))

+ 0 - 0
notrefactored/banning/__init__.py


+ 0 - 7
notrefactored/banning/context_processors.py

@@ -1,7 +0,0 @@
-def banning(request):
-    try:
-        return {
-            'is_banned': request.ban.is_banned(),
-        }
-    except AttributeError:
-        return {}

+ 0 - 12
notrefactored/banning/decorators.py

@@ -1,12 +0,0 @@
-def block_banned(f):
-    def decorator(*args, **kwargs):
-        request = args[0]
-        try:
-            if request.ban.is_banned():
-                from misago.banning.views import error_banned
-                return error_banned(request);
-            return f(*args, **kwargs)
-        except AttributeError:
-            pass
-        return f(*args, **kwargs)
-    return decorator

+ 0 - 4
notrefactored/banning/fixtures.py

@@ -1,4 +0,0 @@
-from misago.monitor.fixtures import load_monitor_fixture
-
-def load_fixtures():
-    load_monitor_fixture({'bans_version': 0})

+ 0 - 56
notrefactored/banning/forms.py

@@ -1,56 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.forms import Form
-
-class BanForm(Form):
-    """
-    New/Edit Ban form
-    """
-    type = forms.ChoiceField(choices=(
-                                      (0, _('Ban Username and e-mail')),
-                                      (1, _('Ban Username')),
-                                      (2, _('Ban E-mail address')),
-                                      (3, _('Ban IP Address'))
-                                      ))
-    reason_user = forms.CharField(widget=forms.Textarea, required=False)
-    reason_admin = forms.CharField(widget=forms.Textarea, required=False)
-    ban = forms.CharField(max_length=255)
-    expires = forms.DateField(required=False)
-    layout = (
-               (
-                 _("Ban Details"),
-                 (
-                  ('nested', (('type', {'label': _("Ban Rule"), 'help_text': _("Select ban type from list and define rule by entering it in text field. If you want to ban specific user, enter here either his Username or E-mail address. If you want to define blanket ban, you can use wildcard (\"*\"). For example to forbid all members from using name suggesting that member is an admin, you can set ban that forbids \"Admin*\" as username."), 'width': 25}),
-                  ('ban', {'width': 75}))),
-                  ('expires', {'label': _("Ban Expiration"), 'help_text': _("If you want to, you can set this ban's expiration date by entering it here using YYYY-MM-DD format. Otherwhise you can leave this field empty making this ban permanent.")}),
-                 ),
-                ),
-                (
-                 _("Ban Message"),
-                 (
-                  ('reason_user', {'label': _("User-visible Ban Message"), 'help_text': _("Optional Ban message that will be displayed to banned members.")}),
-                  ('reason_admin', {'label': _("Team-visible Ban Message"), 'help_text': _("Optional Ban message that will be displayed to forum team members.")}),
-                 ),
-                ),
-               )
-
-
-class SearchBansForm(Form):
-    ban = forms.CharField(required=False)
-    reason = forms.CharField(required=False)
-    type = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=(
-                                      ("0", _('Username and e-mail')),
-                                      ("1", _('Username')),
-                                      ("2", _('E-mail address')),
-                                      ("3", _('IP Address'))
-                                      ), required=False)
-    layout = (
-              (
-               _("Search Bans"),
-               (
-                ('ban', {'label': _("Ban"), 'attrs': {'placeholder': _("Ban contains...")}}),
-                ('reason', {'label': _("Messages"), 'attrs': {'placeholder': _("User or Team message contains...")}}),
-                ('type', {'label': _("Type")}),
-               ),
-              ),
-             )

+ 0 - 17
notrefactored/banning/middleware.py

@@ -1,17 +0,0 @@
-from misago.banning.models import BanCache
-from misago.users.models import Guest
-
-class BanningMiddleware(object):
-    def process_request(self, request):
-        if request.heartbeat or request.user.is_crawler():
-            return None
-        try:
-            request.ban = request.session['ban']
-        except KeyError:
-            request.ban = BanCache()
-            request.session['ban'] = request.ban
-        if not request.firewall.admin:
-            request.ban.check_for_updates(request)
-            # Make sure banned session is downgraded to guest level
-            if request.ban.is_banned():
-                request.session.sign_out(request)

+ 0 - 40
notrefactored/banning/migrations/0001_initial.py

@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Ban'
-        db.create_table(u'banning_ban', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('type', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('ban', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('reason_user', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('reason_admin', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('expires', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-        ))
-        db.send_create_signal(u'banning', ['Ban'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Ban'
-        db.delete_table(u'banning_ban')
-
-
-    models = {
-        u'banning.ban': {
-            'Meta': {'object_name': 'Ban'},
-            'ban': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'type': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['banning']

+ 0 - 0
notrefactored/banning/migrations/__init__.py


+ 0 - 84
notrefactored/banning/models.py

@@ -1,84 +0,0 @@
-import re
-from django.utils import timezone
-from django.db import models
-from django.db.models import Q
-
-BAN_NAME_EMAIL = 0
-BAN_NAME = 1
-BAN_EMAIL = 2
-BAN_IP = 3
-
-
-class Ban(models.Model):
-    type = models.PositiveIntegerField(default=BAN_NAME_EMAIL)
-    ban = models.CharField(max_length=255)
-    reason_user = models.TextField(null=True, blank=True)
-    reason_admin = models.TextField(null=True, blank=True)
-    expires = models.DateTimeField(null=True, blank=True)
-
-
-def check_ban(ip=False, username=False, email=False):
-    bans_model = Ban.objects.filter(Q(expires=None) | Q(expires__gt=timezone.now()))
-    if not (ip and username and email):
-        if ip:
-            bans_model.filter(type=BAN_IP)
-        if username:
-            bans_model.filter(type=BAN_NAME_EMAIL)
-            bans_model.filter(type=BAN_NAME)
-        if email:
-            bans_model.filter(type=BAN_NAME_EMAIL)
-            bans_model.filter(type=BAN_EMAIL)
-    for ban in bans_model.order_by('-expires').iterator():
-        if (
-            # Check user name
-            ((username and (ban.type == BAN_NAME_EMAIL or ban.type == BAN_NAME))
-            and re.search('^' + re.escape(ban.ban).replace('\*', '(.*?)') + '$', username, flags=re.IGNORECASE))
-            or # Check user email
-            ((email and (ban.type == BAN_NAME_EMAIL or ban.type == BAN_EMAIL))
-            and re.search('^' + re.escape(ban.ban).replace('\*', '(.*?)') + '$', email, flags=re.IGNORECASE))
-            or # Check IP address
-            (ip and ban.type == BAN_IP
-            and re.search('^' + re.escape(ban.ban).replace('\*', '(.*?)') + '$', ip, flags=re.IGNORECASE))):
-                return ban
-    return False
-
-
-class BanCache(object):
-    def __init__(self):
-        self.banned = False
-        self.type = None
-        self.expires = None
-        self.reason_user = None
-        self.version = 0
-
-    def check_for_updates(self, request):
-        if (self.version < request.monitor['bans_version']
-            or (self.expires != None and self.expires < timezone.now())):
-            self.version = request.monitor['bans_version']
-
-            # Check Ban
-            if request.user.is_authenticated():
-                ban = check_ban(
-                                ip=request.session.get_ip(request),
-                                username=request.user.username,
-                                email=request.user.email
-                                )
-            else:
-                ban = check_ban(ip=request.session.get_ip(request))
-
-            # Update ban cache
-            if ban:
-                self.banned = True
-                self.reason_user = ban.reason_user
-                self.expires = ban.expires
-                self.type = ban.type
-            else:
-                self.banned = False
-                self.reason_user = None
-                self.expires = None
-                self.type = None
-            return True
-        return False
-
-    def is_banned(self):
-        return self.banned

+ 0 - 169
notrefactored/banning/views.py

@@ -1,169 +0,0 @@
-from django.core.urlresolvers import reverse as django_reverse
-from django.db.models import Q
-from django.template import RequestContext
-from django.utils.translation import ugettext as _
-from misago.admin import site
-from misago.admin.widgets import *
-from misago.banning.forms import BanForm, SearchBansForm
-from misago.banning.models import Ban
-from misago.messages import Message
-
-"""
-Admin mixin
-"""
-def reverse(route, target=None):
-    if target:
-        return django_reverse(route, kwargs={'target': target.pk})
-    return django_reverse(route)
-
-"""
-Views
-"""
-def error_banned(request, user=None, ban=None):
-    if not ban:
-        ban = request.ban
-    response = request.theme.render_to_response('error403_banned.html',
-                                                {
-                                                 'banned_user': user,
-                                                 'ban': ban,
-                                                 'hide_signin': True,
-                                                 'exception_response': True,
-                                                 },
-                                                context_instance=RequestContext(request));
-    response.status_code = 403
-    return response
-
-
-class List(ListWidget):
-    """
-    List Bans
-    """
-    admin = site.get_action('bans')
-    id = 'list'
-    columns = (
-             ('ban', _("Ban"), 50),
-             ('expires', _("Expires")),
-             )
-    default_sorting = 'expires'
-    sortables = {
-               'ban': 1,
-               'expires': 0,
-              }
-    pagination = 20
-    search_form = SearchBansForm
-    empty_message = _('No bans are currently set.')
-    empty_search_message = _('No bans have been found.')
-    nothing_checked_message = _('You have to check at least one ban.')
-    actions = (
-             ('delete', _("Lift selected bans"), _("Are you sure you want to lift selected bans?")),
-             )
-
-    def set_filters(self, model, filters):
-        if 'ban' in filters:
-            model = model.filter(ban__contains=filters['ban'])
-        if 'reason' in filters:
-            model = model.filter(Q(reason_user__contains=filters['reason']) | Q(reason_admin__contains=filters['reason']))
-        if 'type' in filters:
-            model = model.filter(type__in=filters['type'])
-        return model
-
-    def get_item_actions(self, item):
-        return (
-                self.action('pencil', _("Edit Ban"), reverse('admin_bans_edit', item)),
-                self.action('remove', _("Lift Ban"), reverse('admin_bans_delete', item), post=True, prompt=_("Are you sure you want to lift this ban?")),
-                )
-
-    def action_delete(self, items, checked):
-        Ban.objects.filter(id__in=checked).delete()
-        self.request.monitor['bans_version'] = int(self.request.monitor['bans_version']) + 1
-        return Message(_('Selected bans have been lifted successfully.'), 'success'), reverse('admin_bans')
-
-
-class New(FormWidget):
-    """
-    Create Ban
-    """
-    admin = site.get_action('bans')
-    id = 'new'
-    fallback = 'admin_bans'
-    form = BanForm
-    submit_button = _("Set Ban")
-
-    def get_new_url(self, model):
-        return reverse('admin_bans_new')
-
-    def get_edit_url(self, model):
-        return reverse('admin_bans_edit', model)
-
-    def submit_form(self, form, target):
-        new_ban = Ban(
-                      type=form.cleaned_data['type'],
-                      ban=form.cleaned_data['ban'],
-                      reason_user=form.cleaned_data['reason_user'],
-                      reason_admin=form.cleaned_data['reason_admin'],
-                      expires=form.cleaned_data['expires']
-                     )
-        new_ban.save(force_insert=True)
-        self.request.monitor['bans_version'] = int(self.request.monitor['bans_version']) + 1
-        return new_ban, Message(_('New Ban has been set.'), 'success')
-
-
-class Edit(FormWidget):
-    """
-    Edit Ban
-    """
-    admin = site.get_action('bans')
-    id = 'edit'
-    name = _("Edit Ban")
-    fallback = 'admin_bans'
-    form = BanForm
-    target_name = 'ban'
-    notfound_message = _('Requested Ban could not be found.')
-    submit_fallback = True
-
-    def get_url(self, model):
-        return reverse('admin_bans_edit', model)
-
-    def get_edit_url(self, model):
-        return self.get_url(model)
-
-    def get_initial_data(self, model):
-        return {
-                'type': model.type,
-                'ban': model.ban,
-                'reason_user': model.reason_user,
-                'reason_admin': model.reason_admin,
-                'expires': model.expires,
-                }
-
-    def submit_form(self, form, target):
-        target.type = form.cleaned_data['type']
-        target.ban = form.cleaned_data['ban']
-        target.reason_user = form.cleaned_data['reason_user']
-        target.reason_admin = form.cleaned_data['reason_admin']
-        target.expires = form.cleaned_data['expires']
-        target.save(force_update=True)
-        self.request.monitor['bans_version'] = int(self.request.monitor['bans_version']) + 1
-        return target, Message(_('Changes in ban have been saved.'), 'success')
-
-
-class Delete(ButtonWidget):
-    """
-    Delete Ban
-    """
-    admin = site.get_action('bans')
-    id = 'delete'
-    fallback = 'admin_bans'
-    notfound_message = _('Requested Ban could not be found.')
-
-    def action(self, target):
-        target.delete()
-        self.request.monitor['bans_version'] = int(self.request.monitor['bans_version']) + 1
-        if target.type == 0:
-            return Message(_('E-mail and username Ban "%(ban)s" has been lifted.') % {'ban': target.ban}, 'success'), False
-        if target.type == 1:
-            return Message(_('Username Ban "%(ban)s" has been lifted.') % {'ban': target.ban}, 'success'), False
-        if target.type == 2:
-            return Message(_('E-mail Ban "%(ban)s" has been lifted.') % {'ban': target.ban}, 'success'), False
-        if target.type == 3:
-            return Message(_('IP Ban "%(ban)s" has been lifted.') % {'ban': target.ban}, 'success'), False

+ 0 - 0
notrefactored/bruteforce/__init__.py


+ 0 - 7
notrefactored/bruteforce/context_processors.py

@@ -1,7 +0,0 @@
-def is_jammed(request):
-    try:
-        return {
-            'is_jammed': request.jam.is_jammed(),
-        }
-    except AttributeError:
-        return {}

+ 0 - 13
notrefactored/bruteforce/decorators.py

@@ -1,13 +0,0 @@
-from django.utils.translation import ugettext as _
-from misago.views import error403
-
-def block_jammed(f):
-    def decorator(*args, **kwargs):
-        request = args[0]
-        try:
-            if not request.firewall.admin and request.jam.is_jammed():
-                return error403(request, _("You have used up allowed attempts quota and we temporarily banned you from accessing this page."))
-        except AttributeError:
-            pass
-        return f(*args, **kwargs)
-    return decorator

+ 0 - 46
notrefactored/bruteforce/fixtures.py

@@ -1,46 +0,0 @@
-from misago.settings.fixtures import load_settings_fixture, update_settings_fixture
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-settings_fixtures = (
-    # Register and Sign-In Settings
-    ('brute-force', {
-        'name': _("Brute-force Countermeasures"),
-        'description': _("Those settings allow you to protect your forum from brute-force attacks."),
-        'settings': (
-            ('attempts_limit', {
-                'value':        3,
-                'default':      3,
-                'type':         "integer",
-                'input':        "text",
-                'separator':    _("Brute-force Countermeasures"),
-                'name':         _("IP invalid attempts limit"),
-                'description':  _('Enter maximal number of allowed attempts before IP address "jams". Defautly forum records only failed sign-in attempts.'),
-            }),
-            ('registrations_jams', {
-                'value':        False,
-                'default':      False,
-                'type':         "boolean",
-                'input':        "yesno",
-                'name':         _("Protect register form"),
-                'description':  _("Set this setting to yes if you want failed register attempts to count into limit. Majority of failed register attempts are caused by CAPTCHA protection against spam-bots, however same protection may cause problems for users with disabilities or ones that have problems understanding Q&A challenge."),
-            }),
-            ('jams_lifetime', {
-                'value':        15,
-                'default':      15,
-                'type':         "integer",
-                'input':        "text",
-                'name':         _("Automaticaly unlock jammed IPs"),
-                'description':  _('Enter number of minutes since IP address "jams" to automatically unlock it, or 0 to never unlock jammed IP adresses. Jams don\'t count as bans.'),
-            }),
-        ),
-    }),
-)
-
-
-def load_fixtures():
-    load_settings_fixture(settings_fixtures)
-
-
-def update_fixtures():
-    update_settings_fixture(settings_fixtures)

+ 0 - 0
notrefactored/bruteforce/management/__init__.py


+ 0 - 0
notrefactored/bruteforce/management/commands/__init__.py


+ 0 - 12
notrefactored/bruteforce/management/commands/clearattempts.py

@@ -1,12 +0,0 @@
-from datetime import timedelta
-from django.utils import timezone
-from misago.bruteforce.models import SignInAttempt
-
-class Command(BaseCommand):
-    """
-    This command is intended to work as CRON job fired every few days to remove failed sign-in attempts
-    """
-    help = 'Clears sign-in attempts log'
-    def handle(self):
-        SignInAttempt.objects.filter(date__lte=timezone.now() - timedelta(hours=24)).delete()
-        self.stdout.write('Failed Sign-In attempts older than 24h have been removed.\n')

+ 0 - 13
notrefactored/bruteforce/middleware.py

@@ -1,13 +0,0 @@
-from misago.bruteforce.models import JamCache
-
-class JamMiddleware(object):
-    def process_request(self, request):
-        if request.user.is_crawler():
-            return None
-        try:
-            request.jam = request.session['jam']
-        except KeyError:
-            request.jam = JamCache()
-            request.session['jam'] = request.jam
-        if not request.firewall.admin:
-            request.jam.check_for_updates(request)

+ 0 - 34
notrefactored/bruteforce/migrations/0001_initial.py

@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'SignInAttempt'
-        db.create_table(u'bruteforce_signinattempt', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39)),
-            ('date', self.gf('django.db.models.fields.DateTimeField')()),
-        ))
-        db.send_create_signal(u'bruteforce', ['SignInAttempt'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'SignInAttempt'
-        db.delete_table(u'bruteforce_signinattempt')
-
-
-    models = {
-        u'bruteforce.signinattempt': {
-            'Meta': {'object_name': 'SignInAttempt'},
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'})
-        }
-    }
-
-    complete_apps = ['bruteforce']

+ 0 - 0
notrefactored/bruteforce/migrations/__init__.py


+ 0 - 54
notrefactored/bruteforce/models.py

@@ -1,54 +0,0 @@
-from datetime import timedelta
-from random import randint
-from django.db import models
-from django.utils import timezone
-from django.utils.translation import ugettext_lazy as _
-
-"""
-IP's that have exhausted their quota of sign-in attempts are automatically banned for set amount of time.
-
-That IP ban cuts bad IP address from signing into board by either making another sign-in attempts or
-registering "fresh" account.
-"""
-class SignInAttemptsManager(models.Manager):
-    """
-    Attempts manager
-    """
-    def register_attempt(self, ip):
-        attempt = SignInAttempt(ip=ip, date=timezone.now())
-        attempt.save(force_insert=True)
-
-    def is_jammed(self, settings, ip):
-        # Limit is off, dont jam IPs?
-        if settings['attempts_limit'] == 0:
-            return False
-        # Check jam
-        if settings['jams_lifetime'] > 0:
-            attempts = SignInAttempt.objects.filter(
-                                                    date__gt=timezone.now() - timedelta(minutes=settings['jams_lifetime']),
-                                                    ip=ip
-                                                    )
-        else:
-            attempts = SignInAttempt.objects.filter(ip=ip)
-        return attempts.count() > settings['attempts_limit']
-
-
-class SignInAttempt(models.Model):
-    ip = models.GenericIPAddressField()
-    date = models.DateTimeField()
-
-    objects = SignInAttemptsManager()
-
-
-class JamCache(object):
-    jammed = False
-    expires = timezone.now()
-    def check_for_updates(self, request):
-        if self.expires < timezone.now():
-            self.jammed = SignInAttempt.objects.is_jammed(request.settings, request.session.get_ip(request))
-            self.expires = timezone.now() + timedelta(minutes=request.settings['jams_lifetime'])
-            return True
-        return False
-
-    def is_jammed(self):
-        return self.jammed

+ 0 - 30
notrefactored/captcha/__init__.py

@@ -1,30 +0,0 @@
-from django.forms.fields import CharField
-from django.forms.widgets import TextInput
-from django.utils.translation import ugettext_lazy as _
-from recaptcha.client.captcha import API_SSL_SERVER, API_SERVER, VERIFY_SERVER
-
-class ReCaptchaWidget(TextInput):
-    pass
-
-
-class ReCaptchaField(CharField):
-    widget = ReCaptchaWidget # Fakey widget for FormLayout
-    api_error = None # Api error
-    def __init__(self, label=_("Verification Code"), *args, **kwargs):
-        kwargs['label'], kwargs['required'] = label, False
-        super(ReCaptchaField, self).__init__(*args, **kwargs)
-
-
-class QACaptchaField(CharField):
-    pass
-
-
-def get_captcha_dict(settings, api_error = None):
-    error_param = ''
-    if api_error:
-        error_param = '&error=%s' % api_error
-    return {
-            'api_server': API_SERVER,
-            'public_key': settings['recaptcha_public'],
-            'error_param': error_param,
-            }

+ 0 - 69
notrefactored/captcha/fixtures.py

@@ -1,69 +0,0 @@
-from misago.settings.fixtures import load_settings_fixture, update_settings_fixture
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-
-settings_fixtures = (
-   # Spam Countermeasures
-   ('spam', {
-        'name': _("Spam Countermeasures"),
-        'description': _("Those settings allow you to combat automatic registrations and spam messages on your forum."),
-        'settings': (
-            ('bots_registration', {
-                'type':         "string",
-                'input':        "choice",
-                'extra':        {'choices': [('', _("No protection")), ('recaptcha', _("reCaptcha")), ('qa', _("Question & Answer"))]},
-                'separator':    _("Spambots Registrations"),
-                'name':         _("CAPTCHA type"),
-                'description':  _('CAPTCHA stands for "Completely Automated Public Turing test to tell Computers and Humans Apart". Its type of test developed on purpose of blocking automatic registrations.'),
-            }),
-            ('recaptcha_public', {
-                'type':         "string",
-                'input':        "text",
-                'separator':    _("reCaptcha"),
-                'name':         _("Public Key"),
-                'description':  _("Enter public API key that you have received from reCaptcha."),
-            }),
-            ('recaptcha_private', {
-                'type':         "string",
-                'input':        "text",
-                'name':         _("Private Key"),
-                'description':  _("Enter private API key that you have received from reCaptcha."),
-            }),
-            ('recaptcha_ssl', {
-                'value':        False,
-                'type':         "boolean",
-                'input':        "yesno",
-                'name':         _("Use SSL in reCaptcha"),
-                'description':  _("Do you want forum to use SSL when making requests to reCaptha servers?"),
-            }),
-            ('qa_test', {
-                'type':         "string",
-                'input':        "text",
-                'separator':    _("Question and Answer Test"),
-                'name':         _("Question"),
-                'description':  _("Question visible to your users."),
-            }),
-            ('qa_test_help', {
-                'type':         "string",
-                'input':        "text",
-                'name':         _("Help Message"),
-                'description':  _("Optional help message displayed on form."),
-            }),
-            ('qa_test_answers', {
-                'type':         "string",
-                'input':        "textarea",
-                'name':         _("Answers"),
-                'description':  _("Enter allowed answers to this question, each in new line. Test is case-insensitive."),
-            }),
-        ),
-    }),
-)
-
-
-def load_fixtures():
-    load_settings_fixture(settings_fixtures)
-
-
-def update_fixtures():
-    update_settings_fixture(settings_fixtures)

+ 0 - 10
notrefactored/context_processors.py

@@ -1,10 +0,0 @@
-from django.conf import settings
-from misago import get_version
-
-# Register context processors
-def core(request):
-    return {
-        'request_path': request.get_full_path(),
-        'board_address': settings.BOARD_ADDRESS,
-        'version': get_version(),
-    }

+ 0 - 0
notrefactored/cookie_jar/__init__.py


+ 0 - 41
notrefactored/cookie_jar/cookie_jar.py

@@ -1,41 +0,0 @@
-from datetime import datetime, timedelta
-from django.conf import settings
-
-class CookieJar(object):
-    def __init__(self):
-        self._set_cookies = []
-        self._delete_cookies = []
-
-    def set(self, cookie, value, permanent=False):
-        if permanent:
-            # 360 days
-            max_age = 31104000
-        else:
-            # 48 hours
-            max_age = 172800
-        self._set_cookies.append({
-                                  'name': cookie,
-                                  'value': value,
-                                  'max_age': max_age,
-                                  })
-
-    def delete(self, cookie):
-        self._delete_cookies.append(cookie)
-
-    def flush(self, response):
-        for cookie in self._set_cookies:
-            response.set_cookie(
-                                settings.COOKIES_PREFIX + cookie['name'],
-                                cookie['value'],
-                                max_age=cookie['max_age'],
-                                path=settings.COOKIES_PATH,
-                                domain=settings.COOKIES_DOMAIN,
-                                secure=settings.COOKIES_SECURE
-                                )
-
-        for cookie in self._delete_cookies:
-            response.delete_cookie(
-                                   settings.COOKIES_PREFIX + cookie,
-                                   path=settings.COOKIES_PATH,
-                                   domain=settings.COOKIES_DOMAIN,
-                                   )

+ 0 - 12
notrefactored/cookie_jar/middleware.py

@@ -1,12 +0,0 @@
-from misago.cookie_jar.cookie_jar import CookieJar
-
-class CookieJarMiddleware(object):
-    def process_request(self, request):
-        request.cookie_jar = CookieJar()
-
-    def process_response(self, request, response):
-        try:
-            request.cookie_jar.flush(response)
-        except AttributeError:
-            pass
-        return response

+ 0 - 0
notrefactored/crawlers/__init__.py


+ 0 - 23
notrefactored/crawlers/crawler.py

@@ -1,23 +0,0 @@
-from database import CRAWLERS_NAMES, CRAWLERS_AGENTS, CRAWLERS_HOSTS
-
-class Crawler(object):
-    crawler = False
-    host = None
-    username = None
-    
-    def __init__(self, agent = None, ip = None):
-        if agent is not None:
-            for item in CRAWLERS_AGENTS.keys():
-            	if agent.find(item) != -1:
-                    self.crawler = True
-                    self.username = CRAWLERS_AGENTS[item]
-                    
-        if ip is not None:
-            for item in CRAWLERS_HOSTS.keys():
-            	if ip == item:
-                    self.crawler = True
-                    self.username = CRAWLERS_HOSTS[item]
-                    
-        if self.crawler:
-            self.username = CRAWLERS_NAMES[self.username]
-            self.host = ip

+ 0 - 16
notrefactored/crawlers/database.py

@@ -1,16 +0,0 @@
-CRAWLERS_NAMES = {
-    'bing': 'Bingbot',
-    'google': 'Googlebot',
-    'yahoo': 'Yahoo! Slurp',
-    'yahooch': 'Yahoo! Slurp China',
-}
-
-CRAWLERS_AGENTS = {
-    'bingbot/': 'bing',
-    'Googlebot/': 'google',
-    'Yahoo! Slurp China': 'yahooch',
-    'Yahoo! Slurp': 'yahoo',
-}
-
-CRAWLERS_HOSTS = {
-}

+ 0 - 9
notrefactored/crawlers/decorators.py

@@ -1,9 +0,0 @@
-from misago.views import error403
-
-def block_crawlers(f):
-    def decorator(*args, **kwargs):
-        request = args[0]
-        if request.user.is_crawler():
-            return error403(request)
-        return f(*args, **kwargs)
-    return decorator

+ 0 - 15
notrefactored/crawlers/middleware.py

@@ -1,15 +0,0 @@
-from crawler import Crawler
-from misago.users import models
-
-class DetectCrawlerMiddleware(object):
-    def process_request(self, request):
-        # If its correct request (We have client IP), see if it exists in Crawlers DB
-        if request.META.get('HTTP_X_FORWARDED_FOR') or request.META.get('REMOTE_ADDR'):
-            found_crawler = Crawler(
-                                    request.META.get('HTTP_USER_AGENT', ''),
-                                    request.META.get('HTTP_X_FORWARDED_FOR') or request.META.get('REMOTE_ADDR')
-                                    )
-            
-            # If crawler exists in database, use it as this request user
-            if found_crawler.crawler:
-                request.user = models.Crawler(found_crawler.username)

+ 0 - 7
notrefactored/csrf/__init__.py

@@ -1,7 +0,0 @@
-class CSRFProtection(object):
-    def __init__(self, csrf_token):
-        self.csrf_id = '_csrf_token'
-        self.csrf_token = csrf_token
-        
-    def request_secure(self, request):
-        return request.method == 'POST' and request.POST.get(self.csrf_id) == self.csrf_token

+ 0 - 8
notrefactored/csrf/context_processors.py

@@ -1,8 +0,0 @@
-def csrf(request):
-    try:
-        return {
-            'csrf_id': request.csrf.csrf_id,
-            'csrf_token': request.csrf.csrf_token,
-        }
-    except AttributeError:
-        return {}

+ 0 - 10
notrefactored/csrf/decorators.py

@@ -1,10 +0,0 @@
-from django.utils.translation import ugettext as _
-
-def check_csrf(f):
-    def decorator(*args, **kwargs):
-        request = args[0]
-        if not request.csrf.request_secure(request):
-            from misago.views import error403
-            return error403(request, _("Request authorization is invalid. Please try again."))
-        return f(*args, **kwargs)
-    return decorator

+ 0 - 13
notrefactored/csrf/middleware.py

@@ -1,13 +0,0 @@
-from misago.csrf import CSRFProtection
-from misago.utils import get_random_string
-
-class CSRFMiddleware(object):
-    def process_request(self, request):
-        if request.user.is_crawler():
-            return None
-        if 'csrf_token' in request.session:
-            csrf_token = request.session['csrf_token']
-        else:
-            csrf_token = get_random_string(16);
-            request.session['csrf_token'] = csrf_token
-        request.csrf = CSRFProtection(csrf_token)

+ 0 - 0
notrefactored/firewalls/__init__.py


+ 0 - 39
notrefactored/firewalls/firewalls.py

@@ -1,39 +0,0 @@
-from django.conf import settings
-from django.utils.translation import ugettext_lazy as _
-from misago.admin import ADMIN_PATH
-from misago.messages import Message
-from misago.views import error403, error404
-from misago.authn.views import signin
-
-class FirewallForum(object):
-    """
-    Firewall Abstraction
-    """
-    admin = False
-    prefix = ''
-    def behind_firewall(self, path):
-        """
-        Firewall test, it checks if requested path is behind firewall
-        """
-        return path[:len(self.prefix)] == self.prefix
-
-    def process_view(self, request, callback, callback_args, callback_kwargs):
-        return None
-
-
-class FirewallAdmin(FirewallForum):
-    admin = True
-    prefix = '/' + ADMIN_PATH
-    def process_view(self, request, callback, callback_args, callback_kwargs):
-        # Block all crawlers with 403
-        if request.user.is_crawler():
-            request.theme.reset_theme()
-            return error403(request)
-        else:
-            # If we are not authenticated or not admin, force us to sign in right way
-            if not request.user.is_authenticated():
-                return signin(request)
-            elif not request.user.is_god() and not request.acl.admin.is_admin():
-                request.messages.set_message(Message(_("Your account does not have admin privileges")), 'error', 'security')
-                return signin(request)
-            return None

+ 0 - 17
notrefactored/firewalls/middleware.py

@@ -1,17 +0,0 @@
-from django.conf import settings
-from misago.firewalls.firewalls import *
-from misago.themes.theme import Theme
-
-class FirewallMiddleware(object):
-    firewall_admin = FirewallAdmin()
-    firewall_forum = FirewallForum()
-
-    def process_request(self, request):
-        if settings.ADMIN_PATH and self.firewall_admin.behind_firewall(request.path_info):
-            request.firewall = self.firewall_admin
-            request.theme.set_theme('admin')
-        else:
-            request.firewall = self.firewall_forum
-
-    def process_view(self, request, callback, callback_args, callback_kwargs):
-        return request.firewall.process_view(request, callback, callback_args, callback_kwargs)

+ 0 - 175
notrefactored/forms/__init__.py

@@ -1,175 +0,0 @@
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-from mptt.forms import TreeNodeChoiceField
-from misago.forms.layouts import *
-from recaptcha.client.captcha import submit as recaptcha_submit
-
-class Form(forms.Form):
-    """
-    Custom form implementation extending Django Forms functionality
-    """
-    validate_repeats = []
-    repeats_errors = []
-    dont_strip = []
-    error_source = None
-    def __init__(self, data=None, file=None, request=None, *args, **kwargs):
-        self.request = request
-
-        # Extract request from first argument
-        if data != None:
-            super(Form, self).__init__(data, file, *args, **kwargs)
-        else:
-            super(Form, self).__init__(*args, **kwargs)
-
-        # Kill captcha fields
-        try:
-            if self.request.settings['bots_registration'] != 'recaptcha' or self.request.session.get('captcha_passed'):
-                del self.fields['recaptcha']
-        except KeyError:
-            pass
-        try:
-            if self.request.settings['bots_registration'] != 'qa' or self.request.session.get('captcha_passed'):
-                del self.fields['captcha_qa']
-            else:
-                # Make sure we have any questions loaded
-                self.fields['captcha_qa'].label = self.request.settings['qa_test']
-                self.fields['captcha_qa'].help_text = self.request.settings['qa_test_help']
-        except KeyError:
-            pass
-
-        # Let forms do mumbo-jumbo with fields removing
-        self.finalize_form()
-
-    def finalize_form(self):
-        pass
-
-    def full_clean(self):
-        """
-        Trim inputs and strip newlines
-        """
-        self.data = self.data.copy()
-        for key, field in self.fields.iteritems():
-            try:
-                if field.__class__.__name__ in ['ModelChoiceField', 'TreeForeignKey'] and self.data[key]:
-                    self.data[key] = int(self.data[key])
-                elif field.__class__.__name__ == 'ModelMultipleChoiceField':
-                    self.data.setlist(key, [int(x) for x in self.data.getlist(key, [])])
-                elif field.__class__.__name__ not in ['DateField', 'DateTimeField']:
-                    if not key in self.dont_strip:
-                        if field.__class__.__name__ in ['MultipleChoiceField', 'TypedMultipleChoiceField']:
-                            self.data.setlist(key, [x.strip() for x in self.data.getlist(key, [])])
-                        else:
-                            self.data[key] = self.data[key].strip()
-                    if field.__class__.__name__ in ['MultipleChoiceField', 'TypedMultipleChoiceField']:
-                        self.data.setlist(key, [x.replace("\r\n", '') for x in self.data.getlist(key, [])])
-                    elif not field.widget.__class__.__name__ in ['Textarea']:
-                        self.data[key] = self.data[key].replace("\r\n", '')
-            except (KeyError, AttributeError):
-                pass
-        super(Form, self).full_clean()
-
-    def clean(self):
-        """
-        Clean data, do magic checks and stuff
-        """
-        cleaned_data = super(Form, self).clean()
-        self._check_all()
-        return cleaned_data
-
-    def clean_recaptcha(self):
-        """
-        Test reCaptcha, scream if it went wrong
-        """
-        response = recaptcha_submit(
-                                    self.request.POST.get('recaptcha_challenge_field'),
-                                    self.request.POST.get('recaptcha_response_field'),
-                                    self.request.settings['recaptcha_private'],
-                                    self.request.session.get_ip(self.request)
-                                    ).is_valid
-        if not response:
-            raise forms.ValidationError(_("Entered words are incorrect. Please try again."))
-        self.request.session['captcha_passed'] = True
-        return ''
-
-    def clean_captcha_qa(self):
-        """
-        Test QA Captcha, scream if it went wrong
-        """
-
-        if not unicode(self.cleaned_data['captcha_qa']).lower() in (name.lower() for name in unicode(self.request.settings['qa_test_answers']).splitlines()):
-            raise forms.ValidationError(_("The answer you entered is incorrect."))
-        self.request.session['captcha_passed'] = True
-        return self.cleaned_data['captcha_qa']
-
-    def _check_all(self):
-        # Check repeated fields
-        self._check_repeats()
-        # Check CSRF, we dont allow un-csrf'd forms in Misago
-        self._check_csrf()
-        # Check if we have any errors from fields, if we do, we will set fancy form-wide error message
-        self._check_fields_errors()
-
-    def _check_repeats(self):
-        for index, repeat in enumerate(self.validate_repeats):
-            # Check empty fields
-            for field in repeat:
-                if not field in self.data:
-                    try:
-                        if len(repeat) == 2:
-                            self.errors['_'.join(repeat)] = [self.repeats_errors[index]['fill_both']]
-                        else:
-                            self.errors['_'.join(repeat)] = [self.repeats_errors[index]['fill_all']]
-                    except (IndexError, KeyError):
-                        if len(repeat) == 2:
-                            self.errors['_'.join(repeat)] = [_("You have to fill in both fields.")]
-                        else:
-                            self.errors['_'.join(repeat)] = [_("You have to fill in all fields.")]
-                    break
-
-            else:
-                # Check different fields
-                past_field = self.data[repeat[0]]
-                for field in repeat:
-                    if self.data[field] != past_field:
-                        try:
-                            self.errors['_'.join(repeat)] = [self.repeats_errors[index]['different']]
-                        except (IndexError, KeyError):
-                            self.errors['_'.join(repeat)] = [_("Entered values differ from each other.")]
-                        break
-                    past_field = self.data[field]
-
-
-    def _check_csrf(self):
-        if not self.request.csrf.request_secure(self.request):
-            raise forms.ValidationError(_("Request authorization is invalid. Please resubmit your form."))
-
-    def _check_fields_errors(self):
-        if self.errors:
-            if self.error_source and self.error_source in self.errors:
-                field_error, self.errors[self.error_source] = self.errors[self.error_source][0], []
-                raise forms.ValidationError(field_error)
-            raise forms.ValidationError(_("Form contains errors."))
-        
-    def empty_errors(self):
-        for i in self.errors:
-            self.errors[i] = []
-
-
-class YesNoSwitch(forms.CheckboxInput):
-    """
-    Custom Yes-No switch as fancier alternative to checkboxes
-    """
-    pass
-
-
-class ForumChoiceField(TreeNodeChoiceField):
-    """
-    Custom forum choice field
-    """
-    def __init__(self, *args, **kwargs):
-        kwargs['level_indicator'] = u'- - '
-        super(ForumChoiceField, self).__init__(*args, **kwargs)
-
-    def _get_level_indicator(self, obj):
-        level = getattr(obj, obj._mptt_meta.level_attr)
-        return mark_safe(conditional_escape(self.level_indicator) * (level - 1))

+ 0 - 299
notrefactored/forms/layouts.py

@@ -1,299 +0,0 @@
-from UserDict import IterableUserDict
-from django.utils import formats
-
-class FormLayout(object):
-    def __init__(self, form, fieldsets=False):
-        scaffold_fields = FormFields(form)
-        scaffold_fieldsets = FormFieldsets(form, scaffold_fields.fields, fieldsets)
-
-        self.multipart_form = scaffold_fields.multipart_form
-        self.fieldsets = scaffold_fieldsets.fieldsets
-        self.fields = scaffold_fields.fields
-        self.hidden = scaffold_fields.hidden
-
-class FormFields(object):
-    """
-    Hydrator that builds fields list from form and blueprint
-    """
-    def __init__(self, form):
-        self.multipart_form = False
-        self.fields = {}
-        self.hidden = []
-
-        # Extract widgets from meta
-        self.meta_widgets = {}
-        try:
-            self.meta_widgets = form.Meta.widgets
-        except AttributeError:
-            pass
-
-        # Find out field input types
-        for field in form.fields.keys():
-            widget = self._get_widget(field, form.fields[field])
-            widget_name = widget.__class__.__name__
-            bound_field = form[field]
-            blueprint = {
-                         'attrs': {
-                                    'id': bound_field.auto_id,
-                                    'name': bound_field.html_name,
-                                   },
-                         'endrow': False,
-                         'errors': [],
-                         'has_value': bound_field.value() != None,
-                         'help_text': bound_field.help_text,
-                         'hidden': widget.is_hidden,
-                         'html_id': bound_field.auto_id,
-                         'html_name': bound_field.html_name,
-                         'id': field,
-                         'initial': bound_field.field.initial,
-                         'label': bound_field.label,
-                         'last': False,
-                         'nested': [],
-                         'required': bound_field.field.widget.is_required,
-                         'show_hidden_initial': bound_field.field.show_hidden_initial,
-                         'value': bound_field.value(),
-                         'width': 100,
-                         'widget': '',
-                         'choices': [],
-                        }
-
-            # Set multipart form
-            if widget.needs_multipart_form:
-                self.multipart_form = True
-
-            # Get errors?
-            if form.is_bound:
-                for error in bound_field._errors():
-                    blueprint['errors'].append(error)
-                try:
-                    for error in form.errors[field]:
-                        if not error in blueprint['errors']:
-                            blueprint['errors'].append(error)
-                except KeyError:
-                    pass
-
-            # Use clean value instead?
-            try:
-                if field in form.cleaned_data:
-                    blueprint['value'] = form.cleaned_data[field]
-            except AttributeError:
-                pass
-
-            # TextInput
-            if widget_name in ['TextInput', 'PasswordInput', 'Textarea']:
-                blueprint['widget'] = 'text'
-                blueprint['attrs']['type'] = 'text'
-                try:
-                    blueprint['attrs']['maxlength'] = bound_field.field.max_length
-                except AttributeError:
-                    pass
-
-            # PasswordInput
-            if widget_name == 'PasswordInput':
-                blueprint['attrs']['type'] = 'password'
-
-            # Textarea      
-            if widget_name == 'Textarea':
-                blueprint['widget'] = 'textarea'
-
-            # ReCaptcha      
-            if widget_name == 'ReCaptchaWidget':
-                from recaptcha.client.captcha import displayhtml
-                blueprint['widget'] = 'recaptcha'
-                blueprint['attrs'] = {'html': displayhtml(
-                                                          form.request.settings['recaptcha_public'],
-                                                          form.request.settings['recaptcha_ssl'],
-                                                          bound_field.field.api_error,
-                                                          )}
-
-            # HiddenInput
-            if widget_name == 'HiddenInput':
-                blueprint['widget'] = 'hidden'
-
-            # MultipleHiddenInput
-            if widget_name == 'MultipleHiddenInput':
-                blueprint['widget'] = 'multiple_hidden'
-                blueprint['attrs'] = {
-                                      'choices': widget.choices
-                                     }
-
-            # FileInput
-            if widget_name == 'FileInput':
-                blueprint['widget'] = 'file'
-
-            # ClearableFileInput
-            if widget_name == 'ClearableFileInput':
-                blueprint['widget'] = 'file_clearable'
-
-            # DateInput
-            if widget_name == 'DateInput':
-                blueprint['widget'] = 'date'
-                try:
-                    blueprint['value'] = blueprint['value'].strftime('%Y-%m-%d')
-                except AttributeError as e:
-                    pass
-
-            # DateTimeInput
-            if widget_name == 'DateTimeInput':
-                blueprint['widget'] = 'datetime'
-                try:
-                    blueprint['value'] = blueprint['value'].strftime('%Y-%m-%d %H:%M')
-                except AttributeError as e:
-                    pass
-
-            # TimeInput
-            if widget_name == 'TimeInput':
-                blueprint['widget'] = 'time'
-                try:
-                    blueprint['value'] = blueprint['value'].strftime('%H:%M')
-                except AttributeError as e:
-                    pass
-
-            # CheckboxInput
-            if widget_name == 'CheckboxInput':
-                blueprint['widget'] = 'checkbox'
-
-            # Select, NullBooleanSelect, SelectMultiple, RadioSelect, CheckboxSelectMultiple
-            if widget_name in ['Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple']:
-                blueprint['choices'] = widget.choices
-
-            # Yes-no radio select
-            if widget_name == 'YesNoSwitch':
-                blueprint['widget'] = 'yes_no_switch'
-
-            # Select
-            if widget_name == 'Select':
-                blueprint['widget'] = 'select'
-                if not blueprint['value']:
-                    blueprint['value'] = None
-
-            # NullBooleanSelect
-            if widget_name == 'NullBooleanSelect':
-                blueprint['widget'] = 'null_boolean_select'
-
-            # SelectMultiple
-            if widget_name == 'SelectMultiple':
-                blueprint['widget'] = 'select_multiple'
-
-            # RadioSelect
-            if widget_name == 'RadioSelect':
-                blueprint['widget'] = 'radio_select'
-                if not blueprint['value']:
-                    blueprint['value'] = u''
-
-            # CheckboxSelectMultiple
-            if widget_name == 'CheckboxSelectMultiple':
-                blueprint['widget'] = 'checkbox_select_multiple'
-
-            # MultiWidget
-            if widget_name == 'MultiWidget':
-                blueprint['widget'] = 'multi'
-
-            # SplitDateTimeWidget
-            if widget_name == 'SplitDateTimeWidget':
-                blueprint['widget'] = 'split_datetime'
-
-            # SplitHiddenDateTimeWidget
-            if widget_name == 'SplitHiddenDateTimeWidget':
-                blueprint['widget'] = 'split_hidden_datetime'
-
-            # SelectDateWidget
-            if widget_name == 'SelectDateWidget':
-                blueprint['widget'] = 'select_date'
-                blueprint['years'] = widget.years
-
-            # Store field in either of collections
-            if blueprint['hidden']:
-                blueprint['attrs']['type'] = 'hidden'
-                self.hidden.append(blueprint)
-            else:
-                self.fields[field] = blueprint
-
-    def _get_widget(self, name, field):
-        if name in self.meta_widgets:
-            return self.meta_widgets[name]
-        return field.widget
-
-
-class FormFieldsets(object):
-    """
-    Hydrator that builds fieldset from form and blueprint
-    """
-    def __init__(self, form, fields, fieldsets=None):
-        self.fieldsets = []
-
-        # Use form layout
-        if not fieldsets:
-            try:
-                fieldsets = form.layout
-            except AttributeError:
-                pass
-
-        # Build fieldsets data
-        if fieldsets:
-            for blueprint in fieldsets:
-                fieldset = {'legend': None, 'fields': [], 'help': None, 'last': False}
-                fieldset['legend'] = blueprint[0]
-                row_width = 0
-                for field in blueprint[1]:
-                    try:
-                        if isinstance(field, basestring):
-                            fieldset['fields'].append(fields[field])
-                        elif field[0] == 'nested':
-                            subfields = {'label': None, 'help_text': None, 'nested': [], 'errors':[], 'endrow': False, 'last': False, 'width': 100}
-                            subfiels_ids = []
-                            try:
-                                subfields = field[2].update(subfields)
-                            except IndexError:
-                                pass
-                            for subfield in field[1]:
-                                if isinstance(subfield, basestring):
-                                    subfiels_ids.append(subfield)
-                                    subfields['nested'].append(fields[subfield])
-                                    for error in fields[subfield]['errors']:
-                                        if not error in subfields['errors']:
-                                            subfields['errors'].append(error)
-                                else:
-                                    subfiels_ids.append(subfield[0])
-                                    try:
-                                        subfield[1]['attrs'] = dict(fields[subfield[0]]['attrs'], **subfield[1]['attrs'])
-                                    except KeyError:
-                                        pass
-                                    subfields['nested'].append(dict(fields[subfield[0]], **subfield[1]))
-                                    for error in fields[subfield[0]]['errors']:
-                                        if not error in subfields['errors']:
-                                            subfields['errors'].append(error)
-                            if not subfields['label']:
-                                subfields['label'] = subfields['nested'][0]['label']
-                            if not subfields['help_text']:
-                                subfields['help_text'] = subfields['nested'][0]['help_text']
-                            try:
-                                subfields['errors'] = form.errors["_".join(subfiels_ids)]
-                            except KeyError:
-                                pass
-                            fieldset['fields'].append(subfields)
-                        else:
-                            try:
-                                field[1]['attrs'] = dict(fields[field[0]]['attrs'], **field[1]['attrs'])
-                            except KeyError:
-                                pass
-                            fieldset['fields'].append(dict(fields[field[0]], **field[1]))
-                        row_width += fieldset['fields'][-1]['width']
-                        if row_width >= 100:
-                            fieldset['fields'][-1]['endrow'] = True
-                            row_width = 0
-                    except (AttributeError, IndexError, KeyError):
-                        pass
-                if fieldset['fields']:
-                    fieldset['fields'][-1]['endrow'] = True
-                    fieldset['fields'][-1]['last'] = True
-                try:
-                    fieldset['help'] = blueprint[2]
-                except IndexError:
-                    pass
-
-                # Append complete fieldset
-                if fieldset['fields']:
-                    self.fieldsets.append(fieldset)
-            self.fieldsets[-1]['last'] = True
-

+ 0 - 0
notrefactored/forumroles/__init__.py


+ 0 - 114
notrefactored/forumroles/fixtures.py

@@ -1,114 +0,0 @@
-from misago.forumroles.models import ForumRole
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-def load_fixtures():
-    role = ForumRole()
-    role.name = _('Full Access').message
-    role.set_permissions({
-                          'can_see_forum': True,
-                          'can_see_forum_contents': True,
-                          'can_read_threads': 2,
-                          'can_start_threads': 2,
-                          'can_edit_own_threads': True,
-                          'can_soft_delete_own_threads': True,
-                          'can_write_posts': 2,
-                          'can_edit_own_posts': True,
-                          'can_soft_delete_own_posts': True,
-                          'can_upvote_posts': True,
-                          'can_downvote_posts': True,
-                          'can_see_posts_scores': 2,
-                          'can_see_votes': True,
-                          'can_make_polls': True,
-                          'can_vote_in_polls': True,
-                          'can_see_poll_votes': True,
-                          'can_see_attachments': True,
-                          'can_upload_attachments': True,
-                          'can_download_attachments': True,
-                          'attachment_size': 5000,
-                          'attachment_limit': 15,
-                          'can_approve': True,
-                          'can_edit_labels': True,
-                          'can_see_changelog': True,
-                          'can_pin_threads': 2,
-                          'can_edit_threads_posts': True,
-                          'can_move_threads_posts': True,
-                          'can_close_threads': True,
-                          'can_protect_posts': True,
-                          'can_delete_threads': 2,
-                          'can_delete_posts': 2,
-                          'can_delete_polls': 2,
-                          'can_delete_attachments': True,
-                          })
-    role.save(force_insert=True)
-
-    role = ForumRole()
-    role.name = _('Standard Access and Upload').message
-    role.set_permissions({
-                          'can_see_forum': True,
-                          'can_see_forum_contents': True,
-                          'can_read_threads': 2,
-                          'can_start_threads': 2,
-                          'can_edit_own_threads': True,
-                          'can_write_posts': 2,
-                          'can_edit_own_posts': True,
-                          'can_soft_delete_own_posts': True,
-                          'can_upvote_posts': True,
-                          'can_downvote_posts': True,
-                          'can_see_posts_scores': 1,
-                          'can_make_polls': True,
-                          'can_vote_in_polls': True,
-                          'can_upload_attachments': True,
-                          'can_download_attachments': True,
-                          'attachment_size': 100,
-                          'attachment_limit': 3,
-                          })
-    role.save(force_insert=True)
-
-    role = ForumRole()
-    role.name = _('Standard Access').message
-    role.set_permissions({
-                          'can_see_forum': True,
-                          'can_see_forum_contents': True,
-                          'can_read_threads': 2,
-                          'can_start_threads': 2,
-                          'can_edit_own_threads': True,
-                          'can_write_posts': 2,
-                          'can_edit_own_posts': True,
-                          'can_soft_delete_own_posts': True,
-                          'can_upvote_posts': True,
-                          'can_downvote_posts': True,
-                          'can_see_posts_scores': 1,
-                          'can_make_polls': True,
-                          'can_vote_in_polls': True,
-                          'can_download_attachments': True,
-                          })
-    role.save(force_insert=True)
-
-    role = ForumRole()
-    role.name = _('Read and Download').message
-    role.set_permissions({
-                          'can_see_forum': True,
-                          'can_see_forum_contents': True,
-                          'can_read_threads': 2,
-                          'can_download_attachments': True,
-                          'can_see_posts_scores': 1,
-                          })
-    role.save(force_insert=True)
-
-    role = ForumRole()
-    role.name = _('Threads list only').message
-    role.set_permissions({
-                          'can_see_forum': True,
-                          'can_see_forum_contents': True,
-                          })
-    role.save(force_insert=True)
-
-    role = ForumRole()
-    role.name = _('Read only').message
-    role.set_permissions({
-                          'can_see_forum': True,
-                          'can_see_forum_contents': True,
-                          'can_read_threads': 2,
-                          })
-    role.save(force_insert=True)

+ 0 - 20
notrefactored/forumroles/forms.py

@@ -1,20 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.forms import Form
-from misago.utils.validators import validate_sluggable
-
-class ForumRoleForm(Form):
-    name = forms.CharField(max_length=255, validators=[validate_sluggable(
-                                                                         _("Role name must be sluggable."),
-                                                                         _("Role name is too long.")
-                                                                         )])
-
-    def finalize_form(self):
-        self.layout = (
-                       (
-                        _("Basic Role Options"),
-                        (
-                         ('name', {'label': _("Role Name"), 'help_text': _("Role Name is used to identify this role in Admin Control Panel.")}),
-                         ),
-                        ),
-                       )

+ 0 - 34
notrefactored/forumroles/migrations/0001_initial.py

@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'ForumRole'
-        db.create_table(u'forumroles_forumrole', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('permissions', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-        ))
-        db.send_create_signal(u'forumroles', ['ForumRole'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'ForumRole'
-        db.delete_table(u'forumroles_forumrole')
-
-
-    models = {
-        u'forumroles.forumrole': {
-            'Meta': {'object_name': 'ForumRole'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
-        }
-    }
-
-    complete_apps = ['forumroles']

+ 0 - 0
notrefactored/forumroles/migrations/__init__.py


+ 0 - 36
notrefactored/forumroles/models.py

@@ -1,36 +0,0 @@
-from django.db import models
-from django.utils.translation import ugettext as _
-import base64
-try:
-    import cPickle as pickle
-except ImportError:
-    import pickle
-
-
-class ForumRole(models.Model):
-    """
-    Misago User Role model
-    """
-    name = models.CharField(max_length=255)
-    permissions = models.TextField(null=True, blank=True)
-    permissions_cache = {}
-
-    def __unicode__(self):
-        return unicode(_(self.name))
-
-    def get_permissions(self):
-        if self.permissions_cache:
-            return self.permissions_cache
-
-        try:
-            self.permissions_cache = pickle.loads(base64.decodestring(self.permissions))
-        except Exception:
-            # ValueError, SuspiciousOperation, unpickling exceptions. If any of
-            # these happen, just return an empty dictionary (an empty permissions list).
-            self.permissions_cache = {}
-
-        return self.permissions_cache
-
-    def set_permissions(self, permissions):
-        self.permissions_cache = permissions
-        self.permissions = base64.encodestring(pickle.dumps(permissions, pickle.HIGHEST_PROTOCOL))

+ 0 - 143
notrefactored/forumroles/views.py

@@ -1,143 +0,0 @@
-import copy
-from django.core.urlresolvers import reverse as django_reverse
-from django.utils.translation import ugettext as _
-from misago.acl.builder import build_forum_form
-from misago.admin import site
-from misago.admin.widgets import *
-from misago.utils import slugify
-from misago.forms import Form, YesNoSwitch
-from misago.forumroles.forms import ForumRoleForm
-from misago.forumroles.models import ForumRole
-
-def reverse(route, target=None):
-    if target:
-        return django_reverse(route, kwargs={'target': target.pk, 'slug': slugify(target.name)})
-    return django_reverse(route)
-
-"""
-Views
-"""
-class List(ListWidget):
-    admin = site.get_action('roles_forums')
-    id = 'list'
-    columns = (
-               ('role', _("Role")),
-               )
-    nothing_checked_message = _('You have to check at least one role.')
-    actions = (
-               ('delete', _("Delete selected forum roles"), _("Are you sure you want to delete selected roles?")),
-               )
-
-    def sort_items(self, page_items, sorting_method):
-        return page_items.order_by('name')
-
-    def get_item_actions(self, item):
-        return (
-                self.action('adjust', _("Role Permissions"), reverse('admin_roles_forums_acl', item)),
-                self.action('pencil', _("Edit Role"), reverse('admin_roles_forums_edit', item)),
-                self.action('remove', _("Delete Role"), reverse('admin_roles_forums_delete', item), post=True, prompt=_("Are you sure you want to delete this role?")),
-                )
-
-    def action_delete(self, items, checked):
-        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-        Role.objects.filter(id__in=checked).delete()
-        return Message(_('Selected forum roles have been deleted successfully.'), 'success'), reverse('admin_roles_forums')
-
-
-class New(FormWidget):
-    admin = site.get_action('roles_forums')
-    id = 'new'
-    fallback = 'admin_roles_forums'
-    form = ForumRoleForm
-    submit_button = _("Save Role")
-
-    def get_new_url(self, model):
-        return reverse('admin_roles_forums_new')
-
-    def get_edit_url(self, model):
-        return reverse('admin_roles_forums_edit', model)
-
-    def submit_form(self, form, target):
-        new_role = ForumRole(
-                      name=form.cleaned_data['name'],
-                     )
-        new_role.save(force_insert=True)
-        return new_role, Message(_('New Forum Role has been created.'), 'success')
-
-
-class Edit(FormWidget):
-    admin = site.get_action('roles_forums')
-    id = 'edit'
-    name = _("Edit Forum Role")
-    fallback = 'admin_roles_forums'
-    form = ForumRoleForm
-    target_name = 'name'
-    notfound_message = _('Requested Forum Role could not be found.')
-    submit_fallback = True
-
-    def get_url(self, model):
-        return reverse('admin_roles_forums_edit', model)
-
-    def get_edit_url(self, model):
-        return self.get_url(model)
-
-    def get_initial_data(self, model):
-        return {
-                'name': model.name,
-                }
-
-    def submit_form(self, form, target):
-        target.name = form.cleaned_data['name']
-        target.save(force_update=True)
-        return target, Message(_('Changes in forum role "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
-
-
-class ACL(FormWidget):
-    admin = site.get_action('roles_forums')
-    id = 'acl'
-    name = _("Change Forum Role Permissions")
-    fallback = 'admin_roles_forums'
-    target_name = 'name'
-    notfound_message = _('Requested Forum Role could not be found.')
-    submit_fallback = True
-    template = 'acl_form'
-
-    def get_form(self, target):
-        self.form = build_forum_form(self.request, target)
-        return self.form
-
-    def get_url(self, model):
-        return reverse('admin_roles_forums_acl', model)
-
-    def get_edit_url(self, model):
-        return self.get_url(model)
-
-    def get_initial_data(self, model):
-        raw_acl = model.get_permissions()
-        initial = {}
-        for field in self.form.base_fields:
-            if field in raw_acl:
-                initial[field] = raw_acl[field]
-        return initial
-
-    def submit_form(self, form, target):
-        raw_acl = target.get_permissions()
-        for perm in form.cleaned_data:
-            raw_acl[perm] = form.cleaned_data[perm]
-        target.set_permissions(raw_acl)
-        target.save(force_update=True)
-        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-
-        return target, Message(_('Forum Role "%(name)s" permissions have been changed.') % {'name': self.original_name}, 'success')
-
-
-class Delete(ButtonWidget):
-    admin = site.get_action('roles_forums')
-    id = 'delete'
-    fallback = 'admin_roles_forums'
-    notfound_message = _('Requested Forum Role could not be found.')
-
-    def action(self, target):
-        target.delete()
-        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-        return Message(_('Forum Role "%(name)s" has been deleted.') % {'name': _(target.name)}, 'success'), False

+ 0 - 0
notrefactored/forums/__init__.py


+ 0 - 77
notrefactored/forums/acl.py

@@ -1,77 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.acl.builder import BaseACL
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forms import YesNoSwitch
-
-def make_forum_form(request, role, form):
-    form.base_fields['can_see_forum'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_see_forum_contents'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.layout.append((
-                        _("Forums Permissions"),
-                        (
-                         ('can_see_forum', {'label': _("Can see forum")}),
-                         ('can_see_forum_contents', {'label': _("Can see forum contents")}),
-                         ),
-                        ))
-
-
-class ForumsACL(BaseACL):
-    def known_forums(self):
-        return self.acl['can_see']
-
-    def can_see(self, forum):
-        try:
-            return forum.pk in self.acl['can_see']
-        except AttributeError:
-            return long(forum) in self.acl['can_see']
-
-    def can_browse(self, forum):
-        if self.can_see(forum):
-            try:
-                return forum.pk in self.acl['can_browse']
-            except AttributeError:
-                return long(forum) in self.acl['can_browse']
-        return False
-
-    def allow_forum_view(self, forum):
-        if not self.can_see(forum):
-            raise ACLError404()
-        if not self.can_browse(forum):
-            raise ACLError403(_("You don't have permission to browse this forum."))
-
-
-def build_forums(acl, perms, forums, forum_roles):
-    acl.forums = ForumsACL()
-    acl.forums.acl['can_see'] = []
-    acl.forums.acl['can_browse'] = []
-
-    for forum in forums:
-        for perm in perms:
-            try:
-                role = forum_roles[perm['forums'][forum.pk]]
-                if role['can_see_forum'] and forum.pk not in acl.forums.acl['can_see']:
-                    acl.forums.acl['can_see'].append(forum.pk)
-                if role['can_see_forum_contents'] and forum.pk not in acl.forums.acl['can_browse']:
-                    acl.forums.acl['can_browse'].append(forum.pk)
-            except KeyError:
-                pass
-
-
-def cleanup(acl, perms, forums):
-    for forum in forums:
-        if forum.pk in acl.forums.acl['can_browse'] and not forum.pk in acl.forums.acl['can_see']:
-            # First burp: we can read forum but we cant see forum
-            del acl.forums.acl['can_browse'][acl.forums.acl['can_browse'].index(forum.pk)]
-
-        if forum.level > 1:
-            if forum.parent_id not in acl.forums.acl['can_see'] or forum.parent_id not in acl.forums.acl['can_browse']:
-                # Second burp: we cant see or read parent forum
-                try:
-                    del acl.forums.acl['can_see'][acl.forums.acl['can_see'].index(forum.pk)]
-                except ValueError:
-                    pass
-                try:
-                    del acl.forums.acl['can_browse'][acl.forums.acl['can_browse'].index(forum.pk)]
-                except ValueError:
-                    pass

+ 0 - 58
notrefactored/forums/fixtures.py

@@ -1,58 +0,0 @@
-from django.utils import timezone
-from misago.monitor.fixtures import load_monitor_fixture
-from misago.forums.models import Forum
-from misago.threads.models import Thread, Post
-from misago.utils import slugify
-
-def load_fixtures():
-    Forum(token='annoucements', name='annoucements', slug='annoucements', type='forum').insert_at(None, save=True)
-    Forum(token='private', name='private', slug='private', type='forum').insert_at(None, save=True)
-    Forum(token='reports', name='reports', slug='reports', type='forum').insert_at(None, save=True)
-
-    root = Forum(token='root', name='root', slug='root')
-    root.insert_at(None, save=True)
-    cat = Forum(type='category', name='First Category', slug='first-category')
-    cat.insert_at(root, save=True)
-    forum = Forum(type='forum', name='First Forum', slug='first-forum', threads=1, posts=1)
-    forum.insert_at(cat, save=True)
-    Forum(type='redirect', name='Project Homepage', slug='project-homepage', redirect='http://misago-project.org').insert_at(cat, position='last-child', save=True)
-    Forum.objects.populate_tree(True)
-
-    now = timezone.now()
-    thread = Thread.objects.create(
-                                   forum=forum,
-                                   name='Welcome to Misago!',
-                                   slug=slugify('Welcome to Misago!'),
-                                   start=now,
-                                   last=now,
-                                   )
-    post = Post.objects.create(
-                               forum=forum,
-                               thread=thread,
-                               user_name='MisagoProject',
-                               ip='127.0.0.1',
-                               agent='',
-                               post='Welcome to Misago!',
-                               post_preparsed='Welcome to Misago!',
-                               date=now,
-                               )
-    thread.start_post = post
-    thread.start_poster_name = 'MisagoProject'
-    thread.start_poster_slug = 'misagoproject'
-    thread.last_post = post
-    thread.last_poster_name = 'MisagoProject'
-    thread.last_poster_slug = 'misagoproject'
-    thread.save(force_update=True)
-    forum.last_thread = thread
-    forum.last_thread_name = thread.name
-    forum.last_thread_slug = thread.slug
-    forum.last_thread_date = thread.last
-    forum.last_poster = thread.last_poster
-    forum.last_poster_name = thread.last_poster_name
-    forum.last_poster_slug = thread.last_poster_slug
-    forum.save(force_update=True)
-
-    load_monitor_fixture({
-                          'threads': 1,
-                          'posts': 1,
-                          })

+ 0 - 180
notrefactored/forums/forms.py

@@ -1,180 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from mptt.forms import TreeNodeChoiceField
-from misago.forms import Form, YesNoSwitch
-from misago.forums.models import Forum
-from misago.utils.validators import validate_sluggable
-
-class CategoryForm(Form):
-    parent = False
-    perms = False
-    name = forms.CharField(max_length=255, validators=[validate_sluggable(
-                                                                          _("Category name must be sluggable."),
-                                                                          _("Category name is too long.")
-                                                                          )])
-    description = forms.CharField(widget=forms.Textarea, required=False)
-    closed = forms.BooleanField(widget=YesNoSwitch, required=False)
-    style = forms.CharField(max_length=255, required=False)
-    attrs = forms.CharField(max_length=255, required=False)
-    show_details = forms.BooleanField(widget=YesNoSwitch, required=False, initial=True)
-
-    layout = (
-              (
-               _("Basic Options"),
-               (
-                ('parent', {'label': _("Category Parent")}),
-                ('perms', {'label': _("Copy Permissions from")}),
-                ('name', {'label': _("Category Name")}),
-                ('description', {'label': _("Category Description")}),
-                ('closed', {'label': _("Closed Category")}),
-                ),
-              ),
-              (
-               _("Display Options"),
-               (
-                ('attrs', {'label': _("Category Attributes"), 'help_text': _('Custom templates can check categories for predefined attributes that will change way they are rendered.')}),
-                ('show_details', {'label': _("Show Subforums Details"), 'help_text': _('Allows you to prevent this category subforums from displaying statistics, last post data, etc. ect. on forums lists.')}),
-                ('style', {'label': _("Category Style"), 'help_text': _('You can add custom CSS classess to this category, to change way it looks on board index.')}),
-                ),
-              ),
-             )
-
-    def finalize_form(self):
-        self.fields['parent'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(include_self=True), level_indicator=u'- - ')
-        self.fields['perms'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
-
-    def clean_attrs(self):
-        clean = []
-        data = self.cleaned_data['attrs'].strip().split()
-        for i in data:
-            i = i.strip()
-            if not i in clean:
-                clean.append(i)
-        return ' '.join(clean)
-
-
-class ForumForm(Form):
-    parent = False
-    perms = False
-    name = forms.CharField(max_length=255, validators=[validate_sluggable(
-                                                                          _("Forum name must be sluggable."),
-                                                                          _("Forum name is too long.")
-                                                                          )])
-    description = forms.CharField(widget=forms.Textarea, required=False)
-    closed = forms.BooleanField(widget=YesNoSwitch, required=False)
-    style = forms.CharField(max_length=255, required=False)
-    prune_start = forms.IntegerField(min_value=0, initial=0)
-    prune_last = forms.IntegerField(min_value=0, initial=0)
-    attrs = forms.CharField(max_length=255, required=False)
-    show_details = forms.BooleanField(widget=YesNoSwitch, required=False, initial=True)
-
-    layout = (
-              (
-               _("Basic Options"),
-               (
-                ('parent', {'label': _("Forum Parent")}),
-                ('perms', {'label': _("Copy Permissions from")}),
-                ('name', {'label': _("Forum Name")}),
-                ('description', {'label': _("Forum Description")}),
-                ('closed', {'label': _("Closed Forum")}),
-                ),
-               ),
-              (
-               _("Prune Forum"),
-               (
-                ('prune_start', {'label': _("Delete threads with first post older than"), 'help_text': _('Enter number of days since thread start after which thread will be deleted or zero to don\'t delete threads.')}),
-                ('prune_last', {'label': _("Delete threads with last post older than"), 'help_text': _('Enter number of days since since last reply in thread after which thread will be deleted or zero to don\'t delete threads.')}),
-                ),
-               ),
-              (
-               _("Display Options"),
-               (
-                ('attrs', {'label': _("Subforums List Attributes"), 'help_text': _('Custom templates can check forums for predefined attributes that will change way subforums lists are rendered.')}),
-                ('show_details', {'label': _("Show Subforums Details"), 'help_text': _("Allows you to prevent this forum's subforums from displaying statistics, last post data, etc. ect. on subforums list.")}),
-                ('style', {'label': _("Forum Style"), 'help_text': _('You can add custom CSS classess to this forum to change way it looks on forums lists.')}),
-                ),
-               ),
-              )
-
-    def finalize_form(self):
-        self.fields['parent'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ')
-        self.fields['perms'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
-
-    def clean_attrs(self):
-        clean = []
-        data = self.cleaned_data['attrs'].strip().split()
-        for i in data:
-            i = i.strip()
-            if not i in clean:
-                clean.append(i)
-        return ' '.join(clean)
-
-
-class RedirectForm(Form):
-    parent = False
-    perms = False
-    name = forms.CharField(max_length=255, validators=[validate_sluggable(
-                                                                          _("Redirect name must be sluggable."),
-                                                                          _("Redirect name is too long.")
-                                                                          )])
-    description = forms.CharField(widget=forms.Textarea, required=False)
-    redirect = forms.URLField(max_length=255)
-    style = forms.CharField(max_length=255, required=False)
-
-    layout = (
-              (
-               _("Basic Options"),
-               (
-                ('parent', {'label': _("Redirect Parent")}),
-                ('perms', {'label': _("Copy Permissions from")}),
-                ('name', {'label': _("Redirect Name")}),
-                ('redirect', {'label': _("Redirect URL")}),
-                ('description', {'label': _("Redirect Description")}),
-                ),
-               ),
-              (
-               _("Display Options"),
-               (
-                ('style', {'label': _("Redirect Style"), 'help_text': _('You can add custom CSS classess to this redirect to change way it looks on forums lists.')}),
-                ),
-               ),
-              )
-
-    def finalize_form(self):
-        self.fields['parent'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ')
-        self.fields['perms'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
-
-
-class DeleteForm(Form):
-    layout = (
-              (
-               _("Delete Options"),
-               (
-                ('contents', {'label': _("Move threads to")}),
-                ('subforums', {'label': _("Move subforums to")}),
-                ),
-               ),
-              )
-
-    def __init__(self, *args, **kwargs):
-        self.forum = kwargs.pop('forum')
-        super(DeleteForm, self).__init__(*args, **kwargs)
-
-    def finalize_form(self):
-        self.fields['contents'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
-        self.fields['subforums'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
-
-    def clean_contents(self):
-        data = self.cleaned_data['contents']
-        if data:
-            if data.type == 'category':
-                raise forms.ValidationError(_("Categories cannot contain threads."))
-            if data.type == 'redirect':
-                raise forms.ValidationError(_("Redirects cannot contain threads."))
-        return data
-
-    def clean(self):
-        cleaned_data = super(DeleteForm, self).clean()
-        if self.forum.type == 'forum' and cleaned_data['contents'] and cleaned_data['contents'].lft > self.forum.lft and cleaned_data['contents'].rght < self.forum.rght and not cleaned_data['subforums']:
-            raise forms.ValidationError(_("Destination you want to move this forum's threads to will be deleted with this forum."))
-        return cleaned_data

+ 0 - 0
notrefactored/forums/management/__init__.py


+ 0 - 0
notrefactored/forums/management/commands/__init__.py


+ 0 - 12
notrefactored/forums/management/commands/syncdeltas.py

@@ -1,12 +0,0 @@
-from django.core.management.base import BaseCommand
-from django.db.models import F
-from misago.forums.models import Forum
-
-class Command(BaseCommand):
-    """
-    This command is intended to work as CRON job fired every few hours to update threads/posts/clicks history on forum
-    """
-    help = 'Clears users sessions'
-    def handle(self, *args, **options):
-        Forum.objects.all().update(threads_delta=F('threads'), posts_delta=F('posts'), redirects_delta=F('redirects'))
-        self.stdout.write('Forums deltas have been synced.\n')

+ 0 - 235
notrefactored/forums/migrations/0001_initial.py

@@ -1,235 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Forum'
-        db.create_table(u'forums_forum', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('parent', self.gf('mptt.fields.TreeForeignKey')(blank=True, related_name='children', null=True, to=orm['forums.Forum'])),
-            ('type', self.gf('django.db.models.fields.CharField')(max_length=12)),
-            ('token', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('slug', self.gf('django.db.models.fields.SlugField')(max_length=255)),
-            ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('description_preparsed', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('threads', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('threads_delta', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('posts', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('posts_delta', self.gf('django.db.models.fields.IntegerField')(default=0)),
-            ('redirects', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('redirects_delta', self.gf('django.db.models.fields.IntegerField')(default=0)),
-            ('last_thread', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='+', null=True, on_delete=models.SET_NULL, to=orm['threads.Thread'])),
-            ('last_thread_name', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('last_thread_slug', self.gf('django.db.models.fields.SlugField')(max_length=255, null=True, blank=True)),
-            ('last_thread_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-            ('last_poster', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='+', null=True, on_delete=models.SET_NULL, to=orm['users.User'])),
-            ('last_poster_name', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('last_poster_slug', self.gf('django.db.models.fields.SlugField')(max_length=255, null=True, blank=True)),
-            ('last_poster_style', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('prune_start', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('prune_last', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('redirect', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('attrs', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('show_details', self.gf('django.db.models.fields.BooleanField')(default=True)),
-            ('style', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('closed', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('lft', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
-            ('rght', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
-            ('tree_id', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
-            ('level', self.gf('django.db.models.fields.PositiveIntegerField')(db_index=True)),
-        ))
-        db.send_create_signal(u'forums', ['Forum'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Forum'
-        db.delete_table(u'forums_forum')
-
-
-    models = {
-        u'forums.forum': {
-            'Meta': {'object_name': 'Forum'},
-            'attrs': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'description_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Thread']"}),
-            'last_thread_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_thread_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': u"orm['forums.Forum']"}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'posts_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'prune_last': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'prune_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'redirects': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirects_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'show_details': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads_delta': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'})
-        },
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'threads.post': {
-            'Meta': {'object_name': 'Post'},
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'checkpoints': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'edit_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'edit_reason': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'edit_user_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edits': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'mentions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'mention_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'merge': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'post': ('django.db.models.fields.TextField', [], {}),
-            'post_preparsed': ('django.db.models.fields.TextField', [], {}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'reported': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'user_name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'threads.thread': {
-            'Meta': {'object_name': 'Thread'},
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last': ('django.db.models.fields.DateTimeField', [], {}),
-            'last_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'merges': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'replies': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_deleted': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_moderated': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_reported': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'score': ('django.db.models.fields.PositiveIntegerField', [], {'default': '30'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start': ('django.db.models.fields.DateTimeField', [], {}),
-            'start_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'start_poster': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'start_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'start_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'type': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'weight': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['forums']

+ 0 - 0
notrefactored/forums/migrations/__init__.py


+ 0 - 220
notrefactored/forums/models.py

@@ -1,220 +0,0 @@
-from django.conf import settings
-from django.core.cache import cache
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-from mptt.models import MPTTModel, TreeForeignKey
-from misago.forums.signals import move_forum_content, delete_forum_content
-from misago.roles.models import Role
-from misago.users.signals import rename_user
-
-class ForumManager(models.Manager):
-    forums_tree = None
-
-    def token_to_pk(self, token):
-        self.populate_tree()
-        try:
-            return self.forums_tree[token].pk
-        except KeyError:
-            return 0
-
-    def populate_tree(self, force=False):
-        if not self.forums_tree:
-            self.forums_tree = cache.get('forums_tree')
-        if not self.forums_tree or force:
-            self.forums_tree = {}
-            for forum in Forum.objects.order_by('lft'):
-                self.forums_tree[forum.pk] = forum
-                if forum.token:
-                    self.forums_tree[forum.token] = forum
-            cache.set('forums_tree', self.forums_tree)
-
-    def forum_parents(self, forum, include_self=False):
-        self.populate_tree()
-        parents = []
-        parent = self.forums_tree[forum]
-        if include_self:
-            parents.append(parent)
-        while parent.level > 1:
-            parent = self.forums_tree[parent.parent_id]
-            parents.append(parent)
-        result = []
-        for i in reversed(parents):
-            result.append(i)
-        return list(result)
-
-    def parents_aware_forum(self, forum):
-        self.populate_tree()
-        proxy = Forum()
-        try:
-            proxy.id = forum.pk
-            proxy.pk = forum.pk
-        except AttributeError:
-            proxy.id = forum
-            proxy.pk = forum
-        proxy.closed = False
-        for parent in self.forum_parents(proxy.pk):
-            if parent.closed:
-                proxy.closed = True
-                return proxy
-        return proxy
-
-    def treelist(self, acl, parent=None, tracker=None):
-        complete_list = []
-        forums_list = []
-        parents = {}
-
-        if parent:
-            queryset = Forum.objects.filter(pk__in=acl.known_forums).filter(lft__gt=parent.lft).filter(rght__lt=parent.rght).order_by('lft')
-        else:
-            queryset = Forum.objects.filter(pk__in=acl.known_forums).order_by('lft')
-
-        for forum in queryset:
-            forum.subforums = []
-            forum.is_read = False
-            if tracker:
-                forum.is_read = tracker.is_read(forum)
-            parents[forum.pk] = forum
-            complete_list.append(forum)
-            if forum.parent_id in parents:
-                parents[forum.parent_id].subforums.append(forum)
-            else:
-                forums_list.append(forum)
-
-        # Second iteration - sum up forum counters
-        for forum in reversed(complete_list):
-            if forum.parent_id in parents and parents[forum.parent_id].type != 'redirect':
-                parents[forum.parent_id].threads += forum.threads
-                parents[forum.parent_id].posts += forum.posts
-                if acl.can_browse(forum.pk):
-                    # If forum is unread, make parent unread too
-                    if not forum.is_read:
-                        parents[forum.parent_id].is_read = False
-                    # Sum stats
-                    if forum.last_thread_date and (not parents[forum.parent_id].last_thread_date or forum.last_thread_date > parents[forum.parent_id].last_thread_date):
-                        parents[forum.parent_id].last_thread_id = forum.last_thread_id
-                        parents[forum.parent_id].last_thread_name = forum.last_thread_name
-                        parents[forum.parent_id].last_thread_slug = forum.last_thread_slug
-                        parents[forum.parent_id].last_thread_date = forum.last_thread_date
-                        parents[forum.parent_id].last_poster_id = forum.last_poster_id
-                        parents[forum.parent_id].last_poster_name = forum.last_poster_name
-                        parents[forum.parent_id].last_poster_slug = forum.last_poster_slug
-                        parents[forum.parent_id].last_poster_style = forum.last_poster_style
-        return forums_list
-    
-    def ignored_users(self, user, forums):
-        check_ids = []
-        for forum in forums:
-            forum.last_poster_ignored = False
-            if user.is_authenticated() and user.pk != forum.last_poster_id and forum.last_poster_id and not forum.last_poster_id in check_ids:
-                check_ids.append(forum.last_poster_id)
-        ignored_ids = []
-        if check_ids and user.is_authenticated():
-            for user in user.ignores.filter(id__in=check_ids).values('id'):
-                ignored_ids.append(user['id'])
-
-
-class Forum(MPTTModel):
-    parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
-    type = models.CharField(max_length=12)
-    token = models.CharField(max_length=255, null=True, blank=True)
-    name = models.CharField(max_length=255)
-    slug = models.SlugField(max_length=255)
-    description = models.TextField(null=True, blank=True)
-    description_preparsed = models.TextField(null=True, blank=True)
-    threads = models.PositiveIntegerField(default=0)
-    threads_delta = models.PositiveIntegerField(default=0)
-    posts = models.PositiveIntegerField(default=0)
-    posts_delta = models.IntegerField(default=0)
-    redirects = models.PositiveIntegerField(default=0)
-    redirects_delta = models.IntegerField(default=0)
-    last_thread = models.ForeignKey('threads.Thread', related_name='+', null=True, blank=True, on_delete=models.SET_NULL)
-    last_thread_name = models.CharField(max_length=255, null=True, blank=True)
-    last_thread_slug = models.SlugField(max_length=255, null=True, blank=True)
-    last_thread_date = models.DateTimeField(null=True, blank=True)
-    last_poster = models.ForeignKey('users.User', related_name='+', null=True, blank=True, on_delete=models.SET_NULL)
-    last_poster_name = models.CharField(max_length=255, null=True, blank=True)
-    last_poster_slug = models.SlugField(max_length=255, null=True, blank=True)
-    last_poster_style = models.CharField(max_length=255, null=True, blank=True)
-    prune_start = models.PositiveIntegerField(default=0)
-    prune_last = models.PositiveIntegerField(default=0)
-    redirect = models.CharField(max_length=255, null=True, blank=True)
-    attrs = models.CharField(max_length=255, null=True, blank=True)
-    show_details = models.BooleanField(default=True)
-    style = models.CharField(max_length=255, null=True, blank=True)
-    closed = models.BooleanField(default=False)
-
-    objects = ForumManager()
-
-    def __unicode__(self):
-        if self.token == 'root':
-           return unicode(_('Root Category'))
-        return unicode(self.name)
-
-    def set_description(self, description):
-        self.description = description.strip()
-        self.description_preparsed = ''
-        if self.description:
-            import markdown
-            self.description_preparsed = markdown.markdown(description, safe_mode='escape', output_format=settings.OUTPUT_FORMAT)
-
-    def copy_permissions(self, target):
-        if target.pk != self.pk:
-            for role in Role.objects.all():
-                perms = role.get_permissions()
-                try:
-                    perms['forums'][self.pk] = perms['forums'][target.pk]
-                    role.set_permissions(perms)
-                    role.save(force_update=True)
-                except KeyError:
-                    pass
-
-    def move_content(self, target):
-        move_forum_content.send(sender=self, move_to=target)
-
-    def attr(self, att):
-        if self.attrs:
-            return att in self.attrs.split()
-        return False
-
-    def sync(self):
-        self.threads = self.thread_set.filter(moderated=False).filter(deleted=False).count()
-        self.posts = self.post_set.filter(moderated=False).count()
-        self.last_poster = None
-        self.last_poster_name = None
-        self.last_poster_slug = None
-        self.last_poster_style = None
-        self.last_thread = None
-        self.last_thread_date = None
-        self.last_thread_name = None
-        self.last_thread_slug = None
-        try:
-            last_thread = self.thread_set.filter(moderated=False).filter(deleted=False).order_by('-last').all()[0:][0]
-            self.last_poster_name = last_thread.last_poster_name
-            self.last_poster_slug = last_thread.last_poster_slug
-            self.last_poster_style = last_thread.last_poster_style
-            if last_thread.last_poster:
-                self.last_poster = last_thread.last_poster
-            self.last_thread = last_thread
-            self.last_thread_date = last_thread.last
-            self.last_thread_name = last_thread.name
-            self.last_thread_slug = last_thread.slug
-        except (IndexError, AttributeError):
-            pass
-
-    def prune(self):
-        pass
-    
-    def delete(self, *args, **kwargs):
-        delete_forum_content.send(sender=self)
-        super(Forum, self).delete(*args, **kwargs)
-
-"""
-Signals
-"""
-def rename_user_handler(sender, **kwargs):
-    Forum.objects.filter(last_poster=sender).update(
-                                                    last_poster_name=sender.username,
-                                                    last_poster_slug=sender.username_slug,
-                                                    )
-
-rename_user.connect(rename_user_handler, dispatch_uid="rename_forums_last_poster")

+ 0 - 4
notrefactored/forums/signals.py

@@ -1,4 +0,0 @@
-import django.dispatch
-
-move_forum_content = django.dispatch.Signal(providing_args=["move_to"])
-delete_forum_content = django.dispatch.Signal()

+ 0 - 347
notrefactored/forums/views.py

@@ -1,347 +0,0 @@
-import copy
-from django.core.urlresolvers import reverse as django_reverse
-from django.db.models import Q
-from django.utils.translation import ugettext as _
-from mptt.forms import TreeNodeChoiceField
-from misago.admin import site
-from misago.admin.widgets import *
-from misago.forums.forms import CategoryForm, ForumForm, RedirectForm, DeleteForm
-from misago.forums.models import Forum
-from misago.utils import slugify
-
-def reverse(route, target=None):
-    if target:
-        return django_reverse(route, kwargs={'target': target.pk, 'slug': target.slug})
-    return django_reverse(route)
-
-"""
-Views
-"""
-class List(ListWidget):
-    admin = site.get_action('forums')
-    id = 'list'
-    columns = (
-               ('forum', _("Forum")),
-               )
-    nothing_checked_message = _('You have to select at least one forum.')
-    actions = (
-               ('resync', _("Resynchronise forums")),
-               ('prune', _("Prune forums"), _("Are you sure you want to delete all content from selected forums?")),
-               )
-    empty_message = _('No forums are currently defined.')
-
-    def get_items(self):
-        return self.admin.model.objects.get(token='root').get_descendants()
-
-    def sort_items(self, page_items, sorting_method):
-        return page_items.order_by('lft')
-
-    def get_item_actions(self, item):
-        if item.type == 'category':
-            return (
-                    self.action('chevron-up', _("Move Category Up"), reverse('admin_forums_up', item), post=True),
-                    self.action('chevron-down', _("Move Category Down"), reverse('admin_forums_down', item), post=True),
-                    self.action('pencil', _("Edit Category"), reverse('admin_forums_edit', item)),
-                    self.action('remove', _("Delete Category"), reverse('admin_forums_delete', item)),
-                    )
-
-        if item.type == 'forum':
-            return (
-                    self.action('chevron-up', _("Move Forum Up"), reverse('admin_forums_up', item), post=True),
-                    self.action('chevron-down', _("Move Forum Down"), reverse('admin_forums_down', item), post=True),
-                    self.action('pencil', _("Edit Forum"), reverse('admin_forums_edit', item)),
-                    self.action('remove', _("Delete Forum"), reverse('admin_forums_delete', item)),
-                    )
-
-        return (
-                self.action('chevron-up', _("Move Redirect Up"), reverse('admin_forums_up', item), post=True),
-                self.action('chevron-down', _("Move Redirect Down"), reverse('admin_forums_down', item), post=True),
-                self.action('pencil', _("Edit Redirect"), reverse('admin_forums_edit', item)),
-                self.action('remove', _("Delete Redirect"), reverse('admin_forums_delete', item)),
-                )
-
-    def action_resync(self, items, checked):
-        return Message(_('Selected forums have been resynchronised successfully.'), 'success'), reverse('admin_forums')
-
-    def action_prune(self, items, checked):
-        return Message(_('Selected forums have been pruned successfully.'), 'success'), reverse('admin_forums')
-
-
-class NewCategory(FormWidget):
-    admin = site.get_action('forums')
-    id = 'new_category'
-    fallback = 'admin_forums'
-    form = CategoryForm
-    submit_button = _("Save Category")
-
-    def get_new_url(self, model):
-        return reverse('admin_forums_new_category')
-
-    def get_edit_url(self, model):
-        return reverse('admin_forums_edit', model)
-
-    def submit_form(self, form, target):
-        new_forum = Forum(
-                          name=form.cleaned_data['name'],
-                          slug=slugify(form.cleaned_data['name']),
-                          type='category',
-                          attrs=form.cleaned_data['attrs'],
-                          show_details=form.cleaned_data['show_details'],
-                          style=form.cleaned_data['style'],
-                          closed=form.cleaned_data['closed'],
-                          )
-        new_forum.set_description(form.cleaned_data['description'])
-        new_forum.insert_at(form.cleaned_data['parent'], position='last-child', save=True)
-        Forum.objects.populate_tree(True)
-
-        if form.cleaned_data['perms']:
-            new_forum.copy_permissions(form.cleaned_data['perms'])
-            self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-
-        return new_forum, Message(_('New Category has been created.'), 'success')
-
-
-class NewForum(FormWidget):
-    admin = site.get_action('forums')
-    id = 'new_forum'
-    fallback = 'admin_forums'
-    form = ForumForm
-    submit_button = _("Save Forum")
-
-    def get_new_url(self, model):
-        return reverse('admin_forums_new_forum')
-
-    def get_edit_url(self, model):
-        return reverse('admin_forums_edit', model)
-
-    def submit_form(self, form, target):
-        new_forum = Forum(
-                          name=form.cleaned_data['name'],
-                          slug=slugify(form.cleaned_data['name']),
-                          type='forum',
-                          attrs=form.cleaned_data['attrs'],
-                          show_details=form.cleaned_data['show_details'],
-                          style=form.cleaned_data['style'],
-                          closed=form.cleaned_data['closed'],
-                          prune_start=form.cleaned_data['prune_start'],
-                          prune_last=form.cleaned_data['prune_last'],
-                          )
-        new_forum.set_description(form.cleaned_data['description'])
-        new_forum.insert_at(form.cleaned_data['parent'], position='last-child', save=True)
-        Forum.objects.populate_tree(True)
-
-        if form.cleaned_data['perms']:
-            new_forum.copy_permissions(form.cleaned_data['perms'])
-            self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-
-        return new_forum, Message(_('New Forum has been created.'), 'success')
-
-    def __call__(self, request):
-        if self.admin.model.objects.get(token='root').get_descendants().count() == 0:
-            request.messages.set_flash(Message(_("You have to create at least one category before you will be able to create forums.")), 'error', self.admin.id)
-            return redirect(self.get_fallback_url())
-        return super(NewForum, self).__call__(request)
-
-
-class NewRedirect(FormWidget):
-    admin = site.get_action('forums')
-    id = 'new_redirect'
-    fallback = 'admin_forums'
-    form = RedirectForm
-    submit_button = _("Save Forum")
-
-    def get_new_url(self, model):
-        return reverse('admin_forums_new_redirect')
-
-    def get_edit_url(self, model):
-        return reverse('admin_forums_edit', model)
-
-    def submit_form(self, form, target):
-        new_forum = Forum(
-                          name=form.cleaned_data['name'],
-                          slug=slugify(form.cleaned_data['name']),
-                          redirect=form.cleaned_data['redirect'],
-                          style=form.cleaned_data['style'],
-                          type='redirect',
-                          )
-        new_forum.set_description(form.cleaned_data['description'])
-        new_forum.insert_at(form.cleaned_data['parent'], position='last-child', save=True)
-        Forum.objects.populate_tree(True)
-
-        if form.cleaned_data['perms']:
-            new_forum.copy_permissions(form.cleaned_data['perms'])
-            self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-
-        return new_forum, Message(_('New Redirect has been created.'), 'success')
-
-    def __call__(self, request):
-        if self.admin.model.objects.get(token='root').get_descendants().count() == 0:
-            request.messages.set_flash(Message(_("You have to create at least one category before you will be able to create redirects.")), 'error', self.admin.id)
-            return redirect(self.get_fallback_url())
-        return super(NewRedirect, self).__call__(request)
-
-
-class Up(ButtonWidget):
-    admin = site.get_action('forums')
-    id = 'up'
-    fallback = 'admin_forums'
-    notfound_message = _('Requested Forum could not be found.')
-
-    def action(self, target):
-        previous_sibling = target.get_previous_sibling()
-        if previous_sibling:
-            target.move_to(previous_sibling, 'left')
-            return Message(_('Forum "%(name)s" has been moved up.') % {'name': target.name}, 'success'), False
-        return Message(_('Forum "%(name)s" is first child of its parent node and cannot be moved up.') % {'name': target.name}, 'info'), False
-
-
-class Down(ButtonWidget):
-    admin = site.get_action('forums')
-    id = 'down'
-    fallback = 'admin_forums'
-    notfound_message = _('Requested Forum could not be found.')
-
-    def action(self, target):
-        next_sibling = target.get_next_sibling()
-        if next_sibling:
-            target.move_to(next_sibling, 'right')
-            return Message(_('Forum "%(name)s" has been moved down.') % {'name': target.name}, 'success'), False
-        return Message(_('Forum "%(name)s" is last child of its parent node and cannot be moved down.') % {'name': target.name}, 'info'), False
-
-
-class Edit(FormWidget):
-    admin = site.get_action('forums')
-    id = 'edit'
-    name = _("Edit Forum")
-    fallback = 'admin_forums'
-    form = ForumForm
-    target_name = 'name'
-    notfound_message = _('Requested Forum could not be found.')
-    submit_fallback = True
-
-    def get_url(self, model):
-        return reverse('admin_forums_edit', model)
-
-    def get_edit_url(self, model):
-        return self.get_url(model)
-
-    def get_form(self, target):
-        if target.type == 'category':
-            self.name = _("Edit Category")
-            self.form = CategoryForm
-        if target.type == 'redirect':
-            self.name = _("Edit Redirect")
-            self.form = RedirectForm
-        return self.form
-
-    def get_form_instance(self, form, target, initial, post=False):
-        form_inst = super(Edit, self).get_form_instance(form, target, initial, post)
-        valid_targets = Forum.tree.get(token='root').get_descendants(include_self=target.type == 'category').exclude(Q(lft__gte=target.lft) & Q(rght__lte=target.rght))
-        form_inst.fields['parent'] = TreeNodeChoiceField(queryset=valid_targets, level_indicator=u'- - ')
-        return form_inst
-
-    def get_initial_data(self, model):
-        initial = {
-                   'parent': model.parent,
-                   'name': model.name,
-                   'description': model.description,
-                   }
-
-        if model.type == 'redirect':
-            initial['redirect'] = model.redirect
-        else:
-            initial['attrs'] = model.attrs
-            initial['show_details'] = model.show_details
-            initial['style'] = model.style
-            initial['closed'] = model.closed
-
-        if model.type == 'forum':
-            initial['prune_start'] = model.prune_start
-            initial['prune_last'] = model.prune_last
-
-        return initial
-
-    def submit_form(self, form, target):
-        target.name = form.cleaned_data['name']
-        target.slug = slugify(form.cleaned_data['name'])
-        target.set_description(form.cleaned_data['description'])
-        if target.type == 'redirect':
-            target.redirect = form.cleaned_data['redirect']
-        else:
-            target.attrs = form.cleaned_data['attrs']
-            target.show_details = form.cleaned_data['show_details']
-            target.style = form.cleaned_data['style']
-            target.closed = form.cleaned_data['closed']
-
-        if target.type == 'forum':
-            target.prune_start = form.cleaned_data['prune_start']
-            target.prune_last = form.cleaned_data['prune_last']
-
-        if form.cleaned_data['parent'].pk != target.parent.pk:
-            target.move_to(form.cleaned_data['parent'], 'last-child')
-            self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-
-        target.save(force_update=True)
-        Forum.objects.populate_tree(True)
-
-        if form.cleaned_data['perms']:
-            target.copy_permissions(form.cleaned_data['perms'])
-
-        if form.cleaned_data['parent'].pk != target.parent.pk or form.cleaned_data['perms']:
-            self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-
-        return target, Message(_('Changes in forum "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
-
-
-class Delete(FormWidget):
-    admin = site.get_action('forums')
-    id = 'delete'
-    name = _("Delete Forum")
-    fallback = 'admin_forums'
-    template = 'delete'
-    form = DeleteForm
-    target_name = 'name'
-    notfound_message = _('Requested Forum could not be found.')
-    submit_fallback = True
-
-    def get_url(self, model):
-        return reverse('admin_forums_delete', model)
-
-    def get_form(self, target):
-        if target.type == 'category':
-            self.name = _("Delete Category")
-        if target.type == 'redirect':
-            self.name = _("Delete Redirect")
-        return self.form
-
-    def get_form_instance(self, form, target, initial, post=False):
-        if post:
-            form_inst = form(self.request.POST, forum=target, request=self.request, initial=self.get_initial_data(target))
-        else:
-            form_inst = form(forum=target, request=self.request, initial=self.get_initial_data(target))
-        if target.type != 'forum':
-            del form_inst.fields['contents']
-        valid_targets = Forum.tree.get(token='root').get_descendants().exclude(Q(lft__gte=target.lft) & Q(rght__lte=target.rght))
-        form_inst.fields['subforums'] = TreeNodeChoiceField(queryset=valid_targets, required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
-        return form_inst
-
-    def submit_form(self, form, target):
-        if target.type == 'forum':
-            new_forum = form.cleaned_data['contents']
-            if new_forum:
-                target.move_content(new_forum)
-                new_forum.sync()
-                new_forum.save(force_update=True)
-        new_parent = form.cleaned_data['subforums']
-        if new_parent:
-            for child in target.get_descendants():
-                if child.parent_id == target.pk:
-                    child.move_to(new_parent, 'last-child')
-                    child.save(force_update=True)
-        else:
-            for child in target.get_descendants().order_by('-lft'):
-                Forum.objects.get(id=child.pk).delete()
-        Forum.objects.get(id=target.pk).delete()
-        Forum.objects.populate_tree(True)
-        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-        return target, Message(_('Forum "%(name)s" has been deleted.') % {'name': self.original_name}, 'success')

+ 0 - 0
notrefactored/heartbeat/__init__.py


+ 0 - 8
notrefactored/heartbeat/middleware.py

@@ -1,8 +0,0 @@
-from django.conf import settings
-from django.http import HttpResponse
-
-class HeartbeatMiddleware(object):
-    def process_request(self, request):
-        request.heartbeat = settings.HEARTBEAT_PATH and settings.HEARTBEAT_PATH == request.path
-        if request.heartbeat:
-            return HttpResponse('BATTLECRUISER OPERATIONAL')

+ 0 - 60
notrefactored/markdown/__init__.py

@@ -1,60 +0,0 @@
-from misago.markdown.factory import *
-
-# Monkeypatch blockquote parser to handle codes
-from markdown import util
-import markdown.blockprocessors
-from markdown.extensions.fenced_code import FENCED_BLOCK_RE, CODE_WRAP, LANG_TAG
-
-class MisagoBlockQuoteProcessor(markdown.blockprocessors.BlockQuoteProcessor):
-    def run(self, parent, blocks):
-        block = blocks.pop(0)
-        m = self.RE.search(block)
-        if m:
-            before = block[:m.start()] # Lines before blockquote
-            # Pass lines before blockquote in recursively for parsing forst.
-            self.parser.parseBlocks(parent, [before])
-            # Remove ``> `` from begining of each line.
-            block = '\n'.join([self.clean(line) for line in 
-                            block[m.start():].split('\n')])
-
-        sibling = self.lastChild(parent)
-        if sibling and sibling.tag == "blockquote":
-            # Previous block was a blockquote so set that as this blocks parent
-            quote = sibling
-        else:
-            # This is a new blockquote. Create a new parent element.
-            quote = util.etree.SubElement(parent, 'blockquote')
-        # Recursively parse block with blockquote as parent.
-        # change parser state so blockquotes embedded in lists use p tags
-        self.parser.state.set('blockquote')
-        # MONKEYPATCH START
-        block = self.clear_codes(block)
-        # MONKEYPATCH END
-        self.parser.parseChunk(quote, block)
-        self.parser.state.reset()
-
-    # MONKEYPATCH START
-    def clear_codes(self, text):
-        while 1:
-            m = FENCED_BLOCK_RE.search(text)
-            if m:
-                lang = ''
-                if m.group('lang'):
-                    lang = LANG_TAG % m.group('lang')
-                code = CODE_WRAP % (lang, self._escape(m.group('code')))
-                placeholder = self.parser.markdown.htmlStash.store(code, safe=True)
-                text = '%s\n\n%s\n\n%s' % (text[:m.start()].strip(), placeholder.strip(), text[m.end():].strip())
-            else:
-                break
-        return text.strip()
-
-    def _escape(self, txt):
-        """ basic html escaping """
-        txt = txt.replace('&', '&amp;')
-        txt = txt.replace('<', '&lt;')
-        txt = txt.replace('>', '&gt;')
-        txt = txt.replace('"', '&quot;')
-        return txt.strip()
-    # MONKEYPATCH END
-
-markdown.blockprocessors.BlockQuoteProcessor = MisagoBlockQuoteProcessor

+ 0 - 0
notrefactored/markdown/extensions/__init__.py


+ 0 - 45
notrefactored/markdown/extensions/magiclinks.py

@@ -1,45 +0,0 @@
-#-*- coding: utf-8 -*-
-import re
-import markdown
-from markdown.inlinepatterns import LinkPattern
-from markdown.postprocessors import RawHtmlPostprocessor
-from markdown.util import etree
-
-# Global vars
-MAGICLINKS_RE = re.compile(r'(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))', re.UNICODE)
-
-class MagicLinksExtension(markdown.Extension):
-    def extendMarkdown(self, md):
-        md.registerExtension(self)
-        md.treeprocessors.add('mi_magiclinks',
-                              MagicLinksTreeprocessor(md),
-                              '_end')
-
-
-class MagicLinksTreeprocessor(markdown.treeprocessors.Treeprocessor):
-    def run(self, root):
-        return self.walk_tree(root)
-
-    def walk_tree(self, node):
-        def parse_link(matchobj):
-            link = LinkPattern(MAGICLINKS_RE, self.markdown)
-            href = link.sanitize_url(link.unescape(matchobj.group(0).strip()))
-            if href:
-                href = self.escape(href)
-                return self.markdown.htmlStash.store('<a href="%(href)s">%(href)s</a>' % {'href': href}, safe=True)
-            else:
-                return matchobj.group(0)
-
-        if node.tag not in ['code', 'pre', 'a', 'img']:
-            if node.text and unicode(node.text).strip():
-                node.text = MAGICLINKS_RE.sub(parse_link, unicode(node.text))
-            if node.tail and unicode(node.tail).strip():
-                node.tail = MAGICLINKS_RE.sub(parse_link, unicode(node.tail))
-            for i in node:
-                self.walk_tree(i)
-
-    def escape(self, html):
-        html = html.replace('&', '&amp;')
-        html = html.replace('<', '&lt;')
-        html = html.replace('>', '&gt;')
-        return html.replace('"', '&quot;')

+ 0 - 58
notrefactored/markdown/extensions/mentions.py

@@ -1,58 +0,0 @@
-import re
-import markdown
-from markdown.util import etree
-from django.core.urlresolvers import reverse
-from misago.users.models import User
-from misago.utils import slugify
-
-# Global vars
-MENTION_RE = re.compile(r'([^\w]?)@(?P<username>(\w)+)', re.UNICODE)
-
-class MentionsExtension(markdown.Extension):
-    def extendMarkdown(self, md):
-        md.mentions = {}
-        md.registerExtension(self)
-        md.preprocessors.add('mi_mentions',
-                             MentionsPreprocessor(md),
-                             '>mi_quote_title')
-        md.postprocessors.add('mi_mentions',
-                              MentionsPostprocessor(md),
-                              '>mi_quote_title')
-
-
-class MentionsPreprocessor(markdown.preprocessors.Preprocessor):
-    def __init__(self, md):
-        markdown.preprocessors.Preprocessor.__init__(self, md)
-        self.md = md
-
-    def run(self, lines):
-        def mention(match):
-            slug = slugify(match.group(0)[1:])
-            if slug in self.md.mentions:
-                user = self.md.mentions[slug]
-                return '%s[@%s](%s)' % (match.group(1), user.username, reverse('user', kwargs={
-                                                                                              'user': user.pk,
-                                                                                              'username': user.username_slug,
-                                                                                              }))
-            elif len(self.md.mentions) < 32:
-                try:
-                    user = User.objects.get(username_slug=slug)
-                    self.md.mentions[slug] = user
-                    return '%s[@%s](%s)' % (match.group(1), user.username, reverse('user', kwargs={
-                                                                                                  'user': user.pk,
-                                                                                                  'username': user.username_slug,
-                                                                                                  }))
-                except User.DoesNotExist:
-                    pass
-            return match.group(0)
-        clean = []
-        for l, line in enumerate(lines):
-            if line.strip():
-                line = MENTION_RE.sub(mention, line)
-            clean.append(line)
-        return clean
-
-
-class MentionsPostprocessor(markdown.postprocessors.Postprocessor):
-    def run(self, text):
-        return text

+ 0 - 58
notrefactored/markdown/extensions/quotes.py

@@ -1,58 +0,0 @@
-import re
-import markdown
-from markdown.util import etree
-
-# Global vars
-QUOTE_AUTHOR_RE = re.compile(r'^(?P<arrows>(>|\s)+)?@(?P<username>(\w|\d)+)$')
-
-class QuoteTitlesExtension(markdown.Extension):
-    def extendMarkdown(self, md):
-        md.registerExtension(self)
-        md.preprocessors.add('mi_quote_title',
-                             QuoteTitlesPreprocessor(md),
-                             '>fenced_code_block')
-        md.postprocessors.add('mi_quote_title',
-                              QuoteTitlesPostprocessor(md),
-                              '_end')
-
-
-class QuoteTitlesPreprocessor(markdown.preprocessors.Preprocessor):
-    def __init__(self, md):
-        markdown.preprocessors.Preprocessor.__init__(self, md)
-
-    def run(self, lines):
-        clean = []
-        for l, line in enumerate(lines):
-            try:
-                if line.strip():
-                    at_match = QUOTE_AUTHOR_RE.match(line.strip())
-                    if at_match and lines[l + 1].strip()[0] == '>':
-                        username = '<%(token)s:quotetitle>@%(name)s</%(token)s:quotetitle>' % {'token': self.markdown.mi_token, 'name': at_match.group('username')}
-                        if at_match.group('arrows'):
-                            clean.append('> %s%s' % (at_match.group('arrows'), username))
-                        else:
-                            clean.append('> %s' % username)
-                    else:
-                        clean.append(line)
-                else:
-                    clean.append(line)
-            except IndexError:
-                clean.append(line)
-        return clean
-
-
-class QuoteTitlesPostprocessor(markdown.postprocessors.Postprocessor):
-    def run(self, text):
-        text = text.replace('&lt;%s:quotetitle&gt;' % self.markdown.mi_token, '<h3><quotetitle>')
-        text = text.replace('&lt;/%s:quotetitle&gt;' % self.markdown.mi_token, '</quotetitle></h3>')
-        lines = text.splitlines()
-        clean = []
-        for l, line in enumerate(lines):
-            clean.append(line)
-            try:
-                if line == '<blockquote>':
-                    if lines[l + 1][0:7] != '<p><h3>':
-                        clean.append('<h3><quotesingletitle></h3>')
-            except IndexError:
-                pass
-        return '\r\n'.join(clean)

+ 0 - 115
notrefactored/markdown/factory.py

@@ -1,115 +0,0 @@
-import re
-import markdown
-from HTMLParser import HTMLParser
-from django.conf import settings
-from django.utils.importlib import import_module
-from django.utils.translation import ugettext_lazy as _
-from misago.utils import get_random_string
-
-class ClearHTMLParser(HTMLParser):
-    def __init__(self):
-        HTMLParser.__init__(self)
-        self.clean_text = ''
-        self.lookback = []
-        
-    def handle_entityref(self, name):
-        if name == 'gt':
-            self.clean_text += '>'
-        if name == 'lt':
-            self.clean_text += '<'
-
-    def handle_starttag(self, tag, attrs):
-        self.lookback.append(tag)
-
-    def handle_endtag(self, tag):
-        try:
-            if self.lookback[-1] == tag:
-                self.lookback.pop()
-        except IndexError:
-            pass
-        
-    def handle_data(self, data):
-        # String does not repeat itself
-        if self.clean_text[-len(data):] != data:
-            # String is not "QUOTE"
-            try:
-                if self.lookback[-1] in ('strong', 'em'):
-                    self.clean_text += data
-                elif not (data == 'Quote' and self.lookback[-1] == 'h3' and self.lookback[-2] == 'blockquote'):
-                    self.clean_text += data
-            except IndexError:
-                self.clean_text += data
-
-
-def clear_markdown(text):
-    parser = ClearHTMLParser()
-    parser.feed(text)
-    return parser.clean_text
-
-
-def remove_unsupported(md):
-    # References are evil, we dont support them
-    del md.preprocessors['reference']
-    del md.inlinePatterns['reference']
-    del md.inlinePatterns['image_reference']
-    del md.inlinePatterns['short_reference']
-
-
-def signature_markdown(acl, text):
-    md = markdown.Markdown(
-                           safe_mode='escape',
-                           output_format=settings.OUTPUT_FORMAT,
-                           extensions=['nl2br'])
-
-    remove_unsupported(md)
-
-    if not acl.usercp.allow_signature_links():
-        del md.inlinePatterns['link']
-        del md.inlinePatterns['autolink']
-    if not acl.usercp.allow_signature_images():
-        del md.inlinePatterns['image_link']
-
-    del md.parser.blockprocessors['hashheader']
-    del md.parser.blockprocessors['setextheader']
-    del md.parser.blockprocessors['code']
-    del md.parser.blockprocessors['quote']
-    del md.parser.blockprocessors['hr']
-    del md.parser.blockprocessors['olist']
-    del md.parser.blockprocessors['ulist']
-    
-    return md.convert(text)
-
-
-def post_markdown(request, text):
-    md = markdown.Markdown(
-                           safe_mode='escape',
-                           output_format=settings.OUTPUT_FORMAT,
-                           extensions=['nl2br', 'fenced_code'])
-
-    remove_unsupported(md)
-    md.mi_token = get_random_string(16)
-    for extension in settings.MARKDOWN_EXTENSIONS:
-        module = '.'.join(extension.split('.')[:-1])
-        extension = extension.split('.')[-1]
-        module = import_module(module)
-        attr = getattr(module, extension)
-        ext = attr()
-        ext.extendMarkdown(md)
-    text = md.convert(text)
-    return tidy_markdown(md, text)
-
-
-def tidy_markdown(md, text):
-    text = text.replace('<p><h3><quotetitle>', '<h3><quotetitle>')
-    text = text.replace('</quotetitle></h3></p>', '</quotetitle></h3>')
-    text = text.replace('</quotetitle></h3><br>\r\n', '</quotetitle></h3>\r\n<p>')
-    text = text.replace('\r\n<p></p>', '')
-    return md, text
-
-
-def finalize_markdown(text):
-    def trans_quotetitle(match):
-        return _("Posted by %(user)s") % {'user': match.group('content')}
-    text = re.sub(r'<quotetitle>(?P<content>.+)</quotetitle>', trans_quotetitle, text)
-    text = re.sub(r'<quotesingletitle>', _("Quote"), text)
-    return text

+ 0 - 39
notrefactored/messages/__init__.py

@@ -1,39 +0,0 @@
-class Messages(object):
-    def __init__(self, session):
-        self.session = session
-        self.messages = session.get('messages_list', [])
-        self.session['messages_list'] = []
-
-    def set_message(self, message, type='info', owner=None):
-        message.type = type
-        message.owner = owner
-        self.messages.append(message)
-
-    def set_flash(self, message, type='info', owner=None):
-        self.set_message(message, type, owner)
-        self.session['messages_list'].append(message)
-
-    def get_message(self, owner=None):
-        for index, message in enumerate(self.messages):
-            if message.owner == owner:
-                del self.messages[index]
-                return message
-        return None
-
-    def get_messages(self, owner=None):
-        orphans = []
-        messages = []
-        for message in self.messages:
-            if message.owner == owner:
-                messages.append(message)
-            else:
-                orphans.append(message)
-        self.messages = orphans
-        return messages
-
-
-class Message(object):
-    def __init__(self, message=None, type='info', owner=None):
-        self.type = type
-        self.message = message
-        self.owner = owner

+ 0 - 7
notrefactored/messages/context_processors.py

@@ -1,7 +0,0 @@
-def messages(request):
-    try:
-        return {
-            'messages' : request.messages.messages,
-        }
-    except AttributeError:
-        return {}

+ 0 - 5
notrefactored/messages/middleware.py

@@ -1,5 +0,0 @@
-from misago.messages import Messages
-
-class MessagesMiddleware(object):
-    def process_request(self, request):
-        request.messages = Messages(request.session)

+ 0 - 0
notrefactored/monitor/__init__.py


+ 0 - 7
notrefactored/monitor/context_processors.py

@@ -1,7 +0,0 @@
-def monitor(request):
-    try:
-        return {
-            'monitor' : request.monitor,
-        }
-    except AttributeError:
-        return {}

+ 0 - 11
notrefactored/monitor/fixtures.py

@@ -1,11 +0,0 @@
-from django.utils import timezone
-from misago.monitor.models import Item
-
-def load_monitor_fixture(fixture):
-    for id in fixture.keys():
-        item = Item(
-                    id=id,
-                    value=fixture[id],
-                    updated=timezone.now()
-                    )
-        item.save(force_insert=True)

+ 0 - 5
notrefactored/monitor/middleware.py

@@ -1,5 +0,0 @@
-from misago.monitor.monitor import Monitor
-
-class MonitorMiddleware(object):
-    def process_request(self, request):
-        request.monitor = Monitor()

+ 0 - 34
notrefactored/monitor/migrations/0001_initial.py

@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Item'
-        db.create_table(u'monitor_item', (
-            ('id', self.gf('django.db.models.fields.CharField')(max_length=255, primary_key=True)),
-            ('value', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('updated', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-        ))
-        db.send_create_signal(u'monitor', ['Item'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Item'
-        db.delete_table(u'monitor_item')
-
-
-    models = {
-        u'monitor.item': {
-            'Meta': {'object_name': 'Item'},
-            'id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
-            'updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
-        }
-    }
-
-    complete_apps = ['monitor']

+ 0 - 0
notrefactored/monitor/migrations/__init__.py


+ 0 - 6
notrefactored/monitor/models.py

@@ -1,6 +0,0 @@
-from django.db import models
-
-class Item(models.Model):
-    id = models.CharField(max_length=255, primary_key=True)
-    value = models.TextField(blank=True, null=True)
-    updated = models.DateTimeField(blank=True, null=True)

+ 0 - 65
notrefactored/monitor/monitor.py

@@ -1,65 +0,0 @@
-from django.core.cache import cache
-from django.utils import timezone
-from misago.monitor.models import Item
-
-class Monitor(object):
-    def __init__(self):
-        self._cache_deleted = False
-        self._items = {}
-        self.refresh()
-
-    def refresh(self):
-        self._items = cache.get('monitor')
-        if not self._items:
-            self._items = {}
-            for i in Item.objects.all():
-                self._items[i.id] = [i.value, i.updated]
-            cache.set('monitor', self._items)
-
-    def __contains__(self, key):
-        return key in self._items
-
-    def __getitem__(self, key):
-        return self._items[key][0]
-
-    def __setitem__(self, key, value):
-        self._items[key][0] = value
-        cache.set('monitor', self._items)
-        sync_item = Item(id=key, value=value, updated=timezone.now())
-        sync_item.save(force_update=True)
-        return value
-
-    def __delitem__(self, key):
-        pass
-
-    def get(self, key, default=None):
-        if not key in self._items:
-            return default
-        return self._items[key][0]
-
-    def get_updated(self, key):
-        if key in self._items:
-            return self._items[key][1]
-        return None
-
-    def has_key(self, key):
-        return key in self._items
-
-    def keys(self):
-        return self._items.keys()
-
-    def values(self):
-        return self._items.values()
-
-    def items(self):
-        return self._items.items()
-
-    def iterkeys(self):
-        return self._items.iterkeys()
-
-    def itervalues(self):
-        return self._items.itervalues()
-
-    def iteritems(self):
-        return self._items.iteritems()
-

+ 0 - 0
notrefactored/newsfeed/__init__.py


+ 0 - 22
notrefactored/newsfeed/views.py

@@ -1,22 +0,0 @@
-from django.template import RequestContext
-from misago.authn.decorators import block_guest
-from misago.threads.models import Post
-
-@block_guest
-def newsfeed(request):
-    follows = []
-    for user in request.user.follows.iterator():
-        follows.append(user.pk)
-    queryset = []
-    if follows:
-        queryset = Post.objects.filter(forum_id__in=request.acl.threads.get_readable_forums(request.acl))
-        queryset = queryset.filter(deleted=False).filter(moderated=False)
-        queryset = queryset.filter(user_id__in=follows)
-        queryset = queryset.prefetch_related('thread', 'forum', 'user').order_by('-id')
-        queryset = queryset[:18]
-    return request.theme.render_to_response('newsfeed.html',
-                                            {
-                                             'follows': follows,
-                                             'posts': queryset,
-                                             },
-                                            context_instance=RequestContext(request))

+ 0 - 0
notrefactored/newsletters/__init__.py


+ 0 - 55
notrefactored/newsletters/forms.py

@@ -1,55 +0,0 @@
-from django.core.validators import RegexValidator
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.forms import Form, YesNoSwitch
-from misago.ranks.models import Rank
-from misago.utils.validators import validate_sluggable
-
-class NewsletterForm(Form):
-    name = forms.CharField(max_length=255, validators=[validate_sluggable(
-                                                                          _("Newsletter name must be sluggable."),
-                                                                          _("Newsletter name is too long.")
-                                                                          )])
-    step_size = forms.IntegerField(initial=300, min_value=1)
-    content_html = forms.CharField(widget=forms.Textarea)
-    content_plain = forms.CharField(widget=forms.Textarea)
-    ignore_subscriptions = forms.BooleanField(widget=YesNoSwitch, required=False)
-    ranks = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Rank.objects.order_by('name').all(), required=False)
-
-    layout = (
-              (
-               _("Newsletter Options"),
-               (
-                ('name', {'label': _("Newsletter Name"), 'help_text': _("Newsletter name will be used as message subject in e-mails sent to members.")}),
-                ('step_size', {'label': _("Step Size"), 'help_text': _("Number of users that message will be sent to before forum refreshes page displaying sending progress.")}),
-                ('ranks', {'label': _("Limit to roles"), 'help_text': _("You can limit this newsletter only to members who have specific ranks. If you dont set any ranks, this newsletter will be sent to every user.")}),
-                ('ignore_subscriptions', {'label': _("Ignore members preferences"), 'help_text': _("Change this option to yes if you want to send this newsletter to members that don't want to receive newsletters. This is good for emergencies.")}),
-               )
-              ),
-              (
-               _("Message"),
-               (
-                ('content_html', {'label': _("HTML Message"), 'help_text': _("HTML message visible to members who can read HTML e-mails."), 'attrs': {'rows': 10}}),
-                ('content_plain', {'label': _("Plain Text Message"), 'help_text': _("Alternative plain text message that will be visible to members that can't or dont want to read HTML e-mails."), 'attrs': {'rows': 10}}),
-               )
-              ),
-             )
-
-
-class SearchNewslettersForm(Form):
-    name = forms.CharField(max_length=255, required=False)
-    contains = forms.CharField(max_length=255, required=False)
-    type = forms.TypedMultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=((0, _("Only to subscribers")), (1, _("To every member"))), coerce=int, required=False)
-    rank = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Rank.objects.order_by('order').all(), required=False)
-
-    layout = (
-              (
-               _("Search Newsletters"),
-               (
-                ('name', {'label': _("Newsletter Name"), 'attrs': {'placeholder': _("Name contains...")}}),
-                ('contains', {'label': _("Message Contents"), 'attrs': {'placeholder': _("Message contains...")}}),
-                ('type', {'label': _("Newsletter Type")}),
-                ('rank', {'label': _("Recipient Rank")}),
-               ),
-              ),
-             )

+ 0 - 70
notrefactored/newsletters/migrations/0001_initial.py

@@ -1,70 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Newsletter'
-        db.create_table(u'newsletters_newsletter', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('token', self.gf('django.db.models.fields.CharField')(max_length=32)),
-            ('step_size', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('progress', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('content_html', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('content_plain', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('ignore_subscriptions', self.gf('django.db.models.fields.BooleanField')(default=False)),
-        ))
-        db.send_create_signal(u'newsletters', ['Newsletter'])
-
-        # Adding M2M table for field ranks on 'Newsletter'
-        db.create_table(u'newsletters_newsletter_ranks', (
-            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
-            ('newsletter', models.ForeignKey(orm[u'newsletters.newsletter'], null=False)),
-            ('rank', models.ForeignKey(orm[u'ranks.rank'], null=False))
-        ))
-        db.create_unique(u'newsletters_newsletter_ranks', ['newsletter_id', 'rank_id'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Newsletter'
-        db.delete_table(u'newsletters_newsletter')
-
-        # Removing M2M table for field ranks on 'Newsletter'
-        db.delete_table('newsletters_newsletter_ranks')
-
-
-    models = {
-        u'newsletters.newsletter': {
-            'Meta': {'object_name': 'Newsletter'},
-            'content_html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'content_plain': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignore_subscriptions': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'progress': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'ranks': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['ranks.Rank']", 'symmetrical': 'False'}),
-            'step_size': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '32'})
-        },
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        }
-    }
-
-    complete_apps = ['newsletters']

+ 0 - 0
notrefactored/newsletters/migrations/__init__.py


+ 0 - 33
notrefactored/newsletters/models.py

@@ -1,33 +0,0 @@
-from django.db import models
-from misago.utils import get_random_string
-
-class Newsletter(models.Model):
-    name = models.CharField(max_length=255)
-    token = models.CharField(max_length=32)
-    step_size = models.PositiveIntegerField(default=0)
-    progress = models.PositiveIntegerField(default=0)
-    content_html = models.TextField(null=True, blank=True)
-    content_plain = models.TextField(null=True, blank=True)
-    ignore_subscriptions = models.BooleanField(default=False)
-    ranks = models.ManyToManyField('ranks.Rank')
-
-    def generate_token(self):
-        self.token = get_random_string(32)
-
-    def parse_name(self, tokens):
-        name = self.name
-        for key in tokens:
-            name = name.replace(key, tokens[key])
-        return name
-
-    def parse_html(self, tokens):
-        content_html = self.content_html
-        for key in tokens:
-            content_html = content_html.replace(key, tokens[key])
-        return content_html
-
-    def parse_plain(self, tokens):
-        content_plain = self.content_plain
-        for key in tokens:
-            content_plain = content_plain.replace(key, tokens[key])
-        return content_plain

+ 0 - 200
notrefactored/newsletters/views.py

@@ -1,200 +0,0 @@
-from django.conf import settings
-from django.core.urlresolvers import reverse as django_reverse
-from django.db.models import Q
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils.translation import ugettext as _
-from misago.admin import site
-from misago.admin.widgets import *
-from misago.newsletters.forms import NewsletterForm, SearchNewslettersForm
-from misago.newsletters.models import Newsletter
-from misago.users.models import User
-
-def reverse(route, target=None):
-    if target:
-        if route == 'admin_newsletters_send':
-          return django_reverse(route, kwargs={'target': target.pk, 'token': target.token})
-        return django_reverse(route, kwargs={'target': target.pk})
-    return django_reverse(route)
-
-"""
-Views
-"""
-class List(ListWidget):
-    admin = site.get_action('newsletters')
-    id = 'list'
-    columns = (
-             ('newsletter', _("Newsletter")),
-             )
-    nothing_checked_message = _('You have to check at least one newsletter.')
-    actions = (
-             ('delete', _("Delete selected newsletters"), _("Are you sure you want to delete selected newsletters?")),
-             )
-    pagination = 20
-    search_form = SearchNewslettersForm
-
-    def sort_items(self, page_items, sorting_method):
-        return page_items.order_by('-id')
-
-    def set_filters(self, model, filters):
-        if 'rank' in filters:
-            model = model.filter(ranks__in=filters['rank']).distinct()
-        if 'type' in filters:
-            model = model.filter(ignore_subscriptions__in=filters['type'])
-        if 'name' in filters:
-            model = model.filter(name__icontains=filters['name'])
-        if 'content' in filters:
-            model = model.filter(Q(content_html__icontains=filters['content']) | Q(content_plain__icontains=filters['content']))
-        return model
-
-    def get_item_actions(self, item):
-        return (
-                self.action('envelope', _("Send Newsletter"), reverse('admin_newsletters_send', item)),
-                self.action('pencil', _("Edit Newsletter"), reverse('admin_newsletters_edit', item)),
-                self.action('remove', _("Delete Newsletter"), reverse('admin_newsletters_delete', item), post=True, prompt=_("Are you sure you want to delete this newsletter?")),
-                )
-
-    def action_delete(self, items, checked):
-        Newsletter.objects.filter(id__in=checked).delete()
-        return Message(_('Selected newsletters have been deleted successfully.'), 'success'), reverse('admin_newsletters')
-
-
-class New(FormWidget):
-    admin = site.get_action('newsletters')
-    id = 'new'
-    fallback = 'admin_newsletters'
-    form = NewsletterForm
-    submit_button = _("Save Newsletter")
-    tabbed = True
-
-    def get_new_url(self, model):
-        return reverse('admin_newsletters_new')
-
-    def get_edit_url(self, model):
-        return reverse('admin_newsletters_edit', model)
-
-    def submit_form(self, form, target):
-        new_newsletter = Newsletter(
-                      name=form.cleaned_data['name'],
-                      step_size=form.cleaned_data['step_size'],
-                      content_html=form.cleaned_data['content_html'],
-                      content_plain=form.cleaned_data['content_plain'],
-                      ignore_subscriptions=form.cleaned_data['ignore_subscriptions'],
-                     )
-        new_newsletter.generate_token()
-        new_newsletter.save(force_insert=True)
-
-        for rank in form.cleaned_data['ranks']:
-            new_newsletter.ranks.add(rank)
-        new_newsletter.save(force_update=True)
-
-        return new_newsletter, Message(_('New Newsletter has been created.'), 'success')
-
-
-class Edit(FormWidget):
-    admin = site.get_action('newsletters')
-    id = 'edit'
-    name = _("Edit Newsletter")
-    fallback = 'admin_newsletters'
-    form = NewsletterForm
-    target_name = 'name'
-    notfound_message = _('Requested Newsletter could not be found.')
-    submit_fallback = True
-    tabbed = True
-
-    def get_url(self, model):
-        return reverse('admin_newsletters_edit', model)
-
-    def get_edit_url(self, model):
-        return self.get_url(model)
-
-    def get_initial_data(self, model):
-        return {
-                'name': model.name,
-                'step_size': model.step_size,
-                'ignore_subscriptions': model.ignore_subscriptions,
-                'content_html': model.content_html,
-                'content_plain': model.content_plain,
-                'ranks': model.ranks.all(),
-                }
-
-    def submit_form(self, form, target):
-        target.name = form.cleaned_data['name']
-        target.step_size = form.cleaned_data['step_size']
-        target.ignore_subscriptions = form.cleaned_data['ignore_subscriptions']
-        target.content_html = form.cleaned_data['content_html']
-        target.content_plain = form.cleaned_data['content_plain']
-        target.generate_token()
-
-        target.ranks.clear()
-        for rank in form.cleaned_data['ranks']:
-            target.ranks.add(rank)
-
-        target.save(force_update=True)
-        return target, Message(_('Changes in newsletter "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
-
-
-class Delete(ButtonWidget):
-    admin = site.get_action('newsletters')
-    id = 'delete'
-    fallback = 'admin_newsletters'
-    notfound_message = _('Requested newsletter could not be found.')
-
-    def action(self, target):
-        target.delete()
-        return Message(_('Newsletter "%(name)s"" has been deleted.') % {'name': target.name}, 'success'), False
-
-
-def send(request, target, token):
-    try:
-        newsletter = Newsletter.objects.get(pk=target, token=token)
-
-        # Build recipients queryset
-        recipients = User.objects
-        if newsletter.ranks.all():
-            recipients = recipients.filter(rank__in=[x.pk for x in newsletter.ranks.all()])
-        if not newsletter.ignore_subscriptions:
-            recipients = recipients.filter(receive_newsletters=1)
-
-        recipients_total = recipients.count()
-        if recipients_total < 1:
-            request.messages.set_flash(Message(_('No recipients for newsletter "%(newsletter)s" could be found.') % {'newsletter': newsletter.name}), 'error', 'newsletters')
-            return redirect(reverse('admin_newsletters'))
-
-        for user in recipients.all()[newsletter.progress:(newsletter.progress + newsletter.step_size)]:
-            tokens = {
-              '{{ board_name }}': request.settings.board_name,
-              '{{ username }}': user.username,
-              '{{ user_url }}': django_reverse('user', kwargs={'username': user.username_slug, 'user': user.pk}),
-              '{{ board_url }}': settings.BOARD_ADDRESS,
-            }
-            subject = newsletter.parse_name(tokens)
-            user.email_user(request, 'users/newsletter', subject, {
-                                                                'newsletter': newsletter,
-                                                                'subject': subject,
-                                                                'content_html': newsletter.parse_html(tokens),
-                                                                'content_plain': newsletter.parse_plain(tokens),
-                                                                })
-            newsletter.progress += 1
-        newsletter.generate_token()
-        newsletter.save(force_update=True)
-
-        if newsletter.progress >= recipients_total:
-            newsletter.progress = 0
-            newsletter.save(force_update=True)
-            request.messages.set_flash(Message(_('Newsletter "%(newsletter)s" has been sent.') % {'newsletter': newsletter.name}), 'success', 'newsletters')
-            return redirect(reverse('admin_newsletters'))
-
-        # Render Progress
-        response = request.theme.render_to_response('processing.html', {
-                'task_name': _('Sending Newsletter'),
-                'target_name': newsletter.name,
-                'message': _('Sent to %(progress)s from %(total)s users') % {'progress': newsletter.progress, 'total': recipients_total},
-                'progress': newsletter.progress * 100 / recipients_total,
-                'cancel_url': reverse('admin_newsletters'),
-            }, context_instance=RequestContext(request));
-        response['refresh'] = '2;url=%s' % reverse('admin_newsletters_send', newsletter)
-        return response
-    except Newsletter.DoesNotExist:
-        request.messages.set_flash(Message(_('Requested Newsletter could not be found.')), 'error', 'newsletters')
-        return redirect(reverse('admin_newsletters'))

+ 0 - 0
notrefactored/profiles/__init__.py


+ 0 - 37
notrefactored/profiles/decorators.py

@@ -1,37 +0,0 @@
-from functools import wraps
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from misago.utils import slugify
-from misago.views import error404
-from misago.users.models import User
-
-def profile_view(fallback='user'):
-    def outer_decorator(f):
-        def inner_decorator(request, user, username, *args, **kwargs):
-            request = request
-            user_pk = int(user)
-            user_slug = username
-            try:
-                user = User.objects.get(pk=user_pk)
-                if user.username_slug != user_slug:
-                    # Force crawlers to take notice of updated username
-                    return redirect(reverse(fallback, args=(user.username_slug, user.pk)), permanent=True)
-                return f(request, user, *args, **kwargs)
-            except User.DoesNotExist:
-                return error404(request)
-    
-        return wraps(f)(inner_decorator)
-    return outer_decorator
-
-
-def user_view(f):
-    def inner_decorator(request, user, *args, **kwargs):
-        request = request
-        user_pk = int(user)
-        try:
-            user = User.objects.get(pk=user_pk)
-            return f(request, user, *args, **kwargs)
-        except User.DoesNotExist:
-            return error404(request)
-
-    return wraps(f)(inner_decorator)

+ 0 - 0
notrefactored/profiles/details/__init__.py


+ 0 - 4
notrefactored/profiles/details/profile.py

@@ -1,4 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_profile_extension(request):
-    return (('user_details', _('Profile Details')),)

+ 0 - 14
notrefactored/profiles/details/urls.py

@@ -1,14 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_profile_urls(first=False):
-    urlpatterns = []
-    if first:
-        urlpatterns += patterns('misago.profiles.details.views',
-            url(r'^$', 'details', name="user"),
-            url(r'^$', 'details', name="user_details"),
-        )
-    else:
-        urlpatterns += patterns('misago.profiles.details.views',
-            url(r'^details/$', 'details', name="user_details"),
-        )
-    return urlpatterns

+ 0 - 10
notrefactored/profiles/details/views.py

@@ -1,10 +0,0 @@
-from misago.profiles.decorators import profile_view
-from misago.profiles.template import RequestContext
-
-@profile_view('user_details')
-def details(request, user):
-    return request.theme.render_to_response('profiles/details.html',
-                                            context_instance=RequestContext(request, {
-                                             'profile': user,
-                                             'tab': 'details',
-                                             }));

+ 0 - 0
notrefactored/profiles/followers/__init__.py


+ 0 - 4
notrefactored/profiles/followers/profile.py

@@ -1,4 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_profile_extension(request):
-    return (('user_followers', _('Followers')),)

+ 0 - 16
notrefactored/profiles/followers/urls.py

@@ -1,16 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_profile_urls(first=False):
-    urlpatterns = []
-    if first:
-        urlpatterns += patterns('misago.profiles.followers.views',
-            url(r'^$', 'followers', name="user"),
-            url(r'^$', 'followers', name="user_followers"),
-            url(r'^(?P<page>\d+)/$', 'followers', name="user_followers"),
-        )
-    else:
-        urlpatterns += patterns('misago.profiles.followers.views',
-            url(r'^followers/$', 'followers', name="user_followers"),
-            url(r'^followers/(?P<page>\d+)/$', 'followers', name="user_followers"),
-        )
-    return urlpatterns

+ 0 - 17
notrefactored/profiles/followers/views.py

@@ -1,17 +0,0 @@
-from misago.profiles.decorators import profile_view
-from misago.profiles.template import RequestContext
-from misago.utils import make_pagination
-
-@profile_view('user_followers')
-def followers(request, user, page=0):
-    queryset = user.follows_set.order_by('username_slug')
-    count = queryset.count()
-    pagination = make_pagination(page, count, 24)
-    return request.theme.render_to_response('profiles/followers.html',
-                                            context_instance=RequestContext(request, {
-                                             'profile': user,
-                                             'tab': 'followers',
-                                             'items_total': count,
-                                             'items': queryset[pagination['start']:pagination['stop']],
-                                             'pagination': pagination,
-                                             }));

+ 0 - 0
notrefactored/profiles/follows/__init__.py


+ 0 - 4
notrefactored/profiles/follows/profile.py

@@ -1,4 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_profile_extension(request):
-    return (('user_follows', _('Follows')),)

+ 0 - 16
notrefactored/profiles/follows/urls.py

@@ -1,16 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_profile_urls(first=False):
-    urlpatterns = []
-    if first:
-        urlpatterns += patterns('misago.profiles.follows.views',
-            url(r'^$', 'follows', name="user"),
-            url(r'^$', 'follows', name="user_follows"),
-            url(r'^(?P<page>\d+)/$', 'follows', name="user_follows"),
-        )
-    else:
-        urlpatterns += patterns('misago.profiles.follows.views',
-            url(r'^follows/$', 'follows', name="user_follows"),
-            url(r'^follows/(?P<page>\d+)/$', 'follows', name="user_follows"),
-        )
-    return urlpatterns

+ 0 - 17
notrefactored/profiles/follows/views.py

@@ -1,17 +0,0 @@
-from misago.profiles.decorators import profile_view
-from misago.profiles.template import RequestContext
-from misago.utils import make_pagination
-
-@profile_view('user_follows')
-def follows(request, user, page=0):
-    queryset = user.follows.order_by('username_slug')
-    count = queryset.count()
-    pagination = make_pagination(page, count, 24)
-    return request.theme.render_to_response('profiles/follows.html',
-                                            context_instance=RequestContext(request, {
-                                             'profile': user,
-                                             'tab': 'follows',
-                                             'items_total': count,
-                                             'items': queryset[pagination['start']:pagination['stop']],
-                                             'pagination': pagination,
-                                             }));

+ 0 - 6
notrefactored/profiles/forms.py

@@ -1,6 +0,0 @@
-from django import forms
-from misago.forms import Form
-    
-    
-class QuickFindUserForm(Form):
-    username = forms.CharField()

+ 0 - 0
notrefactored/profiles/posts/__init__.py


+ 0 - 4
notrefactored/profiles/posts/profile.py

@@ -1,4 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_profile_extension(request):
-    return (('user_posts', _('Posts')),)

+ 0 - 16
notrefactored/profiles/posts/urls.py

@@ -1,16 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_profile_urls(first=False):
-    urlpatterns = []
-    if first:
-        urlpatterns += patterns('misago.profiles.posts.views',
-            url(r'^$', 'posts', name="user"),
-            url(r'^$', 'posts', name="user_posts"),
-            url(r'^(?P<page>\d+)/$', 'posts', name="user_posts"),
-        )
-    else:
-        urlpatterns += patterns('misago.profiles.posts.views',
-            url(r'^posts/$', 'posts', name="user_posts"),
-            url(r'^posts/(?P<page>\d+)/$', 'posts', name="user_posts"),
-        )
-    return urlpatterns

+ 0 - 17
notrefactored/profiles/posts/views.py

@@ -1,17 +0,0 @@
-from misago.profiles.decorators import profile_view
-from misago.profiles.template import RequestContext
-from misago.utils import make_pagination
-
-@profile_view('user_posts')
-def posts(request, user, page=0):
-    queryset = user.post_set.filter(forum_id__in=request.acl.threads.get_readable_forums(request.acl)).filter(deleted=False).filter(moderated=False).select_related('thread', 'forum').order_by('-id')
-    count = queryset.count()
-    pagination = make_pagination(page, count, 12)
-    return request.theme.render_to_response('profiles/posts.html',
-                                            context_instance=RequestContext(request, {
-                                             'profile': user,
-                                             'tab': 'posts',
-                                             'items_total': count,
-                                             'items': queryset[pagination['start']:pagination['stop']],
-                                             'pagination': pagination,
-                                             }));

+ 0 - 55
notrefactored/profiles/template.py

@@ -1,55 +0,0 @@
-from datetime import timedelta
-from django.conf import settings
-from django.template import RequestContext as DjangoRequestContext
-from django.utils import timezone
-from django.utils.importlib import import_module
-from misago.users.models import User
-
-def RequestContext(request, context=None):
-    if not context:
-        context = {}
-    context['fallback'] = request.path
-        
-    # Find out if we ignore or follow this user
-    context['follows'] = False
-    context['ignores'] = False
-    if request.user.is_authenticated() and request.user.pk != context['profile'].pk:
-        context['follows'] = request.user.is_following(context['profile'])
-        context['ignores'] = request.user.is_ignoring(context['profile'])
-        
-    # Find out if this user allows us to see his activity
-    if request.user.pk != context['profile'].pk:
-        if context['profile'].hide_activity == 2:
-            context['hidden'] = True
-        if context['profile'].hide_activity == 1:
-            context['hidden'] = context['profile'].is_following(request.user)
-    else:
-        context['hidden'] = False
-
-    # Find out if this user is online:
-    if request.user.pk != context['profile'].pk:
-        try:
-            context['online'] = context['profile'].sessions.filter(admin=False).filter(last__gt=(timezone.now() - timedelta(minutes=10))).order_by('-last')[0:1][0]
-        except IndexError:
-            context['online'] = False
-    else:
-        # Fake "right now" time
-        context['online'] = {'last': timezone.now()}
-
-    context['tabs'] = []
-    for extension in settings.PROFILE_EXTENSIONS:
-        profile_module = import_module(extension + '.profile')
-        try:
-            append_links = profile_module.register_profile_extension(request)
-            if append_links:
-                for link in append_links:
-                    link = list(link)
-                    token = link[0][link[0].find('_') + 1:]
-                    context['tabs'].append({
-                                            'route': link[0],
-                                            'active': context['tab'] == token,
-                                            'name': link[1],
-                                            })
-        except AttributeError:
-            pass
-    return DjangoRequestContext(request, context)

+ 0 - 0
notrefactored/profiles/threads/__init__.py


+ 0 - 4
notrefactored/profiles/threads/profile.py

@@ -1,4 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_profile_extension(request):
-    return (('user_threads', _('Threads')),)

+ 0 - 16
notrefactored/profiles/threads/urls.py

@@ -1,16 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_profile_urls(first=False):
-    urlpatterns = []
-    if first:
-        urlpatterns += patterns('misago.profiles.threads.views',
-            url(r'^$', 'threads', name="user"),
-            url(r'^$', 'threads', name="user_threads"),
-            url(r'^(?P<page>\d+)/$', 'threads', name="user_threads"),
-        )
-    else:
-        urlpatterns += patterns('misago.profiles.threads.views',
-            url(r'^threads/$', 'threads', name="user_threads"),
-            url(r'^threads/(?P<page>\d+)/$', 'threads', name="user_threads"),
-        )
-    return urlpatterns

+ 0 - 17
notrefactored/profiles/threads/views.py

@@ -1,17 +0,0 @@
-from misago.profiles.decorators import profile_view
-from misago.profiles.template import RequestContext
-from misago.utils import make_pagination
-
-@profile_view('user_threads')
-def threads(request, user, page=0):
-    queryset = user.thread_set.filter(forum_id__in=request.acl.threads.get_readable_forums(request.acl)).filter(deleted=False).filter(moderated=False).select_related('start_post', 'forum').order_by('-id')
-    count = queryset.count()
-    pagination = make_pagination(page, count, 12)
-    return request.theme.render_to_response('profiles/threads.html',
-                                            context_instance=RequestContext(request, {
-                                             'profile': user,
-                                             'tab': 'threads',
-                                             'items_total': count,
-                                             'items': queryset[pagination['start']:pagination['stop']],
-                                             'pagination': pagination,
-                                             }));

+ 0 - 25
notrefactored/profiles/urls.py

@@ -1,25 +0,0 @@
-from django.conf import settings
-from django.conf.urls import patterns, include, url
-from django.utils.importlib import import_module
-
-urlpatterns = patterns('misago.profiles.views',
-    url(r'^$', 'list', name="users"),
-    url(r'^(?P<page>[0-9]+)/$', 'list', name="users"),
-)
-
-# Build extensions URLs
-iteration = 0
-for extension in settings.PROFILE_EXTENSIONS:
-    iteration += 1
-    profile_extension = import_module(extension + '.urls')
-    try:
-        urlpatterns += patterns('',
-            (r'^(?P<username>\w+)-(?P<user>\d+)/', include(profile_extension.register_profile_urls(iteration == 1))),
-        )
-    except AttributeError:
-        pass
-
-urlpatterns += patterns('misago.profiles.views',
-    url(r'^(?P<rank_slug>(\w|-)+)/$', 'list', name="users"),
-    url(r'^(?P<rank_slug>(\w|-)+)/(?P<page>[0-9]+)/$', 'list', name="users"),
-)

+ 0 - 87
notrefactored/profiles/views.py

@@ -1,87 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from misago.forms import FormFields
-from misago.messages import Message
-from misago.profiles.forms import QuickFindUserForm
-from misago.ranks.models import Rank
-from misago.users.models import User
-from misago.utils import slugify, make_pagination
-from misago.views import error403, error404
-
-def list(request, rank_slug=None, page=1):
-    ranks = Rank.objects.filter(as_tab=1).order_by('order')
-
-    # Find active rank
-    default_rank = False
-    active_rank = None
-    if rank_slug:
-        for rank in ranks:
-            if rank.name_slug == rank_slug:
-                active_rank = rank
-        if not active_rank:
-            return error404(request)
-    elif ranks:
-        default_rank = True
-        active_rank = ranks[0]
-
-    # Empty Defaults
-    message = None
-    users = []
-    items_total = 0
-    pagination = None
-    in_search = False
-
-    # Users search?
-    if request.method == 'POST':
-        if not request.acl.users.can_search_users():
-            return error403(request)
-        in_search = True
-        active_rank = None
-        search_form = QuickFindUserForm(request.POST, request=request)
-        if search_form.is_valid():
-            # Direct hit?
-            username = search_form.cleaned_data['username']
-            try:
-                user = User.objects.get(username__iexact=username)
-                return redirect(reverse('user', args=(user.username_slug, user.pk)))
-            except User.DoesNotExist:
-                pass
-
-            # Looks like well have to find near match
-            if len(username) > 6:
-                username = username[0:-3]
-            elif len(username) > 5:
-                username = username[0:-2]
-            elif len(username) > 4:
-                username = username[0:-1]
-            username = slugify(username.strip())
-
-            # Go for rought match
-            if len(username) > 0:
-                users = User.objects.filter(username_slug__startswith=username).order_by('username_slug')[:10]
-        elif search_form.non_field_errors()[0] == 'form_contains_errors':
-            message = Message(_("To search users you have to enter username in search field."), 'error')
-        else:
-            message = Message(search_form.non_field_errors()[0], 'error')
-    else:
-        search_form = QuickFindUserForm(request=request)
-        if active_rank:
-            users = User.objects.filter(rank=active_rank)
-            items_total = users.count()
-            pagination = make_pagination(page, items_total, 4)
-            users = users.order_by('username_slug')[pagination['start']:pagination['stop']]
-
-    return request.theme.render_to_response('profiles/list.html',
-                                        {
-                                         'message': message,
-                                         'search_form': FormFields(search_form).fields,
-                                         'in_search': in_search,
-                                         'active_rank': active_rank,
-                                         'default_rank': default_rank,
-                                         'items_total': items_total,
-                                         'ranks': ranks,
-                                         'users': users,
-                                         'pagination': pagination,
-                                        },
-                                        context_instance=RequestContext(request));

+ 0 - 0
notrefactored/prune/__init__.py


+ 0 - 32
notrefactored/prune/forms.py

@@ -1,32 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.forms import Form
-from misago.utils.validators import validate_sluggable
-
-class PolicyForm(Form):
-    name = forms.CharField(max_length=255, validators=[validate_sluggable(
-                                                                          _("Policy name must be sluggable."),
-                                                                          _("Policy name is too long.")
-                                                                          )])
-    email = forms.CharField(max_length=255, required=False)
-    posts = forms.IntegerField(min_value=0, initial=0)
-    registered = forms.IntegerField(min_value=0, initial=0)
-    last_visit = forms.IntegerField(min_value=0, initial=0)
-
-    layout = (
-              (
-               _("Basic Policy Options"),
-               (
-                ('name', {'label': _("Policy Name"), 'help_text': _("Short, descriptive name of this pruning policy.")}),
-                )
-               ),
-              (
-               _("Pruning Policy Criteria"),
-               (
-                ('email', {'label': _("Member E-mail Address ends with"), 'help_text': _("If you want to, you can enter more than one e-mail suffix by separating them with comma.")}),
-                ('posts', {'label': _("Member has no more posts than"), 'help_text': _("Maximum number of posts member is allowed to have to fall under policy. For example if you enter in 10 posts and make this only criteria, every user that has less than 10 posts will be deleted. Enter zero to dont use this criteria")}),
-                ('registered', {'label': _("User is member for no more than"), 'help_text': _("Maximal number of days user is member for. For exmaple if you enter in 15 days and make this only criteria, every user who is member for less than 15 days will be deleted. Enter zero to dont use this criteria.")}),
-                ('last_visit', {'label': _("User last visit was before"), 'help_text': _("Maximal allowed inactivity period in days. For example if you enter in 300 days and make this only criteria for deleting users, every member who did not signed into forums in last 300 days will be deleted. Enter zero to dont use this criteria.")}),
-                )
-               ),
-              )

+ 0 - 40
notrefactored/prune/migrations/0001_initial.py

@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Policy'
-        db.create_table(u'prune_policy', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('email', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('posts', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('registered', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('last_visit', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-        ))
-        db.send_create_signal(u'prune', ['Policy'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Policy'
-        db.delete_table(u'prune_policy')
-
-
-    models = {
-        u'prune.policy': {
-            'Meta': {'object_name': 'Policy'},
-            'email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last_visit': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'registered': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['prune']

+ 0 - 0
notrefactored/prune/migrations/__init__.py


+ 0 - 52
notrefactored/prune/models.py

@@ -1,52 +0,0 @@
-from datetime import timedelta
-from django.core.exceptions import ValidationError
-from django.db import models
-from django.db.models import Q
-from django.utils import timezone
-from django.utils.translation import ugettext_lazy as _
-from misago.users.models import User
-
-class Policy(models.Model):
-    """
-    Pruning policy
-    """
-    name = models.CharField(max_length=255)
-    email = models.CharField(max_length=255, null=True, blank=True)
-    posts = models.PositiveIntegerField(default=0)
-    registered = models.PositiveIntegerField(default=0)
-    last_visit = models.PositiveIntegerField(default=0)
-
-    def clean(self):
-        if not (self.email and self.posts and self.registered and self.last_visit):
-            raise ValidationError(_("Pruning policy must have at least one pruning criteria set to be valid."))
-
-    def get_model(self):
-        model = User.objects
-
-        if self.email:
-            if ',' in self.email:
-                qs = None
-                for name in self.email.split(','):
-                    name = name.strip().lower()
-                    if name:
-                        if qs:
-                            qs = qs | Q(email__iendswith=name)
-                        else:
-                            qs = Q(email__iendswith=name)
-                if qs:
-                    model = model.filter(qs)
-            else:
-                model = model.filter(email__iendswith=self.email)
-
-        if self.posts:
-            model = model.filter(posts__lt=self.posts)
-
-        if self.registered:
-            date = timezone.now() - timedelta(days=self.registered)
-            model = model.filter(join_date__gte=date)
-
-        if self.last_visit:
-            date = timezone.now() - timedelta(days=self.last_visit)
-            model = model.filter(last_date__gte=date)
-
-        return model

+ 0 - 212
notrefactored/prune/views.py

@@ -1,212 +0,0 @@
-from django.core.urlresolvers import reverse as django_reverse
-from django import forms
-from django.utils.translation import ungettext, ugettext as _
-from misago.admin import site
-from misago.admin.widgets import *
-from misago.forms import Form
-from misago.prune.forms import PolicyForm
-from misago.prune.models import Policy
-from misago.users.models import User
-
-def reverse(route, target=None):
-    if target:
-        return django_reverse(route, kwargs={'target': target.pk})
-    return django_reverse(route)
-
-"""
-Views
-"""
-class List(ListWidget):
-    admin = site.get_action('prune_users')
-    id = 'list'
-    columns = (
-               ('name', _("Pruning Policy")),
-               )
-    nothing_checked_message = _('You have to check at least one policy.')
-    actions = (
-               ('delete', _("Delete selected policies"), _("Are you sure you want to delete selected policies?")),
-               )
-
-    def sort_items(self, page_items, sorting_method):
-        return page_items.order_by('name')
-
-    def get_item_actions(self, item):
-        return (
-                self.action('filter', _("Apply Policy"), reverse('admin_prune_users_apply', item)),
-                self.action('pencil', _("Edit Policy"), reverse('admin_prune_users_edit', item)),
-                self.action('remove', _("Delete Policy"), reverse('admin_prune_users_delete', item), post=True, prompt=_("Are you sure you want to delete this policy?")),
-                )
-
-    def action_delete(self, items, checked):
-        if not self.request.user.is_god():
-            return Message(_('Only system administrators can delete pruning policies.'), 'error'), reverse('admin_prune_users')
-
-        Policy.objects.filter(id__in=checked).delete()
-        return Message(_('Selected pruning policies have been deleted successfully.'), 'success'), reverse('admin_prune_users')
-
-
-class New(FormWidget):
-    admin = site.get_action('prune_users')
-    id = 'new'
-    fallback = 'admin_prune_users'
-    form = PolicyForm
-    submit_button = _("Save Policy")
-
-    def get_new_url(self, model):
-        return reverse('admin_prune_users_new')
-
-    def get_edit_url(self, model):
-        return reverse('admin_prune_users_edit', model)
-
-    def submit_form(self, form, target):
-        new_policy = Policy(
-                      name=form.cleaned_data['name'],
-                      email=form.cleaned_data['email'],
-                      posts=form.cleaned_data['posts'],
-                      registered=form.cleaned_data['registered'],
-                      last_visit=form.cleaned_data['last_visit'],
-                     )
-        new_policy.clean()
-        new_policy.save(force_insert=True)
-
-        return new_policy, Message(_('New Pruning Policy has been created.'), 'success')
-
-    def __call__(self, request, *args, **kwargs):
-        if not request.user.is_god():
-            request.messages.set_flash(Message(_('Only system administrators can set new pruning policies.')), 'error', self.admin.id)
-            return redirect(reverse('admin_prune_users'))
-
-        return super(New, self).__call__(request, *args, **kwargs)
-
-
-class Edit(FormWidget):
-    admin = site.get_action('prune_users')
-    id = 'edit'
-    name = _("Edit Pruning Policy")
-    fallback = 'admin_prune_users'
-    form = PolicyForm
-    target_name = 'name'
-    notfound_message = _('Requested pruning policy could not be found.')
-    submit_fallback = True
-
-    def get_url(self, model):
-        return reverse('admin_prune_users_edit', model)
-
-    def get_edit_url(self, model):
-        return self.get_url(model)
-
-    def get_initial_data(self, model):
-        return {
-                'name': model.name,
-                'email': model.email,
-                'posts': model.posts,
-                'registered': model.registered,
-                'last_visit': model.last_visit,
-                }
-
-    def submit_form(self, form, target):
-        target.name = form.cleaned_data['name']
-        target.email = form.cleaned_data['email']
-        target.posts = form.cleaned_data['posts']
-        target.registered = form.cleaned_data['registered']
-        target.last_visit = form.cleaned_data['last_visit']
-        target.clean()
-        target.save(force_update=True)
-
-        return target, Message(_('Changes in policy "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
-
-    def __call__(self, request, *args, **kwargs):
-        if not request.user.is_god():
-            request.messages.set_flash(Message(_('Only system administrators can edit pruning policies.')), 'error', self.admin.id)
-            return redirect(reverse('admin_prune_users'))
-
-        return super(Edit, self).__call__(request, *args, **kwargs)
-
-
-class Delete(ButtonWidget):
-    admin = site.get_action('prune_users')
-    id = 'delete'
-    fallback = 'admin_prune_users'
-    notfound_message = _('Requested pruning policy could not be found.')
-
-    def action(self, target):
-        if not self.request.user.is_god():
-            return Message(_('Only system administrators can delete pruning policies.'), 'error'), False
-
-        target.delete()
-        return Message(_('Pruning policy "%(name)s" has been deleted.') % {'name': target.name}, 'success'), False
-
-
-class Apply(FormWidget):
-    admin = site.get_action('prune_users')
-    id = 'apply'
-    name = _("Apply Pruning Policy")
-    fallback = 'admin_prune_users'
-    form = PolicyForm
-    target_name = 'name'
-    notfound_message = _('Requested pruning policy could not be found.')
-    submit_fallback = True
-    template = 'apply'
-
-    def get_url(self, model):
-        return reverse('admin_prune_users_apply', model)
-
-    def __call__(self, request, target=None, slug=None):
-        self.request = request
-
-        # Fetch target
-        model = None
-        if target:
-            model = self.get_and_validate_target(target)
-            self.original_name = self.get_target_name(model)
-            if not model:
-                return redirect(self.get_fallback_url())
-        original_model = model
-
-        # Set filter
-        users = model.get_model()
-        total_users = users
-        total_users = total_users.count()
-
-        if not total_users:
-            request.messages.set_flash(Message(_('Policy "%(name)s" does not apply to any users.') % {'name': model.name}), 'error', self.admin.id)
-            return redirect(reverse('admin_prune_users'))
-
-        message = None
-        if request.method == 'POST':
-            deleted = 0
-            if request.csrf.request_secure(request):
-                for user in users.iterator():
-                    if user.is_protected():
-                        request.messages.set_flash(Message(_('User "%(name)s" is protected and was not deleted.') % {'name': user.username}), 'info', self.admin.id)
-                    else:
-                        user.delete()
-                        deleted += 1
-                if deleted:
-                    request.messages.set_flash(Message(ungettext(
-                                                                 'One user has been deleted.',
-                                                                 '%(deleted)d users have been deleted.',
-                                                                 deleted
-                                                                 ) % {'deleted': deleted}), 'success', self.admin.id)
-                    User.objects.resync_monitor(request.monitor)
-                else:
-                    request.messages.set_flash(Message(_("No users have been deleted.")), 'info', self.admin.id)
-                return redirect(reverse('admin_prune_users'))
-            else:
-                message = Message(_("Request authorization is invalid. Please resubmit your form."), 'error')
-
-        return request.theme.render_to_response(self.get_template(),
-                                                {
-                                                 'admin': self.admin,
-                                                 'action': self,
-                                                 'request': request,
-                                                 'url': self.get_url(model),
-                                                 'fallback': self.get_fallback_url(),
-                                                 'messages': request.messages.get_messages(self.admin.id),
-                                                 'message': message,
-                                                 'tabbed': self.tabbed,
-                                                 'total_users': total_users,
-                                                 'target': self.get_target_name(original_model),
-                                                 'target_model': original_model,
-                                                },
-                                                context_instance=RequestContext(request));

+ 0 - 0
notrefactored/ranks/__init__.py


+ 0 - 129
notrefactored/ranks/fixtures.py

@@ -1,129 +0,0 @@
-from misago.ranks.models import Rank
-from misago.settings.fixtures import load_settings_fixture, update_settings_fixture
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-
-settings_fixtures = (
-    # Users Ranking Settings
-    ('ranking', {
-        'name': _("Members Ranking"),
-        'description': _("Those settings control mechanisms of members activity ranking which allows you to gamificate your forum."),
-        'settings': (
-            ('ranking_inflation', {
-                'value':        5,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0, 'max': 99},
-                'separator':    _("Basic Ranking Settings"),
-                'name':         _("Ranking Inflation"),
-                'description':  _("Enter size of ranking scores inflation in percent. Scores inflation is important mechanism that allows ranking self-regulation, punishing inactivity and requiring users to remain active in order to remain high in ranking."),
-            }),
-            ('ranking_positions_visible', {
-                'value':        True,
-                'type':         "boolean",
-                'input':        "yesno",
-                'name':         _("Don't Keep Users Ranking Positions Secret"),
-                'description':  _("Changing this to yes will cause forum to display user position in ranking on his profile page."),
-            }),
-            ('ranking_scores_visible', {
-                'value':        True,
-                'type':         "boolean",
-                'input':        "yesno",
-                'name':         _("Don't Keep Users Scores Secret"),
-                'description':  _("Changing this to yes will cause forum to display user score on his profile page."),
-            }),
-            ('score_reward_new_thread', {
-                'value':        50,
-                'type':         "integer",
-                'input':        "text",
-                'separator':    _("Posting Rewards"),
-                'name':         _("New Thread Reward"),
-                'description':  _("Score user will receive (or lose) whenever he posts new thread."),
-            }),
-            ('score_reward_new_post', {
-                'value':        100,
-                'type':         "integer",
-                'input':        "text",
-                'name':         _("New Reply Reward"),
-                'description':  _("Score user will receive (or lose) whenever he posts new reply in thread."),
-            }),
-            ('score_reward_new_post_cooldown', {
-                'value':        180,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'name':         _("Reward Cooldown"),
-                'description':  _("Minimal time (in seconds) that has to pass between postings for new message to receive karma vote. This is useful to combat flood."),
-            }),
-            ('score_reward_karma_positive', {
-                'value':        20,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'separator':    _("Karma System"),
-                'name':         _("Upvote Reward"),
-                'description':  _("Score user will receive every time his post receives upvote."),
-            }),
-            ('score_reward_karma_negative', {
-                'value':        10,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'name':         _("Downvote Punishment"),
-                'description':  _("Score user will lose every time his post receives downvote."),
-            }),
-        ),
-    }),
-)
-
-
-def load_fixtures():
-    load_settings_fixture(settings_fixtures)
-    Rank.objects.create(
-                        name=_("Forum Team").message,
-                        name_slug='forum-team',
-                        title=_("Forum Team").message,
-                        style='team',
-                        special=True,
-                        order=0,
-                        as_tab=True,
-                        on_index=True,
-                        )
-
-    Rank.objects.create(
-                        name=_("Most Valuable Posters").message,
-                        name_slug='most-valuable-posters',
-                        title=_("MVP").message,
-                        style='mvp',
-                        special=True,
-                        order=1,
-                        as_tab=True,
-                        )
-
-    Rank.objects.create(
-                        name=_("Lurkers").message,
-                        name_slug='lurkers',
-                        order=1,
-                        criteria="100%"
-                        )
-
-    Rank.objects.create(
-                        name=_("Members").message,
-                        name_slug='members',
-                        order=2,
-                        criteria="75%"
-                        )
-
-    Rank.objects.create(
-                        name=_("Active Members").message,
-                        name_slug='active-members',
-                        style='active',
-                        order=3,
-                        criteria="10%",
-                        as_tab=True,
-                        )
-
-
-def update_fixtures():
-    update_settings_fixture(settings_fixtures)

+ 0 - 44
notrefactored/ranks/forms.py

@@ -1,44 +0,0 @@
-from django.core.validators import RegexValidator
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.forms import Form, YesNoSwitch
-from misago.utils.validators import validate_sluggable
-
-class RankForm(Form):
-    name = forms.CharField(max_length=255, validators=[validate_sluggable(
-                                                                          _("Rank name must be sluggable."),
-                                                                          _("Rank name is too long.")
-                                                                          )])
-    description = forms.CharField(widget=forms.Textarea, required=False)
-    title = forms.CharField(max_length=255, required=False)
-    style = forms.CharField(max_length=255, required=False)
-    special = forms.BooleanField(widget=YesNoSwitch, required=False)
-    as_tab = forms.BooleanField(widget=YesNoSwitch, required=False)
-    on_index = forms.BooleanField(widget=YesNoSwitch, required=False)
-    criteria = forms.CharField(max_length=255, initial='0', validators=[RegexValidator(regex='^(\d+)(%?)$', message=_('This is incorrect rank match rule.'))], required=False)
-
-    layout = (
-              (
-               _("Basic Rank Options"),
-               (
-                ('name', {'label': _("Rank Name"), 'help_text': _("Rank Name is used to identify rank in Admin Control Panel and is used as page and tab title if you decide to make this rank act as tab on users list.")}),
-                ('description', {'label': _("Rank Description"), 'help_text': _("If this rank acts as tab on users list, here you can enter optional description that will be displayed above list of users with this rank.")}),
-                ('as_tab', {'label': _("As Tab on Users List"), 'help_text': _("Should this rank have its own page on users list, containing rank's description and list of users that have it? This is good option for rank used by forum team members or members that should be visible and easily reachable.")}),
-                ('on_index', {'label': _("Display members online"), 'help_text': _("Should users online with this rank be displayed on board index?")}),
-                )
-               ),
-              (
-               _("Rank Looks"),
-               (
-                ('title', {'label': _("Rank Title"), 'help_text': _("Short description of rank's bearer role in your community.")}),
-                ('style', {'label': _("Rank CSS Class"), 'help_text': _("Optional CSS class that will be added to different elements displaying rank's owner or his content, allowing you to make them stand out from other members.")}),
-                )
-               ),
-              (
-               _("Rank Attainability"),
-               (
-                ('special', {'label': _("Special Rank"), 'help_text': _("Special ranks are ignored during updates of user ranking, making them unattainable without admin ingerention.")}),
-                ('criteria', {'label': _("Rank Criteria"), 'help_text': _("This setting allows you to limit number of users that can attain this rank. Enter 0 to assign this rank to all members (good for default rank). To give this rank to 10% of most active members, enter \"10%\". To give this rank to 10 most active members, enter \"10\". This setting is ignored for special ranks as they don't participate in user's ranking updates.")}),
-                ),
-               ),
-              )

+ 0 - 0
notrefactored/ranks/management/__init__.py


+ 0 - 0
notrefactored/ranks/management/commands/__init__.py


+ 0 - 37
notrefactored/ranks/management/commands/updateranking.py

@@ -1,37 +0,0 @@
-from django.core.management.base import BaseCommand, CommandError
-from django.db.models import F
-from misago.settings.settings import Settings
-from misago.ranks.models import Rank
-from misago.users.models import User
-
-class Command(BaseCommand):
-    """
-    This command is intended to work as CRON job fired of once per day or less if you have more users to update user ranking.
-    """
-    help = 'Updates users ranking'
-    def handle(self, *args, **options):
-        # Find special ranks
-        special_ranks = []
-        for rank in Rank.objects.filter(special=1):
-            special_ranks.append(str(rank.pk))
-
-        # Count users that are in ranking
-        users_total = User.objects.exclude(rank__in=special_ranks).count()
-
-        # Update Ranking
-        defaulted_ranks = False
-        for rank in Rank.objects.filter(special=0).order_by('order'):
-            if defaulted_ranks:
-                # Set ranks according to ranking
-                rank.assign_rank(users_total, special_ranks)
-            else:
-                # Set default rank first
-                User.objects.exclude(rank__in=special_ranks).update(rank=rank)
-                defaulted_ranks = True
-
-        # Inflate scores
-        settings = Settings()
-        inflation = float(100 - settings['ranking_inflation']) / 100
-        User.objects.all().update(score=F('score') * inflation, ranking=0)
-
-        self.stdout.write('Users ranking for has been updated.\n')

+ 0 - 50
notrefactored/ranks/migrations/0001_initial.py

@@ -1,50 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Rank'
-        db.create_table(u'ranks_rank', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('name_slug', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('style', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('title', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('special', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('as_tab', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('on_index', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('order', self.gf('django.db.models.fields.IntegerField')(default=0)),
-            ('criteria', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-        ))
-        db.send_create_signal(u'ranks', ['Rank'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Rank'
-        db.delete_table(u'ranks_rank')
-
-
-    models = {
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        }
-    }
-
-    complete_apps = ['ranks']

+ 0 - 0
notrefactored/ranks/migrations/__init__.py


+ 0 - 91
notrefactored/ranks/models.py

@@ -1,91 +0,0 @@
-import math
-from django.conf import settings
-from django.db import models, connection, transaction
-from django.utils.translation import ugettext_lazy as _
-
-class Rank(models.Model):
-    """
-    Misago User Rank
-    Ranks are ready style/title pairs that are assigned to users either by admin (special ranks) or as result of user activity.
-    """
-    name = models.CharField(max_length=255)
-    name_slug = models.CharField(max_length=255, null=True, blank=True)
-    description = models.TextField(null=True, blank=True)
-    style = models.CharField(max_length=255, null=True, blank=True)
-    title = models.CharField(max_length=255, null=True, blank=True)
-    special = models.BooleanField(default=False)
-    as_tab = models.BooleanField(default=False)
-    on_index = models.BooleanField(default=False)
-    order = models.IntegerField(default=0)
-    criteria = models.CharField(max_length=255, null=True, blank=True)
-
-    def __unicode__(self):
-        return unicode(_(self.name))
-
-    def assign_rank(self, users=0, special_ranks=None):
-        if not self.criteria or self.special or users == 0:
-            # Rank cant be rolled in
-            return False
-
-        if self.criteria == "0":
-            # Just update all fellows
-            User.objects.exclude(rank__in=special_ranks).update(rank=self)
-        else:
-            # Count number of users to update
-            if self.criteria[-1] == '%':
-                criteria = int(self.criteria[0:-1])
-                criteria = int(math.ceil(float(users / 100.0) * criteria))
-            else:
-                criteria = int(self.criteria)
-
-            # Join special ranks
-            if special_ranks:
-                special_ranks = ','.join(special_ranks)
-
-            # Run raw query
-            cursor = connection.cursor()
-            try:
-                # Postgresql
-                if (settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2'
-                    or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql'):
-                    if special_ranks:
-                        cursor.execute('''UPDATE users_user
-                            FROM (
-                                SELECT id
-                                FROM users_user
-                                WHERE rank_id NOT IN (%s)
-                                ORDER BY score DESC LIMIT %s
-                                ) AS updateable
-                            SET rank_id=%s
-                            WHERE id = updateable.id
-                            RETURNING *''' % (self.id, special_ranks, criteria))
-                    else:
-                        cursor.execute('''UPDATE users_user
-                            FROM (
-                                SELECT id
-                                FROM users_user
-                                ORDER BY score DESC LIMIT %s
-                                ) AS updateable
-                            SET rank_id=%s
-                            WHERE id = updateable.id
-                            RETURNING *''', [self.id, criteria])
-
-                # MySQL, SQLite and Oracle
-                if (settings.DATABASES['default']['ENGINE'] == 'django.db.backends.mysql'
-                    or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.sqlite3'
-                    or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.oracle'):
-                    if special_ranks:
-                        cursor.execute('''UPDATE users_user
-                            SET rank_id=%s
-                            WHERE rank_id NOT IN (%s)
-                            ORDER BY score DESC
-                            LIMIT %s''' % (self.id, special_ranks, criteria))
-                    else:
-                        cursor.execute('''UPDATE users_user
-                        SET rank_id=%s
-                        ORDER BY score DESC
-                        LIMIT %s''', [self.id, criteria])
-            except Exception as e:
-                print 'Error updating users ranking: %s' % e
-            transaction.commit_unless_managed()
-        return True

+ 0 - 150
notrefactored/ranks/views.py

@@ -1,150 +0,0 @@
-from django.core.urlresolvers import reverse as django_reverse
-from django import forms
-from django.utils.translation import ugettext as _
-from misago.admin import site
-from misago.admin.widgets import *
-from misago.forms import Form
-from misago.utils import slugify
-from misago.ranks.forms import RankForm
-from misago.ranks.models import Rank
-
-def reverse(route, target=None):
-    if target:
-        return django_reverse(route, kwargs={'target': target.pk, 'slug': slugify(target.name)})
-    return django_reverse(route)
-
-"""
-Views
-"""
-class List(ListWidget):
-    admin = site.get_action('ranks')
-    id = 'list'
-    columns = (
-               ('rank', _("Rank")),
-               )
-    table_form_button = _('Reorder Ranks')
-    nothing_checked_message = _('You have to check at least one rank.')
-    actions = (
-               ('delete', _("Delete selected ranks"), _("Are you sure you want to delete selected ranks?")),
-               )
-
-    def get_table_form(self, page_items):
-        order_form = {}
-
-        # Build choices list
-        choices = []
-        for i in range(0, len(page_items)):
-           choices.append([str(i), i + 1])
-
-        # Build selectors list
-        position = 0
-        for item in page_items:
-            order_form['pos_' + str(item.pk)] = forms.ChoiceField(choices=choices, initial=str(position))
-            position += 1
-
-        # Turn dict into object
-        return type('OrderRanksForm', (Form,), order_form)
-
-    def table_action(self, page_items, cleaned_data):
-        for item in page_items:
-            item.order = cleaned_data['pos_' + str(item.pk)]
-            item.save(force_update=True)
-        return Message(_('Ranks order has been changed'), 'success'), reverse('admin_ranks')
-
-    def sort_items(self, page_items, sorting_method):
-        return page_items.order_by('order')
-
-    def get_item_actions(self, item):
-        return (
-                self.action('pencil', _("Edit Rank"), reverse('admin_ranks_edit', item)),
-                self.action('remove', _("Delete Rank"), reverse('admin_ranks_delete', item), post=True, prompt=_("Are you sure you want to delete this rank?")),
-                )
-
-    def action_delete(self, items, checked):
-        Rank.objects.filter(id__in=checked).delete()
-        return Message(_('Selected ranks have been deleted successfully.'), 'success'), reverse('admin_ranks')
-
-
-class New(FormWidget):
-    admin = site.get_action('ranks')
-    id = 'new'
-    fallback = 'admin_ranks'
-    form = RankForm
-    submit_button = _("Save Rank")
-
-    def get_new_url(self, model):
-        return reverse('admin_ranks_new')
-
-    def get_edit_url(self, model):
-        return reverse('admin_ranks_edit', model)
-
-    def submit_form(self, form, target):
-        position = 0
-        last_rank = Rank.objects.latest('order')
-        new_rank = Rank(
-                      name=form.cleaned_data['name'],
-                      name_slug=slugify(form.cleaned_data['name']),
-                      description=form.cleaned_data['description'],
-                      style=form.cleaned_data['style'],
-                      title=form.cleaned_data['title'],
-                      special=form.cleaned_data['special'],
-                      as_tab=form.cleaned_data['as_tab'],
-                      on_index=form.cleaned_data['on_index'],
-                      order=(last_rank.order + 1 if last_rank else 0),
-                      criteria=form.cleaned_data['criteria']
-                     )
-        new_rank.save(force_insert=True)
-        return new_rank, Message(_('New Rank has been created.'), 'success')
-
-
-class Edit(FormWidget):
-    admin = site.get_action('ranks')
-    id = 'edit'
-    name = _("Edit Rank")
-    fallback = 'admin_ranks'
-    form = RankForm
-    target_name = 'name'
-    notfound_message = _('Requested Rank could not be found.')
-    submit_fallback = True
-
-    def get_url(self, model):
-        return reverse('admin_ranks_edit', model)
-
-    def get_edit_url(self, model):
-        return self.get_url(model)
-
-    def get_initial_data(self, model):
-        return {
-                'name': model.name,
-                'description': model.description,
-                'style': model.style,
-                'title': model.title,
-                'special': model.special,
-                'as_tab': model.as_tab,
-                'on_index': model.on_index,
-                'criteria': model.criteria
-                }
-
-    def submit_form(self, form, target):
-        target.name = form.cleaned_data['name']
-        target.name_slug = slugify(form.cleaned_data['name'])
-        target.description = form.cleaned_data['description']
-        target.style = form.cleaned_data['style']
-        target.title = form.cleaned_data['title']
-        target.special = form.cleaned_data['special']
-        target.as_tab = form.cleaned_data['as_tab']
-        target.on_index = form.cleaned_data['on_index']
-        target.criteria = form.cleaned_data['criteria']
-        target.save(force_update=True)
-        return target, Message(_('Changes in rank "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
-
-
-class Delete(ButtonWidget):
-    admin = site.get_action('ranks')
-    id = 'delete'
-    fallback = 'admin_ranks'
-    notfound_message = _('Requested Rank could not be found.')
-
-    def action(self, target):
-        target.delete()
-        return Message(_('Rank "%(name)s" has been deleted.') % {'name': target.name}, 'success'), False

+ 0 - 0
notrefactored/readstracker/__init__.py


+ 0 - 0
notrefactored/readstracker/management/__init__.py


+ 0 - 0
notrefactored/readstracker/management/commands/__init__.py


+ 0 - 15
notrefactored/readstracker/management/commands/cleartracker.py

@@ -1,15 +0,0 @@
-from datetime import timedelta
-from django.conf import settings
-from django.core.management.base import BaseCommand
-from django.utils import timezone
-from misago.readstracker.models import ForumRecord, ThreadRecord
-
-class Command(BaseCommand):
-    """
-    This command is intended to work as CRON job fired every few days to remove old reads tracker entries
-    """
-    help = 'Clears Reads Tracker memory'
-    def handle(self, *args, **options):
-        ForumRecord.objects.filter(updated__lte=timezone.now() - timedelta(days=settings.READS_TRACKER_LENGTH)).delete()
-        ThreadRecord.objects.filter(updated__lte=timezone.now() - timedelta(days=settings.READS_TRACKER_LENGTH)).delete()
-        self.stdout.write('Reads tracker has been cleared.\n')        

+ 0 - 217
notrefactored/readstracker/migrations/0001_initial.py

@@ -1,217 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Record'
-        db.create_table(u'readstracker_record', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['users.User'])),
-            ('forum', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forums.Forum'])),
-            ('threads', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('updated', self.gf('django.db.models.fields.DateTimeField')()),
-            ('cleared', self.gf('django.db.models.fields.DateTimeField')()),
-        ))
-        db.send_create_signal(u'readstracker', ['Record'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Record'
-        db.delete_table(u'readstracker_record')
-
-
-    models = {
-        u'forums.forum': {
-            'Meta': {'object_name': 'Forum'},
-            'attrs': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'description_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Thread']"}),
-            'last_thread_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_thread_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': u"orm['forums.Forum']"}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'posts_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'prune_last': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'prune_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'redirects': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirects_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'show_details': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads_delta': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'})
-        },
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'readstracker.record': {
-            'Meta': {'object_name': 'Record'},
-            'cleared': ('django.db.models.fields.DateTimeField', [], {}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'threads': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'updated': ('django.db.models.fields.DateTimeField', [], {}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']"})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'threads.post': {
-            'Meta': {'object_name': 'Post'},
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'checkpoints': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'edit_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'edit_reason': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'edit_user_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edits': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'mentions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'mention_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'merge': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'post': ('django.db.models.fields.TextField', [], {}),
-            'post_preparsed': ('django.db.models.fields.TextField', [], {}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'reported': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'user_name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'threads.thread': {
-            'Meta': {'object_name': 'Thread'},
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last': ('django.db.models.fields.DateTimeField', [], {}),
-            'last_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'merges': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'replies': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_deleted': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_moderated': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_reported': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'score': ('django.db.models.fields.PositiveIntegerField', [], {'default': '30'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start': ('django.db.models.fields.DateTimeField', [], {}),
-            'start_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'start_poster': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'start_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'start_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'type': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'weight': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['readstracker']

+ 0 - 234
notrefactored/readstracker/migrations/0002_auto__add_threadrecord__del_field_record_threads.py

@@ -1,234 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'ThreadRecord'
-        db.create_table(u'readstracker_threadrecord', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['users.User'])),
-            ('forum', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forums.Forum'])),
-            ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['threads.Thread'])),
-            ('updated', self.gf('django.db.models.fields.DateTimeField')()),
-        ))
-        db.send_create_signal(u'readstracker', ['ThreadRecord'])
-        
-        db.create_index('readstracker_threadrecord', ['updated'])
-        db.create_index('readstracker_threadrecord', ['user_id', 'forum_id'])
-        db.create_index('readstracker_threadrecord', ['user_id', 'thread_id', 'updated'])
-
-        # Deleting field 'Record.threads'
-        db.delete_column(u'readstracker_record', 'threads')
-
-
-    def backwards(self, orm):
-        # Deleting model 'ThreadRecord'
-        db.delete_table(u'readstracker_threadrecord')
-
-        # Adding field 'Record.threads'
-        db.add_column(u'readstracker_record', 'threads',
-                      self.gf('django.db.models.fields.TextField')(null=True, blank=True),
-                      keep_default=False)
-
-
-    models = {
-        u'forums.forum': {
-            'Meta': {'object_name': 'Forum'},
-            'attrs': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'description_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Thread']"}),
-            'last_thread_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_thread_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': u"orm['forums.Forum']"}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'posts_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'prune_last': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'prune_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'redirects': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirects_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'show_details': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads_delta': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'})
-        },
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'readstracker.record': {
-            'Meta': {'object_name': 'Record'},
-            'cleared': ('django.db.models.fields.DateTimeField', [], {}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'updated': ('django.db.models.fields.DateTimeField', [], {}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']"})
-        },
-        u'readstracker.threadrecord': {
-            'Meta': {'object_name': 'ThreadRecord'},
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'updated': ('django.db.models.fields.DateTimeField', [], {}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']"})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'threads.post': {
-            'Meta': {'object_name': 'Post'},
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'checkpoints': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'edit_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'edit_reason': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'edit_user_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edits': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'mentions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'mention_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'merge': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'post': ('django.db.models.fields.TextField', [], {}),
-            'post_preparsed': ('django.db.models.fields.TextField', [], {}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'reported': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'user_name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'threads.thread': {
-            'Meta': {'object_name': 'Thread'},
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last': ('django.db.models.fields.DateTimeField', [], {}),
-            'last_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'merges': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'replies': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_deleted': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_moderated': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_reported': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'score': ('django.db.models.fields.PositiveIntegerField', [], {'default': '30'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start': ('django.db.models.fields.DateTimeField', [], {}),
-            'start_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'start_poster': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'start_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'start_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'weight': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['readstracker']

+ 0 - 221
notrefactored/readstracker/migrations/0003_auto__del_record__add_forumrecord.py

@@ -1,221 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        db.rename_table('readstracker_record', 'readstracker_forumrecord')
-
-        db.create_index('readstracker_forumrecord', ['updated'])
-        db.create_index('readstracker_forumrecord', ['user_id', 'updated'])
-        db.create_index('readstracker_forumrecord', ['user_id', 'forum_id'])
-
-
-    def backwards(self, orm):
-        db.delete_index('readstracker_forumrecord', ['updated'])
-        db.delete_index('readstracker_forumrecord', ['user_id', 'updated'])
-        db.delete_index('readstracker_forumrecord', ['user_id', 'forum_id'])
-
-        db.rename_table('readstracker_forumrecord', 'readstracker_record')
-
-
-    models = {
-        u'forums.forum': {
-            'Meta': {'object_name': 'Forum'},
-            'attrs': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'description_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Thread']"}),
-            'last_thread_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_thread_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': u"orm['forums.Forum']"}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'posts_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'prune_last': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'prune_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'redirects': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirects_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'show_details': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads_delta': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'})
-        },
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'readstracker.forumrecord': {
-            'Meta': {'object_name': 'ForumRecord'},
-            'cleared': ('django.db.models.fields.DateTimeField', [], {}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'updated': ('django.db.models.fields.DateTimeField', [], {}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']"})
-        },
-        u'readstracker.threadrecord': {
-            'Meta': {'object_name': 'ThreadRecord'},
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'updated': ('django.db.models.fields.DateTimeField', [], {}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']"})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'threads.post': {
-            'Meta': {'object_name': 'Post'},
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'checkpoints': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'edit_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'edit_reason': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'edit_user_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edits': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'mentions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'mention_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'merge': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'post': ('django.db.models.fields.TextField', [], {}),
-            'post_preparsed': ('django.db.models.fields.TextField', [], {}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'reported': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'user_name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'threads.thread': {
-            'Meta': {'object_name': 'Thread'},
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last': ('django.db.models.fields.DateTimeField', [], {}),
-            'last_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'merges': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'replies': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_deleted': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_moderated': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_reported': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'score': ('django.db.models.fields.PositiveIntegerField', [], {'default': '30'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start': ('django.db.models.fields.DateTimeField', [], {}),
-            'start_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'start_poster': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'start_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'start_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'weight': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['readstracker']

+ 0 - 0
notrefactored/readstracker/migrations/__init__.py


+ 0 - 37
notrefactored/readstracker/models.py

@@ -1,37 +0,0 @@
-from datetime import timedelta
-from django.conf import settings
-from django.db import models
-from django.utils import timezone
-from misago.forums.signals import move_forum_content
-from misago.threads.signals import move_thread
-
-class ThreadRecord(models.Model):
-    user = models.ForeignKey('users.User')
-    forum = models.ForeignKey('forums.Forum')
-    thread = models.ForeignKey('threads.Thread')
-    updated = models.DateTimeField()
-    
-
-class ForumRecord(models.Model):
-    user = models.ForeignKey('users.User')
-    forum = models.ForeignKey('forums.Forum')
-    updated = models.DateTimeField()
-    cleared = models.DateTimeField()
-    
-    def get_threads(self):
-        threads = {}
-        for thread in ThreadRecord.objects.filter(user=self.user, forum=self.forum, updated__gte=(timezone.now() - timedelta(days=settings.READS_TRACKER_LENGTH))):
-            threads[thread.thread_id] = thread
-        return threads
-
-
-def move_forum_content_handler(sender, **kwargs):
-    ForumRecord.objects.filter(forum=sender).delete()
-
-move_forum_content.connect(move_forum_content_handler, dispatch_uid="move_forum_threads_reads")
-
-
-def move_thread_handler(sender, **kwargs):
-    ThreadRecord.objects.filter(thread=sender).delete()
-
-move_thread.connect(move_thread_handler, dispatch_uid="move_thread_reads")

+ 0 - 99
notrefactored/readstracker/trackers.py

@@ -1,99 +0,0 @@
-from datetime import timedelta
-from django.conf import settings
-from django.utils import timezone
-from misago.readstracker.models import ForumRecord, ThreadRecord
-from misago.threads.models import Thread
-
-class ForumsTracker(object):
-    def __init__(self, user):
-        self.user = user
-        self.cutoff = timezone.now() - timedelta(days=settings.READS_TRACKER_LENGTH)
-        self.forums = {}
-        if user.is_authenticated() and settings.READS_TRACKER_LENGTH > 0:
-            if user.join_date > self.cutoff:
-                self.cutoff = user.join_date
-            for forum in ForumRecord.objects.filter(user=user).filter(updated__gte=self.cutoff).values('id', 'forum_id', 'updated', 'cleared'):
-                 self.forums[forum['forum_id']] = forum
-
-    def is_read(self, forum):
-        if not self.user.is_authenticated() or not forum.last_thread_date:
-            return True
-        try:
-            return forum.last_thread_date <= self.cutoff or forum.last_thread_date <= self.forums[forum.pk]['cleared']
-        except KeyError:
-            return False
-
-
-class ThreadsTracker(object):
-    def __init__(self, request, forum):
-        self.need_create = None
-        self.need_update = None
-        self.request = request
-        self.forum = forum
-        self.cutoff = timezone.now() - timedelta(days=settings.READS_TRACKER_LENGTH)
-        if request.user.is_authenticated():
-            if request.user.join_date > self.cutoff:
-                self.cutoff = request.user.join_date
-            try:
-                self.record = ForumRecord.objects.get(user=request.user, forum=forum)
-                if self.record.cleared > self.cutoff:
-                    self.cutoff = self.record.cleared
-            except ForumRecord.DoesNotExist:
-                self.record = ForumRecord(user=request.user, forum=forum, cleared=self.cutoff)
-            self.threads = self.record.get_threads()
-
-    def get_read_date(self, thread):
-        if not self.request.user.is_authenticated():
-            return timezone.now()
-        try:
-            if self.threads[thread.pk].updated > self.cutoff:
-                return self.threads[thread.pk].updated
-        except KeyError:
-            pass
-        return self.cutoff
-
-    def is_read(self, thread):
-        if not self.request.user.is_authenticated():
-            return True
-        try:
-            return thread.last <= self.cutoff or thread.last <= self.threads[thread.pk].updated
-        except KeyError:
-            return False
-
-    def set_read(self, thread, post):
-        if self.request.user.is_authenticated() and post.date > self.cutoff:
-            try:
-                self.threads[thread.pk].updated = post.date
-                self.need_update = thread
-            except KeyError:
-                self.need_create = thread
-
-    def sync(self):
-        now = timezone.now()
-
-        if self.need_create:
-            new_record = ThreadRecord(
-                                      user=self.request.user,
-                                      thread=self.need_create,
-                                      forum=self.forum,
-                                      updated=now
-                                      )
-            new_record.save(force_insert=True)
-            self.threads[new_record.thread_id] = new_record
-
-        if self.need_update:
-            self.need_update.updated = now
-            self.need_update.save(force_update=True)
-
-        if self.need_create or self.need_update:
-            unread_threads = 0
-            for thread in self.request.acl.threads.filter_threads(self.request, self.forum, self.forum.thread_set.filter(last__gte=self.record.cleared)):
-                if not self.is_read(thread):
-                    unread_threads += 1
-            if not unread_threads:
-                self.record.cleared = now
-            self.record.updated = now
-            if self.record.pk:
-                self.record.save(force_update=True)
-            else:
-                self.record.save(force_insert=True)

+ 0 - 0
notrefactored/register/__init__.py


+ 0 - 102
notrefactored/register/fixtures.py

@@ -1,102 +0,0 @@
-from misago.settings.fixtures import load_settings_fixture, update_settings_fixture
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-settings_fixtures = (
-    # Register and Sign-In Settings
-    ('accounts', {
-        'name': _("Users Accounts Settings"),
-        'description': _("Those settings allow you to increase security of your members accounts."),
-        'settings': (
-            ('account_activation', {
-                'type':         "string",
-                'input':        "choice",
-                'extra':        {'choices': [('', _("No validation required")), ('user', _("Activation Token sent to User")), ('admin', _("Activation by Administrator")), ('block', _("Dont allow new registrations"))]},
-                'separator':    _("Users Registrations"),
-                'name':         _("New accounts validation"),
-            }),
-            ('default_timezone', {
-                'value':        "utc",
-                'type':         "string",
-                'input':        "select",
-                'extra':        {'choices': '#TZ#'},
-                'name':         _("Default Timezone"),
-                'description':  _("Used by guests, crawlers and newly registered users."),
-            }),
-            ('username_length_min', {
-                'value':        3,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 3},
-                'separator':    _("Users Names"),
-                'name':         _("Minimum allowed username length"),
-            }),
-            ('username_length_max', {
-                'value':        16,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 3},
-                'name':         _("Maxim allowed username length"),
-            }),
-            ('password_length', {
-                'value':        4,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 1},
-                'separator':    _("Users Passwords"),
-                'name':         _("Minimum user password length"),
-            }),
-            ('password_complexity', {
-                'value':        [],
-                'type':         "array",
-                'input':        "mlist",
-                'extra':        {'choices': [('case', _("Require mixed Case")), ('digits', _("Require digits")), ('special', _("Require special characters"))]},
-                'name':         _("Password Complexity"),
-            }),
-            ('password_lifetime', {
-                'value':        0,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'name':         _("Password Lifetime"),
-                'description':  _("Enter number of days since password was set to force member to change it with new one, or 0 to dont force your members to change their passwords."),
-            }),
-            ('password_in_email', {
-                'value':        False,
-                'type':         "boolean",
-                'input':        "yesno",
-                'name':         _("Include User Password in Welcoming E-mail"),
-                'description':  _("If you want to, Misago can include new user password in welcoming e-mail that is sent to new users after successful account creation."),
-            }),
-            ('subscribe_start', {
-                'value':        2,
-                'type':         "integer",
-                'input':        "select",
-                'extra':        {'choices': ((0, _("Don't watch")),
-                                             (1, _("Put on watched threads list")),
-                                             (2, _("Put on watched threads list and e-mail user when somebody replies")),
-                                             )},
-                'separator':    _("Default Watching Preferences"),
-                'name':         _("Watch threads user started"),
-            }),
-            ('subscribe_reply', {
-                'value':        2,
-                'type':         "integer",
-                'input':        "select",
-                'extra':        {'choices': ((0, _("Don't watch")),
-                                             (1, _("Put on watched threads list")),
-                                             (2, _("Put on watched threads list and e-mail user when somebody replies")),
-                                             )},
-                'name':         _("Watch threads user replied in"),
-            }),
-        ),
-    }),
-)
-
-
-def load_fixtures():
-    load_settings_fixture(settings_fixtures)
-    
-    
-def update_fixtures():
-    update_settings_fixture(settings_fixtures)

+ 0 - 81
notrefactored/register/forms.py

@@ -1,81 +0,0 @@
-from django import forms
-from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-from misago import captcha
-from misago.timezones import tzlist
-from misago.users.models import User
-from misago.users.validators import validate_username, validate_password, validate_email
-
-
-class UserRegisterForm(Form):
-    username = forms.CharField(max_length=15)
-    email = forms.EmailField(max_length=255)
-    email_rep = forms.EmailField(max_length=255)
-    password = forms.CharField(max_length=255,widget=forms.PasswordInput)
-    password_rep = forms.CharField(max_length=255,widget=forms.PasswordInput)
-    captcha_qa = captcha.QACaptchaField()
-    recaptcha = captcha.ReCaptchaField()
-    accept_tos = forms.BooleanField(required=True,error_messages={'required': _("Acceptation of board ToS is mandatory for membership.")})
-    
-    validate_repeats = (('email', 'email_rep'), ('password', 'password_rep'))
-    repeats_errors = [{
-                       'different': _("Entered addresses do not match."), 
-                       },
-                      {
-                       'different': _("Entered passwords do not match."),
-                       }]
-      
-    def finalize_form(self):
-        self.layout = [
-                      (
-                       None,
-                       [('username', {'label': _('Username'), 'help_text': _("Your displayed username. Between %(min)s and %(max)s characters, only letters and digits are allowed.") % {'min': self.request.settings['username_length_min'], 'max': self.request.settings['username_length_max']},'attrs': {'placeholder': _("Enter your desired username")}})]
-                       ),
-                      (
-                       None,
-                       [('nested', [('email', {'label': _('E-mail address'), 'help_text': _("Working e-mail inbox is required to maintain control over your forum account."), 'attrs': {'placeholder': _("Enter your e-mail")}, 'width': 50}), ('email_rep', {'attrs': {'placeholder': _("Repeat your e-mail")}, 'width': 50})]), 
-                       ('nested', [('password', {'label': _('Password'), 'help_text': _("Password you will be using to sign in to your account. Make sure it's strong."), 'has_value': False, 'attrs': {'placeholder': _("Enter your password")}, 'width': 50}), ('password_rep', {'has_value': False, 'attrs': {'placeholder': _("Repeat your password")}, 'width': 50})])]
-                       ),
-                      (
-                       None,
-                       ['captcha_qa', 'recaptcha']
-                       ),
-                      (
-                       None,
-                       [('accept_tos', {'label': _("Forum Terms of Service"), 'widget': 'forumTos'})]
-                       ),
-                      ]
-        
-        if not self.request.settings['tos_url'] and not self.request.settings['tos_content']:
-            del self.fields['accept_tos']
-            del self.layout[3]
-        
-    def clean_username(self):
-        validate_username(self.cleaned_data['username'], self.request.settings)
-        new_user = User.objects.get_blank_user()
-        new_user.set_username(self.cleaned_data['username'])
-        try:
-            new_user.full_clean()
-        except ValidationError as e:
-            new_user.is_username_valid(e)
-        return self.cleaned_data['username']
-        
-    def clean_email(self):
-        new_user = User.objects.get_blank_user()
-        new_user.set_email(self.cleaned_data['email'])
-        try:
-            new_user.full_clean()
-        except ValidationError as e:
-            new_user.is_email_valid(e)
-        return self.cleaned_data['email']
-        
-    def clean_password(self):
-        validate_password(self.cleaned_data['password'], self.request.settings)
-        new_user = User.objects.get_blank_user()
-        new_user.set_password(self.cleaned_data['password'])
-        try:
-            new_user.full_clean()
-        except ValidationError as e:
-            new_user.is_password_valid(e)
-        return self.cleaned_data['password']

+ 0 - 5
notrefactored/register/urls.py

@@ -1,5 +0,0 @@
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns('misago.register.views',
-    url(r'^$', 'form', name="register"),
-)

+ 0 - 88
notrefactored/register/views.py

@@ -1,88 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.banning.decorators import block_banned
-from misago.bruteforce.decorators import block_jammed
-from misago.bruteforce.models import SignInAttempt
-from misago.crawlers.decorators import block_crawlers
-from misago.forms.layouts import FormLayout
-from misago.messages import Message
-from misago.authn.decorators import block_authenticated
-from misago.authn.methods import sign_user_in
-from misago.register.forms import UserRegisterForm
-from misago.users.models import User
-from misago.views import redirect_message
-
-@block_crawlers
-@block_banned
-@block_authenticated
-@block_jammed
-def form(request):
-    if request.settings['account_activation'] == 'block':
-       return redirect_message(request, Message(_("We are sorry but we don't allow new members registrations at this time.")), 'info')
-    
-    message = None
-    if request.method == 'POST':
-        form = UserRegisterForm(request.POST, request=request)
-        if form.is_valid():
-            need_activation = 0
-            if request.settings['account_activation'] == 'user':
-                need_activation = User.ACTIVATION_USER
-            if request.settings['account_activation'] == 'admin':
-                need_activation = User.ACTIVATION_ADMIN
-                
-            new_user = User.objects.create_user(
-                                                form.cleaned_data['username'],
-                                                form.cleaned_data['email'],
-                                                form.cleaned_data['password'],
-                                                ip=request.session.get_ip(request),
-                                                agent=request.META.get('HTTP_USER_AGENT'),
-                                                activation=need_activation,
-                                                request=request
-                                                )
-                        
-            if need_activation == User.ACTIVATION_NONE:
-                # Sign in user
-                sign_user_in(request, new_user)
-                request.messages.set_flash(Message(_("Welcome aboard, %(username)s! Your account has been registered successfully.") % {'username': new_user.username}), 'success')
-                
-            if need_activation == User.ACTIVATION_USER:
-                # Mail user activation e-mail
-                request.messages.set_flash(Message(_("%(username)s, your account has been registered, but you will have to activate it before you will be able to sign-in. We have sent you an e-mail with activation link.") % {'username': new_user.username}), 'info')
-                new_user.email_user(
-                                    request,
-                                    'users/activation/user',
-                                    _("Welcome aboard, %(username)s!") % {'username': new_user.username},
-                                    )
-                
-            if need_activation == User.ACTIVATION_ADMIN:
-                # Require admin activation
-                request.messages.set_flash(Message(_("%(username)s, Your account has been registered, but you won't be able to sign in until board administrator accepts it. We'll notify when this happens. Thank you for your patience!") % {'username': new_user.username}), 'info')
-                new_user.email_user(
-                                    request,
-                                    'users/activation/admin',
-                                    _("Welcome aboard, %(username)s!") % {'username': new_user.username},
-                                    {'password': form.cleaned_data['password']}
-                                    )
-            
-            User.objects.resync_monitor(request.monitor)
-            return redirect(reverse('index'))
-        else:
-            message = Message(form.non_field_errors()[0], 'error')
-            if request.settings['registrations_jams']:
-                SignInAttempt.objects.register_attempt(request.session.get_ip(request))
-            # Have we jammed our account?
-            if SignInAttempt.objects.is_jammed(request.settings, request.session.get_ip(request)):
-                request.jam.expires = timezone.now()
-                return redirect(reverse('register'))
-    else:
-        form = UserRegisterForm(request=request)
-    return request.theme.render_to_response('register.html',
-                                            {
-                                             'message': message,
-                                             'form': FormLayout(form),
-                                             'hide_signin': True, 
-                                            },
-                                            context_instance=RequestContext(request));

+ 0 - 0
notrefactored/resetpswd/__init__.py


+ 0 - 34
notrefactored/resetpswd/forms.py

@@ -1,34 +0,0 @@
-import hashlib
-from django import forms
-from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-from misago import captcha
-from misago.users.models import User
-    
-    
-class UserResetPasswordForm(Form):
-    email = forms.EmailField(max_length=255)
-    captcha_qa = captcha.QACaptchaField()
-    recaptcha = captcha.ReCaptchaField()
-    error_source = 'email'
-    
-    layout = [
-              (
-               None,
-               [('email', {'label': _("Your E-mail Address"), 'help_text': _("Enter email address password reset confirmation e-mail will be sent to. It must be valid e-mail you used to register on forums."), 'attrs': {'placeholder': _("Enter your e-mail address.")}})]
-               ),
-              (
-               None,
-               ['captcha_qa', 'recaptcha']
-               ),
-              ]
-    
-    def clean_email(self):
-        try:
-            email = self.cleaned_data['email'].lower()
-            email_hash = hashlib.md5(email).hexdigest()
-            self.found_user = User.objects.get(email_hash=email_hash)
-        except User.DoesNotExist:
-            raise ValidationError(_("There is no user with such e-mail address."))
-        return email

+ 0 - 6
notrefactored/resetpswd/urls.py

@@ -1,6 +0,0 @@
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns('misago.resetpswd.views',
-    url(r'^$', 'form', name="forgot_password"),
-    url(r'^(?P<username>[a-z0-9]+)-(?P<user>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'reset', name="reset_password"),
-)

+ 0 - 94
notrefactored/resetpswd/views.py

@@ -1,94 +0,0 @@
-from django.template import RequestContext
-from django.utils.translation import ugettext as _
-from misago.banning.models import check_ban
-from misago.banning.decorators import block_banned
-from misago.banning.views import error_banned
-from misago.bruteforce.decorators import block_jammed
-from misago.crawlers.decorators import block_crawlers
-from misago.forms.layouts import FormLayout
-from misago.messages import Message
-from misago.authn.decorators import block_authenticated
-from misago.resetpswd.forms import UserResetPasswordForm
-from misago.users.models import User
-from misago.views import redirect_message, error404
-from misago.utils import get_random_string
-
-
-@block_crawlers
-@block_banned
-@block_authenticated
-@block_jammed   
-def form(request):
-    message = None
-    
-    if request.method == 'POST':
-        form = UserResetPasswordForm(request.POST, request=request)
-        
-        if form.is_valid():
-            user = form.found_user
-            user_ban = check_ban(username=user.username, email=user.email)
-            
-            if user_ban:
-                return error_banned(request, user, user_ban)
-            elif user.activation != User.ACTIVATION_NONE:
-                return redirect_message(request, Message(_("%(username)s, your account has to be activated in order for you to be able to request new password.") % {'username': user.username}), 'info')
-            
-            user.token = get_random_string(12)
-            user.save(force_update=True)
-            user.email_user(
-                            request,
-                            'users/password/confirm',
-                            _("Confirm New Password Request")
-                            )
-            
-            return redirect_message(request, Message(_("%(username)s, new password request confirmation has been sent to %(email)s.") % {'username': user.username, 'email': user.email}), 'info')
-        else:
-            message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = UserResetPasswordForm(request=request)
-    return request.theme.render_to_response('reset_password.html',
-                                            {
-                                             'message': message,
-                                             'form': FormLayout(form),
-                                            },
-                                            context_instance=RequestContext(request));
-
-
-@block_banned
-@block_authenticated
-@block_jammed
-def reset(request, username="", user="0", token=""):
-    user = int(user)
-    try:
-        user = User.objects.get(pk=user)
-        user_ban = check_ban(username=user.username, email=user.email)
-        
-        if user_ban:
-            return error_banned(request, user, user_ban)
-        
-        if user.activation != User.ACTIVATION_NONE:
-            return redirect_message(request, Message(_("%(username)s, your account has to be activated in order for you to be able to request new password.") % {'username': user.username}), 'info')
-        
-        if not token or not user.token or user.token != token:
-            return redirect_message(request, Message(_("%(username)s, request confirmation link is invalid. Please request new confirmation link.") % {'username': user.username}), 'error')
-        
-        new_password = get_random_string(6)
-        user.token = None
-        user.set_password(new_password)
-        user.save(force_update=True)
-        
-        # Logout signed in and kill remember me tokens
-        Session.objects.filter(user=user).update(user=None)
-        Token.objects.filter(user=user).delete()
-        
-        # Set flash and mail new password
-        user.email_user(
-                        request,
-                        'users/password/new',
-                        _("Your New Password"),
-                        {'password': new_password}
-                        )
-        
-        return redirect_message(request, Message(_("%(username)s, your password has been changed with new one that was sent to %(email)s.") % {'username': user.username, 'email': user.email}), 'success')
-    except User.DoesNotExist:
-        return error404(request)

+ 0 - 0
notrefactored/roles/__init__.py


+ 0 - 50
notrefactored/roles/fixtures.py

@@ -1,50 +0,0 @@
-from misago.roles.models import Role
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-def load_fixtures():
-    role = Role(name=_("Administrator").message, token='admin', protected=True)
-    role.set_permissions({
-                          'name_changes_allowed': 5,
-                          'changes_expire': 7,
-                          'can_use_acp': True,
-                          'can_use_signature': True,
-                          'allow_signature_links': True,
-                          'allow_signature_images': True,
-                          'can_search_users': True,
-                          'can_see_users_emails': True,
-                          'can_see_users_trails': True,
-                          'can_see_hidden_users': True,
-                          'forums': {5: 1, 6: 1, 7: 1},
-                          })
-    role.save(force_insert=True)
-    
-    role = Role(name=_("Moderator").message, token='mod', protected=True)
-    role.set_permissions({
-                          'name_changes_allowed': 3,
-                          'changes_expire': 14,
-                          'can_use_signature': True,
-                          'allow_signature_links': True,
-                          'can_search_users': True,
-                          'can_see_users_emails': True,
-                          'can_see_users_trails': True,
-                          'can_see_hidden_users': True,
-                          'forums': {5: 1, 6: 1, 7: 1},
-                          })
-    role.save(force_insert=True)
-    
-    role = Role(name=_("Registered").message, token='registered')
-    role.set_permissions({
-                          'name_changes_allowed': 2,
-                          'can_use_signature': False,
-                          'can_search_users': True,
-                          'forums': {5: 3, 6: 3, 7: 3},
-                          })
-    role.save(force_insert=True)
-    
-    role = Role(name=_("Guest").message, token='guest')
-    role.set_permissions({
-                          'can_search_users': True,
-                          'forums': {5: 6, 6: 6, 7: 6},
-                          })
-    role.save(force_insert=True)

+ 0 - 26
notrefactored/roles/forms.py

@@ -1,26 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.forms import Form, YesNoSwitch
-from misago.utils.validators import validate_sluggable
-
-class RoleForm(Form):
-    name = forms.CharField(max_length=255,validators=[validate_sluggable(
-                                                                         _("Role name must be sluggable."),
-                                                                         _("Role name is too long.")
-                                                                         )])
-    protected = forms.BooleanField(widget=YesNoSwitch,required=False)
-    
-    def finalize_form(self):
-        self.layout = [
-                       [
-                        _("Basic Role Options"),
-                        [
-                         ('name', {'label': _("Role Name"), 'help_text': _("Role Name is used to identify this role in Admin Control Panel.")}),
-                         ('protected', {'label': _("Protect this Role"), 'help_text': _("Only system administrators can edit or assign protected roles.")}),
-                         ],
-                        ],
-                       ]
-        
-        if not self.request.user.is_god():
-            del self.fields['protected']
-            del self.layout[0][1][1]

+ 0 - 38
notrefactored/roles/migrations/0001_initial.py

@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Role'
-        db.create_table(u'roles_role', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('token', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('protected', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('permissions', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-        ))
-        db.send_create_signal(u'roles', ['Role'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Role'
-        db.delete_table(u'roles_role')
-
-
-    models = {
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        }
-    }
-
-    complete_apps = ['roles']

+ 0 - 0
notrefactored/roles/migrations/__init__.py


+ 0 - 40
notrefactored/roles/models.py

@@ -1,40 +0,0 @@
-from django.db import models
-from django.utils.translation import ugettext as _
-import base64
-try:
-    import cPickle as pickle
-except ImportError:
-    import pickle
-
-class Role(models.Model):
-    """
-    Misago User Role model
-    """
-    name = models.CharField(max_length=255)
-    token = models.CharField(max_length=255,null=True,blank=True)
-    protected = models.BooleanField(default=False)
-    permissions = models.TextField(null=True,blank=True)
-    permissions_cache = {}
-    
-    def __unicode__(self):
-        return unicode(_(self.name))
-    
-    def is_special(self):
-        return token
-    
-    def get_permissions(self):
-        if self.permissions_cache:
-            return self.permissions_cache
-        
-        try:
-            self.permissions_cache = pickle.loads(base64.decodestring(self.permissions))
-        except Exception:
-            # ValueError, SuspiciousOperation, unpickling exceptions. If any of
-            # these happen, just return an empty dictionary (an empty permissions list).
-            self.permissions_cache = {}
-            
-        return self.permissions_cache
-    
-    def set_permissions(self, permissions):
-        self.permissions_cache = permissions
-        self.permissions = base64.encodestring(pickle.dumps(permissions, pickle.HIGHEST_PROTOCOL))

+ 0 - 261
notrefactored/roles/views.py

@@ -1,261 +0,0 @@
-import copy
-from django.core.urlresolvers import reverse as django_reverse
-from django.shortcuts import redirect
-from django.utils.translation import ugettext as _
-from misago.acl.builder import build_form 
-from misago.admin import site
-from misago.admin.widgets import *
-from misago.utils import slugify
-from misago.forms import Form, YesNoSwitch
-from misago.forums.models import Forum
-from misago.forumroles.models import ForumRole
-from misago.roles.forms import RoleForm
-from misago.roles.models import Role
-
-def reverse(route, target=None):
-    if target:
-        return django_reverse(route, kwargs={'target': target.pk, 'slug': slugify(target.name)})
-    return django_reverse(route)
-
-"""
-Views
-"""
-class List(ListWidget):
-    admin = site.get_action('roles')
-    id = 'list'
-    columns=(
-             ('role', _("Role")),
-             )
-    nothing_checked_message = _('You have to check at least one role.')
-    actions=(
-             ('delete', _("Delete selected roles"), _("Are you sure you want to delete selected roles?")),
-             )
-    
-    def sort_items(self, page_items, sorting_method):
-        return page_items.order_by('name')
-    
-    def get_item_actions(self, item):
-        return (
-                self.action('list', _("Forums Permissions"), reverse('admin_roles_masks', item)),
-                self.action('adjust', _("Role Permissions"), reverse('admin_roles_acl', item)),
-                self.action('pencil', _("Edit Role"), reverse('admin_roles_edit', item)),
-                self.action('remove', _("Delete Role"), reverse('admin_roles_delete', item), post=True, prompt=_("Are you sure you want to delete this role?")),
-                )
-
-    def action_delete(self, items, checked):
-        for item in items:
-            if unicode(item.pk) in checked:
-                if item.token:
-                    return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
-                if item.protected and not self.request.user.is_god():
-                    return Message(_('You cannot delete protected roles.'), 'error'), reverse('admin_roles')
-                if item.user_set.count() > 0:
-                    return Message(_('You cannot delete roles that are assigned to users.'), 'error'), reverse('admin_roles')
-        
-        Role.objects.filter(id__in=checked).delete()
-        return Message(_('Selected roles have been deleted successfully.'), 'success'), reverse('admin_roles')
-
-
-class New(FormWidget):
-    admin = site.get_action('roles')
-    id = 'new'
-    fallback = 'admin_roles' 
-    form = RoleForm
-    submit_button = _("Save Role")
-        
-    def get_new_url(self, model):
-        return reverse('admin_roles_new')
-    
-    def get_edit_url(self, model):
-        return reverse('admin_roles_edit', model)
-    
-    def submit_form(self, form, target):
-        new_role = Role(
-                      name = form.cleaned_data['name'],
-                     )
-        new_role.save(force_insert=True)
-        return new_role, Message(_('New Role has been created.'), 'success')    
-    
-   
-class Edit(FormWidget):
-    admin = site.get_action('roles')
-    id = 'edit'
-    name = _("Edit Role")
-    fallback = 'admin_roles'
-    form = RoleForm
-    target_name = 'name'
-    translate_target_name = True
-    notfound_message = _('Requested Role could not be found.')
-    submit_fallback = True
-    
-    def get_url(self, model):
-        return reverse('admin_roles_edit', model)
-    
-    def get_edit_url(self, model):
-        return self.get_url(model)
-    
-    def get_initial_data(self, model):
-        if self.request.user.is_god():
-            return {'name': model.name, 'protected': model.protected}
-        return {'name': model.name}
-    
-    def get_and_validate_target(self, target):
-        result = super(Edit, self).get_and_validate_target(target)
-        if result and result.protected and not self.request.user.is_god():
-            self.request.messages.set_flash(Message(_('Role "%(name)s" is protected, you cannot edit it.') % {'name': _(result.name)}), 'error', self.admin.id)
-            return None
-        return result
-    
-    def submit_form(self, form, target):
-        target.name = form.cleaned_data['name']
-        if self.request.user.is_god():
-            target.protected = form.cleaned_data['protected']
-        target.save(force_update=True)
-        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-        return target, Message(_('Changes in role "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
-
-
-class Forums(ListWidget):
-    admin = site.get_action('roles')
-    id = 'forums'
-    hide_actions = True
-    name = _('Role Forums Permissions')
-    table_form_button = _('Change Permissions')
-    empty_message = _('No forums are currently defined.')
-    template = 'forums'
-    
-    def get_url(self):
-        return reverse('admin_roles_masks', self.role) 
-    
-    def get_items(self):
-        return Forum.objects.get(token='root').get_descendants()
-    
-    def sort_items(self, page_items, sorting_method):
-        final_items = []
-        for forum in Forum.objects.filter(token__in=['annoucements', 'reports', 'private']).order_by('token'):
-            if forum.token == 'annoucements':
-                forum.name = _("Global Annoucements")
-            if forum.token == 'reports':
-                forum.name = _("Reports")
-            if forum.token == 'private':
-                forum.name = _("Private Discussions")
-            final_items.append(forum)
-        for forum in page_items.order_by('lft').all():
-            final_items.append(forum)
-        return final_items
-
-    def add_template_variables(self, variables):
-        variables['target'] = _(self.role.name)
-        return variables
-    
-    def get_table_form(self, page_items):
-        perms = {}
-        try:
-            forums = self.role.get_permissions()['forums']
-            for fid in forums:
-               perms[str(fid)] = str(forums[fid])
-        except KeyError:
-            pass
-        
-        perms_form = {}
-        roles_select = [("0", _("No Access"))]
-        for role in self.roles:
-            roles_select.append((str(role.pk), _(role.name)))
-
-        for item in page_items:
-            perms_form['forum_' + str(item.pk)] = forms.ChoiceField(choices=roles_select,initial=(perms[str(item.pk)] if str(item.pk) in perms else "0"))
-        
-        # Turn dict into object
-        return type('ChangeForumRolesForm', (Form,), perms_form)
-    
-    def table_action(self, page_items, cleaned_data):
-        perms = {}
-        for item in page_items:
-            if cleaned_data['forum_' + str(item.pk)] != "0":
-                perms[item.pk] = long(cleaned_data['forum_' + str(item.pk)])
-        role_perms = self.role.get_permissions()
-        role_perms['forums'] = perms
-        self.role.set_permissions(role_perms)
-        self.role.save(force_update=True)
-        return Message(_('Forum permissions have been saved.'), 'success'), self.get_url()
-        
-    def __call__(self, request, slug, target):
-        self.request = request
-        try:
-            self.role = Role.objects.get(id=target)
-            if self.role and self.role.protected and not request.user.is_god():
-                request.messages.set_flash(Message(_('Role "%(name)s" is protected, you cannot edit it.') % {'name': _(self.role.name)}), 'error', self.admin.id)
-                return redirect(reverse('admin_roles'))
-        except Role.DoesNotExist:
-            request.messages.set_flash(Message(_('Requested Role could not be found.')), 'error', self.admin.id)
-            return redirect(reverse('admin_roles'))
-        self.roles = ForumRole.objects.order_by('name').all()
-        if not self.roles:
-            request.messages.set_flash(Message(_('No forum roles are currently set.')), 'error', self.admin.id)
-            return redirect(reverse('admin_roles'))
-        return super(Forums, self).__call__(request)
-
-
-class ACL(FormWidget):
-    admin = site.get_action('roles')
-    id = 'acl'
-    name = _("Change Role Permissions")
-    fallback = 'admin_roles'
-    target_name = 'name'
-    translate_target_name = True
-    notfound_message = _('Requested Role could not be found.')
-    submit_fallback = True
-    template = 'acl_form'
-    
-    def get_form(self, target):
-        self.form = build_form(self.request, target)
-        return self.form
-    
-    def get_url(self, model):
-        return reverse('admin_roles_acl', model)
-    
-    def get_edit_url(self, model):
-        return self.get_url(model)
-    
-    def get_initial_data(self, model):
-        raw_acl = model.get_permissions()
-        initial = {}
-        for field in self.form.base_fields:
-            if field in raw_acl:
-                initial[field] = raw_acl[field]
-        return initial
-    
-    def get_and_validate_target(self, target):
-        result = super(ACL, self).get_and_validate_target(target)
-        if result and result.protected and not self.request.user.is_god():
-            self.request.messages.set_flash(Message(_('Role "%(name)s" is protected, you cannot edit it.') % {'name': _(result.name)}), 'error', self.admin.id)
-            return None
-        return result
-    
-    def submit_form(self, form, target):
-        raw_acl = target.get_permissions()
-        for perm in form.cleaned_data:
-            raw_acl[perm] = form.cleaned_data[perm]
-        target.set_permissions(raw_acl)
-        target.save(force_update=True)
-        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
-        
-        return target, Message(_('Role "%(name)s" permissions have been changed.') % {'name': self.original_name}, 'success')
-
-
-class Delete(ButtonWidget):
-    admin = site.get_action('roles')
-    id = 'delete'
-    fallback = 'admin_roles'
-    notfound_message = _('Requested Role could not be found.')
-    
-    def action(self, target):
-        if target.token:
-            return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
-        if target.protected and not self.request.user.is_god():
-            return Message(_('This role is protected.'), 'error'), reverse('admin_roles')
-        if target.user_set.count() > 0:
-            return Message(_('This role is assigned to one or more users.'), 'error'), reverse('admin_roles')
-
-        target.delete()
-        return Message(_('Role "%(name)s" has been deleted.') % {'name': _(target.name)}, 'success'), False

+ 0 - 85
notrefactored/search/__init__.py

@@ -1,85 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-class SearchException(Exception):
-    def __init__(self, message):
-        self.message = message
-
-
-class SearchQuery(object):
-    def __init__(self, raw_query=None):
-        """
-        Build search query object
-        """
-        if raw_query:
-            self.parse_query(raw_query)
-        
-    def parse_query(self, raw_query):
-        """
-        Parse raw search query into dict of lists of words that should be found and cant be found in string
-        """
-        self.criteria = {'+': [], '-': []}
-        for word in unicode(raw_query).split():
-            # Trim word and skip it if its empty
-            word = unicode(word).strip().lower()
-            if len(word) == 0:
-                pass
-            
-            # Find word mode
-            mode = '+'
-            if word[0] == '-':
-                mode = '-'
-                word = unicode(word[1:]).strip()
-                
-            # Strip extra crap
-            word = ''.join(e for e in word if e.isalnum())
-            
-            # Slice word?
-            if len(word) <= 3:
-                raise SearchException(_("One or more search phrases are shorter than four characters."))
-            if mode == '+':
-                if len(word) == 5:
-                    word = word[0:-1]
-                if len(word) == 6:
-                    word = word[0:-2]
-                if len(word) > 6:
-                    word = word[0:-3]
-            self.criteria[mode].append(word)
-            
-        # Complain that there are no positive matches
-        if not self.criteria['+'] and not self.criteria['-']:
-            raise SearchException(_("Search query is invalid."))
-    
-    def search(self, value):
-        """
-        See if value meets search criteria, return True for success and False otherwhise
-        """
-        try:
-            value = unicode(value).strip().lower()
-            # Search for only
-            if self.criteria['+'] and not self.criteria['-']:
-               return self.search_for(value)
-            # Search against only
-            if self.criteria['-'] and not self.criteria['+']:
-               return self.search_against(value)
-            # Search if contains for values but not against values
-            return self.search_for(value) and not self.search_against(value)
-        except AttributeError:
-            raise SearchException(_("You have to define search query before you will be able to search."))
-        
-    def search_for(self, value):
-        """
-        See if value is required
-        """
-        for word in self.criteria['+']:
-            if value.find(word) != -1:
-                return True
-        return False
-        
-    def search_against(self, value):
-        """
-        See if value is forbidden
-        """
-        for word in self.criteria['-']:
-            if value.find(word) != -1:
-                return True
-        return False

+ 0 - 0
notrefactored/sessions/__init__.py


+ 0 - 27
notrefactored/sessions/forms.py

@@ -1,27 +0,0 @@
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-
-class SearchSessionsForm(Form):
-    username = forms.CharField(max_length=255, required=False)
-    ip_address = forms.CharField(max_length=255, required=False)
-    useragent = forms.CharField(max_length=255, required=False)
-    type = forms.ChoiceField(choices=(
-                                      ('all', _("All types")),
-                                      ('registered', _("Registered Members Sessions")),
-                                      ('hidden', _("Hidden Sessions")),
-                                      ('guest', _("Guests Sessions")),
-                                      ('crawler', _("Crawler Sessions")),
-                                      ), required=False)
-
-    layout = (
-              (
-               _("Search Sessions"),
-               (
-                ('ip_address', {'label': _("IP Address"), 'attrs': {'placeholder': _("IP begins with...")}}),
-                ('username', {'label': _("Username"), 'attrs': {'placeholder': _("Username begings with...")}}),
-                ('useragent', {'label': _("User Agent"), 'attrs': {'placeholder': _("User Agent contains...")}}),
-                ('type', {'label': _("Session Type")}),
-               ),
-              ),
-             )

+ 0 - 0
notrefactored/sessions/management/__init__.py


+ 0 - 0
notrefactored/sessions/management/commands/__init__.py


+ 0 - 14
notrefactored/sessions/management/commands/clearsessions.py

@@ -1,14 +0,0 @@
-from datetime import timedelta
-from django.conf import settings
-from django.core.management.base import BaseCommand
-from django.utils import timezone
-from misago.sessions.models import Session
-
-class Command(BaseCommand):
-    """
-    This command is intended to work as CRON job fired every few hours to keep sessions table reasonable 
-    """
-    help = 'Clears users sessions'
-    def handle(self, *args, **options):
-        Session.objects.filter(last__lte=timezone.now() - timedelta(seconds=settings.SESSION_LIFETIME)).delete()
-        self.stdout.write('\nSessions have been cleared.\n')

+ 0 - 13
notrefactored/sessions/management/commands/cleartokens.py

@@ -1,13 +0,0 @@
-from datetime import timedelta
-from django.core.management.base import BaseCommand
-from django.utils import timezone
-from misago.sessions.models import Token
-
-class Command(BaseCommand):
-    """
-    This command is intended to work as CRON job fired every few days to remove unused tokens 
-    """
-    help = 'Clears "Remember Me" tokens'
-    def handle(self, *args, **options):
-        Token.objects.filter(accessed__lte=timezone.now() - timedelta(days=5)).delete()
-        self.stdout.write('\nSessions tokens have been cleared.\n')

+ 0 - 30
notrefactored/sessions/middleware.py

@@ -1,30 +0,0 @@
-from django.utils import timezone
-from misago.sessions.sessions import SessionCrawler, SessionHuman
-
-class SessionMiddleware(object):
-    def process_request(self, request):
-        try:
-            if request.user.is_crawler():
-                # Crawler Session
-                request.session = SessionCrawler(request)
-        except AttributeError:
-            # Human Session
-            request.session = SessionHuman(request)
-            request.user = request.session.get_user()
-
-            if request.user.is_authenticated():
-                request.session.set_hidden(request.user.hide_activity > 0)
-
-    def process_response(self, request, response):
-        try:
-            # Sync last visit date
-            if request.user.is_authenticated():
-                visit_sync = request.session.get('visit_sync')
-                if not visit_sync or (timezone.now() - visit_sync).seconds >= 900:
-                    request.session['visit_sync'] = timezone.now()
-                    request.user.last_date = timezone.now()
-                    request.user.save(force_update=True)
-            request.session.save()
-        except AttributeError:
-            pass
-        return response

+ 0 - 154
notrefactored/sessions/migrations/0001_initial.py

@@ -1,154 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Session'
-        db.create_table(u'sessions_session', (
-            ('id', self.gf('django.db.models.fields.CharField')(max_length=42, primary_key=True)),
-            ('data', self.gf('django.db.models.fields.TextField')(db_column='session_data')),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='sessions', null=True, on_delete=models.SET_NULL, to=orm['users.User'])),
-            ('crawler', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39)),
-            ('agent', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('start', self.gf('django.db.models.fields.DateTimeField')()),
-            ('last', self.gf('django.db.models.fields.DateTimeField')()),
-            ('team', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('rank', self.gf('django.db.models.fields.related.ForeignKey')(related_name='sessions', null=True, on_delete=models.SET_NULL, to=orm['ranks.Rank'])),
-            ('admin', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('matched', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('hidden', self.gf('django.db.models.fields.BooleanField')(default=False)),
-        ))
-        db.send_create_signal(u'sessions', ['Session'])
-
-        # Adding model 'Token'
-        db.create_table(u'sessions_token', (
-            ('id', self.gf('django.db.models.fields.CharField')(max_length=42, primary_key=True)),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='signin_tokens', to=orm['users.User'])),
-            ('created', self.gf('django.db.models.fields.DateTimeField')()),
-            ('accessed', self.gf('django.db.models.fields.DateTimeField')()),
-        ))
-        db.send_create_signal(u'sessions', ['Token'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Session'
-        db.delete_table(u'sessions_session')
-
-        # Deleting model 'Token'
-        db.delete_table(u'sessions_token')
-
-
-    models = {
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'sessions.session': {
-            'Meta': {'object_name': 'Session'},
-            'admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'crawler': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'data': ('django.db.models.fields.TextField', [], {'db_column': "'session_data'"}),
-            'hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'id': ('django.db.models.fields.CharField', [], {'max_length': '42', 'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'last': ('django.db.models.fields.DateTimeField', [], {}),
-            'matched': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sessions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['ranks.Rank']"}),
-            'start': ('django.db.models.fields.DateTimeField', [], {}),
-            'team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sessions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"})
-        },
-        u'sessions.token': {
-            'Meta': {'object_name': 'Token'},
-            'accessed': ('django.db.models.fields.DateTimeField', [], {}),
-            'created': ('django.db.models.fields.DateTimeField', [], {}),
-            'id': ('django.db.models.fields.CharField', [], {'max_length': '42', 'primary_key': 'True'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'signin_tokens'", 'to': u"orm['users.User']"})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['sessions']

+ 0 - 0
notrefactored/sessions/migrations/__init__.py


+ 0 - 22
notrefactored/sessions/models.py

@@ -1,22 +0,0 @@
-from django.db import models
-
-class Session(models.Model):
-    id = models.CharField(max_length=42, primary_key=True)
-    data = models.TextField(db_column="session_data")
-    user = models.ForeignKey('users.User', related_name='sessions', null=True, on_delete=models.SET_NULL)
-    crawler = models.CharField(max_length=255, blank=True, null=True)
-    ip = models.GenericIPAddressField()
-    agent = models.CharField(max_length=255)
-    start = models.DateTimeField()
-    last = models.DateTimeField()
-    team = models.BooleanField(default=False)
-    rank = models.ForeignKey('ranks.Rank', related_name='sessions', null=True, on_delete=models.SET_NULL)
-    admin = models.BooleanField(default=False)
-    matched = models.BooleanField(default=False)
-    hidden = models.BooleanField(default=False)
-
-class Token(models.Model):
-    id = models.CharField(max_length=42, primary_key=True)
-    user = models.ForeignKey('users.User', related_name='signin_tokens')
-    created = models.DateTimeField()
-    accessed = models.DateTimeField()

+ 0 - 247
notrefactored/sessions/sessions.py

@@ -1,247 +0,0 @@
-from datetime import timedelta
-from django.conf import settings
-from django.contrib.sessions.backends.base import SessionBase, CreateError
-from django.db.models.loading import cache as model_cache
-from django.utils import timezone
-from django.utils.crypto import salted_hmac
-from django.utils.encoding import force_unicode
-from misago.authn.methods import auth_remember, AuthException
-from misago.sessions.models import *
-from misago.users.models import Guest, User
-from misago.utils import get_random_string
-
-# Assert models are loaded
-if not model_cache.loaded:
-    model_cache.get_models()
-
-
-class IncorrectSessionException(Exception):
-    pass
-
-
-class SessionMisago(SessionBase):
-    """
-    Abstract class for sessions to inherit and extend
-    """
-    def _get_new_session_key(self):
-        return get_random_string(42)
-
-    def _get_session(self):
-        try:
-            return self._session_cache
-        except AttributeError:
-            self._session_cache = self.load()
-        return self._session_cache
-
-    def _hash(self, value):
-        key_salt = "misago.sessions" + self.__class__.__name__
-        return salted_hmac(key_salt, value).hexdigest()
-
-    def delete(self):
-        """We use sessions to track onlines so sorry, only sessions cleaner may delete sessions"""
-        pass
-
-    def flush(self):
-        """We use sessions to track onlines so sorry, only sessions cleaner may delete sessions"""
-        pass
-
-    def load(self):
-        return self.decode(force_unicode(self._session_rk.data))
-
-    def session_expired(self):
-        return False
-
-    def get_hidden(self):
-        return False
-
-    def set_hidden(self, hidden=False):
-        pass
-
-    def get_ip(self, request):
-        return request.META.get('HTTP_X_FORWARDED_FOR', '') or request.META.get('REMOTE_ADDR')
-
-    def set_user(self, user=None):
-        pass
-
-    def get_ban(self):
-        return False
-
-    def set_ban(self, ban):
-        return False
-
-    def save(self):
-        self._session_rk.data = self.encode(self._get_session())
-        self._session_rk.last = timezone.now()
-        self._session_rk.save(force_update=True)
-
-
-class SessionCrawler(SessionMisago):
-    """
-    Crawler Session controller
-    """
-    def __init__(self, request):
-        self.hidden = False
-        self.team = False
-        self._ip = self.get_ip(request)
-        try:
-            self._session_rk = Session.objects.get(crawler=request.user.username, ip=self._ip)
-            self._session_key = self._session_rk.id
-        except Session.DoesNotExist:
-            self.create(request)
-
-    def create(self, request):
-        while True:
-            try:
-                self._session_key = self._get_new_session_key()
-                self._session_rk = Session(
-                                         id=self._session_key,
-                                         data=self.encode({}),
-                                         crawler=request.user.username,
-                                         ip=self._ip,
-                                         agent=request.META.get('HTTP_USER_AGENT', ''),
-                                         start=timezone.now(),
-                                         last=timezone.now(),
-                                         matched=True
-                                         )
-                self._session_rk.save(force_insert=True)
-                break
-            except CreateError:
-                # Key wasn't unique. Try again.
-                continue
-
-    def human_session(self):
-        return False
-
-
-class SessionHuman(SessionMisago):
-    """
-    Human Session controller
-    """
-    def __init__(self, request):
-        self.expired = False
-        self.hidden = False
-        self.team = False
-        self.rank = None
-        self.remember_me = None
-        self._user = None
-        self._ip = self.get_ip(request)
-        self._session_token = None
-        if request.firewall.admin:
-            self._cookie_sid = settings.COOKIES_PREFIX + 'ASID'
-        else:
-            self._cookie_sid = settings.COOKIES_PREFIX + 'SID'
-        try:
-            # Do we have correct session ID?
-            if self._cookie_sid not in request.COOKIES or len(request.COOKIES[self._cookie_sid]) != 42:
-                raise IncorrectSessionException()
-            self._session_key = request.COOKIES[self._cookie_sid]
-            self._session_rk = Session.objects.select_related().get(
-                                                                    pk=self._session_key,
-                                                                    admin=request.firewall.admin
-                                                                    )
-            # IP invalid
-            if request.settings.sessions_validate_ip and self._session_rk.ip != self._ip:
-                raise IncorrectSessionException()
-            # Session expired
-            if timezone.now() - self._session_rk.last > timedelta(seconds=settings.SESSION_LIFETIME):
-                self.expired = True
-                raise IncorrectSessionException()
-            # Change session to matched and extract session user and hidden flag
-            self._session_rk.matched = True
-            self._user = self._session_rk.user
-            self.hidden = self._session_rk.hidden
-            self.team = self._session_rk.team
-        except (Session.DoesNotExist, IncorrectSessionException):
-            # Attempt autolog
-            try:
-                self.remember_me = auth_remember(request, self.get_ip(request))
-                self.create(request, user=self.remember_me.user)
-            except AuthException as e:
-                # Autolog failed
-                self.create(request)
-        self.id = self._session_rk.id
-
-        # Make cookie live longer
-        if request.firewall.admin:
-            request.cookie_jar.set('ASID', self._session_rk.id)
-        else:
-            request.cookie_jar.set('SID', self._session_rk.id)
-
-    def create(self, request, user=None):
-        self._user = user
-        while True:
-            try:
-                self._session_key = self._get_new_session_key()
-                self._session_rk = Session(
-                                         id=self._session_key,
-                                         data=self.encode({}),
-                                         user=self._user,
-                                         ip=self._ip,
-                                         agent=request.META.get('HTTP_USER_AGENT', ''),
-                                         start=timezone.now(),
-                                         last=timezone.now(),
-                                         admin=request.firewall.admin,
-                                         )
-                self._session_rk.save(force_insert=True)
-                if user:
-                    # Update user data
-                    user.set_last_visit(
-                                        self.get_ip(request),
-                                        request.META.get('HTTP_USER_AGENT', ''),
-                                        hidden=self.hidden
-                                        )
-                    user.save(force_update=True)
-                break
-            except CreateError:
-                # Key wasn't unique. Try again.
-                continue
-
-    def save(self):
-        self._session_rk.user = self._user
-        self._session_rk.hidden = self.hidden
-        self._session_rk.team = self.team
-        self._session_rk.rank_id = self.rank
-        super(SessionHuman, self).save()
-
-    def human_session(self):
-        return True
-
-    def session_expired(self):
-        return self.expired
-
-    def get_user(self):
-        if self._user == None:
-            return Guest()
-        return self._user
-
-    def set_user(self, user=None):
-        self._user = user
-
-    def sign_out(self, request):
-        try:
-            if self._user.is_authenticated():
-                if not request.firewall.admin:
-                    cookie_token = settings.COOKIES_PREFIX + 'TOKEN'
-                    if cookie_token in request.COOKIES:
-                        if len(request.COOKIES[cookie_token]) > 0:
-                            Token.objects.filter(id=request.COOKIES[cookie_token]).delete()
-                        request.cookie_jar.delete('TOKEN')
-                self.hidden = False
-                self._user = None
-                request.user = Guest()
-        except AttributeError:
-            pass
-
-    def get_hidden(self):
-        return self.hidden
-
-    def set_hidden(self, hidden=False):
-        self.hidden = hidden
-
-
-class SessionMock(object):
-    def get_ip(self, request):
-        try:
-            return self.ip
-        except AttributeError:
-            return '127.0.0.1'

+ 0 - 45
notrefactored/sessions/views.py

@@ -1,45 +0,0 @@
-from django.utils.translation import ugettext as _
-from misago.admin import site
-from misago.admin.widgets import ListWidget
-from misago.sessions.forms import SearchSessionsForm
-
-class List(ListWidget):
-    admin = site.get_action('online')
-    id = 'list'
-    columns = (
-               ('owner', _("Session Owner")),
-               ('start', _("Session Start"), 25),
-               ('last', _("Last Click"), 25),
-               )
-    default_sorting = 'start'
-    sortables = {
-                 'start': 0,
-                 'last': 0,
-                }
-    hide_actions = True
-    pagination = 50
-    search_form = SearchSessionsForm
-    empty_message = _('Looks like nobody is currently online on forums.')
-
-    def set_filters(self, model, filters):
-        if 'username' in filters:
-            model = model.filter(user__username__istartswith=filters['username'])
-        if 'ip_address' in filters:
-            model = model.filter(ip__startswith=filters['ip_address'])
-        if 'useragent' in filters:
-            model = model.filter(agent__icontains=filters['useragent'])
-        if filters['type'] == 'registered':
-            model = model.filter(user__isnull=False)
-        if filters['type'] == 'hidden':
-            model = model.filter(hidden=True)
-        if filters['type'] == 'guest':
-            model = model.filter(user__isnull=True)
-        if filters['type'] == 'crawler':
-            model = model.filter(crawler__isnull=False)
-        return model
-
-    def prefetch_related(self, items):
-        return items.prefetch_related('user')
-
-    def select_items(self, items):
-        return items.filter(matched=1).filter(admin=0)

+ 0 - 0
notrefactored/settings/__init__.py


+ 0 - 7
notrefactored/settings/context_processors.py

@@ -1,7 +0,0 @@
-def settings(request):
-    try:
-        return {
-            'settings' : request.settings,
-        }
-    except AttributeError:
-        return {}

+ 0 - 146
notrefactored/settings/fixtures.py

@@ -1,146 +0,0 @@
-import base64
-from misago.settings.models import Group, Setting
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-try:
-    import cPickle as pickle
-except ImportError:
-    import pickle
-
-settings_fixture = (
-   # Basic options
-   ('basic', {
-        'name': _("Basic Settings"),
-        'settings': (
-            ('board_name', {
-                'value':        "Misago",
-                'type':         "string",
-                'input':        "text",
-                'separator':    _("Board Name"),
-                'name':         _("Board Name"),
-            }),
-            ('board_header', {
-                'type':         "string",
-                'input':        "text",
-                'name':         _("Board Header"),
-                'description':  _("Some themes allow you to define text in board header. Leave empty to use Board Name instead."),
-            }),
-            ('board_header_postscript', {
-                'value':        "Work in progress",
-                'type':         "string",
-                'input':        "text",
-                'name':         _("Board Header Postscript"),
-                'description':  _("Additional text displayed in some themes board header after board name."),
-            }),
-            ('board_index_title', {
-                'type':         "string",
-                'input':        "text",
-                'separator':    _("Board Index"),
-                'name':         _("Board Index Title"),
-                'description':  _("If you want to, you can replace page title content on Board Index with custom one."),
-            }),
-            ('board_index_meta', {
-                'type':         "string",
-                'input':        "text",
-                'name':         _("Board Index Meta-Description"),
-                'description':  _("Meta-Description used to describe your board's index page."),
-            }),
-            ('board_credits', {
-                'type':         "string",
-                'input':        "textarea",
-                'separator':    _("Board Footer"),
-                'name':         _("Custom Credit"),
-                'description':  _("Custom Credit to display in board footer above software and theme copyright information. You can use HTML."),
-            }),
-            ('email_footnote', {
-                'type':         "string",
-                'input':        "textarea",
-                'separator':    _("Board E-Mails"),
-                'name':         _("Custom Footnote in HTML E-mails"),
-                'description':  _("Custom Footnote to display in HTML e-mail messages sent by board."),
-            }),
-            ('email_footnote_plain', {
-                'type':         "string",
-                'input':        "textarea",
-                'name':         _("Custom Footnote in plain text E-mails"),
-                'description':  _("Custom Footnote to display in plain text e-mail messages sent by board."),
-            }),
-        ),
-   }),
-)
-
-
-def load_settings_group_fixture(group, fixture):
-    model_group = Group(
-                        key=group,
-                        name=get_msgid(fixture['name']),
-                        description=get_msgid(fixture.get('description'))
-                        )
-    model_group.save(force_insert=True)
-    fixture = fixture.get('settings', ())
-    position = 0
-    for setting in fixture:
-        value = setting[1].get('value')
-        value_default = setting[1].get('default')
-        # Convert boolean True and False to 1 and 0, otherwhise it wont work
-        if setting[1].get('type') == 'boolean':
-            value = 1 if value else 0
-            value_default = 1 if value_default else 0
-        # Convert array value to string
-        if setting[1].get('type') == 'array':
-            value = ','.join(value) if value else ''
-            value_default = ','.join(value_default) if value_default else ''
-        # Store setting in database
-        model_setting = Setting(
-                                setting=setting[0],
-                                group=model_group,
-                                value=value,
-                                value_default=value_default,
-                                type=setting[1].get('type'),
-                                input=setting[1].get('input'),
-                                extra=base64.encodestring(pickle.dumps(setting[1].get('extra', {}), pickle.HIGHEST_PROTOCOL)),
-                                position=position,
-                                separator=get_msgid(setting[1].get('separator')),
-                                name=get_msgid(setting[1].get('name')),
-                                description=get_msgid(setting[1].get('description')),
-                            )
-        model_setting.save(force_insert=True)
-        position += 1
-
-
-def update_settings_group_fixture(group, fixture):
-    try:
-        model_group = Group.objects.get(key=group)
-        settings = {}
-        for setting in model_group.setting_set.all():
-            settings[setting.pk] = setting.value
-        model_group.delete()
-        load_settings_group_fixture(group, fixture)
-
-        for setting in settings:
-            try:
-                new_setting = Setting.objects.get(pk=setting)
-                new_setting.value = settings[setting]
-                new_setting.save(force_update=True)
-            except Setting.DoesNotExist:
-                pass
-    except Group.DoesNotExist:
-        load_settings_group_fixture(group, fixture)
-
-
-def load_settings_fixture(fixture):
-    for group in fixture:
-        load_settings_group_fixture(group[0], group[1])
-
-
-def update_settings_fixture(fixture):
-    for group in fixture:
-        update_settings_group_fixture(group[0], group[1])
-
-
-def load_fixtures():
-    load_settings_fixture(settings_fixture)
-
-
-def update_fixtures():
-    update_settings_fixture(settings_fixture)

+ 0 - 5
notrefactored/settings/forms.py

@@ -1,5 +0,0 @@
-from django import forms
-from misago.forms import Form
-
-class SearchForm(Form):
-    search_text = forms.CharField(max_length=255)

+ 0 - 5
notrefactored/settings/middleware.py

@@ -1,5 +0,0 @@
-from misago.settings.settings import Settings
-
-class SettingsMiddleware(object):
-    def process_request(self, request):
-        request.settings = Settings()

+ 0 - 69
notrefactored/settings/migrations/0001_initial.py

@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Group'
-        db.create_table(u'settings_group', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('key', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-        ))
-        db.send_create_signal(u'settings', ['Group'])
-
-        # Adding model 'Setting'
-        db.create_table(u'settings_setting', (
-            ('setting', self.gf('django.db.models.fields.CharField')(max_length=255, primary_key=True)),
-            ('group', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['settings.Group'], to_field='key')),
-            ('value', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('value_default', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('type', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('input', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('extra', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('position', self.gf('django.db.models.fields.IntegerField')(default=0)),
-            ('separator', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-        ))
-        db.send_create_signal(u'settings', ['Setting'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Group'
-        db.delete_table(u'settings_group')
-
-        # Deleting model 'Setting'
-        db.delete_table(u'settings_setting')
-
-
-    models = {
-        u'settings.group': {
-            'Meta': {'object_name': 'Group'},
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'settings.setting': {
-            'Meta': {'object_name': 'Setting'},
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'extra': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['settings.Group']", 'to_field': "'key'"}),
-            'input': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'position': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'separator': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'setting': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
-            'type': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'value_default': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
-        }
-    }
-
-    complete_apps = ['settings']

+ 0 - 0
notrefactored/settings/migrations/__init__.py


+ 0 - 144
notrefactored/settings/models.py

@@ -1,144 +0,0 @@
-import base64
-from django import forms
-from django.core import validators
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import YesNoSwitch
-from misago.timezones import tzlist
-try:
-    import cPickle as pickle
-except ImportError:
-    import pickle
-
-class Group(models.Model):
-    key = models.CharField(max_length=255, unique=True)
-    name = models.CharField(max_length=255)
-    description = models.TextField(null=True, blank=True)
-
-    def is_active(self, active_group):
-        try:
-            return self.pk == active_group.pk
-        except AttributeError:
-            return False
-
-class Setting(models.Model):
-    setting = models.CharField(max_length=255, primary_key=True)
-    group = models.ForeignKey('Group', to_field='key')
-    value = models.TextField(null=True, blank=True)
-    value_default = models.TextField(null=True, blank=True)
-    type = models.CharField(max_length=255)
-    input = models.CharField(max_length=255)
-    extra = models.TextField(null=True, blank=True)
-    position = models.IntegerField(default=0)
-    separator = models.CharField(max_length=255, null=True, blank=True)
-    name = models.CharField(max_length=255)
-    description = models.TextField(null=True, blank=True)
-
-    def get_extra(self):
-        return pickle.loads(base64.decodestring(self.extra))
-
-    def get_value(self):
-        if self.type == 'array':
-            return self.value.split(',')
-        if self.type == 'integer':
-            return int(self.value)
-        if self.type == 'float':
-            return float(self.value)
-        if self.type == 'boolean':
-            return self.value == "1"
-        return self.value
-
-    def set_value(self, value):
-        if self.type == 'array':
-            self.value = ','.join(value)
-        elif self.type == 'integer':
-            self.value = int(value)
-        elif self.type == 'float':
-            self.value = float(value)
-        elif self.type == 'boolean':
-            self.value = 1 if value else 0
-        else:
-            self.value = value
-        if not self.value and self.value_default:
-            self.value = self.value_default
-        return self.value
-
-    def get_field(self):
-        extra = self.get_extra()
-
-        # Set validators
-        field_validators = []
-        if 'min' in extra:
-            if self.type == 'string' or self.type == 'array':
-                field_validators.append(validators.MinLengthValidator(extra['min']))
-            if self.type == 'integer' or self.type == 'float':
-                field_validators.append(validators.MinValueValidator(extra['min']))
-        if 'max' in extra:
-            if self.type == 'string' or self.type == 'array':
-                field_validators.append(validators.MaxLengthValidator(extra['max']))
-            if self.type == 'integer' or self.type == 'float':
-                field_validators.append(validators.MaxValueValidator(extra['max']))
-
-        # Yes-no
-        if self.input == 'yesno':
-            return forms.BooleanField(
-                                   initial=self.get_value(),
-                                   label=_(self.name),
-                                   help_text=_(self.description) if self.description else None,
-                                   required=False,
-                                   widget=YesNoSwitch,
-                                   )
-
-        # Multi-list
-        if self.input == 'mlist':
-            return forms.MultipleChoiceField(
-                                     initial=self.get_value(),
-                                     label=_(self.name),
-                                     help_text=_(self.description) if self.description else None,
-                                     widget=forms.CheckboxSelectMultiple,
-                                     validators=field_validators,
-                                     required=False,
-                                     choices=extra['choices']
-                                     )
-
-        # Select or choice
-        if self.input == 'select' or self.input == 'choice':
-            # Timezone list?
-            if extra['choices'] == '#TZ#':
-                extra['choices'] = tzlist()
-            return forms.ChoiceField(
-                                     initial=self.get_value(),
-                                     label=_(self.name),
-                                     help_text=_(self.description) if self.description else None,
-                                     widget=forms.RadioSelect if self.input == 'choice' else forms.Select,
-                                     validators=field_validators,
-                                     required=False,
-                                     choices=extra['choices']
-                                     )
-
-        # Textarea
-        if self.input == 'textarea':
-            return forms.CharField(
-                                   initial=self.get_value(),
-                                   label=_(self.name),
-                                   help_text=_(self.description) if self.description else None,
-                                   validators=field_validators,
-                                   required=False,
-                                   widget=forms.Textarea
-                                   )
-
-        # Default input
-        default_input = forms.CharField
-        if self.type == 'integer':
-            default_input = forms.IntegerField
-        if self.type == 'float':
-            default_input = forms.FloatField
-
-        # Make text-input
-        return default_input(
-                             initial=self.get_value(),
-                             label=_(self.name),
-                             help_text=_(self.description) if self.description else None,
-                             validators=field_validators,
-                             required=False,
-                             )

+ 0 - 71
notrefactored/settings/settings.py

@@ -1,71 +0,0 @@
-from django.db.utils import DatabaseError
-from django.core.cache import cache
-from misago.settings.models import Setting
-
-class Settings(object):
-    def __init__(self):
-        self._settings = {}
-        self._models = {}
-        self.refresh()
-
-    def refresh(self):
-        self._models = cache.get('settings')
-        if not self._models:
-            self._models = {}
-            try:
-                for i in Setting.objects.all():
-                    self._models[i.pk] = i
-                    self._settings[i.pk] = i.get_value()
-                cache.set('settings', self._models)
-            except DatabaseError:
-                pass
-        else:
-            for i, model in self._models.items():
-                self._settings[i] = model.get_value()
-
-    def __getattr__(self, key):
-        return self._settings[key]
-
-    def __contains__(self, key):
-        return key in self._settings.keys()
-
-    def __getitem__(self, key):
-        return self._settings[key]
-
-    def __setitem__(self, key, value):
-        if key in self._settings.keys():
-            self._models[key].set_value(value)
-            self._models[key].save(force_update=True)
-            self._settings[key] = value
-            cache.set('settings', self._models)
-        return value
-
-    def __delitem__(self, key):
-        pass
-
-    def get(self, key, default=None):
-        try:
-            return self._settings[key]
-        except KeyError:
-            return None
-
-    def has_key(self, key):
-        return key in self._settings.keys()
-
-    def keys(self):
-        return self._settings.keys()
-
-    def values(self):
-        return self._settings.values()
-
-    def items(self):
-        return self._settings.items()
-
-    def iterkeys(self):
-        return self._settings.iterkeys()
-
-    def itervalues(self):
-        return self._settings.itervalues()
-
-    def iteritems(self):
-        return self._settings.iteritems()

+ 0 - 115
notrefactored/settings/views.py

@@ -1,115 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils.translation import ungettext, ugettext as _
-from misago.forms import Form
-from misago.forms.layouts import FormLayout, FormFields
-from misago.messages import Message
-from misago.search import SearchQuery, SearchException
-from misago.settings.forms import SearchForm
-from misago.settings.models import Group, Setting
-from misago.views import error404
-
-def settings(request, group_id=None, group_slug=None):
-    # Load groups and find selected group
-    settings_groups = Group.objects.all().order_by('key')
-    if not group_id:
-        active_group = settings_groups[0]
-        group_id = active_group.pk
-    else:
-        group_id = int(group_id)
-        for group in settings_groups:
-            if group.pk == group_id:
-                active_group = group
-                break
-        else:
-            return error404(request, _('The requested settings group could not be found.'))
-
-    # Load selected group settings and turn them into form
-    group_settings = Setting.objects.filter(group=active_group).order_by('position')
-    last_fieldset = (None, [])
-    group_form = {'layout': []}
-    for setting in group_settings:
-        # New field subgroup?
-        if setting.separator and last_fieldset[0] != setting.separator:
-            if last_fieldset[0]:
-                group_form['layout'].append(last_fieldset)
-            last_fieldset = (_(setting.separator), [])
-        last_fieldset[1].append(setting.pk)
-        group_form[setting.pk] = setting.get_field()
-    group_form['layout'].append(last_fieldset)
-    SettingsGroupForm = type('SettingsGroupForm', (Form,), group_form)
-
-    #Submit form
-    message = request.messages.get_message('admin_settings')
-    if request.method == 'POST':
-        form = SettingsGroupForm(request.POST, request=request)
-        if form.is_valid():
-            for setting in form.cleaned_data.keys():
-                request.settings[setting] = form.cleaned_data[setting]
-            request.messages.set_flash(Message(_('Configuration have been saved.')), 'success', 'admin_settings')
-            return redirect(reverse('admin_settings', kwargs={
-                                                       'group_id': active_group.pk,
-                                                       'group_slug': active_group.key,
-                                                       }))
-        else:
-            message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = SettingsGroupForm(request=request)
-
-    # Display settings group form      
-    return request.theme.render_to_response('settings/settings.html',
-                                            {
-                                            'message': message,
-                                            'groups': settings_groups,
-                                            'active_group': active_group,
-                                            'search_form': FormFields(SearchForm(request=request)),
-                                            'form': FormLayout(form),
-                                            'raw_form': form,
-                                            },
-                                            context_instance=RequestContext(request));
-
-
-def settings_search(request):
-    settings_groups = Group.objects.all().order_by('key')
-    message = None
-    found_settings = []
-    try:
-        if request.method == 'POST' and request.csrf.request_secure(request):
-            form = SearchForm(request.POST, request=request)
-            if form.is_valid():
-                # Start search
-                search_strings = SearchQuery(form.cleaned_data['search_text'])
-
-                # Loop over groups using our search query
-                for setting in Setting.objects.all().order_by('setting'):
-                    if (search_strings.search(_(setting.name))
-                        or (setting.description and search_strings.search(_(setting.description)))
-                        or (setting.value and search_strings.search(setting.value))):
-                        found_settings.append(setting)
-
-                # Scream if nothing could be found
-                if found_settings:
-                    message = Message(ungettext(
-                                                    'One setting that match search criteria has been found.',
-                                                    '%(count)d settings that match search criteria have been found.',
-                                                len(found_settings)) % {
-                                                    'count': len(found_settings),
-                                                }, 'success')
-                else:
-                    raise SearchException(_('No settings that match search criteria has been found.'))
-            else:
-                raise SearchException(_('Search query is empty.'))
-        else:
-            raise SearchException(_('Search query is invalid.'))
-    except SearchException as e:
-        message = Message(e.message, 'error')
-    return request.theme.render_to_response('settings/search_results.html',
-                                    {
-                                    'message': message,
-                                    'groups': settings_groups,
-                                    'active_group': None,
-                                    'found_settings': found_settings,
-                                    'search_form': FormFields(form),
-                                    },
-                                    context_instance=RequestContext(request));

+ 0 - 0
notrefactored/setup/__init__.py


+ 0 - 34
notrefactored/setup/fixtures.py

@@ -1,34 +0,0 @@
-from django.utils.importlib import import_module
-
-def load_app_fixtures(app):
-    """
-    See if application has fixtures module defining load_fixtures function
-    If it does, execute that function
-    """
-    app += '.fixtures'
-    try:
-        fixture = import_module(app)
-        fixture.load_fixtures()
-        return True
-    except (ImportError, AttributeError):
-        return False
-    except Exception as e:
-        print 'Could not load fixtures from %s:\n%s' % (app, e)
-        return False
-
-
-def update_app_fixtures(app):
-    """
-    See if application has fixtures module defining update_fixtures function
-    If it does, execute that function
-    """
-    app += '.fixtures'
-    try:
-        fixture = import_module(app)
-        fixture.update_fixtures()
-        return True
-    except (ImportError, AttributeError):
-        return False
-    except Exception as e:
-        print 'Could not update fixtures from %s:\n%s' % (app, e)
-        return False

+ 0 - 0
notrefactored/setup/management/__init__.py


+ 0 - 0
notrefactored/setup/management/commands/__init__.py


+ 0 - 37
notrefactored/setup/management/commands/about.py

@@ -1,37 +0,0 @@
-from django.core.management.base import BaseCommand, CommandError
-from django.utils import timezone
-from misago import get_version
-
-class Command(BaseCommand):
-    """
-    Displays version number and license
-    """
-    help = 'Displays Misago Credits'
-    def handle(self, *args, **options):
-        self.stdout.write('\n')
-        self.stdout.write('                                    _\n')
-        self.stdout.write('                         ____ ___  (_)________  ____  ____ \n')
-        self.stdout.write('                        / __ `__ \/ / ___/ __ `/ __ `/ __ \ \n')
-        self.stdout.write('                       / / / / / / (__  ) /_/ / /_/ / /_/ / \n')
-        self.stdout.write('                      /_/ /_/ /_/_/____/\__,_/\__, /\____/ \n')
-        self.stdout.write('                                             /____/\n')
-        self.stdout.write('\n')
-        self.stdout.write('                    Your community is powered by Misago v.%s' % get_version())
-        self.stdout.write('\n              For help and feedback visit http://misago-project.org')
-        self.stdout.write('\n\n')
-        self.stdout.write('================================================================================')
-        self.stdout.write('\n\n')
-        self.stdout.write('Copyright (C) %s, Rafal Piton' % timezone.now().year)
-        self.stdout.write('\n')
-        self.stdout.write('\nThis program is free software; you can redistribute it and/or modify it under')
-        self.stdout.write('\nthe terms of the GNU General Public License version 3 as published by')
-        self.stdout.write('\nthe Free Software Foundation')
-        self.stdout.write('\n')
-        self.stdout.write('\nThis program is distributed in the hope that it will be useful, but')
-        self.stdout.write('\nWITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY')
-        self.stdout.write('\nor FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License')
-        self.stdout.write('\nfor more details.')
-        self.stdout.write('\n')
-        self.stdout.write('\nYou should have received a copy of the GNU General Public License along')
-        self.stdout.write('\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.')
-        self.stdout.write('\n\n')

+ 0 - 47
notrefactored/setup/management/commands/initdata.py

@@ -1,47 +0,0 @@
-from django.conf import settings
-from django.core.management.base import BaseCommand, CommandError
-from django.db import (connections, router, transaction, DEFAULT_DB_ALIAS,
-      IntegrityError, DatabaseError)
-from django.utils import timezone
-from misago.setup.fixtures import load_app_fixtures, update_app_fixtures
-from misago.setup.models import Fixture
-from optparse import make_option
-
-class Command(BaseCommand):
-    """
-    Loads Misago fixtures
-    """
-    help = 'Load Misago fixtures'
-    option_list = BaseCommand.option_list + (
-        make_option('--quiet',
-            action='store_true',
-            dest='quiet',
-            default=False,
-            help='Dont display output from this message'),
-        )
-    
-    def handle(self, *args, **options):
-        if not options['quiet']:
-            self.stdout.write('\nLoading data from fixtures...')
-            
-        fixture_data = {}
-        for fixture in Fixture.objects.all():
-            fixture_data[fixture.app_name] = fixture
-        loaded = 0
-        updated = 0
-        
-        for app in settings.INSTALLED_APPS_COMPLETE:
-            if app in fixture_data:
-                if update_app_fixtures(app):
-                    updated += 1
-                    if not options['quiet']:
-                        self.stdout.write('Updating fixtures from %s' % app)
-            else:
-                if load_app_fixtures(app):
-                    loaded += 1
-                    Fixture.objects.create(app_name=app)
-                    if not options['quiet']:
-                        self.stdout.write('Loading fixtures from %s' % app)
-        
-        if not options['quiet']:
-            self.stdout.write('\nLoaded %s fixtures and updated %s fixtures.\n' % (loaded, updated))

+ 0 - 15
notrefactored/setup/management/commands/initmisago.py

@@ -1,15 +0,0 @@
-from django.core.management import call_command
-from django.core.management.base import BaseCommand, CommandError
-
-class Command(BaseCommand):
-    """
-    Builds Misago database from scratch
-    """
-    help = 'Install Misago to database'
-    
-    def handle(self, *args, **options):
-        self.stdout.write('\nInstalling Misago to database...')
-        call_command('syncdb')
-        call_command('migrate')
-        call_command('initdata')
-        self.stdout.write('\nInstallation complete! Don\'t forget to run adduser to create first admin!\n')

+ 0 - 14
notrefactored/setup/management/commands/updmisago.py

@@ -1,14 +0,0 @@
-from django.core.management import call_command
-from django.core.management.base import BaseCommand, CommandError
-
-class Command(BaseCommand):
-    """
-    Updates Misago to latest version
-    """
-    help = 'Update Misago database to latest version'
-    
-    def handle(self, *args, **options):
-        self.stdout.write('\nUpdating Misago database to latest version...')
-        call_command('migrate')
-        call_command('initdata')
-        self.stdout.write('\nUpdate complete!\n')

+ 0 - 32
notrefactored/setup/migrations/0001_initial.py

@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Fixture'
-        db.create_table(u'setup_fixture', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('app_name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-        ))
-        db.send_create_signal(u'setup', ['Fixture'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Fixture'
-        db.delete_table(u'setup_fixture')
-
-
-    models = {
-        u'setup.fixture': {
-            'Meta': {'object_name': 'Fixture'},
-            'app_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
-        }
-    }
-
-    complete_apps = ['setup']

+ 0 - 0
notrefactored/setup/migrations/__init__.py


+ 0 - 4
notrefactored/setup/models.py

@@ -1,4 +0,0 @@
-from django.db import models
-
-class Fixture(models.Model):
-    app_name = models.CharField(max_length=255)

+ 0 - 0
notrefactored/stats/__init__.py


+ 0 - 28
notrefactored/stats/forms.py

@@ -1,28 +0,0 @@
-from datetime import timedelta
-from django import forms
-from django.utils import timezone as tz
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-
-class GenerateStatisticsForm(Form):
-    provider_model = forms.ChoiceField()
-    date_start = forms.DateField(initial=tz.now() - timedelta(days=7))
-    date_end = forms.DateField(initial=tz.now())
-    stats_precision = forms.ChoiceField(choices=(('day', _('For each day')), ('week', _('For each week')), ('month', _('For each month')), ('year', _('For each year'))))
-
-    layout = (
-              (None, (
-                        ('provider_model', {'label': _('Report Type'), 'help_text': _('Select statistics provider.')}),
-                        ('nested', (
-                            ('date_start', {'label': _('Time'), 'help_text': _('Enter start and end date for time period you want to take data from to use in graph.'), 'attrs': {'placeholder': _('Start Date: YYYY-MM-DD')}, 'width': 50}),
-                            ('date_end', {'attrs': {'placeholder': _('End Date: YYYY-MM-DD')}, 'width': 50}),
-                        )),
-                        ('stats_precision', {'label': _('Graph Precision')}),
-                      )),
-              )
-
-    def __init__(self, *args, **kwargs):
-        provider_choices = kwargs.get('provider_choices')
-        del kwargs['provider_choices']
-        super(GenerateStatisticsForm, self).__init__(*args, **kwargs)
-        self.fields['provider_model'] = forms.ChoiceField(choices=provider_choices)

+ 0 - 170
notrefactored/stats/views.py

@@ -1,170 +0,0 @@
-import math
-from datetime import datetime, timedelta
-from django.core.urlresolvers import reverse
-from django.db import models
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.forms import FormLayout
-from misago.messages import Message
-from misago.stats.forms import GenerateStatisticsForm
-from misago.views import error404
-
-def form(request):
-    """
-    Allow admins to generate fancy statistic graphs for different models
-    """
-    statistics_providers = []
-    models_map = {}
-    for model in models.get_models():
-        try:
-            getattr(model.objects, 'filter_stats')
-            statistics_providers.append((str(model.__name__).lower(), model.statistics_name))
-            models_map[str(model.__name__).lower()] = model
-        except AttributeError:
-            pass
-
-    if not statistics_providers:
-        """
-        Something went FUBAR - Misago ships with some stats providers out of box
-        If those providers cant be found, this means Misago filesystem is corrupted
-        """
-        return request.theme.render_to_response('stats/not_available.html',
-                                                context_instance=RequestContext(request));
-
-    message = None
-    if request.method == 'POST':
-        form = GenerateStatisticsForm(request.POST, provider_choices=statistics_providers, request=request)
-        if form.is_valid():
-            date_start = form.cleaned_data['date_start']
-            date_end = form.cleaned_data['date_end']
-            if date_start > date_end:
-                # Reverse dates if start is after end
-                date_temp = date_end
-                date_end = date_start
-                date_start = date_temp
-            # Assert that dates are correct
-            if date_end == date_start:
-                message = Message(_('Start and end date are same'), type='error')
-            elif check_dates(date_start, date_end, form.cleaned_data['stats_precision']):
-                message = check_dates(date_start, date_end, form.cleaned_data['stats_precision'])
-            else:
-                request.messages.set_flash(Message(_('Statistical report has been created.')), 'success', 'admin_stats')
-                return redirect(reverse('admin_stats_graph', kwargs={
-                                                       'model': form.cleaned_data['provider_model'],
-                                                       'date_start': date_start.strftime('%Y-%m-%d'),
-                                                       'date_end': date_end.strftime('%Y-%m-%d'),
-                                                       'precision': form.cleaned_data['stats_precision']
-                                                        }))
-        else:
-            message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = GenerateStatisticsForm(provider_choices=statistics_providers, request=request)
-
-    return request.theme.render_to_response('stats/form.html', {
-                                            'form': FormLayout(form),
-                                            'message': message,
-                                            }, context_instance=RequestContext(request));
-
-
-def graph(request, model, date_start, date_end, precision):
-    """
-    Generate fancy graph for model and stuff
-    """
-    if date_start == date_end:
-        # Bad dates
-        raise error404()
-
-    # Turn stuff into datetime's
-    date_start = datetime.strptime(date_start, '%Y-%m-%d')
-    date_end = datetime.strptime(date_end, '%Y-%m-%d')
-
-
-    statistics_providers = []
-    models_map = {}
-    for model_obj in models.get_models():
-        try:
-            getattr(model_obj.objects, 'filter_stats')
-            statistics_providers.append((str(model_obj.__name__).lower(), model_obj.statistics_name))
-            models_map[str(model_obj.__name__).lower()] = model_obj
-        except AttributeError:
-            pass
-
-    if not statistics_providers:
-        # Like before, q.q on lack of models
-        return request.theme.render_to_response('stats/not_available.html',
-                                                context_instance=RequestContext(request));
-
-    if not model in models_map or check_dates(date_start, date_end, precision):
-        # Bad model name or graph data!
-        raise error404()
-
-    form = GenerateStatisticsForm(
-                                  provider_choices=statistics_providers,
-                                  request=request,
-                                  initial={'provider_model': model, 'date_start': date_start, 'date_end': date_end, 'stats_precision': precision})
-    return request.theme.render_to_response('stats/graph.html', {
-                                            'title': models_map[model].statistics_name,
-                                            'graph': build_graph(models_map[model], date_start, date_end, precision),
-                                            'form': FormLayout(form),
-                                            'message': request.messages.get_message('admin_stats'),
-                                            }, context_instance=RequestContext(request));
-
-
-def check_dates(date_start, date_end, precision):
-    date_diff = date_end - date_start
-    date_diff = date_diff.seconds + date_diff.days * 86400
-
-    if ((precision == 'day' and date_diff / 86400 > 60)
-        or (precision == 'week' and date_diff / 604800 > 60)
-        or (precision == 'month' and date_diff / 2592000 > 60)
-        or (precision == 'year' and date_diff / 31536000 > 60)):
-        return Message(_('Too many many items to display on graph.'), 'error')
-    elif ((precision == 'day' and date_diff / 86400 < 1)
-          or (precision == 'week' and date_diff / 604800 < 1)
-          or (precision == 'month' and date_diff / 2592000 < 1)
-          or (precision == 'year' and date_diff / 31536000 < 1)):
-        return Message(_('Too few items to display on graph'), 'error')
-    return None
-
-
-def build_graph(model, date_start, date_end, precision):
-    if precision == 'day':
-        format = 'F j, Y'
-        step = 86400
-    if precision == 'week':
-        format = 'W, Y'
-        step = 604800
-    if precision == 'month':
-        format = 'F, Y'
-        step = 2592000
-    if precision == 'year':
-        format = 'Y'
-        step = 31536000
-
-    date_end = timezone.make_aware(date_end, timezone.get_current_timezone())
-    date_start = timezone.make_aware(date_start, timezone.get_current_timezone())
-
-    date_diff = date_end - date_start
-    date_diff = date_diff.seconds + date_diff.days * 86400
-    steps = int(math.ceil(float(date_diff / step))) + 1
-    timeline = [0 for i in range(0, steps)]
-    for i in range(0, steps):
-        step_date = date_end - timedelta(seconds=(i * step));
-        timeline[steps - i - 1] = step_date
-    stat = {'total': 0, 'max': 0, 'stat': [0 for i in range(0, steps)], 'timeline': timeline, 'start': date_start, 'end': date_end, 'format': format}
-
-    # Loop model items
-    for item in model.objects.filter_stats(date_start, date_end).iterator():
-        date_diff = date_end - item.get_date()
-        date_diff = date_diff.seconds + date_diff.days * 86400
-        date_diff = steps - int(math.floor(float(date_diff / step))) - 2
-        stat['stat'][date_diff] += 1
-        stat['total'] += 1
-
-    # Find max
-    for i in stat['stat']:
-        if i > stat['max']:
-            stat['max'] = i
-    return stat

+ 0 - 7
notrefactored/stopwatch/__init__.py

@@ -1,7 +0,0 @@
-import time
-
-class Stopwatch(object):
-    def __init__(self):
-        self.start_time = time.time()
-    def time(self):
-        return time.time() - self.start_time 

+ 0 - 16
notrefactored/stopwatch/middleware.py

@@ -1,16 +0,0 @@
-from django.conf import settings
-from misago.stopwatch import Stopwatch
-
-class StopwatchMiddleware(object):
-    def process_request(self, request):
-        request.stopwatch = Stopwatch()
-
-    def process_response(self, request, response):
-        try:
-            if settings.STOPWATCH_LOG:
-                stat_file = open(settings.STOPWATCH_LOG, 'a')
-                stat_file.write("%s %s s\n" % (request.path_info, request.stopwatch.time()))
-                stat_file.close()
-        except AttributeError:
-            pass
-        return response

+ 0 - 0
notrefactored/team/__init__.py


+ 0 - 16
notrefactored/team/views.py

@@ -1,16 +0,0 @@
-from django.utils.translation import ugettext as _
-from misago.admin import site
-from misago.admin.widgets import ListWidget
-
-class List(ListWidget):
-    admin = site.get_action('team')
-    id = 'list'
-    columns = (
-             ('username', _("Team Member")),
-             )
-    default_sorting = 'username_slug'
-    hide_actions = True
-    pagination = 50
-
-    def select_items(self, items):
-        return items.filter(is_team=1)

+ 0 - 0
notrefactored/template/__init__.py


+ 0 - 0
notrefactored/template/templatetags/__init__.py


+ 0 - 168
notrefactored/template/templatetags/django2jinja.py

@@ -1,168 +0,0 @@
-import math
-import urllib
-from coffin.template import Library
-from django.conf import settings
-from misago.utils import slugify
-
-register = Library()
-
-@register.object(name='widthratio')
-def widthratio(min=0, max=100, range=100):
-    return int(math.ceil(float(float(min) / float(max) * int(range))))
-
-
-@register.object(name='query')
-def query_string(**kwargs):
-    query = urllib.urlencode(kwargs)
-    return '?%s' % (query if kwargs else '')
-
-@register.filter(name='low')
-def low(value):
-    if not value:
-        return u''
-    try:
-        rest = value[1:]
-    except IndexError:
-        rest = ''
-    return '%s%s' % (unicode(value[0]).lower(), rest)
-
-
-@register.filter(name="slugify")
-def slugify_function(format_string):
-    return slugify(format_string)
-
-
-"""
-Markdown filters
-"""
-@register.filter(name='markdown')
-def parse_markdown(value, format=None):
-    import markdown
-    if not format:
-        format = settings.OUTPUT_FORMAT
-    return markdown.markdown(value, safe_mode='escape', output_format=format).strip()
-
-@register.filter(name='markdown_short')
-def short_markdown(value, length=300):
-    from misago.markdown.factory import clear_markdown
-    value = clear_markdown(value)
-    if len(value) <= length:
-        return ' '.join(value.splitlines())
-    value = ' '.join(value.splitlines())
-    value = value[0:length]
-    while value[-1] != ' ':
-        value = value[0:-1]
-    value = value.strip()
-    if value[-3:3] != '...':
-        value = '%s...' % value
-    return value
-
-
-@register.filter(name='markdown_final')
-def finalize_markdown(value):
-    from misago.markdown.factory import finalize_markdown
-    return finalize_markdown(value)
-
-
-"""
-Date and time filters
-"""
-from datetime import datetime, timedelta
-from django.utils.dateformat import format, time_format
-from django.utils.timezone import is_aware, localtime, utc
-from django.utils.translation import pgettext, ungettext, ugettext as _
-from misago.utils import slugify, formats
-
-def date(val, arg=""):
-    if not val:
-        return _("Never")
-    if not arg:
-        arg = formats['DATE_FORMAT']
-    elif arg in formats:
-        arg = formats[arg]
-    return format(localtime(val), arg)
-
-
-def reldate(val, arg=""):
-    if not val:
-        return _("Never")
-    now = datetime.now(utc if is_aware(val) else None)
-    local_now = localtime(now)
-    diff = now - val
-    local = localtime(val)
-
-    # Today check
-    if format(local, 'Y-z') == format(local_now, 'Y-z'):
-        return _("Today, %(hour)s") % {'hour': time_format(local, formats['TIME_FORMAT'])}
-    # Yesteday check
-    yesterday = localtime(now - timedelta(days=1))
-    if format(local, 'Y-z') == format(yesterday, 'Y-z'):
-        return _("Yesterday, %(hour)s") % {'hour': time_format(local, formats['TIME_FORMAT'])}
-    # Tomorrow Check
-    tomorrow = localtime(now + timedelta(days=1))
-    if format(local, 'Y-z') == format(tomorrow, 'Y-z'):
-        return _("Tomorrow, %(hour)s") % {'hour': time_format(local, formats['TIME_FORMAT'])}
-    # Day of Week check
-    if format(local, 'D') != format(local_now, 'D') and diff.days > -7 and diff.days < 7:
-        return _("%(day)s, %(hour)s") % {'day': format(local, 'l'), 'hour': time_format(local, formats['TIME_FORMAT'])}
-
-    # Fallback to custom      
-    return date(val, arg)
-
-
-def reltimesince(val, arg=""):
-    if not val:
-        return _("Never")
-    now = datetime.now(utc if is_aware(val) else None)
-    diff = now - val
-    local = localtime(val)
-
-    # Difference is greater than day for sure
-    if diff.days != 0:
-        return reldate(val, arg)
-
-    # Display specific time
-    if diff.seconds >= 0:
-        if diff.seconds <= 5:
-            return _("Just now")
-        if diff.seconds <= 60:
-            return _("Minute ago")
-        if diff.seconds < 3600:
-            minutes = int(math.floor(diff.seconds / 60.0))
-            return ungettext(
-                    "Minute ago",
-                    "%(minutes)s minutes ago",
-                minutes) % {'minutes': minutes}
-        if diff.seconds < 10800:
-            hours = int(math.floor(diff.seconds / 3600.0))
-            minutes = (diff.seconds - (hours * 3600)) / 60
-            if minutes > 0:
-                return ungettext(
-                    "Hour and %(minutes)s ago",
-                    "%(hours)s hours and %(minutes)s ago",
-                hours) % {'hours': hours, 'minutes': ungettext(
-                        "%(minutes)s minute",
-                        "%(minutes)s minutes",
-                    minutes) % {'minutes': minutes}}
-                return _("%(hours)s hours and %(minutes)s minutes ago") % {'hours': hours, 'minutes': minutes}
-            return ungettext(
-                    "Hour ago",
-                    "%(hours)s hours ago",
-                hours) % {'hours': hours}
-
-    # Fallback to reldate
-    return reldate(val, arg)
-
-@register.filter(name='date')
-def date_filter(val, arg=""):
-    return date(val, arg)
-
-
-@register.filter(name='reldate')
-def reldate_filter(val, arg=""):
-    return reldate(val, arg)
-
-
-@register.filter(name='reltimesince')
-def reltimesince_filter(val, arg=""):
-    return reltimesince(val, arg)

+ 0 - 0
notrefactored/themes/__init__.py


+ 0 - 51
notrefactored/themes/forms.py

@@ -1,51 +0,0 @@
-from django.conf import settings
-from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.forms import Form
-from misago.themes.models import ThemeAdjustment
-from misago.utils.validators import validate_sluggable
-
-available_themes = []
-for theme in settings.INSTALLED_THEMES[0:-1]:
-    available_themes.append((theme, theme))
-
-
-class ThemeAdjustmentForm(Form):
-    theme = forms.ChoiceField(choices=available_themes, required=False)
-    useragents = forms.CharField(widget=forms.Textarea, required=False)
-    
-    layout = (
-              (
-               _("Theme Adjustment"),
-               (
-                ('theme', {'label': _("Theme"), 'help_text': _("Select theme that is to replace default one.")}),
-                ('useragents', {'label': _("UserAgent Strings"), 'help_text': _("Enter UserAgent strings for which selected theme has to replace default one. Each string has to be entered in new line. This is case insensitive")}),
-                ),
-               ),
-              )
-
-    def __init__(self, adjustment=None, *args, **kwargs):
-        self.request = kwargs['request']
-        if adjustment:
-            self.adjustment = adjustment
-        else:
-            self.adjustment = ThemeAdjustment()
-        super(ThemeAdjustmentForm, self).__init__(*args, **kwargs)
-        
-    def clean_theme(self):
-        self.adjustment.theme = self.cleaned_data['theme']
-        self.adjustment.full_clean()
-        return self.cleaned_data['theme']
-
-    def clean_useragents(self):
-        agents_raw = self.cleaned_data['useragents'].strip().lower().splitlines()
-        agents = []
-        for line in agents_raw:
-            line = line.strip()
-            if line and not line in agents:
-                agents.append(line)
-        self.cleaned_data['useragents'] = agents
-        if not agents:
-            raise ValidationError(_("You have to enter at least one UserAgent."))
-        return self.cleaned_data['useragents']

+ 0 - 24
notrefactored/themes/middleware.py

@@ -1,24 +0,0 @@
-from django.conf import settings
-from django.core.cache import cache
-from misago.themes.theme import Theme
-from misago.themes.models import ThemeAdjustment
-
-class ThemeMiddleware(object):
-    def process_request(self, request):
-        if not settings.INSTALLED_THEMES:
-            raise ValueError('There are no themes installed!')
-        request.theme = Theme(settings.INSTALLED_THEMES[0])
-        
-        # Adjust theme for specific client?
-        if request.META.get('HTTP_USER_AGENT'):
-            adjustments = cache.get('client_adjustments', 'nada')
-            if adjustments == 'nada':
-                adjustments = ThemeAdjustment.objects.all()
-                cache.set('client_adjustments', adjustments)
-            if adjustments:
-                user_agent = request.META.get('HTTP_USER_AGENT').lower()
-                for item in adjustments:
-                    if item.adjust_theme(user_agent):
-                        request.theme = Theme(item.theme)
-                        break
-            

+ 0 - 34
notrefactored/themes/migrations/0001_initial.py

@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'ThemeAdjustment'
-        db.create_table(u'themes_themeadjustment', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('theme', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)),
-            ('useragents', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-        ))
-        db.send_create_signal(u'themes', ['ThemeAdjustment'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'ThemeAdjustment'
-        db.delete_table(u'themes_themeadjustment')
-
-
-    models = {
-        u'themes.themeadjustment': {
-            'Meta': {'object_name': 'ThemeAdjustment'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'theme': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
-            'useragents': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'})
-        }
-    }
-
-    complete_apps = ['themes']

+ 0 - 0
notrefactored/themes/migrations/__init__.py


+ 0 - 25
notrefactored/themes/models.py

@@ -1,25 +0,0 @@
-from django.core.cache import cache
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-
-class ThemeAdjustment(models.Model):
-    """
-    ThemeAdjustment - theme that is set for specified user agents
-    """
-    theme = models.CharField(max_length=255, unique=True,
-                             error_messages={'unique': _("User agents for this theme are already defined.")})
-    useragents = models.TextField(null=True, blank=True)
-    
-    def adjust_theme(self, useragent):
-        for string in self.useragents.splitlines():
-            if string in useragent:
-                return True
-        return False
-    
-    def save(self, *args, **kwargs):
-        cache.delete('client_adjustments')
-        super(ThemeAdjustment, self).save(*args, **kwargs)
-
-    def delete(self, *args, **kwargs):
-        cache.delete('client_adjustments')
-        super(ThemeAdjustment, self).delete(*args, **kwargs)

+ 0 - 55
notrefactored/themes/theme.py

@@ -1,55 +0,0 @@
-from django.conf import settings
-from coffin.shortcuts import render, render_to_response
-from coffin.template.loader import get_template, select_template, render_to_string
-
-'''Monkeypatch Django to mimic Jinja2 behaviour'''
-from django.utils import safestring
-if not hasattr(safestring, '__html__'):
-    safestring.SafeString.__html__ = lambda self: str(self)
-    safestring.SafeUnicode.__html__ = lambda self: unicode(self)
-
-class Theme(object):
-    def __init__(self, theme):
-        self.set_theme(theme);
-
-    def set_theme(self, theme):
-        if theme not in settings.INSTALLED_THEMES:
-            raise ValueError('"%s" is not correct theme name.' % theme)
-        if theme[0] == '_':
-            raise ValueError('"%s" is a template package, not a theme.' % theme[1:])
-        self._theme = theme;
-
-    def reset_theme(self):
-        self._theme = settings.INSTALLED_THEMES[0]
-
-    def get_theme(self):
-        return self._theme
-
-    def prefix_templates(self, templates):
-        if isinstance(templates, str):
-            return ('%s/%s' % (self._theme, templates), templates)
-        else:
-            prefixed = []
-            for template in templates:
-                prefixed.append('%s/%s' % (self._theme, template))
-            prefixed += templates
-            return prefixed
-
-    def render(self, request, *args, **kwargs):
-        return render(request, *args, **kwargs)
-
-    def render_to_string(self, templates, *args, **kwargs):
-        templates = self.prefix_templates(templates)
-        return render_to_string(templates, *args, **kwargs)
-
-    def render_to_response(self, templates, *args, **kwargs):
-        templates = self.prefix_templates(templates)
-        return render_to_response(templates, *args, **kwargs)
-
-    def get_email_templates(self, template, contex={}):
-            email_type_plain = '_email/%s_plain.html' % template
-            email_type_html = '_email/%s_html.html' % template
-            return (
-                    select_template(('%s/%s' % (self._theme, email_type_plain[1:]), email_type_plain)),
-                    select_template(('%s/%s' % (self._theme, email_type_html[1:]), email_type_html)),
-                    )

+ 0 - 109
notrefactored/themes/views.py

@@ -1,109 +0,0 @@
-from django.core.urlresolvers import reverse as django_reverse
-from django import forms
-from django.utils.translation import ugettext as _
-from misago.admin import site
-from misago.admin.widgets import *
-from misago.forms import Form
-from misago.utils import slugify
-from misago.themes.forms import ThemeAdjustmentForm
-from misago.themes.models import ThemeAdjustment
-
-def reverse(route, target=None):
-    if target:
-        return django_reverse(route, kwargs={'target': target.pk, 'slug': slugify(target.theme)})
-    return django_reverse(route)
-
-"""
-Views
-"""
-class List(ListWidget):
-    admin = site.get_action('clients')
-    id = 'list'
-    columns = (
-               ('theme', _("Theme")),
-               )
-    nothing_checked_message = _('You have to check at least one adjustment.')
-    actions = (
-               ('delete', _("Delete selected adjustments"), _("Are you sure you want to delete selected theme adjustments?")),
-               )
-
-    def get_item_actions(self, item):
-        return (
-                self.action('pencil', _("Edit Adjustment"), reverse('admin_clients_edit', item)),
-                self.action('remove', _("Delete Adjustment"), reverse('admin_clients_delete', item), post=True, prompt=_("Are you sure you want to delete this adjustment?")),
-                )
-
-    def action_delete(self, items, checked):
-        ThemeAdjustment.objects.filter(id__in=checked).delete()
-        return Message(_('Selected adjustment have been deleted successfully.'), 'success'), reverse('admin_clients')
-
-
-class New(FormWidget):
-    admin = site.get_action('clients')
-    id = 'new'
-    fallback = 'admin_clients'
-    form = ThemeAdjustmentForm
-    submit_button = _("Save Rank")
-
-    def get_form_instance(self, form, model, initial, post=False):
-        if post:
-            return form(model, self.request.POST, request=self.request, initial=self.get_initial_data(model))
-        return form(model, request=self.request, initial=self.get_initial_data(model))
-    
-    def get_new_url(self, model):
-        return reverse('admin_clients_new')
-
-    def get_edit_url(self, model):
-        return reverse('admin_clients_edit', model)
-
-    def submit_form(self, form, target):
-        new_rank = ThemeAdjustment.objects.create(
-                                                  theme=form.cleaned_data['theme'],
-                                                  useragents='\r\n'.join(form.cleaned_data['useragents']),
-                                                  )
-        return new_rank, Message(_('New adjustment has been created.'), 'success')
-
-
-class Edit(FormWidget):
-    admin = site.get_action('clients')
-    id = 'edit'
-    name = _("Edit Rank")
-    fallback = 'admin_clients'
-    form = ThemeAdjustmentForm
-    target_name = 'theme'
-    notfound_message = _('Requested adjustment could not be found.')
-    submit_fallback = True
-
-    def get_url(self, model):
-        return reverse('admin_clients_edit', model)
-
-    def get_edit_url(self, model):
-        return self.get_url(model)
-
-    def get_form_instance(self, form, model, initial, post=False):
-        if post:
-            return form(model, self.request.POST, request=self.request, initial=self.get_initial_data(model))
-        return form(model, request=self.request, initial=self.get_initial_data(model))
-    
-    def get_initial_data(self, model):
-        return {
-                'theme': model.theme,
-                'useragents': model.useragents,
-                }
-
-    def submit_form(self, form, target):
-        target.theme = form.cleaned_data['theme']
-        target.useragents = '\r\n'.join(form.cleaned_data['useragents'])
-        target.save(force_update=True)
-        return target, Message(_('Adjustment using theme "%(name)s" has been saved.') % {'name': target.theme}, 'success')
-
-
-class Delete(ButtonWidget):
-    admin = site.get_action('clients')
-    id = 'delete'
-    fallback = 'admin_clients'
-    notfound_message = _('Requested adjustment could not be found.')
-
-    def action(self, target):
-        target.delete()
-        return Message(_('Adjustment using theme "%(name)s" has been deleted.') % {'name': target.theme}, 'success'), False

+ 0 - 0
notrefactored/threads/__init__.py


+ 0 - 587
notrefactored/threads/acl.py

@@ -1,587 +0,0 @@
-from django import forms
-from django.db import models
-from django.db.models import Q
-from django.utils.translation import ugettext_lazy as _
-from misago.acl.builder import BaseACL
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forms import YesNoSwitch
-
-def make_forum_form(request, role, form):
-    form.base_fields['can_read_threads'] = forms.TypedChoiceField(choices=(
-                                                                  (0, _("No")),
-                                                                  (1, _("Yes, owned")),
-                                                                  (2, _("Yes, all")),
-                                                                  ), coerce=int)
-    form.base_fields['can_start_threads'] = forms.TypedChoiceField(choices=(
-                                                                   (0, _("No")),
-                                                                   (1, _("Yes, with moderation")),
-                                                                   (2, _("Yes")),
-                                                                   ), coerce=int)
-    form.base_fields['can_edit_own_threads'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_soft_delete_own_threads'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_write_posts'] = forms.TypedChoiceField(choices=(
-                                                                 (0, _("No")),
-                                                                 (1, _("Yes, with moderation")),
-                                                                 (2, _("Yes")),
-                                                                 ), coerce=int)
-    form.base_fields['can_edit_own_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_soft_delete_own_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_upvote_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_downvote_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_see_posts_scores'] = forms.TypedChoiceField(choices=(
-                                                                      (0, _("No")),
-                                                                      (1, _("Yes, final score")),
-                                                                      (2, _("Yes, both up and down-votes")),
-                                                                      ), coerce=int)
-    form.base_fields['can_see_votes'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_make_polls'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_vote_in_polls'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_see_poll_votes'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_see_attachments'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_upload_attachments'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_download_attachments'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['attachment_size'] = forms.IntegerField(min_value=0, initial=100)
-    form.base_fields['attachment_limit'] = forms.IntegerField(min_value=0, initial=3)
-    form.base_fields['can_approve'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_edit_labels'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_see_changelog'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_pin_threads'] = forms.TypedChoiceField(choices=(
-                                                                 (0, _("No")),
-                                                                 (1, _("Yes, to stickies")),
-                                                                 (2, _("Yes, to annoucements")),
-                                                                 ), coerce=int)
-    form.base_fields['can_edit_threads_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_move_threads_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_close_threads'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_protect_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_delete_threads'] = forms.TypedChoiceField(choices=(
-                                                                    (0, _("No")),
-                                                                    (1, _("Yes, soft-delete")),
-                                                                    (2, _("Yes, hard-delete")),
-                                                                    ), coerce=int)
-    form.base_fields['can_delete_posts'] = forms.TypedChoiceField(choices=(
-                                                                  (0, _("No")),
-                                                                  (1, _("Yes, soft-delete")),
-                                                                  (2, _("Yes, hard-delete")),
-                                                                   ), coerce=int)
-    form.base_fields['can_delete_polls'] = forms.TypedChoiceField(choices=(
-                                                                  (0, _("No")),
-                                                                  (1, _("Yes, soft-delete")),
-                                                                  (2, _("Yes, hard-delete")),
-                                                                  ), coerce=int)
-    form.base_fields['can_delete_attachments'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-
-    form.layout.append((
-                        _("Threads"),
-                        (
-                         ('can_read_threads', {'label': _("Can read threads")}),
-                         ('can_start_threads', {'label': _("Can start new threads")}),
-                         ('can_edit_own_threads', {'label': _("Can edit own threads")}),
-                         ('can_soft_delete_own_threads', {'label': _("Can soft-delete own threads")}),
-                        ),
-                       ),)
-    form.layout.append((
-                        _("Posts"),
-                        (
-                         ('can_write_posts', {'label': _("Can write posts")}),
-                         ('can_edit_own_posts', {'label': _("Can edit own posts")}),
-                         ('can_soft_delete_own_posts', {'label': _("Can soft-delete own posts")}),
-                        ),
-                       ),)
-    form.layout.append((
-                        _("Karma"),
-                        (
-                         ('can_upvote_posts', {'label': _("Can upvote posts")}),
-                         ('can_downvote_posts', {'label': _("Can downvote posts")}),
-                         ('can_see_posts_scores', {'label': _("Can see post score")}),
-                         ('can_see_votes', {'label': _("Can see who voted on post")}),
-                        ),
-                       ),)
-    form.layout.append((
-                        _("Polls"),
-                        (
-                         ('can_make_polls', {'label': _("Can make polls")}),
-                         ('can_vote_in_polls', {'label': _("Can vote in polls")}),
-                         ('can_see_poll_votes', {'label': _("Can see who voted in poll")}),
-                        ),
-                       ),)
-    form.layout.append((
-                        _("Attachments"),
-                        (
-                         ('can_see_attachments', {'label': _("Can see attachments")}),
-                         ('can_upload_attachments', {'label': _("Can upload attachments")}),
-                         ('can_download_attachments', {'label': _("Can download attachments")}),
-                         ('attachment_size', {'label': _("Max size of single attachment (in Kb)"), 'help_text': _("Enter zero for no limit.")}),
-                         ('attachment_limit', {'label': _("Max number of attachments per post"), 'help_text': _("Enter zero for no limit.")}),
-                        ),
-                       ),)
-    form.layout.append((
-                        _("Moderation"),
-                        (
-                         ('can_approve', {'label': _("Can accept threads and posts")}),
-                         ('can_edit_labels', {'label': _("Can edit thread labels")}),
-                         ('can_see_changelog', {'label': _("Can see edits history")}),
-                         ('can_make_annoucements', {'label': _("Can make annoucements")}),
-                         ('can_pin_threads', {'label': _("Can change threads weight")}),
-                         ('can_edit_threads_posts', {'label': _("Can edit threads and posts")}),
-                         ('can_move_threads_posts', {'label': _("Can move, merge and split threads and posts")}),
-                         ('can_close_threads', {'label': _("Can close threads")}),
-                         ('can_protect_posts', {'label': _("Can protect posts"), 'help_text': _("Protected posts cannot be changed by their owners.")}),
-                         ('can_delete_threads', {'label': _("Can delete threads")}),
-                         ('can_delete_posts', {'label': _("Can delete posts")}),
-                         ('can_delete_polls', {'label': _("Can delete polls")}),
-                         ('can_delete_attachments', {'label': _("Can delete attachments")}),
-                        ),
-                       ),)
-
-
-class ThreadsACL(BaseACL):
-    def get_role(self, forum):
-        try:
-            try:
-                return self.acl[forum.pk]
-            except AttributeError:
-                return self.acl[forum]
-        except KeyError:
-            return {}
-
-    def allow_thread_view(self, user, thread):
-        try:
-            forum_role = self.acl[thread.forum_id]
-            if forum_role['can_read_threads'] == 0:
-                raise ACLError403(_("You don't have permission to read threads in this forum."))
-            if forum_role['can_read_threads'] == 1 and thread.weight < 2 and thread.start_poster_id != user.id:
-                raise ACLError404()
-            if thread.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == thread.start_poster)):
-                raise ACLError404()
-            if thread.deleted and not forum_role['can_delete_threads']:
-                raise ACLError404()
-        except KeyError:
-            raise ACLError403(_("You don't have permission to read threads in this forum."))
-
-    def allow_post_view(self, user, thread, post):
-        forum_role = self.acl[thread.forum_id]
-        if post.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == post.user)):
-            raise ACLError404()
-        if post.deleted and not (forum_role['can_delete_posts'] or (user.is_authenticated() and user == post.user)):
-            raise ACLError404()
-
-    def get_readable_forums(self, acl):
-        readable = []
-        for forum in self.acl:
-            if acl.forums.can_browse(forum) and self.acl[forum]['can_read_threads']:
-                readable.append(forum)
-        return readable
-
-    def filter_threads(self, request, forum, queryset):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_approve']:
-                if request.user.is_authenticated():
-                    queryset = queryset.filter(Q(moderated=0) | Q(start_poster=request.user))
-                else:
-                    queryset = queryset.filter(moderated=0)
-            if forum_role['can_read_threads'] == 1:
-                queryset = queryset.filter(Q(weight=2) | Q(start_poster_id=request.user.id))
-            if not forum_role['can_delete_threads']:
-                queryset = queryset.filter(deleted=False)
-        except KeyError:
-            return False
-        return queryset
-
-    def filter_posts(self, request, thread, queryset):
-        try:
-            forum_role = self.acl[thread.forum.pk]
-            if not forum_role['can_approve']:
-                if request.user.is_authenticated():
-                    queryset = queryset.filter(Q(moderated=0) | Q(user=request.user))
-                else:
-                    queryset = queryset.filter(moderated=0)
-        except KeyError:
-            return False
-        return queryset
-
-    def can_start_threads(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
-                return False
-            if forum.closed and forum_role['can_close_threads'] == 0:
-                return False
-            return True
-        except KeyError:
-            return False
-
-    def allow_new_threads(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
-                raise ACLError403(_("You don't have permission to start new threads in this forum."))
-            if forum.closed and forum_role['can_close_threads'] == 0:
-                raise ACLError403(_("This forum is closed, you can't start new threads in it."))
-        except KeyError:
-            raise ACLError403(_("You don't have permission to start new threads in this forum."))
-
-    def can_edit_thread(self, user, forum, thread, post):
-        try:
-            forum_role = self.acl[thread.forum_id]
-            if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
-                return False
-            if forum_role['can_edit_threads_posts']:
-                return True
-            if forum_role['can_edit_own_threads'] and not post.protected and post.user_id == user.pk:
-                return True
-            return False
-        except KeyError:
-            return False
-
-    def allow_thread_edit(self, user, forum, thread, post):
-        try:
-            forum_role = self.acl[thread.forum_id]
-            if thread.deleted or post.deleted:
-                self.allow_deleted_post_view(forum)
-            if not forum_role['can_close_threads']:
-                if forum.closed:
-                    raise ACLError403(_("You can't edit threads in closed forums."))
-                if thread.closed:
-                    raise ACLError403(_("You can't edit closed threads."))
-            if not forum_role['can_edit_threads_posts']:
-                if post.user_id != user.pk:
-                    raise ACLError403(_("You can't edit other members threads."))
-                if not forum_role['can_edit_own_threads']:
-                    raise ACLError403(_("You can't edit your threads."))
-                if post.protected:
-                    raise ACLError403(_("This thread is protected, you cannot edit it."))
-        except KeyError:
-            raise ACLError403(_("You don't have permission to edit threads in this forum."))
-
-    def can_reply(self, forum, thread):
-        try:
-            forum_role = self.acl[forum.pk]
-            if forum_role['can_write_posts'] == 0:
-                return False
-            if (forum.closed or thread.closed) and forum_role['can_close_threads'] == 0:
-                return False
-            return True
-        except KeyError:
-            return False
-
-    def allow_reply(self, forum, thread):
-        try:
-            forum_role = self.acl[thread.forum.pk]
-            if forum_role['can_write_posts'] == 0:
-                raise ACLError403(_("You don't have permission to write replies in this forum."))
-            if forum_role['can_close_threads'] == 0:
-                if forum.closed:
-                    raise ACLError403(_("You can't write replies in closed forums."))
-                if thread.closed:
-                    raise ACLError403(_("You can't write replies in closed threads."))
-        except KeyError:
-            raise ACLError403(_("You don't have permission to write replies in this forum."))
-
-    def can_edit_reply(self, user, forum, thread, post):
-        try:
-            forum_role = self.acl[thread.forum_id]
-            if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
-                return False
-            if forum_role['can_edit_threads_posts']:
-                return True
-            if forum_role['can_edit_own_posts'] and not post.protected and post.user_id == user.pk:
-                return True
-            return False
-        except KeyError:
-            return False
-
-    def allow_reply_edit(self, user, forum, thread, post):
-        try:
-            forum_role = self.acl[thread.forum_id]
-            if thread.deleted or post.deleted:
-                self.allow_deleted_post_view(forum)
-            if not forum_role['can_close_threads']:
-                if forum.closed:
-                    raise ACLError403(_("You can't edit replies in closed forums."))
-                if thread.closed:
-                    raise ACLError403(_("You can't edit replies in closed threads."))
-            if not forum_role['can_edit_threads_posts']:
-                if post.user_id != user.pk:
-                    raise ACLError403(_("You can't edit other members replies."))
-                if not forum_role['can_edit_own_posts']:
-                    raise ACLError403(_("You can't edit your replies."))
-                if post.protected:
-                    raise ACLError403(_("This reply is protected, you cannot edit it."))
-        except KeyError:
-            raise ACLError403(_("You don't have permission to edit replies in this forum."))
-
-    def can_see_changelog(self, user, forum, post):
-        try:
-            forum_role = self.acl[forum.pk]
-            return forum_role['can_see_changelog'] or user.pk == post.user_id
-        except KeyError:
-            return False
-
-    def allow_changelog_view(self, user, forum, post):
-        try:
-            forum_role = self.acl[forum.pk]
-            if post.thread.deleted or post.deleted:
-                self.allow_deleted_post_view(forum)
-            if not (forum_role['can_see_changelog'] or user.pk == post.user_id):
-                raise ACLError403(_("You don't have permission to see history of changes made to this post."))
-        except KeyError:
-            raise ACLError403(_("You don't have permission to see history of changes made to this post."))
-
-    def can_make_revert(self, forum, thread):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
-                return False
-            return forum_role['can_edit_threads_posts']
-        except KeyError:
-            return False
-
-    def allow_revert(self, forum, thread):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_close_threads']:
-                if forum.closed:
-                    raise ACLError403(_("You can't make reverts in closed forums."))
-                if thread.closed:
-                    raise ACLError403(_("You can't make reverts in closed threads."))
-            if not forum_role['can_edit_threads_posts']:
-                raise ACLError403(_("You don't have permission to make reverts in this forum."))
-        except KeyError:
-            raise ACLError403(_("You don't have permission to make reverts in this forum."))
-
-    def can_mod_threads(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            return (
-                    forum_role['can_approve']
-                    or forum_role['can_pin_threads']
-                    or forum_role['can_move_threads_posts']
-                    or forum_role['can_close_threads']
-                    or forum_role['can_delete_threads']
-                    )
-        except KeyError:
-            return False
-
-    def can_mod_posts(self, thread):
-        try:
-            forum_role = self.acl[thread.forum.pk]
-            return (
-                    forum_role['can_edit_threads_posts']
-                    or forum_role['can_move_threads_posts']
-                    or forum_role['can_close_threads']
-                    or forum_role['can_delete_threads']
-                    or forum_role['can_delete_posts']
-                    )
-        except KeyError:
-            return False
-
-    def can_approve(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            return forum_role['can_approve']
-        except KeyError:
-            return False
-
-    def can_protect(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            return forum_role['can_protect_posts']
-        except KeyError:
-            return False
-
-    def can_delete_thread(self, user, forum, thread, post):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
-                return False
-            if post.protected and not forum_role['can_protect_posts']:
-                return False
-            if forum_role['can_delete_threads']:
-                return forum_role['can_delete_threads']
-            if thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads']:
-                return 1
-            return False
-        except KeyError:
-            return False
-
-    def allow_delete_thread(self, user, forum, thread, post, delete=False):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_close_threads']:
-                if forum.closed:
-                    raise ACLError403(_("You don't have permission to delete threads in closed forum."))
-                if thread.closed:
-                    raise ACLError403(_("This thread is closed, you cannot delete it."))
-            if post.protected and not forum_role['can_protect_posts']:
-                raise ACLError403(_("This post is protected, you cannot delete it."))
-            if delete and forum_role['can_delete_threads'] < 2:
-                raise ACLError403(_("You cannot hard delete this thread."))
-            if not (forum_role['can_delete_threads'] or (thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads'])):
-                raise ACLError403(_("You don't have permission to delete this thread."))
-            if thread.deleted and not delete:
-                raise ACLError403(_("This thread is already deleted."))
-        except KeyError:
-            raise ACLError403(_("You don't have permission to delete this thread."))
-
-    def can_delete_post(self, user, forum, thread, post):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
-                return False
-            if post.protected and not forum_role['can_protect_posts']:
-                return False
-            if forum_role['can_delete_posts']:
-                return forum_role['can_delete_posts']
-            if post.user_id == user.pk and not post.protected and forum_role['can_soft_delete_own_posts']:
-                return 1
-            return False
-        except KeyError:
-            return False
-
-    def allow_delete_post(self, user, forum, thread, post, delete=False):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_close_threads']:
-                if forum.closed:
-                    raise ACLError403(_("You don't have permission to delete posts in closed forum."))
-                if thread.closed:
-                    raise ACLError403(_("This thread is closed, you cannot delete its posts."))
-            if post.protected and not forum_role['can_protect_posts']:
-                raise ACLError403(_("This post is protected, you cannot delete it."))
-            if delete and forum_role['can_delete_posts'] < 2:
-                raise ACLError403(_("You cannot hard delete this post."))
-            if not (forum_role['can_delete_posts'] or (post.user_id == user.pk and forum_role['can_soft_delete_own_posts'])):
-                raise ACLError403(_("You don't have permission to delete this post."))
-            if post.deleted and not delete:
-                raise ACLError403(_("This post is already deleted."))
-        except KeyError:
-            raise ACLError403(_("You don't have permission to delete this post."))
-
-    def can_see_deleted_threads(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            return forum_role['can_delete_threads']
-        except KeyError:
-            return False
-
-    def can_see_deleted_posts(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            return forum_role['can_delete_posts']
-        except KeyError:
-            return False
-
-    def allow_deleted_post_view(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_delete_posts']:
-                raise ACLError404()
-        except KeyError:
-            raise ACLError404()
-        
-    def can_upvote_posts(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            return forum_role['can_upvote_posts']
-        except KeyError:
-            return False
-        
-    def can_downvote_posts(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            return forum_role['can_downvote_posts']
-        except KeyError:
-            return False
-        
-    def can_see_post_score(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            return forum_role['can_see_posts_scores']
-        except KeyError:
-            return False
-        
-    def can_see_post_votes(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            return forum_role['can_see_votes']
-        except KeyError:
-            return False
-
-    def allow_post_upvote(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_upvote_posts']:
-                raise ACLError403(_("You cannot upvote posts in this forum."))
-        except KeyError:
-            raise ACLError403(_("You cannot upvote posts in this forum."))
-
-    def allow_post_downvote(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_downvote_posts']:
-                raise ACLError403(_("You cannot downvote posts in this forum."))
-        except KeyError:
-            raise ACLError403(_("You cannot downvote posts in this forum."))
-        
-    def allow_post_votes_view(self, forum):
-        try:
-            forum_role = self.acl[forum.pk]
-            if not forum_role['can_see_votes']:
-                raise ACLError403(_("You don't have permission to see who voted on this post."))
-        except KeyError:
-            raise ACLError403(_("You don't have permission to see who voted on this post."))
-
-
-def build_forums(acl, perms, forums, forum_roles):
-    acl.threads = ThreadsACL()
-    for forum in forums:
-        forum_role = {
-                     'can_read_threads': 0,
-                     'can_start_threads': 0,
-                     'can_edit_own_threads': False,
-                     'can_soft_delete_own_threads': False,
-                     'can_write_posts': 0,
-                     'can_edit_own_posts': False,
-                     'can_soft_delete_own_posts': False,
-                     'can_upvote_posts': False,
-                     'can_downvote_posts': False,
-                     'can_see_posts_scores': 0,
-                     'can_see_votes': False,
-                     'can_make_polls': False,
-                     'can_vote_in_polls': False,
-                     'can_see_poll_votes': False,
-                     'can_see_attachments': False,
-                     'can_upload_attachments': False,
-                     'can_download_attachments': False,
-                     'attachment_size': 100,
-                     'attachment_limit': 3,
-                     'can_approve': False,
-                     'can_edit_labels': False,
-                     'can_see_changelog': False,
-                     'can_make_annoucements': False,
-                     'can_pin_threads': 0,
-                     'can_edit_threads_posts': False,
-                     'can_move_threads_posts': False,
-                     'can_close_threads': False,
-                     'can_protect_posts': False,
-                     'can_delete_threads': 0,
-                     'can_delete_posts': 0,
-                     'can_delete_polls': 0,
-                     'can_delete_attachments': False,
-                     }
-        for perm in perms:
-            try:
-                role = forum_roles[perm['forums'][forum.pk]]
-                for p in forum_role:
-                    try:
-                        if p in ['attachment_size', 'attachment_limit'] and role[p] == 0:
-                            forum_role[p] = 0
-                        elif role[p] > forum_role[p]:
-                            forum_role[p] = role[p]
-                    except KeyError:
-                        pass
-            except KeyError:
-                pass
-        acl.threads.acl[forum.pk] = forum_role

+ 0 - 127
notrefactored/threads/fixtures.py

@@ -1,127 +0,0 @@
-from misago.settings.fixtures import load_settings_fixture, update_settings_fixture
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-settings_fixtures = (
-    # Threads Settings
-    ('threads', {
-         'name': _("Threads and Posts Settings"),
-         'description': _("Those settings control your forum's threads and posts."),
-         'settings': (
-            ('thread_name_min', {
-                'value':        4,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 1},
-                'separator':    _("Threads"),
-                'name':         _("Min. Thread Name Length"),
-                'description':  _('Minimal allowed thread name length.'),
-            }),
-            ('thread_name_max', {
-                'value':        60,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 5, 'max': 100},
-                'name':         _("Max. Thread Name Length"),
-                'description':  _('Maximum allowed thread name length.'),
-            }),
-            ('threads_per_page', {
-                'value':        40,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 5},
-                'name':         _("Threads per page"),
-                'description':  _("Number of threads displayed on page in forum view."),
-            }),
-            ('avatars_on_threads_list', {
-                'value':        False,
-                'type':         "boolean",
-                'input':        "yesno",
-                'name':         _("Display avatars on threads list"),
-                'description':  _("Unlike basic user data, avatars are not cached - turning this option on will cause one extra query on threads lists."),
-            }),
-            ('thread_ranking_size', {
-                'value':        6,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0, 'max': 30},
-                'separator':    _("Thread Popularity Ranking"),
-                'name':         _('Threads on "Popular Threads" list'),
-                'description':  _('Enter number of threads to be displayed on "Popular Threads" list on board index or 0 to don\'t display any threads there.'),
-            }),
-            ('thread_ranking_refresh', {
-                'value':        60,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'name':         _('Ranking Update Frequency'),
-                'description':  _('Enter minimum of number of minutes between ranking updates or zero to update ranking on every request - strongly discouraged for active forums.'),
-            }),
-            ('thread_ranking_initial_score', {
-                'value':        30,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'name':         _('Initial Thread Score'),
-                'description':  _("Initial Thread Score helps new threads overtake old threads in ranking."),
-            }),
-            ('thread_ranking_reply_score', {
-                'value':        5,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'name':         _('New Reply Score'),
-                'description':  _("Only replies visible to all members increase thread inflation."),
-            }),
-            ('thread_ranking_inflation', {
-                'value':        20,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0, 'max': 99},
-                'name':         _('Score inflation'),
-                'description':  _("Thread popularity system requires inflation to be defined in order to be effective. updatethreadranking task will lower thread scores by percent defined here on every launch. For example, yf you enter 5, thread scores will be lowered by 5% on every update. Enter zero to disable inflation."),
-            }),
-            ('post_length_min', {
-                'value':        5,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 5},
-                'separator':    _("Posts"),
-                'name':         _("Min. Post Length"),
-                'description':  _("Minimal allowed post length."),
-            }),
-            ('post_merge_time', {
-                'value':        5,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'name':         _("Automatic Post Merge timespan"),
-                'description':  _("Forum can automatically merge member posts if interval between postings is shorter than specified number of minutes."),
-            }),
-            ('posts_per_page', {
-                'value':        15,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 5},
-                'name':         _("Posts per page"),
-                'description':  _("Number of posts per page in thread view."),
-            }),
-            ('thread_length', {
-                'value':        300,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'name':         _("Thread Length Limit"),
-                'description':  _('Long threads are hard to follow and search. You can force users to create few shorter threads instead of one long by setting thread lenght limits. Users with "Can close threads" permission will still be able to post in threads that have reached posts limit.'),
-            }),
-       ),
-    }),
-)
-
-
-def load_fixtures():
-    load_settings_fixture(settings_fixtures)
-
-
-def update_fixtures():
-    update_settings_fixture(settings_fixtures)

+ 0 - 226
notrefactored/threads/forms.py

@@ -1,226 +0,0 @@
-from django import forms
-from django.conf import settings
-from django.utils.translation import ungettext, ugettext_lazy as _
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forms import Form, ForumChoiceField
-from misago.forums.models import Forum
-from misago.threads.models import Thread
-from misago.utils import slugify
-from misago.utils.validators import validate_sluggable
-
-class ThreadNameMixin(object):
-    def clean_thread_name(self):
-        data = self.cleaned_data['thread_name']
-        slug = slugify(data)
-        if len(slug) < self.request.settings['thread_name_min']:
-            raise forms.ValidationError(ungettext(
-                                                  "Thread name must contain at least one alpha-numeric character.",
-                                                  "Thread name must contain at least %(count)d alpha-numeric characters.",
-                                                  self.request.settings['thread_name_min']
-                                                  ) % {'count': self.request.settings['thread_name_min']})
-        if len(data) > self.request.settings['thread_name_max']:
-            raise forms.ValidationError(ungettext(
-                                                  "Thread name cannot be longer than %(count)d character.",
-                                                  "Thread name cannot be longer than %(count)d characters.",
-                                                  self.request.settings['thread_name_max']
-                                                  ) % {'count': self.request.settings['thread_name_max']})
-        return data
-
-
-class PostForm(Form, ThreadNameMixin):
-    post = forms.CharField(widget=forms.Textarea)
-
-    def __init__(self, data=None, file=None, request=None, mode=None, *args, **kwargs):
-        self.mode = mode
-        super(PostForm, self).__init__(data, file, request=request, *args, **kwargs)
-
-    def finalize_form(self):
-        self.layout = [
-                       [
-                        None,
-                        [
-                         ('thread_name', {'label': _("Thread Name")}),
-                         ('edit_reason', {'label': _("Edit Reason")}),
-                         ('post', {'label': _("Post Content")}),
-                         ],
-                        ],
-                       ]
-
-        if self.mode in ['edit_thread', 'edit_post']:
-            self.fields['edit_reason'] = forms.CharField(max_length=255, required=False, help_text=_("Optional reason for changing this post."))
-        else:
-            del self.layout[0][1][1]
-
-        if self.mode not in ['edit_thread', 'new_thread']:
-            del self.layout[0][1][0]
-        else:
-            self.fields['thread_name'] = forms.CharField(
-                                                         max_length=self.request.settings['thread_name_max'],
-                                                         validators=[validate_sluggable(
-                                                                                        _("Thread name must contain at least one alpha-numeric character."),
-                                                                                        _("Thread name is too long. Try shorter name.")
-                                                                                        )])
-
-    def clean_post(self):
-        data = self.cleaned_data['post']
-        if len(data) < self.request.settings['post_length_min']:
-            raise forms.ValidationError(ungettext(
-                                                  "Post content cannot be empty.",
-                                                  "Post content cannot be shorter than %(count)d characters.",
-                                                  self.request.settings['post_length_min']
-                                                  ) % {'count': self.request.settings['post_length_min']})
-        return data
-
-
-
-class SplitThreadForm(Form, ThreadNameMixin):
-    def finalize_form(self):
-        self.layout = [
-                       [
-                        None,
-                        [
-                         ('thread_name', {'label': _("New Thread Name")}),
-                         ('thread_forum', {'label': _("New Thread Forum")}),
-                         ],
-                        ],
-                       ]
-
-        self.fields['thread_name'] = forms.CharField(
-                                                     max_length=self.request.settings['thread_name_max'],
-                                                     validators=[validate_sluggable(
-                                                                                    _("Thread name must contain at least one alpha-numeric character."),
-                                                                                    _("Thread name is too long. Try shorter name.")
-                                                                                    )])
-        self.fields['thread_forum'] = ForumChoiceField(queryset=Forum.tree.get(token='root').get_descendants().filter(pk__in=self.request.acl.forums.acl['can_browse']))
-
-    def clean_thread_forum(self):
-        new_forum = self.cleaned_data['thread_forum']
-        # Assert its forum and its not current forum
-        if new_forum.type != 'forum':
-            raise forms.ValidationError(_("This is not a forum."))
-        return new_forum
-
-
-class MovePostsForm(Form, ThreadNameMixin):
-    error_source = 'thread_url'
-
-    def __init__(self, data=None, request=None, thread=None, *args, **kwargs):
-        self.thread = thread
-        super(MovePostsForm, self).__init__(data, request=request, *args, **kwargs)
-
-    def finalize_form(self):
-        self.layout = [
-                       [
-                        None,
-                        [
-                         ('thread_url', {'label': _("New Thread Link"), 'help_text': _("To select new thread, simply copy and paste here its link.")}),
-                         ],
-                        ],
-                       ]
-
-        self.fields['thread_url'] = forms.CharField()
-
-    def clean_thread_url(self):
-        from django.core.urlresolvers import resolve
-        from django.http import Http404
-        thread_url = self.cleaned_data['thread_url']
-        try:
-            thread_url = thread_url[len(settings.BOARD_ADDRESS):]
-            match = resolve(thread_url)
-            thread = Thread.objects.get(pk=match.kwargs['thread'])
-            self.request.acl.threads.allow_thread_view(self.request.user, thread)
-            if thread.pk == self.thread.pk:
-                raise forms.ValidationError(_("New thread is same as current one."))
-            return thread
-        except (Http404, KeyError):
-            raise forms.ValidationError(_("This is not a correct thread URL."))
-        except (Thread.DoesNotExist, ACLError403, ACLError404):
-            raise forms.ValidationError(_("Thread could not be found."))
-
-
-class QuickReplyForm(Form):
-    post = forms.CharField(widget=forms.Textarea)
-
-
-class MoveThreadsForm(Form):
-    error_source = 'new_forum'
-
-    def __init__(self, data=None, request=None, forum=None, *args, **kwargs):
-        self.forum = forum
-        super(MoveThreadsForm, self).__init__(data, request=request, *args, **kwargs)
-
-    def finalize_form(self):
-        self.fields['new_forum'] = ForumChoiceField(queryset=Forum.tree.get(token='root').get_descendants().filter(pk__in=self.request.acl.forums.acl['can_browse']))
-        self.layout = [
-                       [
-                        None,
-                        [
-                         ('new_forum', {'label': _("Move Threads to"), 'help_text': _("Select forum you want to move threads to.")}),
-                         ],
-                        ],
-                       ]
-
-    def clean_new_forum(self):
-        new_forum = self.cleaned_data['new_forum']
-        # Assert its forum and its not current forum
-        if new_forum.type != 'forum':
-            raise forms.ValidationError(_("This is not forum."))
-        if new_forum.pk == self.forum.pk:
-            raise forms.ValidationError(_("New forum is same as current one."))
-        return new_forum
-
-
-class MergeThreadsForm(Form, ThreadNameMixin):
-    def __init__(self, data=None, request=None, threads=[], *args, **kwargs):
-        self.threads = threads
-        super(MergeThreadsForm, self).__init__(data, request=request, *args, **kwargs)
-
-    def finalize_form(self):
-        self.fields['new_forum'] = ForumChoiceField(queryset=Forum.tree.get(token='root').get_descendants().filter(pk__in=self.request.acl.forums.acl['can_browse']), initial=self.threads[0].forum)
-        self.fields['thread_name'] = forms.CharField(
-                                                     max_length=self.request.settings['thread_name_max'],
-                                                     initial=self.threads[0].name,
-                                                     validators=[validate_sluggable(
-                                                                                    _("Thread name must contain at least one alpha-numeric character."),
-                                                                                    _("Thread name is too long. Try shorter name.")
-                                                                                    )])
-        self.layout = [
-                       [
-                        None,
-                        [
-                         ('thread_name', {'label': _("Thread Name"), 'help_text': _("Name of new thread that will be created as result of merge.")}),
-                         ('new_forum', {'label': _("Thread Forum"), 'help_text': _("Select forum you want to put new thread in.")}),
-                         ],
-                        ],
-                       [
-                        _("Merge Order"),
-                        [
-                         ],
-                        ],
-                       ]
-
-        choices = []
-        for i, thread in enumerate(self.threads):
-            choices.append((str(i), i + 1))
-        for i, thread in enumerate(self.threads):
-            self.fields['thread_%s' % thread.pk] = forms.ChoiceField(choices=choices, initial=str(i))
-            self.layout[1][1].append(('thread_%s' % thread.pk, {'label': thread.name}))
-
-    def clean_new_forum(self):
-        new_forum = self.cleaned_data['new_forum']
-        # Assert its forum
-        if new_forum.type != 'forum':
-            raise forms.ValidationError(_("This is not forum."))
-        return new_forum
-
-    def clean(self):
-        cleaned_data = super(MergeThreadsForm, self).clean()
-        self.merge_order = {}
-        lookback = []
-        for thread in self.threads:
-            order = int(cleaned_data['thread_%s' % thread.pk])
-            if order in lookback:
-                raise forms.ValidationError(_("One or more threads have same position in merge order."))
-            lookback.append(order)
-            self.merge_order[order] = thread
-        return cleaned_data

+ 0 - 0
notrefactored/threads/management/__init__.py


+ 0 - 0
notrefactored/threads/management/commands/__init__.py


+ 0 - 18
notrefactored/threads/management/commands/updatethreadranking.py

@@ -1,18 +0,0 @@
-from django.core.management.base import BaseCommand
-from django.db.models import F
-from misago.settings.settings import Settings
-from misago.threads.models import Thread
-
-class Command(BaseCommand):
-    """
-    This command is intended to work as CRON job fired every few days to update thread popularity ranking
-    """
-    help = 'Updates Popular Threads ranking'
-    def handle(self, *args, **options):
-        settings = Settings()
-        if settings['thread_ranking_inflation'] > 0:
-            inflation = float(100 - settings['thread_ranking_inflation']) / 100
-            Thread.objects.all().update(score=F('score') * inflation)
-            self.stdout.write('Thread ranking has been updated.\n')
-        else:
-            self.stdout.write('Thread ranking inflation is disabled.\n')

+ 0 - 382
notrefactored/threads/migrations/0001_initial.py

@@ -1,382 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'Thread'
-        db.create_table(u'threads_thread', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('forum', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forums.Forum'])),
-            ('weight', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('slug', self.gf('django.db.models.fields.SlugField')(max_length=255)),
-            ('replies', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('replies_reported', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('replies_moderated', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('replies_deleted', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('merges', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('score', self.gf('django.db.models.fields.PositiveIntegerField')(default=30)),
-            ('upvotes', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('downvotes', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('start', self.gf('django.db.models.fields.DateTimeField')()),
-            ('start_post', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='+', null=True, on_delete=models.SET_NULL, to=orm['threads.Post'])),
-            ('start_poster', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['users.User'], null=True, on_delete=models.SET_NULL, blank=True)),
-            ('start_poster_name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('start_poster_slug', self.gf('django.db.models.fields.SlugField')(max_length=255)),
-            ('start_poster_style', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('last', self.gf('django.db.models.fields.DateTimeField')()),
-            ('last_post', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='+', null=True, on_delete=models.SET_NULL, to=orm['threads.Post'])),
-            ('last_poster', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='+', null=True, on_delete=models.SET_NULL, to=orm['users.User'])),
-            ('last_poster_name', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('last_poster_slug', self.gf('django.db.models.fields.SlugField')(max_length=255, null=True, blank=True)),
-            ('last_poster_style', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('moderated', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('closed', self.gf('django.db.models.fields.BooleanField')(default=False)),
-        ))
-        db.send_create_signal(u'threads', ['Thread'])
-
-        # Adding model 'Post'
-        db.create_table(u'threads_post', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('forum', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forums.Forum'])),
-            ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['threads.Thread'])),
-            ('merge', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['users.User'], null=True, on_delete=models.SET_NULL, blank=True)),
-            ('user_name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39)),
-            ('agent', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('post', self.gf('django.db.models.fields.TextField')()),
-            ('post_preparsed', self.gf('django.db.models.fields.TextField')()),
-            ('upvotes', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('downvotes', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('checkpoints', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('date', self.gf('django.db.models.fields.DateTimeField')()),
-            ('edits', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('edit_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-            ('edit_reason', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('edit_user', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='+', null=True, on_delete=models.SET_NULL, to=orm['users.User'])),
-            ('edit_user_name', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('edit_user_slug', self.gf('django.db.models.fields.SlugField')(max_length=255, null=True, blank=True)),
-            ('reported', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('moderated', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('deleted', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('protected', self.gf('django.db.models.fields.BooleanField')(default=False)),
-        ))
-        db.send_create_signal(u'threads', ['Post'])
-
-        # Adding M2M table for field mentions on 'Post'
-        db.create_table(u'threads_post_mentions', (
-            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
-            ('post', models.ForeignKey(orm[u'threads.post'], null=False)),
-            ('user', models.ForeignKey(orm[u'users.user'], null=False))
-        ))
-        db.create_unique(u'threads_post_mentions', ['post_id', 'user_id'])
-
-        # Adding model 'Karma'
-        db.create_table(u'threads_karma', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('forum', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forums.Forum'])),
-            ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['threads.Thread'])),
-            ('post', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['threads.Post'])),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['users.User'], null=True, on_delete=models.SET_NULL, blank=True)),
-            ('user_name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('user_slug', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('date', self.gf('django.db.models.fields.DateTimeField')()),
-            ('ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39)),
-            ('agent', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('score', self.gf('django.db.models.fields.IntegerField')(default=0)),
-        ))
-        db.send_create_signal(u'threads', ['Karma'])
-
-        # Adding model 'Change'
-        db.create_table(u'threads_change', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('forum', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forums.Forum'])),
-            ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['threads.Thread'])),
-            ('post', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['threads.Post'])),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['users.User'], null=True, on_delete=models.SET_NULL, blank=True)),
-            ('user_name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('user_slug', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('date', self.gf('django.db.models.fields.DateTimeField')()),
-            ('ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39)),
-            ('agent', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('reason', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('thread_name_new', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('thread_name_old', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('post_content', self.gf('django.db.models.fields.TextField')()),
-            ('size', self.gf('django.db.models.fields.IntegerField')(default=0)),
-            ('change', self.gf('django.db.models.fields.IntegerField')(default=0)),
-        ))
-        db.send_create_signal(u'threads', ['Change'])
-
-        # Adding model 'Checkpoint'
-        db.create_table(u'threads_checkpoint', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('forum', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forums.Forum'])),
-            ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['threads.Thread'])),
-            ('post', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['threads.Post'])),
-            ('action', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['users.User'], null=True, on_delete=models.SET_NULL, blank=True)),
-            ('user_name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('user_slug', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('date', self.gf('django.db.models.fields.DateTimeField')()),
-            ('ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39)),
-            ('agent', self.gf('django.db.models.fields.CharField')(max_length=255)),
-        ))
-        db.send_create_signal(u'threads', ['Checkpoint'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Thread'
-        db.delete_table(u'threads_thread')
-
-        # Deleting model 'Post'
-        db.delete_table(u'threads_post')
-
-        # Removing M2M table for field mentions on 'Post'
-        db.delete_table('threads_post_mentions')
-
-        # Deleting model 'Karma'
-        db.delete_table(u'threads_karma')
-
-        # Deleting model 'Change'
-        db.delete_table(u'threads_change')
-
-        # Deleting model 'Checkpoint'
-        db.delete_table(u'threads_checkpoint')
-
-
-    models = {
-        u'forums.forum': {
-            'Meta': {'object_name': 'Forum'},
-            'attrs': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'description_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Thread']"}),
-            'last_thread_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_thread_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': u"orm['forums.Forum']"}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'posts_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'prune_last': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'prune_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'redirects': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirects_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'show_details': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads_delta': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'})
-        },
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'threads.change': {
-            'Meta': {'object_name': 'Change'},
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'change': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'post': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Post']"}),
-            'post_content': ('django.db.models.fields.TextField', [], {}),
-            'reason': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'thread_name_new': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'thread_name_old': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'user_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'user_slug': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'threads.checkpoint': {
-            'Meta': {'object_name': 'Checkpoint'},
-            'action': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'post': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Post']"}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'user_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'user_slug': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'threads.karma': {
-            'Meta': {'object_name': 'Karma'},
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'post': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Post']"}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'user_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'user_slug': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'threads.post': {
-            'Meta': {'object_name': 'Post'},
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'checkpoints': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'edit_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'edit_reason': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'edit_user_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edits': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'mentions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'mention_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'merge': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'post': ('django.db.models.fields.TextField', [], {}),
-            'post_preparsed': ('django.db.models.fields.TextField', [], {}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'reported': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'user_name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'threads.thread': {
-            'Meta': {'object_name': 'Thread'},
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last': ('django.db.models.fields.DateTimeField', [], {}),
-            'last_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'merges': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'replies': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_deleted': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_moderated': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_reported': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'score': ('django.db.models.fields.PositiveIntegerField', [], {'default': '30'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start': ('django.db.models.fields.DateTimeField', [], {}),
-            'start_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'start_poster': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'start_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'start_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'type': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'weight': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['threads']

+ 0 - 0
notrefactored/threads/migrations/__init__.py


+ 0 - 392
notrefactored/threads/models.py

@@ -1,392 +0,0 @@
-from datetime import timedelta
-from django.conf import settings
-from django.db import models
-from django.db.models import F
-from django.utils import timezone
-from django.utils.translation import ugettext_lazy as _
-from misago.forums.signals import move_forum_content
-from misago.threads.signals import move_thread, merge_thread, move_post, merge_post
-from misago.users.signals import delete_user_content, rename_user
-from misago.utils import slugify, ugettext_lazy
-from misago.readstracker.models import ForumRecord, ThreadRecord
-from misago.watcher.models import ThreadWatch
-
-class ThreadManager(models.Manager):
-    def filter_stats(self, start, end):
-        return self.filter(start__gte=start).filter(start__lte=end)
-
-    def with_reads(self, queryset, user):
-        threads = []
-        threads_dict = {}
-        forum_reads = {}
-        cutoff = timezone.now() - timedelta(days=settings.READS_TRACKER_LENGTH)
-
-        if user.is_authenticated() and user.join_date > cutoff:
-            cutoff = user.join_date
-            for row in ForumRecord.objects.filter(user=user).values('forum_id', 'cleared'):
-                forum_reads[row['forum_id']] = row['cleared']
-
-        for thread in queryset:
-            thread.is_read = True
-            if user.is_authenticated() and thread.last > cutoff:
-                try:
-                    thread.is_read = thread.last <= forum_reads[thread.forum_id]
-                except KeyError:
-                    pass
-
-            threads.append(thread)
-            threads_dict[thread.pk] = thread
-
-        if user.is_authenticated():
-            for read in ThreadRecord.objects.filter(user=user).filter(thread__in=threads_dict.keys()):
-                try:
-                    threads_dict[read.thread_id].is_read = (threads_dict[read.thread_id].last <= cutoff or 
-                                                            threads_dict[read.thread_id].last <= read.updated or
-                                                            threads_dict[read.thread_id].last <= forum_reads[read.forum_id])
-                except KeyError:
-                    pass
-
-        return threads
-
-
-class Thread(models.Model):
-    forum = models.ForeignKey('forums.Forum')
-    weight = models.PositiveIntegerField(default=0)
-    name = models.CharField(max_length=255)
-    slug = models.SlugField(max_length=255)
-    replies = models.PositiveIntegerField(default=0)
-    replies_reported = models.PositiveIntegerField(default=0)
-    replies_moderated = models.PositiveIntegerField(default=0)
-    replies_deleted = models.PositiveIntegerField(default=0)
-    merges = models.PositiveIntegerField(default=0)
-    score = models.PositiveIntegerField(default=30)
-    upvotes = models.PositiveIntegerField(default=0)
-    downvotes = models.PositiveIntegerField(default=0)
-    start = models.DateTimeField()
-    start_post = models.ForeignKey('Post', related_name='+', null=True, blank=True, on_delete=models.SET_NULL)
-    start_poster = models.ForeignKey('users.User', null=True, blank=True, on_delete=models.SET_NULL)
-    start_poster_name = models.CharField(max_length=255)
-    start_poster_slug = models.SlugField(max_length=255)
-    start_poster_style = models.CharField(max_length=255, null=True, blank=True)
-    last = models.DateTimeField()
-    last_post = models.ForeignKey('Post', related_name='+', null=True, blank=True, on_delete=models.SET_NULL)
-    last_poster = models.ForeignKey('users.User', related_name='+', null=True, blank=True, on_delete=models.SET_NULL)
-    last_poster_name = models.CharField(max_length=255, null=True, blank=True)
-    last_poster_slug = models.SlugField(max_length=255, null=True, blank=True)
-    last_poster_style = models.CharField(max_length=255, null=True, blank=True)
-    moderated = models.BooleanField(default=False)
-    deleted = models.BooleanField(default=False)
-    closed = models.BooleanField(default=False)
-
-    objects = ThreadManager()
-
-    statistics_name = _('New Threads')
-
-    def get_date(self):
-        return self.start
-
-    def move_to(self, move_to):
-        move_thread.send(sender=self, move_to=move_to)
-        self.forum = move_to
-
-    def merge_with(self, thread, merge):
-        merge_thread.send(sender=self, new_thread=thread, merge=merge)
-
-    def sync(self):
-        # Counters
-        self.replies = self.post_set.filter(moderated=False).count() - 1
-        if self.replies < 0:
-            self.replies = 0
-        self.replies_reported = self.post_set.filter(reported=True).count()
-        self.replies_moderated = self.post_set.filter(moderated=True).count()
-        self.replies_deleted = self.post_set.filter(deleted=True).count()
-        # First post
-        start_post = self.post_set.order_by('merge', 'id')[0:][0]
-        self.start = start_post.date
-        self.start_post = start_post
-        self.start_poster = start_post.user
-        self.start_poster_name = start_post.user_name
-        self.start_poster_slug = slugify(start_post.user_name)
-        self.start_poster_style = start_post.user.rank.style if start_post.user else ''
-        self.upvotes = start_post.upvotes
-        self.downvotes = start_post.downvotes
-        # Last visible post
-        if self.replies > 0:
-            last_post = self.post_set.order_by('-merge', '-id').filter(moderated=False)[0:][0]
-        else:
-            last_post = start_post
-        self.last = last_post.date
-        self.last_post = last_post
-        self.last_poster = last_post.user
-        self.last_poster_name = last_post.user_name
-        self.last_poster_slug = slugify(last_post.user_name)
-        self.last_poster_style = last_post.user.rank.style if last_post.user else ''
-        # Flags
-        self.moderated = start_post.moderated
-        self.deleted = start_post.deleted
-        self.merges = last_post.merge
-        
-    def email_watchers(self, request, post):
-        from misago.acl.builder import get_acl
-        from misago.acl.utils import ACLError403, ACLError404
-        
-        for watch in ThreadWatch.objects.filter(thread=self).filter(email=True).filter(last_read__gte=self.previous_last):
-            user = watch.user
-            if user.pk != request.user.pk:
-                try:
-                    acl = get_acl(request, user)
-                    acl.forums.allow_forum_view(self.forum)
-                    acl.threads.allow_thread_view(user, self)
-                    acl.threads.allow_post_view(user, self, post)
-                    if not user.is_ignoring(request.user):
-                        user.email_user(
-                            request,
-                            'post_notification',
-                            _('New reply in thread "%(thread)s"') % {'thread': self.name},
-                            {'author': request.user, 'post': post, 'thread': self}
-                            )
-                except (ACLError403, ACLError404):
-                    pass
-
-
-class PostManager(models.Manager):
-    def filter_stats(self, start, end):
-        return self.filter(date__gte=start).filter(date__lte=end)
-
-
-class Post(models.Model):
-    forum = models.ForeignKey('forums.Forum')
-    thread = models.ForeignKey(Thread)
-    merge = models.PositiveIntegerField(default=0)
-    user = models.ForeignKey('users.User', null=True, blank=True, on_delete=models.SET_NULL)
-    user_name = models.CharField(max_length=255)
-    ip = models.GenericIPAddressField()
-    agent = models.CharField(max_length=255)
-    post = models.TextField()
-    post_preparsed = models.TextField()
-    upvotes = models.PositiveIntegerField(default=0)
-    downvotes = models.PositiveIntegerField(default=0)
-    mentions = models.ManyToManyField('users.User', related_name="mention_set")
-    checkpoints = models.BooleanField(default=False)
-    date = models.DateTimeField()
-    edits = models.PositiveIntegerField(default=0)
-    edit_date = models.DateTimeField(null=True, blank=True)
-    edit_reason = models.CharField(max_length=255, null=True, blank=True)
-    edit_user = models.ForeignKey('users.User', related_name='+', null=True, blank=True, on_delete=models.SET_NULL)
-    edit_user_name = models.CharField(max_length=255, null=True, blank=True)
-    edit_user_slug = models.SlugField(max_length=255, null=True, blank=True)
-    reported = models.BooleanField(default=False)
-    moderated = models.BooleanField(default=False)
-    deleted = models.BooleanField(default=False)
-    protected = models.BooleanField(default=False)
-
-    objects = PostManager()
-
-    statistics_name = _('New Posts')
-
-    def get_date(self):
-        return self.date
-
-    def move_to(self, thread):
-        move_post.send(sender=self, move_to=thread)
-        self.thread = thread
-        self.forum = thread.forum
-        
-    def merge_with(self, post):
-        post.post = '%s\n- - -\n%s' % (post.post, self.post)
-        merge_post.send(sender=self, new_post=post)
-
-    def set_checkpoint(self, request, action):
-        if request.user.is_authenticated():
-            self.checkpoints = True
-            self.checkpoint_set.create(
-                                       forum=self.forum,
-                                       thread=self.thread,
-                                       post=self,
-                                       action=action,
-                                       user=request.user,
-                                       user_name=request.user.username,
-                                       user_slug=request.user.username_slug,
-                                       date=timezone.now(),
-                                       ip=request.session.get_ip(request),
-                                       agent=request.META.get('HTTP_USER_AGENT'),
-                                       )
-            
-    def notify_mentioned(self, request, users):
-        from misago.acl.builder import get_acl
-        from misago.acl.utils import ACLError403, ACLError404
-        
-        mentioned = self.mentions.all()
-        for slug, user in users.items():
-            if user.pk != request.user.pk and user not in mentioned:
-                self.mentions.add(user)
-                try:                    
-                    acl = get_acl(request, user)
-                    acl.forums.allow_forum_view(self.forum)
-                    acl.threads.allow_thread_view(user, self.thread)
-                    acl.threads.allow_post_view(user, self.thread, self)
-                    if not user.is_ignoring(request.user):
-                        alert = user.alert(ugettext_lazy("%(username)s has mentioned you in his reply in thread %(thread)s").message)
-                        alert.profile('username', request.user)
-                        alert.post('thread', self.thread, self)
-                        alert.save_all()
-                except (ACLError403, ACLError404):
-                    pass
-
-
-class Karma(models.Model):
-    forum = models.ForeignKey('forums.Forum')
-    thread = models.ForeignKey(Thread)
-    post = models.ForeignKey(Post)
-    user = models.ForeignKey('users.User', null=True, blank=True, on_delete=models.SET_NULL)
-    user_name = models.CharField(max_length=255)
-    user_slug = models.CharField(max_length=255)
-    date = models.DateTimeField()
-    ip = models.GenericIPAddressField()
-    agent = models.CharField(max_length=255)
-    score = models.IntegerField(default=0)
-    
-
-class Change(models.Model):
-    forum = models.ForeignKey('forums.Forum')
-    thread = models.ForeignKey(Thread)
-    post = models.ForeignKey(Post)
-    user = models.ForeignKey('users.User', null=True, blank=True, on_delete=models.SET_NULL)
-    user_name = models.CharField(max_length=255)
-    user_slug = models.CharField(max_length=255)
-    date = models.DateTimeField()
-    ip = models.GenericIPAddressField()
-    agent = models.CharField(max_length=255)
-    reason = models.CharField(max_length=255, null=True, blank=True)
-    thread_name_new = models.CharField(max_length=255, null=True, blank=True)
-    thread_name_old = models.CharField(max_length=255, null=True, blank=True)
-    post_content = models.TextField()
-    size = models.IntegerField(default=0)
-    change = models.IntegerField(default=0)
-
-
-class Checkpoint(models.Model):
-    forum = models.ForeignKey('forums.Forum')
-    thread = models.ForeignKey(Thread)
-    post = models.ForeignKey(Post)
-    action = models.CharField(max_length=255)
-    user = models.ForeignKey('users.User', null=True, blank=True, on_delete=models.SET_NULL)
-    user_name = models.CharField(max_length=255)
-    user_slug = models.CharField(max_length=255)
-    date = models.DateTimeField()
-    ip = models.GenericIPAddressField()
-    agent = models.CharField(max_length=255)
-
-
-"""
-Signals
-"""
-def rename_user_handler(sender, **kwargs):
-    Thread.objects.filter(start_poster=sender).update(
-                                                     start_poster_name=sender.username,
-                                                     start_poster_slug=sender.username_slug,
-                                                     )
-    Thread.objects.filter(last_poster=sender).update(
-                                                     last_poster_name=sender.username,
-                                                     last_poster_slug=sender.username_slug,
-                                                     )
-    Post.objects.filter(user=sender).update(
-                                            user_name=sender.username,
-                                            )
-    Post.objects.filter(edit_user=sender).update(
-                                                 edit_user_name=sender.username,
-                                                 edit_user_slug=sender.username_slug,
-                                                 )
-    Karma.objects.filter(user=sender).update(
-                                             user_name=sender.username,
-                                             user_slug=sender.username_slug,
-                                             )
-    Change.objects.filter(user=sender).update(
-                                              user_name=sender.username,
-                                              user_slug=sender.username_slug,
-                                              )
-    Checkpoint.objects.filter(user=sender).update(
-                                                  user_name=sender.username,
-                                                  user_slug=sender.username_slug,
-                                                  )
-
-rename_user.connect(rename_user_handler, dispatch_uid="rename_user_threads")
-
-
-def delete_user_content_handler(sender, **kwargs):
-    for thread in Thread.objects.filter(start_poster=sender):
-        thread.delete()
-    threads = []
-    prev_posts = []
-    for post in sender.post_set.filter(checkpoints=True):
-        threads.append(post.thread_id)
-        prev_post = Post.objects.filter(thread=post.thread_id).exclude(merge__gt=post.merge).exclude(user=sender).order_by('merge', '-id')[:1][0]
-        post.checkpoint_set.update(post=prev_post)
-        if not prev_post.pk in prev_posts:
-            prev_posts.append(prev_post.pk)
-    sender.post_set.all().delete()
-    Post.objects.filter(id__in=prev_posts).update(checkpoints=True)
-    for post in sender.post_set.distinct().values('thread_id').iterator():
-        if not post['thread_id'] in threads:
-            threads.append(post['thread_id'])
-    for post in Post.objects.filter(user=sender):
-        post.delete()
-    for thread in Thread.objects.filter(id__in=threads):
-        thread.sync()
-        thread.save(force_update=True)
-
-delete_user_content.connect(delete_user_content_handler, dispatch_uid="delete_user_threads_posts")
-
-
-def move_forum_content_handler(sender, **kwargs):
-    Thread.objects.filter(forum=sender).update(forum=kwargs['move_to'])
-    Post.objects.filter(forum=sender).update(forum=kwargs['move_to'])
-    Karma.objects.filter(forum=sender).update(forum=kwargs['move_to'])
-    Change.objects.filter(forum=sender).update(forum=kwargs['move_to'])
-    Checkpoint.objects.filter(forum=sender).update(forum=kwargs['move_to'])
-
-move_forum_content.connect(move_forum_content_handler, dispatch_uid="move_forum_threads_posts")
-
-
-def move_thread_handler(sender, **kwargs):
-    Post.objects.filter(thread=sender).update(forum=kwargs['move_to'])
-    Karma.objects.filter(thread=sender).update(forum=kwargs['move_to'])
-    Change.objects.filter(thread=sender).update(forum=kwargs['move_to'])
-    Checkpoint.objects.filter(thread=sender).update(forum=kwargs['move_to'])
-
-move_thread.connect(move_thread_handler, dispatch_uid="move_thread")
-
-
-def merge_thread_handler(sender, **kwargs):
-    Post.objects.filter(thread=sender).update(thread=kwargs['new_thread'], merge=F('merge') + kwargs['merge'])
-    Karma.objects.filter(thread=sender).update(thread=kwargs['new_thread'])
-    Change.objects.filter(thread=sender).update(thread=kwargs['new_thread'])
-    Checkpoint.objects.filter(thread=sender).delete()
-
-merge_thread.connect(merge_thread_handler, dispatch_uid="merge_threads")
-
-
-def move_posts_handler(sender, **kwargs):
-    Change.objects.filter(post=sender).update(forum=kwargs['move_to'].forum, thread=kwargs['move_to'])
-    Karma.objects.filter(post=sender).update(forum=kwargs['move_to'].forum, thread=kwargs['move_to'])
-    if sender.checkpoints:
-        prev_post = Post.objects.filter(thread=sender.thread_id).filter(merge__lte=sender.merge).exclude(id=sender.pk).order_by('merge', '-id')[:1][0]
-        Checkpoint.objects.filter(post=sender).update(post=prev_post)
-        prev_post.checkpoints = True
-        prev_post.save(force_update=True)
-    sender.checkpoints = False
-
-move_post.connect(move_posts_handler, dispatch_uid="move_posts")
-
-
-def merge_posts_handler(sender, **kwargs):
-    Change.objects.filter(post=sender).update(post=kwargs['new_post'])
-    Checkpoint.objects.filter(post=sender).update(post=kwargs['new_post'])
-    Karma.objects.filter(post=sender).update(post=kwargs['new_post'])
-    if sender.checkpoints:
-        kwargs['new_post'].checkpoints = True
-    kwargs['new_post'].upvotes += self.upvotes
-    kwargs['new_post'].downvotes += self.downvotes
-    kwargs['new_post'].score += self.score
-
-merge_post.connect(merge_posts_handler, dispatch_uid="merge_posts")

+ 0 - 6
notrefactored/threads/signals.py

@@ -1,6 +0,0 @@
-import django.dispatch
-
-move_thread = django.dispatch.Signal(providing_args=["move_to"])
-move_post = django.dispatch.Signal(providing_args=["move_to"])
-merge_thread = django.dispatch.Signal(providing_args=["new_thread", "merge"])
-merge_post = django.dispatch.Signal(providing_args=["new_post"])

+ 0 - 161
notrefactored/threads/tests.py

@@ -1,161 +0,0 @@
-from django.core.management import call_command
-from django.utils import timezone, unittest
-from django.test.client import RequestFactory
-from misago.settings.models import Setting
-from misago.forums.models import Forum
-from misago.sessions.sessions import SessionMock
-from misago.threads.models import Thread, Post, Change, Checkpoint
-from misago.threads.testutils import create_thread, create_post 
-from misago.users.models import User
-
-class DeleteThreadTestCase(unittest.TestCase):
-    def setUp(self):
-        call_command('loaddata', quiet=True)
-        self.factory = RequestFactory()
-        
-        Post.objects.all().delete()
-        Thread.objects.all().delete()
-        User.objects.all().delete()
-        self.user = User.objects.create_user('Neddart', 'ned@test.com', 'pass')
-        self.user_alt = User.objects.create_user('Robert', 'rob@test.com', 'pass')
-        self.forum = Forum.objects.get(id=1)
-        
-        self.thread = create_thread(self.forum)
-        self.post = create_post(self.thread, self.user)
-     
-    def make_request(self, user=None):
-        request = self.factory.get('/customer/details')
-        request.session = SessionMock()
-        request.user = user
-        request.META['HTTP_USER_AGENT'] = 'TestAgent'
-        return request
-        
-    def test_deletion_owned(self):
-        """Check if user content delete results in correct deletion of thread"""
-        # Assert that test has been correctly initialised
-        self.assertEqual(Thread.objects.count(), 1)
-        self.assertEqual(Post.objects.count(), 1)
-        
-        # Run test
-        self.user.delete_content()
-        self.assertEqual(Thread.objects.count(), 0)
-        self.assertEqual(Post.objects.count(), 0)
-        
-    def test_deletion_other(self):
-        """Check if user content delete results in correct deletion of post"""
-        # Create second post
-        self.post = create_post(self.thread, self.user_alt)
-        
-        # Assert that test has been correctly initialised
-        self.assertEqual(Thread.objects.count(), 1)
-        self.assertEqual(Post.objects.count(), 2)
-        
-        # Run test
-        self.user_alt.delete_content()
-        self.assertEqual(Thread.objects.count(), 1)
-        self.assertEqual(Post.objects.count(), 1)
-        
-    def test_deletion_owned_other(self):
-        """Check if user content delete results in correct deletion of thread and posts"""
-        # Create second post
-        self.post = create_post(self.thread, self.user_alt)
-                
-        # Assert that test has been correctly initialised
-        self.assertEqual(Thread.objects.count(), 1)
-        self.assertEqual(Post.objects.count(), 2)
-        
-        # Run test
-        self.user.delete_content()
-        self.assertEqual(Thread.objects.count(), 0)
-        self.assertEqual(Post.objects.count(), 0)
-        
-    def test_deletion_checkpoints(self):
-        """Check if user content delete results in correct update of thread checkpoints"""
-        # Create an instance of a GET request.
-        request = self.make_request(self.user_alt)
-        
-        # Create second and third post
-        self.post = create_post(self.thread, self.user)
-        self.post_sec = create_post(self.thread, self.user_alt)
-        self.post_sec.set_checkpoint(request, 'locked')
-        self.post_sec.save(force_update=True)
-                
-        # Assert that test has been correctly initialised
-        self.assertEqual(Thread.objects.count(), 1)
-        self.assertEqual(Post.objects.count(), 3)
-        
-        # Run test
-        self.user_alt.delete_content()
-        self.assertEqual(Thread.objects.count(), 1)
-        self.assertEqual(Post.objects.count(), 2)
-        self.assertEqual(Checkpoint.objects.count(), 1)
-        self.assertEqual(Post.objects.filter(checkpoints=True).count(), 1)
-        self.assertEqual(Post.objects.get(id=self.post.pk).checkpoints, True)
-        self.assertEqual(Post.objects.get(id=self.post.pk).checkpoint_set.count(), 1)
-    
-    def test_threads_merge(self):
-        """Check if threads are correctly merged"""
-        # Create second thread
-        self.thread_b = create_thread(self.forum)
-        self.post_b = create_post(self.thread_b, self.user)
-        
-        # Merge threads
-        self.thread_b.merge_with(self.thread, 1)
-        self.thread_b.delete()
-        self.thread.merges += 1
-        self.thread.save(force_update=True)
-        
-        # See if merger was correct
-        self.assertEqual(Thread.objects.count(), 1)
-        self.assertEqual(Post.objects.count(), 2)
-        last_post = Post.objects.order_by('-id')[:1][0]
-        self.assertEqual(last_post.thread_id, self.thread.pk)
-        self.assertEqual(last_post.merge, 1)
-                
-        # Create third thread
-        self.thread_c = create_thread(self.forum)
-        self.post_c = create_post(self.thread_c, self.user)
-              
-        # Merge first thread into third one
-        self.thread.merge_with(self.thread_c, 1)
-        self.thread.delete()
-
-        # See if merger was correct
-        self.assertEqual(Thread.objects.count(), 1)
-        self.assertEqual(Post.objects.count(), 3)
-        last_post = Post.objects.get(id=last_post.pk)
-        self.assertEqual(last_post.thread_id, self.thread_c.pk)
-        self.assertEqual(last_post.merge, 2)
-        
-    def test_threads_move_checkpoints(self):
-        """Check if post_move correctly handles checkpoints"""
-        # Create thread with two posts
-        self.thread_b = create_thread(self.forum)
-        self.post_b = create_post(self.thread_b, self.user)
-        self.post_c = create_post(self.thread_b, self.user)
-        
-        # Create an instance of a GET request.
-        request = self.make_request(self.user)
-        
-        # Add checkpoint to post c
-        self.post_c.set_checkpoint(request, 'locked')
-        self.post_c.save(force_update=True)
-        
-        # Move post and sync threads
-        self.post_c.move_to(self.thread)
-        self.post_c.save(force_update=True)
-        self.thread.sync()
-        self.thread.save(force_update=True)
-        self.thread_b.sync()
-        self.thread_b.save(force_update=True)
-        
-        # See threads and post counters
-        self.assertEqual(Thread.objects.count(), 2)
-        self.assertEqual(Post.objects.count(), 3)
-        
-        # Refresh post b
-        self.post_b = Post.objects.get(id=self.post_b.pk)
-        
-        # Check if post b has post's c checkpoints
-        self.assertEqual(self.post_b.checkpoints, True)
-        self.assertEqual(self.post_b.checkpoint_set.count(), 1)

+ 0 - 40
notrefactored/threads/testutils.py

@@ -1,40 +0,0 @@
-from django.utils import timezone
-from misago.threads.models import Thread, Post, Change, Checkpoint
-
-def create_thread(forum):
-    thread = Thread()
-    thread.forum = forum
-    thread.name = 'Test Thread'
-    thread.slug = 'test-thread'
-    thread.start = timezone.now()
-    thread.last = timezone.now()
-    thread.save(force_insert=True)
-    return thread
-
-
-def create_post(thread, user):
-    now = timezone.now()
-    post = Post()
-    post.forum = thread.forum
-    post.thread = thread
-    post.date = now
-    post.user = user
-    post.user_name = user.username
-    post.ip = '127.0.0.1'
-    post.agent = 'No matter'
-    post.post = 'No matter'
-    post.post_preparsed = 'No matter'
-    post.save(force_insert=True)
-    if not thread.start_post:
-        thread.start = now
-        thread.start_post = post
-        thread.start_poster = user
-        thread.start_poster_name = user.username
-        thread.start_poster_slug = user.username_slug
-    thread.last = now
-    thread.last_post = post
-    thread.last_poster = user
-    thread.last_poster_name = user.username
-    thread.last_poster_slug = user.username_slug
-    thread.save(force_update=True)
-    return post

+ 0 - 34
notrefactored/threads/urls.py

@@ -1,34 +0,0 @@
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns('misago.threads.views',
-    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/$', 'ThreadsView', name="forum"),
-    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<page>\d+)/$', 'ThreadsView', name="forum"),
-    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/new/$', 'PostingNewThreadView', name="thread_new"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/$', 'ThreadView', name="thread"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/last/$', 'LastReplyView', name="thread_last"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/find-(?P<post>\d+)/$', 'FindReplyView', name="thread_find"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/new/$', 'NewReplyView', name="thread_new"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/moderated/$', 'FirstModeratedView', name="thread_moderated"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reported/$', 'FirstReportedView', name="thread_reported"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/show-hidden/$', 'ShowHiddenRepliesView', name="thread_show_hidden"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/watch/$', 'WatchThreadView', name="thread_watch"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/watch/email/$', 'WatchEmailThreadView', name="thread_watch_email"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/unwatch/$', 'UnwatchThreadView', name="thread_unwatch"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/unwatch/email/$', 'UnwatchEmailThreadView', name="thread_unwatch_email"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<page>\d+)/$', 'ThreadView', name="thread"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reply/$', 'PostingView', name="thread_reply", kwargs={'mode': 'new_post'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<quote>\d+)/reply/$', 'PostingNewReplyView', name="thread_reply"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/edit/$', 'PostingEditThreadView', name="thread_edit"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/edit/$', 'PostingEditReplyView', name="post_edit"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/delete/$', 'DeleteView', name="thread_delete", kwargs={'mode': 'delete_thread'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/hide/$', 'DeleteView', name="thread_hide", kwargs={'mode': 'hide_thread'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/delete/$', 'DeleteView', name="post_delete", kwargs={'mode': 'delete_post'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/hide/$', 'DeleteView', name="post_hide", kwargs={'mode': 'hide_post'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/info/$', 'DetailsView', name="post_info"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/upvote/$', 'UpvotePostView', name="post_upvote"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/downvote/$', 'DownvotePostView', name="post_downvote"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/votes/$', 'KarmaVotesView', name="post_votes"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/$', 'ChangelogView', name="changelog"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/$', 'ChangelogDiffView', name="changelog_diff"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/revert/$', 'ChangelogRevertView', name="changelog_revert"),
-)

+ 0 - 9
notrefactored/threads/views/__init__.py

@@ -1,9 +0,0 @@
-from misago.threads.views.list import *
-from misago.threads.views.jumps import *
-from misago.threads.views.thread import *
-from misago.threads.views.delete import *
-from misago.threads.views.karmas import *
-from misago.threads.views.posting import *
-from misago.threads.views.details import *
-from misago.threads.views.changelog import *
-

+ 0 - 14
notrefactored/threads/views/base.py

@@ -1,14 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from misago.utils import make_pagination
-
-class BaseView(object):
-    def __new__(cls, request, **kwargs):
-        obj = super(BaseView, cls).__new__(cls)
-        return obj(request, **kwargs)
-
-    def redirect_to_post(self, post):
-        pagination = make_pagination(0, self.request.acl.threads.filter_posts(self.request, self.thread, self.thread.post_set).filter(id__lte=post.pk).count(), self.request.settings.posts_per_page)
-        if pagination['total'] > 1:
-            return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug, 'page': pagination['total']}) + ('#post-%s' % post.pk))
-        return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}) + ('#post-%s' % post.pk))

+ 0 - 125
notrefactored/threads/views/changelog.py

@@ -1,125 +0,0 @@
-import difflib
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils.translation import ugettext as _
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forums.models import Forum
-from misago.markdown import post_markdown
-from misago.messages import Message
-from misago.threads.models import Thread, Post, Change
-from misago.threads.views.base import BaseView
-from misago.views import error403, error404
-from misago.utils import make_pagination, slugify
-
-class ChangelogBaseView(BaseView):
-    def fetch_target(self, kwargs):
-        self.thread = Thread.objects.get(pk=kwargs['thread'])
-        self.forum = self.thread.forum
-        self.proxy = Forum.objects.parents_aware_forum(self.forum)
-        self.request.acl.forums.allow_forum_view(self.forum)
-        self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
-        self.parents = Forum.objects.forum_parents(self.forum.pk, True)
-        self.post = Post.objects.select_related('user').get(pk=kwargs['post'], thread=self.thread.pk)
-        self.post.thread = self.thread
-        self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
-        self.request.acl.threads.allow_changelog_view(self.request.user, self.forum, self.post)
-
-    def dispatch(self, request, **kwargs):
-        raise NotImplementedError('ChangelogBaseView cannot be called directly. Did you forget to define custom "dispatch" method?')
-
-    def __call__(self, request, **kwargs):
-        self.request = request
-        self.forum = None
-        self.thread = None
-        self.post = None
-        try:
-            self.fetch_target(kwargs)
-            if not request.user.is_authenticated():
-                raise ACLError403(_("Guest, you have to sign-in in order to see posts changelogs."))
-        except (Forum.DoesNotExist, Thread.DoesNotExist, Post.DoesNotExist, Change.DoesNotExist):
-            return error404(self.request)
-        except ACLError403 as e:
-            return error403(request, e.message)
-        except ACLError404 as e:
-            return error404(request, e.message)
-        return self.dispatch(request, **kwargs)
-
-
-class ChangelogView(ChangelogBaseView):
-    def dispatch(self, request, **kwargs):
-        return request.theme.render_to_response('threads/changelog.html',
-                                                {
-                                                 'forum': self.forum,
-                                                 'parents': self.parents,
-                                                 'thread': self.thread,
-                                                 'post': self.post,
-                                                 'edits': self.post.change_set.prefetch_related('user').order_by('-id')
-                                                 },
-                                                context_instance=RequestContext(request))
-
-
-class ChangelogDiffView(ChangelogBaseView):
-    def fetch_target(self, kwargs):
-        super(ChangelogDiffView, self).fetch_target(kwargs)
-        self.change = self.post.change_set.get(pk=kwargs['change'])
-
-    def dispatch(self, request, **kwargs):
-        try:
-            next = self.post.change_set.filter(id__gt=self.change.pk)[:1][0]
-        except IndexError:
-            next = None
-        try:
-            prev = self.post.change_set.filter(id__lt=self.change.pk).order_by('-id')[:1][0]
-        except IndexError:
-            prev = None
-        self.forum.closed = self.proxy.closed
-        return request.theme.render_to_response('threads/changelog_diff.html',
-                                                {
-                                                 'forum': self.forum,
-                                                 'parents': self.parents,
-                                                 'thread': self.thread,
-                                                 'post': self.post,
-                                                 'change': self.change,
-                                                 'next': next,
-                                                 'prev': prev,
-                                                 'message': request.messages.get_message('changelog'),
-                                                 'l': 1,
-                                                 'diff': difflib.ndiff(self.change.post_content.splitlines(), self.post.post.splitlines()),
-                                                 },
-                                                context_instance=RequestContext(request))
-
-
-class ChangelogRevertView(ChangelogDiffView):
-    def fetch_target(self, kwargs):
-        super(ChangelogDiffView, self).fetch_target(kwargs)
-        self.change = self.post.change_set.get(pk=kwargs['change'])
-        self.request.acl.threads.allow_revert(self.proxy, self.thread)
-
-    def dispatch(self, request, **kwargs):
-        if ((not self.change.thread_name_old or self.thread.name == self.change.thread_name_old)
-            and (self.change.post_content == self.post.post)):
-            request.messages.set_flash(Message(_("No changes to revert.")), 'error', 'changelog')
-            return redirect(reverse('changelog_diff', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug, 'post': self.post.pk, 'change': self.change.pk}))
-
-        if self.change.thread_name_old and self.change.thread_name_old != self.thread.name:
-            self.thread.name = self.change.thread_name_old
-            self.thread.slug = slugify(self.change.thread_name_old)
-            self.thread.save(force_update=True)
-
-            if self.forum.last_thread_id == self.thread.pk:
-                self.forum.last_thread_name = self.change.thread_name_old
-                self.forum.last_thread_slug = slugify(self.change.thread_name_old)
-                self.forum.save(force_update=True)
-
-        if self.change.post_content != self.post.post:
-            self.post.post = self.change.post_content
-            md, self.post.post_preparsed = post_markdown(request, self.change.post_content)
-            self.post.save(force_update=True)
-
-        from misago.template.templatetags.django2jinja import reldate
-        request.messages.set_flash(Message(_("Post has been reverted to state from %(date)s.") % {'date': reldate(self.change.date).lower()}), 'success', 'threads_%s' % self.post.pk)
-        pagination = make_pagination(0, request.acl.threads.filter_posts(self.request, self.thread, self.thread.post_set).filter(id__lte=self.post.pk).count(), self.request.settings.posts_per_page)
-        if pagination['total'] > 1:
-            return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug, 'page': pagination['total']}) + ('#post-%s' % self.post.pk))
-        return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}) + ('#post-%s' % self.post.pk))

+ 0 - 106
notrefactored/threads/views/delete.py

@@ -1,106 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forums.models import Forum
-from misago.messages import Message
-from misago.threads.models import Thread, Post
-from misago.threads.views.base import BaseView
-from misago.views import error403, error404
-from misago.utils import make_pagination
-
-class DeleteView(BaseView):
-    def fetch_thread(self, kwargs):
-        self.thread = Thread.objects.get(pk=kwargs['thread'])
-        self.forum = self.thread.forum
-        self.request.acl.forums.allow_forum_view(self.forum)
-        self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
-        if self.mode in ['tread_delete', 'hide_thread']:
-            self.request.acl.threads.allow_delete_thread(
-                                                         self.request.user,
-                                                         self.forum,
-                                                         self.thread,
-                                                         self.thread.start_post,
-                                                         self.mode == 'delete_thread')
-            # Assert we are not user trying to delete thread with replies
-            acl = self.request.acl.threads.get_role(self.thread.forum_id)
-            if not acl['can_delete_threads']:
-                if self.thread.post_set.exclude(user_id=self.request.user.id).count() > 0:
-                    raise ACLError403(_("Somebody has already replied to this thread. You cannot delete it."))
-
-    def fetch_post(self, kwargs):
-        self.post = self.thread.post_set.get(pk=kwargs['post'])
-        if self.post.pk == self.thread.start_post_id:
-            raise Post.DoesNotExist()
-        self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
-        self.request.acl.threads.allow_delete_post(
-                                                   self.request.user,
-                                                   self.forum,
-                                                   self.thread,
-                                                   self.post,
-                                                   self.mode == 'delete_post')
-        acl = self.request.acl.threads.get_role(self.thread.forum_id)
-        if not acl['can_delete_posts'] and self.thread.post_set.filter(id__gt=self.post.pk).count() > 0:
-            raise ACLError403(_("Somebody has already replied to this post, you cannot delete it."))
-
-    def __call__(self, request, **kwargs):
-        self.request = request
-        self.mode = kwargs['mode']
-        try:
-            if not request.user.is_authenticated():
-                raise ACLError403(_("Guest, you have to sign-in in order to be able to delete replies."))
-            self.fetch_thread(kwargs)
-            if self.mode in ['hide_post', 'delete_post']:
-                self.fetch_post(kwargs)
-        except (Thread.DoesNotExist, Post.DoesNotExist):
-            return error404(self.request)
-        except ACLError403 as e:
-            return error403(request, e.message)
-        except ACLError404 as e:
-            return error404(request, e.message)
-
-        if self.mode == 'delete_thread':
-            self.thread.delete()
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            request.messages.set_flash(Message(_('Thread "%(thread)s" has been deleted.') % {'thread': self.thread.name}), 'success', 'threads')
-            return redirect(reverse('forum', kwargs={'forum': self.thread.forum.pk, 'slug': self.thread.forum.slug}))
-
-        if self.mode == 'hide_thread':
-            self.thread.start_post.deleted = True
-            self.thread.start_post.save(force_update=True)
-            self.thread.last_post.set_checkpoint(request, 'deleted')
-            self.thread.last_post.save(force_update=True)
-            self.thread.sync()
-            self.thread.save(force_update=True)
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            request.messages.set_flash(Message(_('Thread "%(thread)s" has been deleted.') % {'thread': self.thread.name}), 'success', 'threads')
-            if request.acl.threads.can_see_deleted_threads(self.thread.forum):
-                return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}))
-            return redirect(reverse('forum', kwargs={'forum': self.thread.forum.pk, 'slug': self.thread.forum.slug}))
-
-        if self.mode == 'delete_post':
-            self.post.delete()
-            self.thread.sync()
-            self.thread.save(force_update=True)
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            request.messages.set_flash(Message(_("Selected Reply has been deleted.")), 'success', 'threads')
-            return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}))
-
-        if self.mode == 'hide_post':
-            self.post.deleted = True
-            self.post.edit_date = timezone.now()
-            self.post.edit_user = request.user
-            self.post.edit_user_name = request.user.username
-            self.post.edit_user_slug = request.user.username_slug
-            self.post.save(force_update=True)
-            self.thread.sync()
-            self.thread.save(force_update=True)
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            request.messages.set_flash(Message(_("Selected Reply has been deleted.")), 'success', 'threads_%s' % self.post.pk)
-            return self.redirect_to_post(self.post)

+ 0 - 41
notrefactored/threads/views/details.py

@@ -1,41 +0,0 @@
-from django.template import RequestContext
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forums.models import Forum
-from misago.threads.models import Thread, Post
-from misago.threads.views.base import BaseView
-from misago.views import error403, error404
-
-class DetailsView(BaseView):
-    def fetch_target(self, kwargs):
-        self.thread = Thread.objects.get(pk=kwargs['thread'])
-        self.forum = self.thread.forum
-        self.proxy = Forum.objects.parents_aware_forum(self.forum)
-        self.request.acl.forums.allow_forum_view(self.forum)
-        self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
-        self.parents = Forum.objects.forum_parents(self.forum.pk, True)
-        self.post = Post.objects.select_related('user').get(pk=kwargs['post'], thread=self.thread.pk)
-        self.post.thread = self.thread
-        self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
-        self.request.acl.users.allow_details_view()
-
-    def __call__(self, request, **kwargs):
-        self.request = request
-        self.forum = None
-        self.thread = None
-        self.post = None
-        try:
-            self.fetch_target(kwargs)
-        except (Forum.DoesNotExist, Thread.DoesNotExist, Post.DoesNotExist):
-            return error404(self.request)
-        except ACLError403 as e:
-            return error403(request, e.message)
-        except ACLError404 as e:
-            return error404(request, e.message)
-        return request.theme.render_to_response('threads/details.html',
-                                                {
-                                                 'forum': self.forum,
-                                                 'parents': self.parents,
-                                                 'thread': self.thread,
-                                                 'post': self.post,
-                                                 },
-                                                context_instance=RequestContext(request))

+ 0 - 242
notrefactored/threads/views/jumps.py

@@ -1,242 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.acl.utils import ACLError403, ACLError404
-from misago.authn.decorators import block_guest
-from misago.csrf.decorators import check_csrf
-from misago.forums.models import Forum
-from misago.messages import Message
-from misago.readstracker.trackers import ThreadsTracker
-from misago.threads.models import Thread, Post, Karma
-from misago.threads.views.base import BaseView
-from misago.views import error403, error404
-from misago.utils import make_pagination
-from misago.watcher.models import ThreadWatch
-
-class JumpView(BaseView):
-    def fetch_thread(self, thread):
-        self.thread = Thread.objects.get(pk=thread)
-        self.forum = self.thread.forum
-        self.request.acl.forums.allow_forum_view(self.forum)
-        self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
-
-    def fetch_post(self, post):
-        self.post = self.thread.post_set.get(pk=post)
-        self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
-
-    def redirect(self, post):
-        pagination = make_pagination(0, self.request.acl.threads.filter_posts(self.request, self.thread, self.thread.post_set.filter(date__lt=post.date)).count() + 1, self.request.settings.posts_per_page)
-        if pagination['total'] > 1:
-            return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug, 'page': pagination['total']}) + ('#post-%s' % post.pk))
-        return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}) + ('#post-%s' % post.pk))
-
-    def make_jump(self):
-        raise NotImplementedError('JumpView cannot be called directly.')
-
-    def __call__(self, request, slug=None, thread=None, post=None):
-        self.request = request
-        try:
-            self.fetch_thread(thread)
-            if post:
-                self.fetch_post(post)
-            return self.make_jump()
-        except (Thread.DoesNotExist, Post.DoesNotExist):
-            return error404(self.request)
-        except ACLError403 as e:
-            return error403(request, e.message)
-        except ACLError404 as e:
-            return error404(request, e.message)
-
-
-class LastReplyView(JumpView):
-    def make_jump(self):
-        return self.redirect(self.thread.post_set.order_by('-id')[:1][0])
-
-
-class FindReplyView(JumpView):
-    def make_jump(self):
-        return self.redirect(self.post)
-
-
-class NewReplyView(JumpView):
-    def make_jump(self):
-        if not self.request.user.is_authenticated():
-            return self.redirect(self.thread.post_set.order_by('-id')[:1][0])
-        tracker = ThreadsTracker(self.request, self.forum)
-        read_date = tracker.get_read_date(self.thread)
-        post = self.thread.post_set.filter(date__gt=read_date).order_by('id')[:1]
-        if not post:
-            return self.redirect(self.thread.post_set.order_by('-id')[:1][0])
-        return self.redirect(post[0])
-
-
-class FirstModeratedView(JumpView):
-    def make_jump(self):
-        if not self.request.acl.threads.can_approve(self.forum):
-            raise ACLError404()
-        try:
-            return self.redirect(
-                self.thread.post_set.get(moderated=True))
-        except Post.DoesNotExist:
-            return error404(self.request)
-
-
-class FirstReportedView(JumpView):
-    def make_jump(self):
-        if not self.request.acl.threads.can_mod_posts(self.forum):
-            raise ACLError404()
-        try:
-            return self.redirect(
-                self.thread.post_set.get(reported=True))
-        except Post.DoesNotExist:
-            return error404(self.request)
-
-
-class ShowHiddenRepliesView(JumpView):
-    def make_jump(self):
-        @block_guest
-        @check_csrf
-        def view(request):
-            ignored_exclusions = request.session.get('unignore_threads', [])
-            ignored_exclusions.append(self.thread.pk)
-            request.session['unignore_threads'] = ignored_exclusions
-            request.messages.set_flash(Message(_('Replies made to this thread by members on your ignore list have been revealed.')), 'success', 'threads')
-            return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}))
-        return view(self.request)
-
-
-class WatchThreadView(JumpView):
-    def get_retreat(self):
-        return redirect(self.request.POST.get('retreat', reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug})))
-
-    def update_watcher(self, request, watcher):
-        request.messages.set_flash(Message(_('This thread has been added to your watched threads list.')), 'success', 'threads')
-
-    def make_jump(self):
-        @block_guest
-        @check_csrf
-        def view(request):
-            try:
-                watcher = ThreadWatch.objects.get(user=request.user, thread=self.thread)
-            except ThreadWatch.DoesNotExist:
-                watcher = ThreadWatch()
-                watcher.user = request.user
-                watcher.forum = self.forum
-                watcher.thread = self.thread
-                watcher.last_read = timezone.now()
-            self.update_watcher(request, watcher)
-            if watcher.pk:
-                watcher.save(force_update=True)
-            else:
-                watcher.save(force_insert=True)
-            return self.get_retreat()
-        return view(self.request)
-
-
-class WatchEmailThreadView(WatchThreadView):
-    def update_watcher(self, request, watcher):
-        watcher.email = True
-        if watcher.pk:
-            request.messages.set_flash(Message(_('You will now receive e-mail with notification when somebody replies to this thread.')), 'success', 'threads')
-        else:
-            request.messages.set_flash(Message(_('This thread has been added to your watched threads list. You will also receive e-mail with notification when somebody replies to it.')), 'success', 'threads')
-
-
-class UnwatchThreadView(WatchThreadView):
-    def update_watcher(self, request, watcher):
-        watcher.deleted = True
-        watcher.delete()
-        if watcher.email:
-            request.messages.set_flash(Message(_('This thread has been removed from your watched threads list. You will no longer receive e-mails with notifications when somebody replies to it.')), 'success', 'threads')
-        else:
-            request.messages.set_flash(Message(_('This thread has been removed from your watched threads list.')), 'success', 'threads')
-
-
-class UnwatchEmailThreadView(WatchThreadView):
-    def update_watcher(self, request, watcher):
-        watcher.email = False
-        request.messages.set_flash(Message(_('You will no longer receive e-mails with notifications when somebody replies to this thread.')), 'success', 'threads')
-
-
-class UpvotePostView(JumpView):        
-    def make_jump(self):
-        @block_guest
-        @check_csrf
-        def view(request):
-            if self.post.user_id == request.user.id:
-                return error404(request)
-            self.check_acl(request)
-            try:
-                vote = Karma.objects.get(user=request.user, post=self.post)
-                if self.thread.start_post_id == self.post.pk:
-                    if vote.score > 0:
-                        self.thread.upvotes -= 1
-                    else:
-                        self.thread.downvotes -= 1
-                if vote.score > 0:
-                    self.post.upvotes -= 1
-                    request.user.karma_given_p -= 1
-                    if self.post.user_id:
-                        self.post.user.karma_p -= 1
-                else:
-                    self.post.downvotes -= 1
-                    request.user.karma_given_n -= 1
-                    if self.post.user_id:
-                        self.post.user.karma_n -= 1
-            except Karma.DoesNotExist:
-                vote = Karma()
-            vote.forum = self.forum
-            vote.thread = self.thread
-            vote.post = self.post
-            vote.user = request.user
-            vote.user_name = request.user.username
-            vote.user_slug = request.user.username_slug
-            vote.date = timezone.now()
-            vote.ip = request.session.get_ip(request)
-            vote.agent = request.META.get('HTTP_USER_AGENT')
-            self.make_vote(request, vote)
-            request.messages.set_flash(Message(_('Your vote has been saved.')), 'success', 'threads_%s' % self.post.pk)
-            if vote.pk:
-                vote.save(force_update=True)
-            else:
-                vote.save(force_insert=True)
-            if self.thread.start_post_id == self.post.pk:
-                if vote.score > 0:
-                    self.thread.upvotes += 1
-                else:
-                    self.thread.downvotes += 1
-                self.thread.save(force_update=True)
-            if vote.score > 0:
-                self.post.upvotes += 1
-                request.user.karma_given_p += 1
-                if self.post.user_id:
-                    self.post.user.karma_p += 1
-                    self.post.user.score += request.settings['score_reward_karma_positive']
-            else:
-                self.post.downvotes += 1
-                request.user.karma_given_n += 1
-                if self.post.user_id:
-                    self.post.user.karma_n += 1
-                    self.post.user.score -= request.settings['score_reward_karma_negative']
-            self.post.save(force_update=True)
-            request.user.save(force_update=True)
-            if self.post.user_id:
-                self.post.user.save(force_update=True)
-            return self.redirect(self.post)
-        return view(self.request)
-    
-    def check_acl(self, request):
-        request.acl.threads.allow_post_upvote(self.forum)
-    
-    def make_vote(self, request, vote):
-        vote.score = 1
-
-
-class DownvotePostView(UpvotePostView):
-    def check_acl(self, request):
-        request.acl.threads.allow_post_downvote(self.forum)
-    
-    def make_vote(self, request, vote):
-        vote.score = -1

+ 0 - 43
notrefactored/threads/views/karmas.py

@@ -1,43 +0,0 @@
-from django.template import RequestContext
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forums.models import Forum
-from misago.threads.models import Thread, Post
-from misago.threads.views.base import BaseView
-from misago.views import error403, error404
-
-class KarmaVotesView(BaseView):
-    def fetch_target(self, kwargs):
-        self.thread = Thread.objects.get(pk=kwargs['thread'])
-        self.forum = self.thread.forum
-        self.proxy = Forum.objects.parents_aware_forum(self.forum)
-        self.request.acl.forums.allow_forum_view(self.forum)
-        self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
-        self.parents = Forum.objects.forum_parents(self.forum.pk, True)
-        self.post = Post.objects.select_related('user').get(pk=kwargs['post'], thread=self.thread.pk)
-        self.post.thread = self.thread
-        self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
-        self.request.acl.threads.allow_post_votes_view(self.forum)
-
-    def __call__(self, request, **kwargs):
-        self.request = request
-        self.forum = None
-        self.thread = None
-        self.post = None
-        try:
-            self.fetch_target(kwargs)
-        except (Forum.DoesNotExist, Thread.DoesNotExist, Post.DoesNotExist):
-            return error404(self.request)
-        except ACLError403 as e:
-            return error403(request, e.message)
-        except ACLError404 as e:
-            return error404(request, e.message)
-        return request.theme.render_to_response('threads/karmas.html',
-                                                {
-                                                 'forum': self.forum,
-                                                 'parents': self.parents,
-                                                 'thread': self.thread,
-                                                 'post': self.post,
-                                                 'upvotes': self.post.karma_set.filter(score=1),
-                                                 'downvotes': self.post.karma_set.filter(score=-1),
-                                                 },
-                                                context_instance=RequestContext(request))

+ 0 - 392
notrefactored/threads/views/list.py

@@ -1,392 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.db.models import Q
-from django import forms
-from django.forms import ValidationError
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forms import Form, FormLayout, FormFields
-from misago.forums.models import Forum
-from misago.messages import Message
-from misago.readstracker.trackers import ForumsTracker, ThreadsTracker
-from misago.threads.forms import MoveThreadsForm, MergeThreadsForm
-from misago.threads.models import Thread, Post
-from misago.threads.views.base import BaseView
-from misago.views import error403, error404
-from misago.utils import make_pagination, slugify
-
-class ThreadsView(BaseView):
-    def fetch_forum(self, forum):
-        self.forum = Forum.objects.get(pk=forum, type='forum')
-        self.proxy = Forum.objects.parents_aware_forum(self.forum)
-        self.request.acl.forums.allow_forum_view(self.forum)
-        self.parents = Forum.objects.forum_parents(self.forum.pk)
-        if self.forum.lft + 1 != self.forum.rght:
-            self.forum.subforums = Forum.objects.treelist(self.request.acl.forums, self.forum, tracker=ForumsTracker(self.request.user))
-        self.tracker = ThreadsTracker(self.request, self.forum)
-
-    def fetch_threads(self, page):
-        self.count = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).count()
-        self.pagination = make_pagination(page, self.count, self.request.settings.threads_per_page)
-        self.threads = []
-        ignored_users = []
-        queryset_anno = Thread.objects.filter(Q(forum=Forum.objects.token_to_pk('annoucements')) | (Q(forum=self.forum) & Q(weight=2)))
-        queryset_threads = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).order_by('-weight', '-last')
-        if self.request.user.is_authenticated():
-            ignored_users = self.request.user.ignored_users()
-            if ignored_users:
-                queryset_threads = queryset_threads.extra(where=["`threads_thread`.`start_poster_id` IS NULL OR `threads_thread`.`start_poster_id` NOT IN (%s)" % ','.join([str(i) for i in ignored_users])])
-        if self.request.settings.avatars_on_threads_list:
-            queryset_anno = queryset_anno.prefetch_related('start_poster', 'last_post')
-            queryset_threads = queryset_threads.prefetch_related('start_poster', 'last_poster')
-        for thread in queryset_anno:
-            self.threads.append(thread)
-        for thread in queryset_threads:
-            self.threads.append(thread)
-        if self.request.settings.threads_per_page < self.count:
-            self.threads = self.threads[self.pagination['start']:self.pagination['stop']]
-        for thread in self.threads:
-            thread.is_read = self.tracker.is_read(thread)
-            thread.last_poster_ignored = thread.last_poster_id in ignored_users
-
-    def get_thread_actions(self):
-        acl = self.request.acl.threads.get_role(self.forum)
-        actions = []
-        try:
-            if acl['can_approve']:
-                actions.append(('accept', _('Accept threads')))
-            if acl['can_pin_threads'] == 2:
-                actions.append(('annouce', _('Change to annoucements')))
-            if acl['can_pin_threads'] > 0:
-                actions.append(('sticky', _('Change to sticky threads')))
-            if acl['can_pin_threads'] > 0:
-                actions.append(('normal', _('Change to standard thread')))
-            if acl['can_move_threads_posts']:
-                actions.append(('move', _('Move threads')))
-                actions.append(('merge', _('Merge threads')))
-            if acl['can_close_threads']:
-                actions.append(('open', _('Open threads')))
-                actions.append(('close', _('Close threads')))
-            if acl['can_delete_threads']:
-                actions.append(('undelete', _('Undelete threads')))
-                actions.append(('soft', _('Soft delete threads')))
-            if acl['can_delete_threads'] == 2:
-                actions.append(('hard', _('Hard delete threads')))
-        except KeyError:
-            pass
-        return actions
-
-    def make_form(self):
-        self.form = None
-        list_choices = self.get_thread_actions();
-        if (not self.request.user.is_authenticated()
-            or not list_choices):
-            return
-
-        form_fields = {}
-        form_fields['list_action'] = forms.ChoiceField(choices=list_choices)
-        list_choices = []
-        for item in self.threads:
-            if item.forum_id == self.forum.pk:
-                list_choices.append((item.pk, None))
-        if not list_choices:
-            return
-        form_fields['list_items'] = forms.MultipleChoiceField(choices=list_choices, widget=forms.CheckboxSelectMultiple)
-        self.form = type('ThreadsViewForm', (Form,), form_fields)
-
-    def handle_form(self):
-        if self.request.method == 'POST':
-            self.form = self.form(self.request.POST, request=self.request)
-            if self.form.is_valid():
-                checked_items = []
-                posts = []
-                for thread in self.threads:
-                    if str(thread.pk) in self.form.cleaned_data['list_items'] and thread.forum_id == self.forum.pk:
-                        posts.append(thread.start_post_id)
-                        if thread.start_post_id != thread.last_post_id:
-                            posts.append(thread.last_post_id)
-                        checked_items.append(thread.pk)
-                if checked_items:
-                    if posts:
-                        for post in Post.objects.filter(id__in=posts).prefetch_related('user'):
-                            for thread in self.threads:
-                                if thread.start_post_id == post.pk:
-                                    thread.start_post = post
-                                if thread.last_post_id == post.pk:
-                                    thread.last_post = post
-                                if thread.start_post_id == post.pk or thread.last_post_id == post.pk:
-                                    break
-                    form_action = getattr(self, 'action_' + self.form.cleaned_data['list_action'])
-                    try:
-                        response = form_action(checked_items)
-                        if response:
-                            return response
-                        return redirect(self.request.path)
-                    except forms.ValidationError as e:
-                        self.message = Message(e.messages[0], 'error')
-                else:
-                    self.message = Message(_("You have to select at least one thread."), 'error')
-            else:
-                if 'list_action' in self.form.errors:
-                    self.message = Message(_("Action requested is incorrect."), 'error')
-                else:
-                    self.message = Message(form.non_field_errors()[0], 'error')
-        else:
-            self.form = self.form(request=self.request)
-
-    def action_accept(self, ids):
-        accepted = 0
-        last_posts = []
-        users = []
-        for thread in self.threads:
-            if thread.pk in ids and thread.moderated:
-                accepted += 1
-                # Sync thread and post
-                thread.moderated = False
-                thread.replies_moderated -= 1
-                thread.save(force_update=True)
-                thread.start_post.moderated = False
-                thread.start_post.save(force_update=True)
-                thread.last_post.set_checkpoint(self.request, 'accepted')
-                last_posts.append(thread.last_post.pk)
-                # Sync user
-                if thread.last_post.user:
-                    thread.start_post.user.threads += 1
-                    thread.start_post.user.posts += 1
-                    users.append(thread.start_post.user)
-        if accepted:
-            Post.objects.filter(id__in=last_posts).update(checkpoints=True)
-            self.request.monitor['threads'] = int(self.request.monitor['threads']) + accepted
-            self.request.monitor['posts'] = int(self.request.monitor['posts']) + accepted
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            for user in users:
-                user.save(force_update=True)
-            self.request.messages.set_flash(Message(_('Selected threads have been marked as reviewed and made visible to other members.')), 'success', 'threads')
-
-    def action_annouce(self, ids):
-        acl = self.request.acl.threads.get_role(self.forum)
-        annouced = []
-        for thread in self.threads:
-            if thread.pk in ids and thread.weight < 2:
-                annouced.append(thread.pk)
-        if annouced:
-            Thread.objects.filter(id__in=annouced).update(weight=2)
-            self.request.messages.set_flash(Message(_('Selected threads have been turned into annoucements.')), 'success', 'threads')
-
-    def action_sticky(self, ids):
-        acl = self.request.acl.threads.get_role(self.forum)
-        sticky = []
-        for thread in self.threads:
-            if thread.pk in ids and thread.weight != 1 and (acl['can_pin_threads'] == 2 or thread.weight < 2):
-                sticky.append(thread.pk)
-        if sticky:
-            Thread.objects.filter(id__in=sticky).update(weight=1)
-            self.request.messages.set_flash(Message(_('Selected threads have been sticked to the top of list.')), 'success', 'threads')
-
-    def action_normal(self, ids):
-        normalised = []
-        for thread in self.threads:
-            if thread.pk in ids and thread.weight > 0:
-                normalised.append(thread.pk)
-        if normalised:
-            Thread.objects.filter(id__in=normalised).update(weight=0)
-            self.request.messages.set_flash(Message(_('Selected threads weight has been removed.')), 'success', 'threads')
-
-    def action_move(self, ids):
-        threads = []
-        for thread in self.threads:
-            if thread.pk in ids:
-                threads.append(thread)
-        if self.request.POST.get('origin') == 'move_form':
-            form = MoveThreadsForm(self.request.POST, request=self.request, forum=self.forum)
-            if form.is_valid():
-                new_forum = form.cleaned_data['new_forum']
-                for thread in threads:
-                    thread.move_to(new_forum)
-                    thread.save(force_update=True)
-                new_forum.sync()
-                new_forum.save(force_update=True)
-                self.forum.sync()
-                self.forum.save(force_update=True)
-                self.request.messages.set_flash(Message(_('Selected threads have been moved to "%(forum)s".') % {'forum': new_forum.name}), 'success', 'threads')
-                return None
-            self.message = Message(form.non_field_errors()[0], 'error')
-        else:
-            form = MoveThreadsForm(request=self.request, forum=self.forum)
-        return self.request.theme.render_to_response('threads/move_threads.html',
-                                                     {
-                                                      'message': self.message,
-                                                      'forum': self.forum,
-                                                      'parents': self.parents,
-                                                      'threads': threads,
-                                                      'form': FormLayout(form),
-                                                      },
-                                                     context_instance=RequestContext(self.request));
-
-    def action_merge(self, ids):
-        if len(ids) < 2:
-            raise ValidationError(_("You have to pick two or more threads to merge."))
-        threads = []
-        for thread in self.threads:
-            if thread.pk in ids:
-                threads.append(thread)
-        if self.request.POST.get('origin') == 'merge_form':
-            form = MergeThreadsForm(self.request.POST, request=self.request, threads=threads)
-            if form.is_valid():
-                new_thread = Thread.objects.create(
-                                                   forum=form.cleaned_data['new_forum'],
-                                                   name=form.cleaned_data['thread_name'],
-                                                   slug=slugify(form.cleaned_data['thread_name']),
-                                                   start=timezone.now(),
-                                                   last=timezone.now()
-                                                   )
-                last_merge = 0
-                last_thread = None
-                merged = []
-                for i in range(0, len(threads)):
-                    thread = form.merge_order[i]
-                    merged.append(thread.pk)
-                    if last_thread and last_thread.last > thread.start:
-                        last_merge += thread.merges + 1
-                    thread.merge_with(new_thread, last_merge=last_merge)
-                    last_thread = thread
-                Thread.objects.filter(id__in=merged).delete()
-                new_thread.sync()
-                new_thread.save(force_update=True)
-                self.forum.sync()
-                self.forum.save(force_update=True)
-                if form.cleaned_data['new_forum'].pk != self.forum.pk:
-                    form.cleaned_data['new_forum'].sync()
-                    form.cleaned_data['new_forum'].save(force_update=True)
-                self.request.messages.set_flash(Message(_('Selected threads have been merged into new one.')), 'success', 'threads')
-                return None
-            self.message = Message(form.non_field_errors()[0], 'error')
-        else:
-            form = MergeThreadsForm(request=self.request, threads=threads)
-        return self.request.theme.render_to_response('threads/merge.html',
-                                                     {
-                                                      'message': self.message,
-                                                      'forum': self.forum,
-                                                      'parents': self.parents,
-                                                      'threads': threads,
-                                                      'form': FormLayout(form),
-                                                      },
-                                                     context_instance=RequestContext(self.request));
-
-    def action_open(self, ids):
-        opened = []
-        last_posts = []
-        for thread in self.threads:
-            if thread.pk in ids and thread.closed:
-                opened.append(thread.pk)
-                thread.last_post.set_checkpoint(self.request, 'opened')
-                last_posts.append(thread.last_post.pk)
-        if opened:
-            Post.objects.filter(id__in=last_posts).update(checkpoints=True)
-            Thread.objects.filter(id__in=opened).update(closed=False)
-            self.request.messages.set_flash(Message(_('Selected threads have been opened.')), 'success', 'threads')
-
-    def action_close(self, ids):
-        closed = []
-        last_posts = []
-        for thread in self.threads:
-            if thread.pk in ids and not thread.closed:
-                closed.append(thread.pk)
-                thread.last_post.set_checkpoint(self.request, 'closed')
-                last_posts.append(thread.last_post.pk)
-        if closed:
-            Post.objects.filter(id__in=last_posts).update(checkpoints=True)
-            Thread.objects.filter(id__in=closed).update(closed=True)
-            self.request.messages.set_flash(Message(_('Selected threads have been closed.')), 'success', 'threads')
-
-    def action_undelete(self, ids):
-        undeleted = []
-        last_posts = []
-        posts = 0
-        for thread in self.threads:
-            if thread.pk in ids and thread.deleted:
-                undeleted.append(thread.pk)
-                posts += thread.replies + 1
-                thread.start_post.deleted = False
-                thread.start_post.save(force_update=True)
-                thread.last_post.set_checkpoint(self.request, 'undeleted')
-        if undeleted:
-            self.request.monitor['threads'] = int(self.request.monitor['threads']) + len(undeleted)
-            self.request.monitor['posts'] = int(self.request.monitor['posts']) + posts
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            Post.objects.filter(id__in=last_posts).update(checkpoints=True)
-            Thread.objects.filter(id__in=undeleted).update(deleted=False)
-            self.request.messages.set_flash(Message(_('Selected threads have been undeleted.')), 'success', 'threads')
-
-    def action_soft(self, ids):
-        deleted = []
-        last_posts = []
-        posts = 0
-        for thread in self.threads:
-            if thread.pk in ids and not thread.deleted:
-                deleted.append(thread.pk)
-                posts += thread.replies + 1
-                thread.start_post.deleted = True
-                thread.start_post.save(force_update=True)
-                thread.last_post.set_checkpoint(self.request, 'deleted')
-                last_posts.append(thread.last_post.pk)
-        if deleted:
-            self.request.monitor['threads'] = int(self.request.monitor['threads']) - len(deleted)
-            self.request.monitor['posts'] = int(self.request.monitor['posts']) - posts
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            Post.objects.filter(id__in=last_posts).update(checkpoints=True)
-            Thread.objects.filter(id__in=deleted).update(deleted=True)
-            self.request.messages.set_flash(Message(_('Selected threads have been softly deleted.')), 'success', 'threads')
-
-    def action_hard(self, ids):
-        deleted = []
-        posts = 0
-        for thread in self.threads:
-            if thread.pk in ids:
-                deleted.append(thread.pk)
-                posts += thread.replies + 1
-                thread.delete()
-        if deleted:
-            self.request.monitor['threads'] = int(self.request.monitor['threads']) - len(deleted)
-            self.request.monitor['posts'] = int(self.request.monitor['posts']) - posts
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            self.request.messages.set_flash(Message(_('Selected threads have been deleted.')), 'success', 'threads')
-
-    def __call__(self, request, slug=None, forum=None, page=0):
-        self.request = request
-        self.pagination = None
-        self.parents = None
-        self.message = request.messages.get_message('threads')
-        try:
-            self.fetch_forum(forum)
-            self.fetch_threads(page)
-            self.make_form()
-            if self.form:
-                response = self.handle_form()
-                if response:
-                    return response
-        except Forum.DoesNotExist:
-            return error404(request)
-        except ACLError403 as e:
-            return error403(request, e.message)
-        except ACLError404 as e:
-            return error404(request, e.message)
-        # Merge proxy into forum
-        self.forum.closed = self.proxy.closed
-        return request.theme.render_to_response('threads/list.html',
-                                                {
-                                                 'message': self.message,
-                                                 'forum': self.forum,
-                                                 'parents': self.parents,
-                                                 'count': self.count,
-                                                 'list_form': FormFields(self.form).fields if self.form else None,
-                                                 'threads': self.threads,
-                                                 'pagination': self.pagination,
-                                                 },
-                                                context_instance=RequestContext(request));

+ 0 - 435
notrefactored/threads/views/posting.py

@@ -1,435 +0,0 @@
-from datetime import timedelta
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forms import FormLayout
-from misago.forums.models import Forum
-from misago.markdown import post_markdown
-from misago.messages import Message
-from misago.template.templatetags.django2jinja import date
-from misago.threads.forms import PostForm
-from misago.threads.models import Thread, Post
-from misago.threads.views.base import BaseView
-from misago.views import error403, error404
-from misago.utils import make_pagination, slugify, ugettext_lazy
-from misago.watcher.models import ThreadWatch
-
-
-class PostingBaseView(BaseView):
-    def __call__(self, request, **kwargs):
-        self.request = request
-
-        # Empty context attributes
-        self.forum = None
-        self.thread = None
-        self.quote = None
-        self.post = None
-
-        # Let inheriting class  set context
-        self.set_context()
-
-        # And set forum parents for render
-        self.parents = Forum.objects.forum_parents(self.forum.pk, True)
-
-        # Create form instance
-        
-
-    def set_context(self):
-        raise NotImplementedError(u"\"set_context\" method should be implemented in inheriting objects.")
-
-
-class PostingNewThreadView(PostingBaseView):
-    pass
-
-
-class PostingEditThreadView(PostingBaseView):
-    pass
-
-
-class PostingNewReplyView(PostingBaseView):
-    pass
-
-
-class PostingEditReplyView(PostingBaseView):
-    pass
-
-
-class PostingView(BaseView):
-    def fetch_target(self, kwargs):
-        if self.mode == 'new_thread':
-            self.fetch_forum(kwargs)
-        else:
-            self.fetch_thread(kwargs)
-            if self.mode == 'edit_thread':
-                self.fetch_post(self.thread.start_post_id)
-            if self.mode == 'edit_post':
-                self.fetch_post(kwargs['post'])
-
-    def fetch_forum(self, kwargs):
-        self.forum = Forum.objects.get(pk=kwargs['forum'], type='forum')
-        self.proxy = Forum.objects.parents_aware_forum(self.forum)
-        self.request.acl.forums.allow_forum_view(self.forum)
-        self.request.acl.threads.allow_new_threads(self.proxy)
-        self.parents = Forum.objects.forum_parents(self.forum.pk, True)
-
-    def fetch_thread(self, kwargs):
-        self.thread = Thread.objects.get(pk=kwargs['thread'])
-        self.forum = self.thread.forum
-        self.proxy = Forum.objects.parents_aware_forum(self.forum)
-        self.request.acl.forums.allow_forum_view(self.forum)
-        self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
-        self.request.acl.threads.allow_reply(self.proxy, self.thread)
-        self.parents = Forum.objects.forum_parents(self.forum.pk, True)
-        if kwargs.get('quote'):
-            self.quote = Post.objects.select_related('user').get(pk=kwargs['quote'], thread=self.thread.pk)
-            self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.quote)
-
-    def fetch_post(self, post):
-        self.post = self.thread.post_set.get(pk=post)
-        self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
-        if self.mode == 'edit_thread':
-            self.request.acl.threads.allow_thread_edit(self.request.user, self.proxy, self.thread, self.post)
-        if self.mode == 'edit_post':
-            self.request.acl.threads.allow_reply_edit(self.request.user, self.proxy, self.thread, self.post)
-
-    def get_form(self, bound=False):
-        initial = {}
-        if self.mode == 'edit_thread':
-            initial['thread_name'] = self.thread.name
-        if self.mode in ['edit_thread', 'edit_post']:
-            initial['post'] = self.post.post
-        if self.quote:
-            quote_post = []
-            if self.quote.user:
-                quote_post.append('@%s' % self.quote.user.username)
-            else:
-                quote_post.append('@%s' % self.quote.user_name)
-            for line in self.quote.post.splitlines():
-                quote_post.append('> %s' % line)
-            quote_post.append('\n')
-            initial['post'] = '\n'.join(quote_post)
-
-        if bound:
-            return PostForm(self.request.POST, request=self.request, mode=self.mode, initial=initial)
-        return PostForm(request=self.request, mode=self.mode, initial=initial)
-
-    def __call__(self, request, **kwargs):
-        self.request = request
-        self.forum = None
-        self.thread = None
-        self.quote = None
-        self.post = None
-        self.parents = None
-        self.mode = kwargs.get('mode')
-        if self.request.POST.get('quick_reply') and self.mode == 'new_post':
-            self.mode = 'new_post_quick'
-        try:
-            self.fetch_target(kwargs)
-            if not request.user.is_authenticated():
-                raise ACLError403(_("Guest, you have to sign-in in order to post replies."))
-        except (Forum.DoesNotExist, Thread.DoesNotExist, Post.DoesNotExist):
-            return error404(self.request)
-        except ACLError403 as e:
-            return error403(request, e.message)
-        except ACLError404 as e:
-            return error404(request, e.message)
-
-        message = request.messages.get_message('threads')
-        if request.method == 'POST':
-            form = self.get_form(True)
-            # Show message preview
-            if 'preview' in request.POST:
-                if form['post'].value():
-                    md, preparsed = post_markdown(request, form['post'].value())
-                else:
-                    md, preparsed = None, None
-                form.empty_errors()
-                return request.theme.render_to_response('threads/posting.html',
-                                                        {
-                                                         'mode': self.mode,
-                                                         'forum': self.forum,
-                                                         'thread': self.thread,
-                                                         'post': self.post,
-                                                         'quote': self.quote,
-                                                         'parents': self.parents,
-                                                         'message': message,
-                                                         'preview': preparsed,
-                                                         'form': FormLayout(form),
-                                                         },
-                                                        context_instance=RequestContext(request));
-            # Commit form to database
-            if form.is_valid():                
-                # Record original vars if user is editing 
-                if self.mode in ['edit_thread', 'edit_post']:
-                    old_name = self.thread.name
-                    old_post = self.post.post
-                    # If there is no change, throw user back
-                    changed_name = (old_name != form.cleaned_data['thread_name']) if self.mode == 'edit_thread' else False
-                    changed_post = old_post != form.cleaned_data['post']
-                    changed_anything = changed_name or changed_post
-
-                # Some extra initialisation
-                now = timezone.now()
-                md = None
-                moderation = False
-                if not request.acl.threads.acl[self.forum.pk]['can_approve']:
-                    if self.mode == 'new_thread' and request.acl.threads.acl[self.forum.pk]['can_start_threads'] == 1:
-                        moderation = True
-                    if self.mode in ['new_post', 'new_post_quick'] and request.acl.threads.acl[self.forum.pk]['can_write_posts'] == 1:
-                        moderation = True
-
-                # Get or create new thread
-                if self.mode == 'new_thread':
-                    thread = Thread.objects.create(
-                                                   forum=self.forum,
-                                                   name=form.cleaned_data['thread_name'],
-                                                   slug=slugify(form.cleaned_data['thread_name']),
-                                                   start=now,
-                                                   last=now,
-                                                   moderated=moderation,
-                                                   score=request.settings['thread_ranking_initial_score'],
-                                                   )
-                    if moderation:
-                        thread.replies_moderated += 1
-                else:
-                    thread = self.thread
-                    if self.mode == 'edit_thread':
-                        thread.name = form.cleaned_data['thread_name']
-                        thread.slug = slugify(form.cleaned_data['thread_name'])
-                thread.previous_last = thread.last 
-
-                # Create new message
-                if self.mode in ['new_thread', 'new_post', 'new_post_quick']:
-                    # Use last post instead?
-                    if self.mode in ['new_post', 'new_post_quick']:
-                        merge_diff = (now - self.thread.last)
-                        merge_diff = (merge_diff.days * 86400) + merge_diff.seconds
-                    if (self.mode in ['new_post', 'new_post_quick']
-                        and request.settings.post_merge_time
-                        and merge_diff < (request.settings.post_merge_time * 60)
-                        and self.thread.last_poster_id == request.user.id):
-                        # Overtake posting
-                        post = self.thread.last_post
-                        post.appended = True
-                        post.moderated = moderation
-                        post.date = now
-                        post.post = '%s\n\n- - -\n**%s**\n%s' % (post.post, _("Added on %(date)s:") % {'date': date(now, 'SHORT_DATETIME_FORMAT')}, form.cleaned_data['post'])
-                        md, post.post_preparsed = post_markdown(request, post.post)
-                        post.save(force_update=True)
-                        thread.last = now
-                        thread.save(force_update=True)
-                        self.forum.last = now
-                        self.forum.save(force_update=True)
-                        # Ignore rest of posting action
-                        request.messages.set_flash(Message(_("Your reply has been added to previous one.")), 'success', 'threads_%s' % post.pk)
-                        return self.redirect_to_post(post)
-                    else:
-                        md, post_preparsed = post_markdown(request, form.cleaned_data['post'])
-                        post = Post.objects.create(
-                                                   forum=self.forum,
-                                                   thread=thread,
-                                                   merge=thread.merges,
-                                                   user=request.user,
-                                                   user_name=request.user.username,
-                                                   ip=request.session.get_ip(request),
-                                                   agent=request.META.get('HTTP_USER_AGENT'),
-                                                   post=form.cleaned_data['post'],
-                                                   post_preparsed=post_preparsed,
-                                                   date=now,
-                                                   moderated=moderation,
-                                                   )
-                        post.appended = False
-                elif changed_post:
-                    # Change message
-                    post = self.post
-                    post.post = form.cleaned_data['post']
-                    md, post.post_preparsed = post_markdown(request, form.cleaned_data['post'])
-                    post.edits += 1
-                    post.edit_date = now
-                    post.edit_user = request.user
-                    post.edit_user_name = request.user.username
-                    post.edit_user_slug = request.user.username_slug
-                    post.save(force_update=True)
-
-                # Record this edit in changelog?
-                if self.mode in ['edit_thread', 'edit_post'] and changed_anything:
-                    self.post.change_set.create(
-                                                forum=self.forum,
-                                                thread=self.thread,
-                                                post=self.post,
-                                                user=request.user,
-                                                user_name=request.user.username,
-                                                user_slug=request.user.username_slug,
-                                                date=now,
-                                                ip=request.session.get_ip(request),
-                                                agent=request.META.get('HTTP_USER_AGENT'),
-                                                reason=form.cleaned_data['edit_reason'],
-                                                size=len(self.post.post),
-                                                change=len(self.post.post) - len(old_post),
-                                                thread_name_old=old_name if self.mode == 'edit_thread' and form.cleaned_data['thread_name'] != old_name else None,
-                                                thread_name_new=self.thread.name if self.mode == 'edit_thread' and form.cleaned_data['thread_name'] != old_name else None,
-                                                post_content=old_post,
-                                                )
-
-                # Set thread start post and author data
-                if self.mode == 'new_thread':
-                    thread.start_post = post
-                    thread.start_poster = request.user
-                    thread.start_poster_name = request.user.username
-                    thread.start_poster_slug = request.user.username_slug
-                    if request.user.rank and request.user.rank.style:
-                        thread.start_poster_style = request.user.rank.style
-                    # Reward user for posting new thread?
-                    if not request.user.last_post or request.user.last_post < timezone.now() - timedelta(seconds=request.settings['score_reward_new_post_cooldown']):
-                        request.user.score += request.settings['score_reward_new_thread']
-
-                # New post - increase post counters, thread score
-                # Notify quoted post author and close thread if it has hit limit
-                if self.mode in ['new_post', 'new_post_quick']:
-                    if moderation:
-                        thread.replies_moderated += 1
-                    else:
-                        thread.replies += 1
-                        if thread.last_poster_id != request.user.pk:
-                            thread.score += request.settings['thread_ranking_reply_score']
-                        # Notify quoted poster of reply?
-                        if self.quote and self.quote.user_id and self.quote.user_id != request.user.pk and not self.quote.user.is_ignoring(request.user):
-                            alert = self.quote.user.alert(ugettext_lazy("%(username)s has replied to your post in thread %(thread)s").message)
-                            alert.profile('username', request.user)
-                            alert.post('thread', self.thread, post)
-                            alert.save_all()
-                        if (self.request.settings.thread_length > 0
-                            and not thread.closed
-                            and thread.replies >= self.request.settings.thread_length):
-                            thread.closed = True
-                            post.set_checkpoint(self.request, 'limit')
-                    # Reward user for posting new post?
-                    if not post.appended and (not request.user.last_post or request.user.last_post < timezone.now() - timedelta(seconds=request.settings['score_reward_new_post_cooldown'])):
-                        request.user.score += request.settings['score_reward_new_post']
-
-                # Update last poster data
-                if not moderation and self.mode not in ['edit_thread', 'edit_post']:
-                    thread.last = now
-                    thread.last_post = post
-                    thread.last_poster = request.user
-                    thread.last_poster_name = request.user.username
-                    thread.last_poster_slug = request.user.username_slug
-                    thread.last_poster_style = request.user.rank.style
-
-                # Final update of thread entry
-                if self.mode != 'edit_post':
-                    thread.save(force_update=True)
-
-                # Update forum and monitor
-                if not moderation:
-                    if self.mode == 'new_thread':
-                        self.request.monitor['threads'] = int(self.request.monitor['threads']) + 1
-                        self.forum.threads += 1
-
-                    if self.mode in ['new_thread', 'new_post', 'new_post_quick']:
-                        self.request.monitor['posts'] = int(self.request.monitor['posts']) + 1
-                        self.forum.posts += 1
-
-                    if self.mode in ['new_thread', 'new_post', 'new_post_quick'] or (
-                        self.mode == 'edit_thread'
-                        and self.forum.last_thread_id == thread.pk
-                        and self.forum.last_thread_name != thread.name):
-                        self.forum.last_thread = thread
-                        self.forum.last_thread_name = thread.name
-                        self.forum.last_thread_slug = thread.slug
-                        self.forum.last_thread_date = thread.last
-
-                    if self.mode in ['new_thread', 'new_post', 'new_post_quick']:
-                        self.forum.last_poster = thread.last_poster
-                        self.forum.last_poster_name = thread.last_poster_name
-                        self.forum.last_poster_slug = thread.last_poster_slug
-                        self.forum.last_poster_style = thread.last_poster_style
-
-                    if self.mode != 'edit_post':
-                        self.forum.save(force_update=True)
-
-                # Update user
-                if not moderation:
-                    if self.mode == 'new_thread':
-                        request.user.threads += 1
-                    request.user.posts += 1
-                if self.mode in ['new_thread', 'new_post', 'new_post_quick']:
-                    request.user.last_post = thread.last
-                    request.user.save(force_update=True)
-                    
-                # Notify users about post
-                if md:
-                    try:
-                        if self.quote and self.quote.user_id:
-                            del md.mentions[self.quote.user.username_slug]
-                    except KeyError:
-                        pass
-                    if md.mentions:
-                        post.notify_mentioned(request, md.mentions)
-                        post.save(force_update=True)
-
-                # Set thread watch status
-                if self.mode == 'new_thread' and request.user.subscribe_start:
-                    ThreadWatch.objects.create(
-                                               user=request.user,
-                                               forum=self.forum,
-                                               thread=thread,
-                                               last_read=now,
-                                               email=(request.user.subscribe_start == 2),
-                                               )
-                    
-                if self.mode in ['new_post', 'new_post_quick'] and request.user.subscribe_reply:
-                    try:
-                        watcher = ThreadWatch.objects.get(user=request.user, thread=self.thread)
-                    except ThreadWatch.DoesNotExist:
-                        ThreadWatch.objects.create(
-                                                   user=request.user,
-                                                   forum=self.forum,
-                                                   thread=thread,
-                                                   last_read=now,
-                                                   email=(request.user.subscribe_reply == 2),
-                                                   )
-
-                # Set flash and redirect user to his post
-                if self.mode == 'new_thread':
-                    if moderation:
-                        request.messages.set_flash(Message(_("New thread has been posted. It will be hidden from other members until moderator reviews it.")), 'success', 'threads')
-                    else:
-                        request.messages.set_flash(Message(_("New thread has been posted.")), 'success', 'threads')
-                    return redirect(reverse('thread', kwargs={'thread': thread.pk, 'slug': thread.slug}) + ('#post-%s' % post.pk))
-
-                if self.mode in ['new_post', 'new_post_quick']:
-                    thread.email_watchers(request, post)
-                    if moderation:
-                        request.messages.set_flash(Message(_("Your reply has been posted. It will be hidden from other members until moderator reviews it.")), 'success', 'threads_%s' % post.pk)
-                    else:
-                        request.messages.set_flash(Message(_("Your reply has been posted.")), 'success', 'threads_%s' % post.pk)
-                    return self.redirect_to_post(post)
-
-                if self.mode == 'edit_thread':
-                    request.messages.set_flash(Message(_("Your thread has been edited.")), 'success', 'threads_%s' % self.post.pk)
-                if self.mode == 'edit_post':
-                    request.messages.set_flash(Message(_("Your reply has been edited.")), 'success', 'threads_%s' % self.post.pk)
-                    return self.redirect_to_post(self.post)
-                return redirect(reverse('thread', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug}) + ('#post-%s' % self.post.pk))
-            message = Message(form.non_field_errors()[0], 'error')
-        else:
-            form = self.get_form()
-
-        # Merge proxy into forum
-        self.forum.closed = self.proxy.closed
-        return request.theme.render_to_response('threads/posting.html',
-                                                {
-                                                 'mode': self.mode,
-                                                 'forum': self.forum,
-                                                 'thread': self.thread,
-                                                 'post': self.post,
-                                                 'quote': self.quote,
-                                                 'parents': self.parents,
-                                                 'message': message,
-                                                 'form': FormLayout(form),
-                                                 },
-                                                context_instance=RequestContext(request));

+ 0 - 566
notrefactored/threads/views/thread.py

@@ -1,566 +0,0 @@
-from django.core.urlresolvers import reverse
-from django import forms
-from django.db.models import F
-from django.forms import ValidationError
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.acl.utils import ACLError403, ACLError404
-from misago.forms import Form, FormLayout, FormFields
-from misago.forums.models import Forum
-from misago.markdown import post_markdown
-from misago.messages import Message
-from misago.readstracker.trackers import ThreadsTracker
-from misago.threads.forms import MoveThreadsForm, SplitThreadForm, MovePostsForm, QuickReplyForm
-from misago.threads.models import Thread, Post, Karma, Change, Checkpoint
-from misago.threads.views.base import BaseView
-from misago.views import error403, error404
-from misago.utils import make_pagination, slugify
-from misago.watcher.models import ThreadWatch
-
-class ThreadView(BaseView):
-    def fetch_thread(self, thread):
-        self.thread = Thread.objects.get(pk=thread)
-        self.forum = self.thread.forum
-        self.proxy = Forum.objects.parents_aware_forum(self.forum)
-        self.request.acl.forums.allow_forum_view(self.forum)
-        self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
-        self.parents = Forum.objects.forum_parents(self.forum.pk, True)
-        self.tracker = ThreadsTracker(self.request, self.forum)
-        if self.request.user.is_authenticated():
-            try:
-                self.watcher = ThreadWatch.objects.get(user=self.request.user, thread=self.thread)
-            except ThreadWatch.DoesNotExist:
-                pass
-
-    def fetch_posts(self, page):
-        self.count = self.request.acl.threads.filter_posts(self.request, self.thread, Post.objects.filter(thread=self.thread)).count()
-        self.posts = self.request.acl.threads.filter_posts(self.request, self.thread, Post.objects.filter(thread=self.thread)).prefetch_related('checkpoint_set', 'user', 'user__rank')
-        if self.thread.merges > 0:
-            self.posts = self.posts.order_by('merge', 'pk')
-        else:
-            self.posts = self.posts.order_by('pk')
-        self.pagination = make_pagination(page, self.count, self.request.settings.posts_per_page)
-        if self.request.settings.posts_per_page < self.count:
-            self.posts = self.posts[self.pagination['start']:self.pagination['stop']]
-        self.read_date = self.tracker.get_read_date(self.thread)
-        ignored_users = []
-        if self.request.user.is_authenticated():
-            ignored_users = self.request.user.ignored_users()
-        posts_dict = {}
-        for post in self.posts:
-            posts_dict[post.pk] = post
-            post.message = self.request.messages.get_message('threads_%s' % post.pk)
-            post.is_read = post.date <= self.read_date or (post.pk != self.thread.start_post_id and post.moderated)
-            post.karma_vote = None
-            post.ignored = self.thread.start_post_id != post.pk and not self.thread.pk in self.request.session.get('unignore_threads', []) and post.user_id in ignored_users
-            if post.ignored:
-                self.ignored = True
-        last_post = self.posts[len(self.posts) - 1]
-        if not self.tracker.is_read(self.thread):
-            self.tracker.set_read(self.thread, last_post)
-            self.tracker.sync()
-        if self.watcher and last_post.date > self.watcher.last_read:
-            self.watcher.last_read = timezone.now()
-            self.watcher.save(force_update=True)
-        if self.request.user.is_authenticated():
-            for karma in Karma.objects.filter(post_id__in=posts_dict.keys()).filter(user=self.request.user):
-                posts_dict[karma.post_id].karma_vote = karma
-
-    def get_post_actions(self):
-        acl = self.request.acl.threads.get_role(self.thread.forum_id)
-        actions = []
-        try:
-            if acl['can_approve'] and self.thread.replies_moderated > 0:
-                actions.append(('accept', _('Accept posts')))
-            if acl['can_move_threads_posts']:
-                actions.append(('merge', _('Merge posts into one')))
-                actions.append(('split', _('Split posts to new thread')))
-                actions.append(('move', _('Move posts to other thread')))
-            if acl['can_protect_posts']:
-                actions.append(('protect', _('Protect posts')))
-                actions.append(('unprotect', _('Remove posts protection')))
-            if acl['can_delete_posts']:
-                if self.thread.replies_deleted > 0:
-                    actions.append(('undelete', _('Undelete posts')))
-                actions.append(('soft', _('Soft delete posts')))
-            if acl['can_delete_posts'] == 2:
-                actions.append(('hard', _('Hard delete posts')))
-        except KeyError:
-            pass
-        return actions
-
-    def make_posts_form(self):
-        self.posts_form = None
-        list_choices = self.get_post_actions();
-        if (not self.request.user.is_authenticated()
-            or not list_choices):
-            return
-
-        form_fields = {}
-        form_fields['list_action'] = forms.ChoiceField(choices=list_choices)
-        list_choices = []
-        for item in self.posts:
-            list_choices.append((item.pk, None))
-        if not list_choices:
-            return
-        form_fields['list_items'] = forms.MultipleChoiceField(choices=list_choices, widget=forms.CheckboxSelectMultiple)
-        self.posts_form = type('PostsViewForm', (Form,), form_fields)
-
-    def handle_posts_form(self):
-        if self.request.method == 'POST' and self.request.POST.get('origin') == 'posts_form':
-            self.posts_form = self.posts_form(self.request.POST, request=self.request)
-            if self.posts_form.is_valid():
-                checked_items = []
-                for post in self.posts:
-                    if str(post.pk) in self.posts_form.cleaned_data['list_items']:
-                        checked_items.append(post.pk)
-                if checked_items:
-                    form_action = getattr(self, 'post_action_' + self.posts_form.cleaned_data['list_action'])
-                    try:
-                        response = form_action(checked_items)
-                        if response:
-                            return response
-                        return redirect(self.request.path)
-                    except forms.ValidationError as e:
-                        self.message = Message(e.messages[0], 'error')
-                else:
-                    self.message = Message(_("You have to select at least one post."), 'error')
-            else:
-                if 'list_action' in self.posts_form.errors:
-                    self.message = Message(_("Action requested is incorrect."), 'error')
-                else:
-                    self.message = Message(posts_form.non_field_errors()[0], 'error')
-        else:
-            self.posts_form = self.posts_form(request=self.request)
-
-    def post_action_accept(self, ids):
-        accepted = 0
-        for post in self.posts:
-            if post.pk in ids and post.moderated:
-                accepted += 1
-        if accepted:
-            self.thread.post_set.filter(id__in=ids).update(moderated=False)
-            self.thread.sync()
-            self.thread.save(force_update=True)
-            self.request.messages.set_flash(Message(_('Selected posts have been accepted and made visible to other members.')), 'success', 'threads')
-
-    def post_action_merge(self, ids):
-        users = []
-        posts = []
-        for post in self.posts:
-            if post.pk in ids:
-                posts.append(post)
-                if not post.user_id in users:
-                    users.append(post.user_id)
-                if len(users) > 1:
-                    raise forms.ValidationError(_("You cannot merge replies made by different members!"))
-        if len(posts) < 2:
-            raise forms.ValidationError(_("You have to select two or more posts you want to merge."))
-        new_post = posts[0]
-        for post in posts[1:]:
-            post.merge_with(new_post)
-            post.delete()
-        md, new_post.post_preparsed = post_markdown(self.request, new_post.post)
-        new_post.save(force_update=True)
-        self.thread.sync()
-        self.thread.save(force_update=True)
-        self.forum.sync()
-        self.forum.save(force_update=True)
-        self.request.messages.set_flash(Message(_('Selected posts have been merged into one message.')), 'success', 'threads')
-
-    def post_action_split(self, ids):
-        for id in ids:
-            if id == self.thread.start_post_id:
-                raise forms.ValidationError(_("You cannot split first post from thread."))
-        message = None
-        if self.request.POST.get('do') == 'split':
-            form = SplitThreadForm(self.request.POST, request=self.request)
-            if form.is_valid():
-                new_thread = Thread()
-                new_thread.forum = form.cleaned_data['thread_forum']
-                new_thread.name = form.cleaned_data['thread_name']
-                new_thread.slug = slugify(form.cleaned_data['thread_name'])
-                new_thread.start = timezone.now()
-                new_thread.last = timezone.now()
-                new_thread.start_poster_name = 'n'
-                new_thread.start_poster_slug = 'n'
-                new_thread.last_poster_name = 'n'
-                new_thread.last_poster_slug = 'n'
-                new_thread.save(force_insert=True)
-                prev_merge = -1
-                merge = -1
-                for post in self.posts:
-                    if post.pk in ids:
-                        if prev_merge != post.merge:
-                            prev_merge = post.merge
-                            merge += 1
-                        post.merge = merge
-                        post.move_to(new_thread)
-                        post.save(force_update=True)
-                new_thread.sync()
-                new_thread.save(force_update=True)
-                self.thread.sync()
-                self.thread.save(force_update=True)
-                self.forum.sync()
-                self.forum.save(force_update=True)
-                if new_thread.forum != self.forum:
-                    new_thread.forum.sync()
-                    new_thread.forum.save(force_update=True)
-                self.request.messages.set_flash(Message(_("Selected posts have been split to new thread.")), 'success', 'threads')
-                return redirect(reverse('thread', kwargs={'thread': new_thread.pk, 'slug': new_thread.slug}))
-            message = Message(form.non_field_errors()[0], 'error')
-        else:
-            form = SplitThreadForm(request=self.request, initial={
-                                                                  'thread_name': _('[Split] %s') % self.thread.name,
-                                                                  'thread_forum': self.forum,
-                                                                  })
-        return self.request.theme.render_to_response('threads/split.html',
-                                                     {
-                                                      'message': message,
-                                                      'forum': self.forum,
-                                                      'parents': self.parents,
-                                                      'thread': self.thread,
-                                                      'posts': ids,
-                                                      'form': FormLayout(form),
-                                                      },
-                                                     context_instance=RequestContext(self.request));
-
-    def post_action_move(self, ids):
-        message = None
-        if self.request.POST.get('do') == 'move':
-            form = MovePostsForm(self.request.POST, request=self.request, thread=self.thread)
-            if form.is_valid():
-                thread = form.cleaned_data['thread_url']
-                prev_merge = -1
-                merge = -1
-                for post in self.posts:
-                    if post.pk in ids:
-                        if prev_merge != post.merge:
-                            prev_merge = post.merge
-                            merge += 1
-                        post.merge = merge + thread.merges
-                        post.move_to(thread)
-                        post.save(force_update=True)
-                if self.thread.post_set.count() == 0:
-                    self.thread.delete()
-                else:
-                    self.thread.sync()
-                    self.thread.save(force_update=True)
-                thread.sync()
-                thread.save(force_update=True)
-                thread.forum.sync()
-                thread.forum.save(force_update=True)
-                if self.forum.pk != thread.forum.pk:
-                    self.forum.sync()
-                    self.forum.save(force_update=True)
-                self.request.messages.set_flash(Message(_("Selected posts have been moved to new thread.")), 'success', 'threads')
-                return redirect(reverse('thread', kwargs={'thread': thread.pk, 'slug': thread.slug}))
-            message = Message(form.non_field_errors()[0], 'error')
-        else:
-            form = MovePostsForm(request=self.request)
-        return self.request.theme.render_to_response('threads/move_posts.html',
-                                                     {
-                                                      'message': message,
-                                                      'forum': self.forum,
-                                                      'parents': self.parents,
-                                                      'thread': self.thread,
-                                                      'posts': ids,
-                                                      'form': FormLayout(form),
-                                                      },
-                                                     context_instance=RequestContext(self.request));
-
-    def post_action_undelete(self, ids):
-        undeleted = []
-        for post in self.posts:
-            if post.pk in ids and post.deleted:
-                undeleted.append(post.pk)
-        if undeleted:
-            self.thread.post_set.filter(id__in=undeleted).update(deleted=False)
-            self.thread.sync()
-            self.thread.save(force_update=True)
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            self.request.messages.set_flash(Message(_('Selected posts have been restored.')), 'success', 'threads')
-
-    def post_action_protect(self, ids):
-        protected = 0
-        for post in self.posts:
-            if post.pk in ids and not post.protected:
-                protected += 1
-        if protected:
-            self.thread.post_set.filter(id__in=ids).update(protected=True)
-            self.request.messages.set_flash(Message(_('Selected posts have been protected from edition.')), 'success', 'threads')
-
-    def post_action_unprotect(self, ids):
-        unprotected = 0
-        for post in self.posts:
-            if post.pk in ids and post.protected:
-                unprotected += 1
-        if unprotected:
-            self.thread.post_set.filter(id__in=ids).update(protected=False)
-            self.request.messages.set_flash(Message(_('Protection from editions has been removed from selected posts.')), 'success', 'threads')
-
-    def post_action_soft(self, ids):
-        deleted = []
-        for post in self.posts:
-            if post.pk in ids and not post.deleted:
-                if post.pk == self.thread.start_post_id:
-                    raise forms.ValidationError(_("You cannot delete first post of thread using this action. If you want to delete thread, use thread moderation instead."))
-                deleted.append(post.pk)
-        if deleted:
-            self.thread.post_set.filter(id__in=deleted).update(deleted=True)
-            self.thread.sync()
-            self.thread.save(force_update=True)
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            self.request.messages.set_flash(Message(_('Selected posts have been deleted.')), 'success', 'threads')
-
-    def post_action_hard(self, ids):
-        deleted = []
-        for post in self.posts:
-            if post.pk in ids:
-                if post.pk == self.thread.start_post_id:
-                    raise forms.ValidationError(_("You cannot delete first post of thread using this action. If you want to delete thread, use thread moderation instead."))
-                deleted.append(post.pk)
-        if deleted:
-            for post in self.posts:
-                if post.pk in deleted:
-                    post.delete()
-            self.thread.sync()
-            self.thread.save(force_update=True)
-            self.forum.sync()
-            self.forum.save(force_update=True)
-            self.request.messages.set_flash(Message(_('Selected posts have been deleted.')), 'success', 'threads')
-
-    def get_thread_actions(self):
-        acl = self.request.acl.threads.get_role(self.thread.forum_id)
-        actions = []
-        try:
-            if acl['can_approve'] and self.thread.moderated:
-                actions.append(('accept', _('Accept this thread')))
-            if acl['can_pin_threads'] == 2 and self.thread.weight < 2:
-                actions.append(('annouce', _('Change this thread to annoucement')))
-            if acl['can_pin_threads'] > 0 and self.thread.weight != 1:
-                actions.append(('sticky', _('Change this thread to sticky')))
-            if acl['can_pin_threads'] > 0:
-                if self.thread.weight == 2:
-                    actions.append(('normal', _('Change this thread to normal')))
-                if self.thread.weight == 1:
-                    actions.append(('normal', _('Unpin this thread')))
-            if acl['can_move_threads_posts']:
-                actions.append(('move', _('Move this thread')))
-            if acl['can_close_threads']:
-                if self.thread.closed:
-                    actions.append(('open', _('Open this thread')))
-                else:
-                    actions.append(('close', _('Close this thread')))
-            if acl['can_delete_threads']:
-                if self.thread.deleted:
-                    actions.append(('undelete', _('Undelete this thread')))
-                else:
-                    actions.append(('soft', _('Soft delete this thread')))
-            if acl['can_delete_threads'] == 2:
-                actions.append(('hard', _('Hard delete this thread')))
-        except KeyError:
-            pass
-        return actions
-
-    def make_thread_form(self):
-        self.thread_form = None
-        list_choices = self.get_thread_actions();
-        if (not self.request.user.is_authenticated()
-            or not list_choices):
-            return
-        form_fields = {'thread_action': forms.ChoiceField(choices=list_choices)}
-        self.thread_form = type('ThreadViewForm', (Form,), form_fields)
-
-    def handle_thread_form(self):
-        if self.request.method == 'POST' and self.request.POST.get('origin') == 'thread_form':
-            self.thread_form = self.thread_form(self.request.POST, request=self.request)
-            if self.thread_form.is_valid():
-                form_action = getattr(self, 'thread_action_' + self.thread_form.cleaned_data['thread_action'])
-                try:
-                    response = form_action()
-                    if response:
-                        return response
-                    return redirect(self.request.path)
-                except forms.ValidationError as e:
-                    self.message = Message(e.messages[0], 'error')
-            else:
-                if 'thread_action' in self.thread_form.errors:
-                    self.message = Message(_("Action requested is incorrect."), 'error')
-                else:
-                    self.message = Message(form.non_field_errors()[0], 'error')
-        else:
-            self.thread_form = self.thread_form(request=self.request)
-
-    def thread_action_accept(self):
-        # Sync thread and post
-        self.thread.moderated = False
-        self.thread.replies_moderated -= 1
-        self.thread.save(force_update=True)
-        self.thread.start_post.moderated = False
-        self.thread.start_post.save(force_update=True)
-        self.thread.last_post.set_checkpoint(self.request, 'accepted')
-        # Sync user
-        if self.thread.last_post.user:
-            self.thread.start_post.user.threads += 1
-            self.thread.start_post.user.posts += 1
-            self.thread.start_post.user.save(force_update=True)
-        # Sync forum
-        self.forum.sync()
-        self.forum.save(force_update=True)
-        # Update monitor
-        self.request.monitor['threads'] = int(self.request.monitor['threads']) + 1
-        self.request.monitor['posts'] = int(self.request.monitor['posts']) + self.thread.replies + 1
-        self.request.messages.set_flash(Message(_('Thread has been marked as reviewed and made visible to other members.')), 'success', 'threads')
-
-    def thread_action_annouce(self):
-        self.thread.weight = 2
-        self.thread.save(force_update=True)
-        self.request.messages.set_flash(Message(_('Thread has been turned into annoucement.')), 'success', 'threads')
-
-    def thread_action_sticky(self):
-        self.thread.weight = 1
-        self.thread.save(force_update=True)
-        self.request.messages.set_flash(Message(_('Thread has been turned into sticky.')), 'success', 'threads')
-
-    def thread_action_normal(self):
-        self.thread.weight = 0
-        self.thread.save(force_update=True)
-        self.request.messages.set_flash(Message(_('Thread weight has been changed to normal.')), 'success', 'threads')
-
-    def thread_action_move(self):
-        message = None
-        if self.request.POST.get('do') == 'move':
-            form = MoveThreadsForm(self.request.POST, request=self.request, forum=self.forum)
-            if form.is_valid():
-                new_forum = form.cleaned_data['new_forum']
-                self.thread.move_to(new_forum)
-                self.thread.save(force_update=True)
-                self.forum.sync()
-                self.forum.save(force_update=True)
-                new_forum.sync()
-                new_forum.save(force_update=True)
-                self.request.messages.set_flash(Message(_('Thread has been moved to "%(forum)s".') % {'forum': new_forum.name}), 'success', 'threads')
-                return None
-            message = Message(form.non_field_errors()[0], 'error')
-        else:
-            form = MoveThreadsForm(request=self.request, forum=self.forum)
-        return self.request.theme.render_to_response('threads/move_thread.html',
-                                                     {
-                                                      'message': message,
-                                                      'forum': self.forum,
-                                                      'parents': self.parents,
-                                                      'thread': self.thread,
-                                                      'form': FormLayout(form),
-                                                      },
-                                                     context_instance=RequestContext(self.request));
-
-    def thread_action_open(self):
-        self.thread.closed = False
-        self.thread.save(force_update=True)
-        self.thread.last_post.set_checkpoint(self.request, 'opened')
-        self.request.messages.set_flash(Message(_('Thread has been opened.')), 'success', 'threads')
-
-    def thread_action_close(self):
-        self.thread.closed = True
-        self.thread.save(force_update=True)
-        self.thread.last_post.set_checkpoint(self.request, 'closed')
-        self.request.messages.set_flash(Message(_('Thread has been closed.')), 'success', 'threads')
-
-    def thread_action_undelete(self):
-        # Update thread
-        self.thread.deleted = False
-        self.thread.replies_deleted -= 1
-        self.thread.save(force_update=True)
-        # Update first post in thread
-        self.thread.start_post.deleted = False
-        self.thread.start_post.save(force_update=True)
-        # Set checkpoint
-        self.thread.last_post.set_checkpoint(self.request, 'undeleted')
-        # Update forum
-        self.forum.sync()
-        self.forum.save(force_update=True)
-        # Update monitor
-        self.request.monitor['threads'] = int(self.request.monitor['threads']) + 1
-        self.request.monitor['posts'] = int(self.request.monitor['posts']) + self.thread.replies + 1
-        self.request.messages.set_flash(Message(_('Thread has been undeleted.')), 'success', 'threads')
-
-    def thread_action_soft(self):
-        # Update thread
-        self.thread.deleted = True
-        self.thread.replies_deleted += 1
-        self.thread.save(force_update=True)
-        # Update first post in thread
-        self.thread.start_post.deleted = True
-        self.thread.start_post.save(force_update=True)
-        # Set checkpoint
-        self.thread.last_post.set_checkpoint(self.request, 'deleted')
-        # Update forum
-        self.forum.sync()
-        self.forum.save(force_update=True)
-        # Update monitor
-        self.request.monitor['threads'] = int(self.request.monitor['threads']) - 1
-        self.request.monitor['posts'] = int(self.request.monitor['posts']) - self.thread.replies - 1
-        self.request.messages.set_flash(Message(_('Thread has been deleted.')), 'success', 'threads')
-
-    def thread_action_hard(self):
-        # Delete thread
-        self.thread.delete()
-        # Update forum
-        self.forum.sync()
-        self.forum.save(force_update=True)
-        # Update monitor
-        self.request.monitor['threads'] = int(self.request.monitor['threads']) - 1
-        self.request.monitor['posts'] = int(self.request.monitor['posts']) - self.thread.replies - 1
-        self.request.messages.set_flash(Message(_('Thread "%(thread)s" has been deleted.') % {'thread': self.thread.name}), 'success', 'threads')
-        return redirect(reverse('forum', kwargs={'forum': self.forum.pk, 'slug': self.forum.slug}))
-
-    def __call__(self, request, slug=None, thread=None, page=0):
-        self.request = request
-        self.pagination = None
-        self.parents = None
-        self.ignored = False
-        self.watcher = None
-        try:
-            self.fetch_thread(thread)
-            self.fetch_posts(page)
-            self.message = request.messages.get_message('threads')
-            self.make_thread_form()
-            if self.thread_form:
-                response = self.handle_thread_form()
-                if response:
-                    return response
-            self.make_posts_form()
-            if self.posts_form:
-                response = self.handle_posts_form()
-                if response:
-                    return response
-        except Thread.DoesNotExist:
-            return error404(self.request)
-        except ACLError403 as e:
-            return error403(request, e.message)
-        except ACLError404 as e:
-            return error404(request, e.message)
-        # Merge proxy into forum
-        self.forum.closed = self.proxy.closed
-        return request.theme.render_to_response('threads/thread.html',
-                                                {
-                                                 'message': self.message,
-                                                 'forum': self.forum,
-                                                 'parents': self.parents,
-                                                 'thread': self.thread,
-                                                 'is_read': self.tracker.is_read(self.thread),
-                                                 'count': self.count,
-                                                 'posts': self.posts,
-                                                 'ignored_posts': self.ignored,
-                                                 'watcher': self.watcher,
-                                                 'pagination': self.pagination,
-                                                 'quick_reply': FormFields(QuickReplyForm(request=request)).fields,
-                                                 'thread_form': FormFields(self.thread_form).fields if self.thread_form else None,
-                                                 'posts_form': FormFields(self.posts_form).fields if self.posts_form else None,
-                                                 },
-                                                context_instance=RequestContext(request));

+ 0 - 87
notrefactored/timezones/__init__.py

@@ -1,87 +0,0 @@
-import datetime
-from django.utils.translation import ugettext_lazy as _
-from django.utils import timezone
-import pytz
-
-raw_tz = (
-    ('Pacific/Apia', _('(UTC-13:00) Samoa'), _('(UTC-14:00) Samoa')),
-    ('Pacific/Midway', _('(UTC-11:00) Midway Islands, American Samoa')),
-    ('Pacific/Honolulu', _('(UTC-10:00) Cook Islands, Hawaii, Society Islands')),
-    ('America/Adak', _('(UTC-10:00) Aleutian Islands'), _('(UTC-09:00) Aleutian Islands')),
-    ('Pacific/Marquesas', _('(UTC-09:30) Marquesas Islands')),
-    ('Pacific/Gambier', _('(UTC-09:00) Gambier Islands')),
-    ('America/Anchorage', _('(UTC-09:00) Alaska Standard Time'), _('(UTC-08:00) Alaska Daylight Time')),
-    ('Pacific/Pitcairn', _('(UTC-08:00) Pitcairn Islands')),
-    ('America/Los_Angeles', _('(UTC-08:00) Pacific Time (Canada and US)'), _('(UTC-07:00) Pacific Time (Canada and US)')),
-    ('America/Santa_Isabel', _('(UTC-08:00) Baja California'), _('(UTC-07:00) Baja California')),
-    ('America/Phoenix', _('(UTC-07:00) Mountain Standard Time (No DST)')),
-    ('America/Hermosillo', _('(UTC-07:00) Sonora')),
-    ('America/Denver', _('(UTC-07:00) Mountain Standard Time'), _('(UTC-06:00) Mountain Summer Time')),
-    ('America/Chihuahua', _('(UTC-07:00) Baja California Sur, Chihuahua, Nayarit, Sinaloa'), _('(UTC-06:00) Baja California Sur, Chihuahua, Nayarit, Sinaloa')),
-    ('America/Costa_Rica', _('(UTC-06:00) Costa Rica, El Salvador, Galapagos, Guatemala, Managua')),
-    ('America/Chicago', _('(UTC-06:00) Central Standard Time'), _('(UTC-05:00) Central Daylight Time')),
-    ('America/Mexico_City', _('(UTC-06:00) Mexican Central Zone'), _('(UTC-05:00) Mexican Central Zone')),
-    ('America/Panama', _('(UTC-05:00) Bogota, Cayman, Guayaquil, Jamaica, Lima, Panama')),
-    ('America/New_York', _('(UTC-05:00) Eastern Standard Time'), _('(UTC-04:00) Eastern Daylight Time')),
-    ('America/Caracas', _('(UTC-04:30) Caracas')),
-    ('America/Puerto_Rico', _('(UTC-04:00) Barbados, Dominica, Puerto Rico, Santo Domingo')),
-    ('America/Santiago', _('(UTC-04:00) Bermuda, Campo Grande, Goose Bay, Santiago, Thule'), _('(UTC-03:00) Bermuda, Campo Grande, Goose Bay, Santiago, Thule')),
-    ('America/St_Johns', _('(UTC-03:30) Newfoundland Time')),
-    ('America/Argentina/La_Rioja', _('(UTC-03:00) San Juan, San Luis, Santa Cruz')),
-    ('America/Sao_Paulo', _('(UTC-03:00) Buenos Aires, Godthab, Sao Paulo, Montevideo'), _('(UTC-02:00) Buenos Aires, Godthab, Sao Paulo, Montevideo')),
-    ('America/Noronha', _('(UTC-02:00) Atlantic islands')),
-    ('Atlantic/Cape_Verde', _('(UTC-01:00) Cape Verde Time')),
-    ('Atlantic/Azores', _('(UTC-01:00) Azores, Scoresbysund'), _('(UTC) Azores, Scoresbysund')),
-    ('utc', _('(UTC) Coordinated Universal Time')),
-    ('Africa/Dakar', _('(UTC) Dakar, Rabat')),
-    ('Europe/Lisbon', _('(UTC) Western European Time'), _('(UTC+01:00) Western European Summer Time')),
-    ('Africa/Algiers', _('(UTC+01:00) West Africa Time')),
-    ('Europe/Zurich', _('(UTC+01:00) Central European Time'), _('(UTC+02:00) Central European Summer Time')),
-    ('Africa/Cairo', _('(UTC+02:00) Central Africa Time')),
-    ('Europe/Athens', _('(UTC+02:00) Eastern European Time'), _('(UTC+03:00) Eastern European Summer Time')),
-    ('Asia/Qatar', _('(UTC+03:00) East Africa Time')),
-    ('Europe/Minsk', _('(UTC+03:00) Further-eastern European Time')),
-    ('Asia/Tehran', _('(UTC+3:30) Iran Time'), _('(UTC+4:30) Iran Time')),
-    ('Europe/Moscow', _('(UTC+4:00) Moscow Standard Time, Georgian Time')),
-    ('Asia/Dubai', _('(UTC+04:00) United Arab Emirates Standard Time')),
-    ('Asia/Baku', _('(UTC+05:00) Baku, Yerevan'), _('(UTC+06:00) Baku, Yerevan')),
-    ('Asia/Kabul', _('(UTC+04:30) Afghanistan Standard Time')),
-    ('Asia/Karachi', _('(UTC+05:00) Ashgabat, Dushanbe, Karachi, Maldives, Tashkent')),
-    ('Asia/Kolkata', _('(UTC+05:30) Colombo, Kolkata')),
-    ('Asia/Kathmandu', _('(UTC+05:45) Kathmandu')),
-    ('Asia/Almaty', _('(UTC+06:00) Astana, Bishkek, Dhaka, Thimphu, Yekaterinburg')),
-    ('Asia/Rangoon', _('(UTC+06:30) Yangon, Cocos Islands')),
-    ('Asia/Bangkok', _('(UTC+07:00) Bangkok, Ho Chi Minh, Jakarta, Novosibirsk')),
-    ('Asia/Taipei', _('(UTC+08:00) Beijing, Hong Kong, Kuala Lumpur, Singapore, Taipei')),
-    ('Australia/Perth', _('(UTC+08:00) Australian Western Standard Time')),
-    ('Australia/Eucla', _('(UTC+08:45) Eucla Area')),
-    ('Asia/Tokyo', _('(UTC+09:00) Tokyo, Seoul, Irkutsk, Pyongyang')),
-    ('Australia/Darwin', _('(UTC+09:30) Australian Central Standard Time')),
-    ('Australia/Adelaide', _('(UTC+09:30) Australian Central Standard Time')),
-    ('Australia/Melbourne', _('(UTC+10:00) Australian Eastern Standard Time'), _('(UTC+11:00) Australian Eastern Summer Time')),
-    ('Australia/Lord_Howe', _('(UTC+10:30) Lord Howe Island'), _('(UTC+11:00) Lord Howe Island')),
-    ('Pacific/Guadalcanal', _('(UTC+11:00) Guadalcanal, Honiara, Noumea, Vladivostok')),
-    ('Pacific/Norfolk', _('(UTC+11:30) Norfolk Island')),
-    ('Pacific/Wake', _('(UTC+12:00) Kamchatka, Marshall Islands')),
-    ('Pacific/Auckland', _('(UTC+12:00) Auckland, Fiji'), _('(UTC+13:00) Auckland, Fiji')),
-    ('Pacific/Chatham', _('(UTC+12:45) Chatham Islands'), _('(UTC+13:45) Chatham Islands')),
-    ('Pacific/Enderbury', _('(UTC+13:00) Phoenix Islands')),
-    ('Pacific/Kiritimati', _('(UTC+14:00) Nuku\'alofa')),
-)
-
-def tzlist():
-    """
-    Generate user-friendly timezone list for selects
-    """
-    ready_list = []
-    utc_dt = datetime.datetime.utcnow().replace(tzinfo=pytz.utc)
-    for tz in raw_tz:
-        if len(tz) == 3:
-            tzinfo = pytz.timezone(tz[0])
-            if utc_dt.astimezone(tzinfo).dst().seconds > 0:
-                ready_list.append((tz[0], tz[2]))
-            else:
-                ready_list.append((tz[0], tz[1]))
-        else:
-           ready_list.append((tz[0], tz[1]))
-    return tuple(ready_list)

+ 0 - 0
notrefactored/tos/__init__.py


+ 0 - 43
notrefactored/tos/fixtures.py

@@ -1,43 +0,0 @@
-from misago.settings.fixtures import load_settings_fixture, update_settings_fixture
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-settings_fixtures = (
-    # Avatars Settings
-    ('tos', {
-         'name': _("Forum Terms of Service"),
-         'description': _("Those settings allow you to set up forum terms of service."),
-         'settings': (
-            ('tos_title', {
-                'value':        "Terms of Service",
-                'type':         "string",
-                'input':        "text",
-                'separator':    _("Terms of Service Options"),
-                'name':         _("Page Title"),
-                'description':  _("Title of page community ToS are displayed on."),
-            }),
-            ('tos_url', {
-                'value':        "",
-                'type':         "string",
-                'input':        "text",
-                'name':         _("Link to remote page with ToS"),
-                'description':  _("If your forum's ToS are located on remote page, enter here its address."),
-            }),
-            ('tos_content', {
-                'value':        "",
-                'type':         "string",
-                'input':        "textarea",
-                'name':         _("OR enter ToS content"),
-                'description':  _("Instead of linking to remote page, forum can create dedicated ToS page for you. To display ToS page, enter here your forum Terms of Service."),
-            }),
-       ),
-    }),
-)
-
-
-def load_fixtures():
-    load_settings_fixture(settings_fixtures)
-
-
-def update_fixtures():
-    update_settings_fixture(settings_fixtures)

+ 0 - 8
notrefactored/tos/views.py

@@ -1,8 +0,0 @@
-from django.template import RequestContext
-from misago.views import error404
-
-def forum_tos(request):
-    if request.settings.tos_url or not request.settings.tos_content:
-        return error404(request)
-    return request.theme.render_to_response('forum_tos.html',
-                                            context_instance=RequestContext(request));

+ 0 - 0
notrefactored/usercp/__init__.py


+ 0 - 81
notrefactored/usercp/acl.py

@@ -1,81 +0,0 @@
-from datetime import timedelta
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-from django.utils import timezone
-from misago.acl.builder import BaseACL
-from misago.forms import YesNoSwitch
-
-def make_form(request, role, form):
-    if role.token != 'guest':
-        form.base_fields['name_changes_allowed'] = forms.IntegerField(min_value=0, initial=1)
-        form.base_fields['changes_expire'] = forms.IntegerField(min_value=0, initial=0)
-        form.base_fields['can_use_signature'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-        form.base_fields['allow_signature_links'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-        form.base_fields['allow_signature_images'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-        form.layout.append((
-                            _("Profile Settings"),
-                            (
-                             ('name_changes_allowed', {'label': _("Allowed Username changes number"), 'help_text': _("Enter zero to don't allow users with this role to change their names.")}),
-                             ('changes_expire', {'label': _("Don't count username changes older than"), 'help_text': _("Number of days since name change that makes that change no longer count to limit. For example, if you enter 7 days and set changes limit 3, users with this rank will not be able to make more than three changes in duration of 7 days. Enter zero to make all changes count.")}),
-                             ('can_use_signature', {'label': _("Can have signature")}),
-                             ('allow_signature_links', {'label': _("Can put links in signature")}),
-                             ('allow_signature_images', {'label': _("Can put images in signature")}),
-                             ),
-                            ))
-
-
-class UserCPACL(BaseACL):
-    def show_username_change(self):
-        return self.acl['name_changes_allowed'] > 0
-
-    def changes_expire(self):
-        return self.acl['changes_expire'] > 0
-
-    def changes_left(self, user):
-        if not self.acl['name_changes_allowed']:
-            return 0
-
-        if self.acl['changes_expire']:
-            changes_left = self.acl['name_changes_allowed'] - user.namechanges.filter(
-                                                    date__gte=timezone.now() - timedelta(days=self.acl['changes_expire']),
-                                                    ).count()
-        else:
-            changes_left = self.acl['name_changes_allowed'] - user.namechanges.all().count()
-
-        if changes_left:
-            return changes_left
-        return 0
-
-    def can_use_signature(self):
-        return self.acl['signature']
-
-    def allow_signature_links(self):
-        return self.acl['signature_links']
-
-    def allow_signature_images(self):
-        return self.acl['signature_images']
-
-
-def build(acl, roles):
-    acl.usercp = UserCPACL()
-    acl.usercp.acl['name_changes_allowed'] = 0
-    acl.usercp.acl['changes_expire'] = 0
-    acl.usercp.acl['signature'] = False
-    acl.usercp.acl['signature_links'] = False
-    acl.usercp.acl['signature_images'] = False
-
-    for role in roles:
-        if 'name_changes_allowed' in role and role['name_changes_allowed'] > acl.usercp.acl['name_changes_allowed']:
-            acl.usercp.acl['name_changes_allowed'] = role['name_changes_allowed']
-
-        if 'changes_expire' in role and role['changes_expire'] > acl.usercp.acl['changes_expire']:
-            acl.usercp.acl['changes_expire'] = role['changes_expire']
-
-        if 'can_use_signature' in role and role['can_use_signature']:
-            acl.usercp.acl['signature'] = role['can_use_signature']
-
-        if 'allow_signature_links' in role and role['allow_signature_links']:
-            acl.usercp.acl['signature_links'] = role['allow_signature_links']
-
-        if 'allow_signature_images' in role and role['allow_signature_images']:
-            acl.usercp.acl['signature_images'] = role['allow_signature_images']

+ 0 - 0
notrefactored/usercp/avatar/__init__.py


+ 0 - 32
notrefactored/usercp/avatar/forms.py

@@ -1,32 +0,0 @@
-from PIL import Image
-from django import forms
-from django.conf import settings
-from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-
-class UploadAvatarForm(Form):
-    avatar_upload = forms.ImageField(error_messages={'invalid_image': _("Uploaded file is not correct image.")})
-    error_source = 'avatar_upload'
-
-    layout = [
-              [
-               None,
-               [
-                ('avatar_upload', {'label': _("Upload Image File"), 'help_text': _("Select image file on your computer you wish to use as forum avatar. You will be able to crop image after upload. Animations will be stripped.")}),
-                ],
-               ],
-              ]
-
-    def clean_avatar_upload(self):
-        image = self.cleaned_data.get('avatar_upload', False)
-        if image:
-            if image._size > self.request.settings.upload_limit * 1024:
-                if self.request.settings.upload_limit > 1024:
-                    limit = '%s Mb' % "{:10.2f}".format(float(self.request.settings.upload_limit / 1024.0))
-                else:
-                    limit = '%s Kb' % self.request.settings.upload_limit
-                raise ValidationError(_("Avatar image cannot be larger than %(limit)s.") % {'limit': limit})
-        else:
-            raise ValidationError(_("Couldn't read uploaded image"))
-        return image

+ 0 - 21
notrefactored/usercp/avatar/urls.py

@@ -1,21 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_usercp_urls(first=False):
-    urlpatterns = []
-    if first:
-        urlpatterns += patterns('misago.usercp.avatar.views',
-            url(r'^$', 'avatar', name="usercp"),
-            url(r'^$', 'avatar', name="usercp_avatar"),
-        )
-    else:
-        urlpatterns += patterns('misago.usercp.avatar.views',
-            url(r'^avatar/$', 'avatar', name="usercp_avatar"),
-        )
-    urlpatterns += patterns('misago.usercp.avatar.views',
-        url(r'^avatar/gallery/$', 'gallery', name="usercp_avatar_gallery"),
-        url(r'^avatar/upload/$', 'upload', name="usercp_avatar_upload"),
-        url(r'^avatar/upload/crop/$', 'crop', name="usercp_avatar_upload_crop", kwargs={'upload': True}),
-        url(r'^avatar/crop/$', 'crop', name="usercp_avatar_crop"),
-        url(r'^avatar/gravatar/$', 'gravatar', name="usercp_avatar_gravatar"),
-    )
-    return urlpatterns

+ 0 - 4
notrefactored/usercp/avatar/usercp.py

@@ -1,4 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_usercp_extension(request):
-    return (('usercp_avatar', _('Change Avatar')),)

+ 0 - 228
notrefactored/usercp/avatar/views.py

@@ -1,228 +0,0 @@
-from path import path
-from PIL import Image
-from django.conf import settings
-from django.core.exceptions import ValidationError
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.utils.translation import ugettext as _
-from misago.authn.decorators import block_guest
-from misago.forms import FormLayout
-from misago.messages import Message
-from misago.usercp.template import RequestContext
-from misago.usercp.avatar.forms import UploadAvatarForm
-from misago.views import error404
-from misago.utils import get_random_string
-from misago.utils.avatars import resizeimage
-
-def avatar_view(f):
-    def decorator(*args, **kwargs):
-        request = args[0]
-        if request.user.avatar_ban:
-            return request.theme.render_to_response('usercp/avatar_banned.html',
-                                                    context_instance=RequestContext(request, {
-                                                     'tab': 'avatar',
-                                                     }));
-        return f(*args, **kwargs)
-    return decorator
-
-
-@block_guest
-@avatar_view
-def avatar(request):
-    message = request.messages.get_message('usercp_avatar')
-    return request.theme.render_to_response('usercp/avatar.html',
-                                            context_instance=RequestContext(request, {
-                                             'message': message,
-                                             'tab': 'avatar',
-                                             }));
-
-
-@block_guest
-@avatar_view
-def gravatar(request):
-    if not 'gravatar' in request.settings.avatars_types:
-        return error404(request)
-    if request.user.avatar_type != 'gravatar':
-        if request.csrf.request_secure(request):
-            request.user.delete_avatar()
-            request.user.avatar_type = 'gravatar'
-            request.user.save(force_update=True)
-            request.messages.set_flash(Message(_("Your avatar has been changed to Gravatar.")), 'success', 'usercp_avatar')
-        else:
-            request.messages.set_flash(Message(_("Request authorisation is invalid.")), 'error', 'usercp_avatar')
-    return redirect(reverse('usercp_avatar'))
-
-
-@block_guest
-@avatar_view
-def gallery(request):
-    if not 'gallery' in request.settings.avatars_types:
-        return error404(request)
-
-    allowed_avatars = []
-    galleries = []
-    for directory in path(settings.STATICFILES_DIRS[0]).joinpath('avatars').dirs():
-        if directory[-7:] != '_locked' and directory[-8:] != '_default':
-            gallery = {'name': directory[-7:], 'avatars': []}
-            avatars = directory.files('*.gif')
-            avatars += directory.files('*.jpg')
-            avatars += directory.files('*.jpeg')
-            avatars += directory.files('*.png')
-            for item in avatars:
-                gallery['avatars'].append('/'.join(path(item).splitall()[-2:]))
-            galleries.append(gallery)
-            allowed_avatars += gallery['avatars']
-
-    if not allowed_avatars:
-        request.messages.set_flash(Message(_("No avatars are avaiable.")), 'info', 'usercp_avatar')
-        return redirect(reverse('usercp_avatar'))
-
-    message = request.messages.get_message('usercp_avatar')
-    if request.method == 'POST':
-        if request.csrf.request_secure(request):
-            new_avatar = request.POST.get('avatar_image')
-            if new_avatar in allowed_avatars:
-                request.user.delete_avatar()
-                request.user.avatar_type = 'gallery'
-                request.user.avatar_image = new_avatar
-                request.user.save(force_update=True)
-                request.messages.set_flash(Message(_("Your avatar has been changed to one from gallery.")), 'success', 'usercp_avatar')
-                return redirect(reverse('usercp_avatar'))
-            message = Message(_("Selected Avatar is incorrect."), 'error')
-        else:
-            message = Message(_("Request authorisation is invalid."), 'error')
-
-    return request.theme.render_to_response('usercp/avatar_gallery.html',
-                                            context_instance=RequestContext(request, {
-                                             'message': message,
-                                             'galleries': galleries,
-                                             'tab': 'avatar',
-                                             }));
-
-
-@block_guest
-@avatar_view
-def upload(request):
-    if not 'upload' in request.settings.avatars_types:
-        return error404(request)
-    message = request.messages.get_message('usercp_avatar')
-    if request.method == 'POST':
-        form = UploadAvatarForm(request.POST, request.FILES, request=request)
-        if form.is_valid():
-            request.user.delete_avatar_temp()
-            image = form.cleaned_data['avatar_upload']
-            image_name, image_extension = path(image.name.lower()).splitext()
-            image_name = '%s_tmp_%s%s' % (request.user.pk, get_random_string(8), image_extension)
-            image_path = settings.MEDIA_ROOT + 'avatars/' + image_name
-            request.user.avatar_temp = image_name
-
-            with open(image_path, 'wb+') as destination:
-                for chunk in image.chunks():
-                    destination.write(chunk)
-            request.user.save()
-            try:
-                image = Image.open(image_path)
-                if not image.format in ['GIF', 'PNG', 'JPEG']:
-                    raise ValidationError()
-                image.seek(0)
-                image.save(image_path)
-                if request.POST.get('js_check'):
-                    return redirect(reverse('usercp_avatar_upload_crop'))
-                # Redirect to crop page didnt happen, handle avatar with old school hollywood way
-                image_path = settings.MEDIA_ROOT + 'avatars/'
-                source = Image.open(image_path + request.user.avatar_temp)
-                image_name, image_extension = path(request.user.avatar_temp).splitext()
-                image_name = '%s_%s%s' % (request.user.pk, get_random_string(8), image_extension)
-                resizeimage(source, settings.AVATAR_SIZES[0], image_path + image_name, info=source.info, format=source.format)
-                for size in settings.AVATAR_SIZES[1:]:
-                    resizeimage(source, size, image_path + str(size) + '_' + image_name, info=source.info, format=source.format)
-                # Update user model one more time
-                request.user.delete_avatar_image()
-                request.user.delete_avatar_original()
-                request.user.avatar_type = 'upload'
-                request.user.avatar_original = '%s_org_%s%s' % (request.user.pk, get_random_string(8), image_extension)
-                source.save(image_path + request.user.avatar_original)
-                request.user.delete_avatar_temp()
-                request.user.avatar_image = image_name
-                request.user.save(force_update=True)
-                # Set message and adios!
-                request.messages.set_flash(Message(_("Your avatar has changed.")), 'success', 'usercp_avatar')
-                return redirect(reverse('usercp_avatar'))
-            except ValidationError:
-                request.user.delete_avatar()
-                request.user.default_avatar(request.settings)
-                message = Message(_("Only gif, jpeg and png files are allowed for member avatars."), 'error')
-        else:
-            message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = UploadAvatarForm(request=request)
-
-    return request.theme.render_to_response('usercp/avatar_upload.html',
-                                            context_instance=RequestContext(request, {
-                                             'message': message,
-                                             'form': FormLayout(form),
-                                             'tab': 'avatar',
-                                             }));
-
-
-@block_guest
-@avatar_view
-def crop(request, upload=False):
-    if upload and (not request.user.avatar_temp or not 'upload' in request.settings.avatars_types):
-        return error404(request)
-
-    if not upload and request.user.avatar_type != 'upload':
-        request.messages.set_flash(Message(_("Crop Avatar option is avaiable only when you use uploaded image as your avatar.")), 'error', 'usercp_avatar')
-        return redirect(reverse('usercp_avatar'))
-
-    message = request.messages.get_message('usercp_avatar')
-    if request.method == 'POST':
-        if request.csrf.request_secure(request):
-            try:
-                image_path = settings.MEDIA_ROOT + 'avatars/'
-                if upload:
-                    source = Image.open(image_path + request.user.avatar_temp)
-                else:
-                    source = Image.open(image_path + request.user.avatar_original)
-                width, height = source.size
-
-                aspect = float(width) / float(request.POST['crop_b'])
-                crop_x = int(aspect * float(request.POST['crop_x']))
-                crop_y = int(aspect * float(request.POST['crop_y']))
-                crop_w = int(aspect * float(request.POST['crop_w']))
-                crop = source.crop((crop_x, crop_y, crop_x + crop_w, crop_y + crop_w))
-
-                if upload:
-                    image_name, image_extension = path(request.user.avatar_temp).splitext()
-                else:
-                    image_name, image_extension = path(request.user.avatar_original).splitext()
-                image_name = '%s_%s%s' % (request.user.pk, get_random_string(8), image_extension)
-                resizeimage(crop, settings.AVATAR_SIZES[0], image_path + image_name, info=source.info, format=source.format)
-                for size in settings.AVATAR_SIZES[1:]:
-                    resizeimage(crop, size, image_path + str(size) + '_' + image_name, info=source.info, format=source.format)
-
-                request.user.delete_avatar_image()
-                if upload:
-                    request.user.delete_avatar_original()
-                    request.user.avatar_type = 'upload'
-                    request.user.avatar_original = '%s_org_%s%s' % (request.user.pk, get_random_string(8), image_extension)
-                    source.save(image_path + request.user.avatar_original)
-                request.user.delete_avatar_temp()
-                request.user.avatar_image = image_name
-                request.user.save(force_update=True)
-                request.messages.set_flash(Message(_("Your avatar has been cropped.")), 'success', 'usercp_avatar')
-                return redirect(reverse('usercp_avatar'))
-            except Exception:
-                message = Message(_("Form contains errors."), 'error')
-        else:
-            message = Message(_("Request authorisation is invalid."), 'error')
-
-
-    return request.theme.render_to_response('usercp/avatar_crop.html',
-                                            context_instance=RequestContext(request, {
-                                             'message': message,
-                                             'after_upload': upload,
-                                             'avatar_size': settings.AVATAR_SIZES[0],
-                                             'source': 'avatars/%s' % (request.user.avatar_temp if upload else request.user.avatar_original),
-                                             'tab': 'avatar',
-                                             }));

+ 0 - 0
notrefactored/usercp/credentials/__init__.py


+ 0 - 52
notrefactored/usercp/credentials/forms.py

@@ -1,52 +0,0 @@
-import hashlib
-from django import forms
-from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-from misago.users.models import User
-from misago.users.validators import validate_password, validate_email
-
-class CredentialsChangeForm(Form):
-    new_email = forms.EmailField(max_length=255, required=False)
-    new_password = forms.CharField(max_length=255, widget=forms.PasswordInput, required=False)
-    current_password = forms.CharField(max_length=255, widget=forms.PasswordInput)
-
-    layout = [
-              (
-               None,
-               [
-                ('new_email', {'label': _('New E-mail'), 'help_text': _("Enter new e-mail address or leave this field empty if you want only to change your password.")}),
-                ('new_password', {'label': _('New Password'), 'help_text': _("Enter new password or leave this empty if you only want to change your e-mail address.")}),
-                ('current_password', {'label': _('Current Password'), 'help_text': _("Confirm changes by entering new password.")})
-                ]
-               ),
-              ]
-
-    def clean_new_email(self):
-        if self.cleaned_data['new_email']:
-            new_hash = hashlib.md5(self.cleaned_data['new_email'].lower()).hexdigest()
-            if new_hash == self.request.user.email_hash:
-                raise ValidationError(_("New e-mail is same as your current e-mail."))
-            try:
-                User.objects.get(email_hash=new_hash)
-                raise ValidationError(_("New e-mail address is already in use by other member."))
-            except User.DoesNotExist:
-                pass
-            validate_email(self.cleaned_data['new_email'])
-        return self.cleaned_data['new_email'].lower()
-
-    def clean_new_password(self):
-        if self.cleaned_data['new_password']:
-            validate_password(self.cleaned_data['new_password'])
-        return self.cleaned_data['new_password']
-
-    def clean_current_password(self):
-        if not self.request.user.check_password(self.cleaned_data['current_password']):
-            raise ValidationError(_("You have entered wrong password."))
-        return ''
-
-    def clean(self):
-        cleaned_data = super(CredentialsChangeForm, self).clean()
-        if not cleaned_data['new_email'] and not cleaned_data['new_password']:
-            raise ValidationError(_("You have to enter either new e-mail address or new password."))
-        return cleaned_data

+ 0 - 17
notrefactored/usercp/credentials/urls.py

@@ -1,17 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_usercp_urls(first=False):
-    urlpatterns = []
-    if first:
-        urlpatterns += patterns('misago.usercp.credentials.views',
-            url(r'^$', 'credentials', name="usercp"),
-            url(r'^$', 'credentials', name="usercp_credentials"),
-        )
-    else:
-        urlpatterns += patterns('misago.usercp.credentials.views',
-            url(r'^credentials/$', 'credentials', name="usercp_credentials"),
-        )
-    urlpatterns += patterns('misago.usercp.credentials.views',
-        url(r'^credentials/activate/(?P<token>[a-zA-Z0-9]+)/$', 'activate', name="usercp_credentials_activate"),
-    )
-    return urlpatterns

+ 0 - 4
notrefactored/usercp/credentials/usercp.py

@@ -1,4 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_usercp_extension(request):
-    return (('usercp_credentials', _('Change E-mail or Password')),)

+ 0 - 72
notrefactored/usercp/credentials/views.py

@@ -1,72 +0,0 @@
-from django.core.exceptions import ValidationError
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.utils.translation import ugettext as _
-from misago.authn.decorators import block_guest
-from misago.forms import FormLayout
-from misago.messages import Message
-from misago.usercp.template import RequestContext
-from misago.usercp.credentials.forms import CredentialsChangeForm
-from misago.views import error404
-from misago.utils import get_random_string
-
-@block_guest
-def credentials(request):
-    message = request.messages.get_message('usercp_credentials')
-    if request.method == 'POST':
-        form = CredentialsChangeForm(request.POST, request=request)
-        if form.is_valid():
-            token = get_random_string(12)
-            request.user.email_user(
-                                    request,
-                                    'users/new_credentials',
-                                    _("Activate new Sign-In Credentials"),
-                                    {'token': token}
-                                    )
-            request.session['new_credentials'] = {
-                                                  'token': token,
-                                                  'email_hash': request.user.email_hash,
-                                                  'new_email': form.cleaned_data['new_email'],
-                                                  'new_password': form.cleaned_data['new_password'],
-                                                  }
-            if form.cleaned_data['new_email']:
-                request.user.email = form.cleaned_data['new_email']
-                request.messages.set_flash(Message(_("We have sent e-mail message to your new e-mail address with link you have to click to confirm change of your sign-in credentials. This link will be valid only for duration of this session, do not sign out until you confirm change!")), 'success', 'usercp_credentials')
-            else:
-                request.messages.set_flash(Message(_("We have sent e-mail message to your e-mail address with link you have to click to confirm change of your sign-in credentials. This link will be valid only for duration of this session, do not sign out until you confirm change!")), 'success', 'usercp_credentials')
-            return redirect(reverse('usercp_credentials'))
-        message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = CredentialsChangeForm(request=request)
-
-    return request.theme.render_to_response('usercp/credentials.html',
-                                            context_instance=RequestContext(request, {
-                                             'message': message,
-                                             'form': FormLayout(form),
-                                             'tab': 'credentials',
-                                             }));
-
-
-@block_guest
-def activate(request, token):
-    new_credentials = request.session.get('new_credentials')
-    if not new_credentials or new_credentials['token'] != token:
-        return error404(request)
-
-    if new_credentials['new_email']:
-        request.user.set_email(new_credentials['new_email'])
-    if new_credentials['new_password']:
-        request.user.set_password(new_credentials['new_password'])
-
-    try:
-        request.user.full_clean()
-        request.user.save(force_update=True)
-        request.user.sessions.exclude(id=request.session.id).delete()
-        request.user.signin_tokens.all().delete()
-        request.messages.set_flash(Message(_("%(username)s, your Sign-In credentials have been changed.") % {'username': request.user.username}), 'success', 'security')
-        request.session.sign_out(request)
-        del request.session['new_credentials']
-        return redirect(reverse('sign_in'))
-    except ValidationError:
-        request.messages.set_flash(Message(_("Your new credentials have been invalidated. Please try again.")), 'error', 'usercp_credentials')
-        return redirect(reverse('usercp_credentials'))

+ 0 - 47
notrefactored/usercp/fixtures.py

@@ -1,47 +0,0 @@
-from misago.settings.fixtures import load_settings_fixture, update_settings_fixture
-from misago.utils import ugettext_lazy as _
-from misago.utils import get_msgid
-
-settings_fixtures = (
-    # Avatars Settings
-    ('avatars', {
-         'name': _("Users Avatars Settings"),
-         'description': _("Those settings allow you to control your users avatars."),
-         'settings': (
-            ('avatars_types', {
-                'value':        ['gravatar', 'gallery'],
-                'type':         "array",
-                'input':        "mlist",
-                'extra':        {'choices': [('gravatar', _("Gravatar")), ('upload', _("Uploaded Avatar")), ('gallery', _("Avatars Gallery"))]},
-                'separator':    _("General Settings"),
-                'name':         _("Allowed Avatars"),
-                'description':  _("Select Avatar types allowed on your forum."),
-            }),
-            ('default_avatar', {
-                'value':        "gravatar",
-                'type':         "string",
-                'input':        "select",
-                'extra':        {'choices': [('gravatar', _("Gravatar")), ('gallery', _("Random Avatar from Gallery"))]},
-                'name':         _("Default Avatar"),
-                'description':  _("Default Avatar assigned to new members. If you creade directory and name it \"_default\", forum will select random avatar from that directory instead of regular gallery. If no avatar can be picked from gallery, Gravatar will be used."),
-            }),
-            ('upload_limit', {
-                'value':        128,
-                'type':         "integer",
-                'input':        "text",
-                'extra':        {'min': 0},
-                'separator':    _("Avatar Upload Settings"),
-                'name':         _("Maxmimum size of uploaded file"),
-                'description':  _("Select maximum allowed file size (in KB) for Avatar uploads."),
-            }),
-       ),
-    }),
-)
-
-
-def load_fixtures():
-    load_settings_fixture(settings_fixtures)
-
-
-def update_fixtures():
-    update_settings_fixture(settings_fixtures)

+ 0 - 117
notrefactored/usercp/migrations/0001_initial.py

@@ -1,117 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'UsernameChange'
-        db.create_table(u'usercp_usernamechange', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='namechanges', to=orm['users.User'])),
-            ('date', self.gf('django.db.models.fields.DateTimeField')()),
-            ('old_username', self.gf('django.db.models.fields.CharField')(max_length=255)),
-        ))
-        db.send_create_signal(u'usercp', ['UsernameChange'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'UsernameChange'
-        db.delete_table(u'usercp_usernamechange')
-
-
-    models = {
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'usercp.usernamechange': {
-            'Meta': {'object_name': 'UsernameChange'},
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'old_username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'namechanges'", 'to': u"orm['users.User']"})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['usercp']

+ 0 - 0
notrefactored/usercp/migrations/__init__.py


+ 0 - 6
notrefactored/usercp/models.py

@@ -1,6 +0,0 @@
-from django.db import models
-
-class UsernameChange(models.Model):
-    user = models.ForeignKey('users.User', related_name='namechanges')
-    date = models.DateTimeField()
-    old_username = models.CharField(max_length=255)

+ 0 - 0
notrefactored/usercp/options/__init__.py


+ 0 - 42
notrefactored/usercp/options/forms.py

@@ -1,42 +0,0 @@
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-from misago.timezones import tzlist
-from misago.forms import Form
-
-
-class UserForumOptionsForm(Form):
-    newsletters = forms.BooleanField(required=False)
-    timezone = forms.ChoiceField(choices=tzlist())
-    hide_activity = forms.ChoiceField(choices=(
-                                               (0, _("Show my presence to everyone")),
-                                               (1, _("Show my presence to people I follow")),
-                                               (2, _("Show my presence to nobody")),
-                                               ))
-    subscribe_start = forms.ChoiceField(choices=(
-                                                 (0, _("Don't watch")),
-                                                 (1, _("Put on watched threads list")),
-                                                 (2, _("Put on watched threads list and e-mail me when somebody replies")),
-                                                 ))
-    subscribe_reply = forms.ChoiceField(choices=(
-                                                 (0, _("Don't watch")),
-                                                 (1, _("Put on watched threads list")),
-                                                 (2, _("Put on watched threads list and e-mail me when somebody replies")),
-                                                 ))
-
-    layout = (
-              (
-               _("Forum Options"),
-               (
-                ('hide_activity', {'label': _("Your Visibility"), 'help_text': _("If you want to, you can limit other members ability to track your presence on forums.")}),
-                ('timezone', {'label': _("Your Current Timezone"), 'help_text': _("If dates and hours displayed by forums are inaccurate, you can fix it by adjusting timezone setting.")}),
-                ('newsletters', {'label': _("Newsletters"), 'help_text': _("On occasion board administrator may want to send e-mail message to multiple members."), 'inline': _("Yes, I want to subscribe forum newsletter")}),
-                )
-               ),
-              (
-               _("Watching Threads"),
-               (
-                ('subscribe_start', {'label': _("Threads I start")}),
-                ('subscribe_reply', {'label': _("Threads I reply to")}),
-                )
-               ),
-              )

+ 0 - 11
notrefactored/usercp/options/urls.py

@@ -1,11 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_usercp_urls(first=False):
-    if first:
-        return patterns('misago.usercp.options.views',
-            url(r'^$', 'options', name="usercp"),
-            url(r'^$', 'options', name="usercp_options"),
-        )
-    return patterns('misago.usercp.options.views',
-        url(r'^options/$', 'options', name="usercp_options"),
-    )

+ 0 - 4
notrefactored/usercp/options/usercp.py

@@ -1,4 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_usercp_extension(request):
-    return (('usercp_options', _('Forum Options')),)

+ 0 - 40
notrefactored/usercp/options/views.py

@@ -1,40 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.utils.translation import ugettext as _
-from misago.forms import FormLayout
-from misago.messages import Message
-from misago.authn.decorators import block_guest
-from misago.usercp.options.forms import UserForumOptionsForm
-from misago.usercp.template import RequestContext
-
-
-@block_guest
-def options(request):
-    message = request.messages.get_message('usercp_options')
-    if request.method == 'POST':
-        form = UserForumOptionsForm(request.POST, request=request)
-        if form.is_valid():
-            request.user.receive_newsletters = form.cleaned_data['newsletters']
-            request.user.hide_activity = form.cleaned_data['hide_activity']
-            request.user.timezone = form.cleaned_data['timezone']
-            request.user.subscribe_start = form.cleaned_data['subscribe_start']
-            request.user.subscribe_reply = form.cleaned_data['subscribe_reply']
-            request.user.save(force_update=True)
-            request.messages.set_flash(Message(_("Forum options have been changed.")), 'success', 'usercp_options')
-            return redirect(reverse('usercp'))
-        message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = UserForumOptionsForm(request=request, initial={
-                                                             'newsletters': request.user.receive_newsletters,
-                                                             'hide_activity': request.user.hide_activity,
-                                                             'timezone': request.user.timezone,
-                                                             'subscribe_start': request.user.subscribe_start,
-                                                             'subscribe_reply': request.user.subscribe_reply,
-                                                             })
-
-    return request.theme.render_to_response('usercp/options.html',
-                                            context_instance=RequestContext(request, {
-                                             'message': message,
-                                             'tab': 'options',
-                                             'form': FormLayout(form)
-                                             }));

+ 0 - 0
notrefactored/usercp/signature/__init__.py


+ 0 - 16
notrefactored/usercp/signature/forms.py

@@ -1,16 +0,0 @@
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-
-
-class SignatureForm(Form):
-    signature = forms.CharField(widget=forms.Textarea, required=False)
-
-    layout = (
-              (
-               None,
-               (
-                ('signature', {'label': _("Your Signature"), 'attrs': {'rows': 10}}),
-                )
-               ),
-              )

+ 0 - 11
notrefactored/usercp/signature/urls.py

@@ -1,11 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_usercp_urls(first=False):
-    if first:
-        return patterns('misago.usercp.signature.views',
-            url(r'^$', 'signature', name="usercp"),
-            url(r'^$', 'signature', name="usercp_signature"),
-        )
-    return patterns('misago.usercp.signature.views',
-        url(r'^signature/$', 'signature', name="usercp_signature"),
-    )

+ 0 - 5
notrefactored/usercp/signature/usercp.py

@@ -1,5 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_usercp_extension(request):
-    if request.acl.usercp.can_use_signature():
-        return (('usercp_signature', _('Edit Signature')),)

+ 0 - 47
notrefactored/usercp/signature/views.py

@@ -1,47 +0,0 @@
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.utils.translation import ugettext as _
-from misago.authn.decorators import block_guest
-from misago.forms import FormLayout
-from misago.markdown import signature_markdown
-from misago.messages import Message
-from misago.usercp.template import RequestContext
-from misago.usercp.signature.forms import SignatureForm
-from misago.views import error403, error404
-
-@block_guest
-def signature(request):
-    # Intercept all requests if we can't use signature
-    if not request.acl.usercp.can_use_signature():
-        return error403(request)
-    if request.user.signature_ban:
-        return request.theme.render_to_response('usercp/signature_banned.html',
-                                                context_instance=RequestContext(request, {
-                                                 'tab': 'signature',
-                                                 }));
-
-    siggy_text = ''
-    message = request.messages.get_message('usercp_signature')
-    if request.method == 'POST':
-        form = SignatureForm(request.POST, request=request, initial={'signature': request.user.signature})
-        if form.is_valid():
-            request.user.signature = form.cleaned_data['signature']
-            if request.user.signature:
-                request.user.signature_preparsed = signature_markdown(request.acl,
-                                                                      request.user.signature)
-            else:
-                request.user.signature_preparsed = None
-            request.user.save(force_update=True)
-            request.messages.set_flash(Message(_("Your signature has been changed.")), 'success', 'usercp_signature')
-            return redirect(reverse('usercp_signature'))
-        else:
-            message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = SignatureForm(request=request, initial={'signature': request.user.signature})
-
-    return request.theme.render_to_response('usercp/signature.html',
-                                            context_instance=RequestContext(request, {
-                                             'message': message,
-                                             'tab': 'signature',
-                                             'form': FormLayout(form),
-                                             }));

+ 0 - 25
notrefactored/usercp/template.py

@@ -1,25 +0,0 @@
-from django.conf import settings
-from django.template import RequestContext as DjangoRequestContext
-from django.utils.importlib import import_module
-
-def RequestContext(request, context=None):
-    if not context:
-        context = {}
-    context['tabs'] = []
-    for extension in settings.USERCP_EXTENSIONS:
-        usercp_module = import_module(extension + '.usercp')
-        try:
-            append_links = usercp_module.register_usercp_extension(request)
-            if append_links:
-                for link in append_links:
-                    link = list(link)
-                    token = link[0][link[0].find('_') + 1:]
-                    context['tabs'].append({
-                                            'route': link[0],
-                                            'active': context['tab'] == token,
-                                            'name': link[1],
-                                            })
-        except AttributeError:
-            pass
-
-    return DjangoRequestContext(request, context)

+ 0 - 22
notrefactored/usercp/urls.py

@@ -1,22 +0,0 @@
-from django.conf import settings
-from django.conf.urls import include, patterns, url
-from django.utils.importlib import import_module
-
-urlpatterns = []
-iteration = 0
-for extension in settings.USERCP_EXTENSIONS:
-    iteration += 1
-    usercp_module = import_module(extension + '.urls')
-    try:
-        urlpatterns += patterns('',
-            (r'^', include(usercp_module.register_usercp_urls(iteration == 1))),
-        )
-    except AttributeError:
-        pass
-
-urlpatterns += patterns('misago.usercp.views',
-    url(r'^follow/(?P<user>\d+)/$', 'follow', name="follow_user"),
-    url(r'^unfollow/(?P<user>\d+)/$', 'unfollow', name="unfollow_user"),
-    url(r'^ignore/(?P<user>\d+)/$', 'ignore', name="ignore_user"),
-    url(r'^unignore/(?P<user>\d+)/$', 'unignore', name="unignore_user"),
-)

+ 0 - 0
notrefactored/usercp/username/__init__.py


+ 0 - 31
notrefactored/usercp/username/forms.py

@@ -1,31 +0,0 @@
-from django import forms
-from django.core.exceptions import ValidationError
-from misago.users.validators import validate_username
-from django.utils.translation import ugettext_lazy as _
-from misago.forms import Form
-
-class UsernameChangeForm(Form):
-    username = forms.CharField(max_length=255)
-    error_source = 'username'
-
-    layout = [
-              [
-               None,
-               [
-                ('username', {'label': _("Change Username to"), 'help_text': _("Enter new desired username.")}),
-                ],
-               ],
-              ]
-
-    def clean_username(self):
-        org_username = self.request.user.username
-        if org_username == self.cleaned_data['username']:
-            raise ValidationError(_("Your new username is same as current one."))
-        validate_username(self.cleaned_data['username'], self.request.settings)
-        self.request.user.set_username(self.cleaned_data['username'])
-        try:
-            self.request.user.full_clean()
-        except ValidationError as e:
-            self.request.user.is_username_valid(e)
-            self.request.user.set_username(org_username)
-        return self.cleaned_data['username']

+ 0 - 11
notrefactored/usercp/username/urls.py

@@ -1,11 +0,0 @@
-from django.conf.urls import patterns, url
-
-def register_usercp_urls(first=False):
-    if first:
-        return patterns('misago.usercp.username.views',
-            url(r'^$', 'username', name="usercp"),
-            url(r'^$', 'username', name="usercp_username"),
-        )
-    return patterns('misago.usercp.username.views',
-        url(r'^username/$', 'username', name="usercp_username"),
-    )

+ 0 - 5
notrefactored/usercp/username/usercp.py

@@ -1,5 +0,0 @@
-from django.utils.translation import ugettext_lazy as _
-
-def register_usercp_extension(request):
-    if request.acl.usercp.show_username_change():
-        return (('usercp_username', _('Change Username')),)

+ 0 - 73
notrefactored/usercp/username/views.py

@@ -1,73 +0,0 @@
-from datetime import timedelta
-from django.core.urlresolvers import reverse
-from django.db.models import F
-from django.shortcuts import redirect
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.alerts.models import Alert
-from misago.authn.decorators import block_guest
-from misago.forms import FormLayout
-from misago.messages import Message
-from misago.users.models import User
-from misago.usercp.template import RequestContext
-from misago.usercp.models import UsernameChange
-from misago.usercp.username.forms import UsernameChangeForm
-from misago.views import error404
-from misago.utils import ugettext_lazy
-
-@block_guest
-def username(request):
-    if not request.acl.usercp.show_username_change():
-        return error404(request)
-
-    changes_left = request.acl.usercp.changes_left(request.user)
-    next_change = None
-    if request.acl.usercp.changes_expire() and not changes_left:
-        next_change = request.user.namechanges.filter(
-                                                      date__gte=timezone.now() - timedelta(days=request.acl.usercp.acl['changes_expire']),
-                                                      ).order_by('-date')[0]
-        next_change = next_change.date + timedelta(days=request.acl.usercp.acl['changes_expire'])
-
-    message = request.messages.get_message('usercp_username')
-    if request.method == 'POST':
-        if not changes_left:
-            message = Message(_("You have exceeded the maximum number of name changes."), 'error')
-            form = UsernameChangeForm(request=request)
-        else:
-            org_username = request.user.username
-            form = UsernameChangeForm(request.POST, request=request)
-            if form.is_valid():
-                request.user.set_username(form.cleaned_data['username'])
-                request.user.save(force_update=True)
-                request.user.sync_username()
-                request.user.namechanges.create(date=timezone.now(), old_username=org_username)
-                request.messages.set_flash(Message(_("Your username has been changed.")), 'success', 'usercp_username')
-                # Alert followers of namechange
-                alert_time = timezone.now()
-                bulk_alerts = []
-                alerted_users = []
-                for follower in request.user.follows_set.iterator():
-                    alerted_users.append(follower.pk)
-                    alert = Alert(user=follower, message=ugettext_lazy("User that you are following, %(username)s, has changed his name to %(newname)s").message, date=alert_time)
-                    alert.strong('username', org_username)
-                    alert.profile('newname', request.user)
-                    alert.hydrate()
-                    bulk_alerts.append(alert)
-                if bulk_alerts:
-                    Alert.objects.bulk_create(bulk_alerts)
-                    User.objects.filter(id__in=alerted_users).update(alerts=F('alerts') + 1)
-                # Hop back
-                return redirect(reverse('usercp_username'))
-            message = Message(form.non_field_errors()[0], 'error')
-    else:
-        form = UsernameChangeForm(request=request)
-
-    return request.theme.render_to_response('usercp/username.html',
-                                            context_instance=RequestContext(request, {
-                                             'message': message,
-                                             'changes_left': changes_left,
-                                             'form': FormLayout(form),
-                                             'next_change': next_change,
-                                             'changes_history': request.user.namechanges.order_by('-date')[:10],
-                                             'tab': 'username',
-                                             }));

+ 0 - 76
notrefactored/usercp/views.py

@@ -1,76 +0,0 @@
-from django.core.urlresolvers import NoReverseMatch
-from django.shortcuts import redirect
-from django.utils.translation import ugettext as _
-from misago.authn.decorators import block_guest
-from misago.csrf.decorators import check_csrf
-from misago.messages import Message
-from misago.users.models import User
-from misago.profiles.decorators import user_view
-from misago.views import error404
-from misago.utils import ugettext_lazy
-
-def fallback(request):
-    try:
-        return redirect(request.POST.get('fallback', '/'))
-    except NoReverseMatch:
-        return redirect('index')
-
-@block_guest
-@check_csrf
-@user_view
-def follow(request, user):
-    if request.user.pk == user.pk:
-        return error404(request)
-    if not request.user.is_following(user):
-        request.messages.set_flash(Message(_("You are now following %(username)s") % {'username': user.username}), 'success')
-        request.user.follows.add(user)
-        request.user.following += 1
-        request.user.save(force_update=True)
-        user.followers += 1
-        if not user.is_ignoring(request.user):
-            alert = user.alert(ugettext_lazy("%(username)s is now following you").message)
-            alert.profile('username', request.user)
-            alert.save_all()
-        else:
-            user.save(force_update=True)
-    return fallback(request)
-
-
-@block_guest
-@check_csrf
-@user_view
-def unfollow(request, user):
-    if request.user.pk == user.pk:
-        return error404(request)
-    if request.user.is_following(user):
-        request.messages.set_flash(Message(_("You have stopped following %(username)s") % {'username': user.username}))
-        request.user.follows.remove(user)
-        request.user.following -= 1
-        request.user.save(force_update=True)
-        user.followers -= 1
-        user.save(force_update=True)
-    return fallback(request)
-
-
-@block_guest
-@check_csrf
-@user_view
-def ignore(request, user):
-    if request.user.pk == user.pk:
-        return error404(request)
-    if not request.user.is_ignoring(user):
-        request.messages.set_flash(Message(_("You are now ignoring %(username)s") % {'username': user.username}), 'success')
-        request.user.ignores.add(user)
-    return fallback(request)
-
-
-@block_guest
-@check_csrf
-@user_view
-def unignore(request, user):
-    if request.user.pk == user.pk:
-        return error404(request)
-    if request.user.is_ignoring(user):
-        request.messages.set_flash(Message(_("You have stopped ignoring %(username)s") % {'username': user.username}))
-        request.user.ignores.remove(user)
-    return fallback(request)

+ 0 - 0
notrefactored/users/__init__.py


+ 0 - 60
notrefactored/users/acl.py

@@ -1,60 +0,0 @@
-from django import forms
-from django.utils.translation import ugettext_lazy as _
-from misago.acl.builder import BaseACL
-from misago.acl.utils import ACLError404
-from misago.forms import YesNoSwitch
-
-def make_form(request, role, form):
-    form.base_fields['can_search_users'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_see_users_emails'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_see_users_trails'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    form.base_fields['can_see_hidden_users'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
-    
-    form.layout.append((
-                        _("User Profiles"),
-                        (
-                         ('can_search_users', {'label': _("Can search user profiles")}),
-                         ('can_see_users_emails', {'label': _("Can see members e-mail's")}),
-                         ('can_see_users_trails', {'label': _("Can see members ip's and user-agents")}),
-                         ('can_see_hidden_users', {'label': _("Can see mebers that hide their presence")}),
-                         ),
-                        ))
-
-
-class UsersACL(BaseACL):
-    def can_search_users(self):
-        return self.acl['can_search_users']
-    
-    def can_see_users_emails(self):
-        return self.acl['can_see_users_emails']
-
-    def can_see_users_trails(self):
-        return self.acl['can_see_users_trails']
-
-    def can_see_hidden_users(self):
-        return self.acl['can_see_hidden_users']
-    
-    def allow_details_view(self):
-        if not self.acl['can_see_users_trails']:
-            raise ACLError404()
-
-
-def build(acl, roles):
-    acl.users = UsersACL()
-    acl.users.acl['can_search_users'] = False
-    acl.users.acl['can_see_users_emails'] = False
-    acl.users.acl['can_see_users_trails'] = False
-    acl.users.acl['can_see_hidden_users'] = False
-
-    for role in roles:
-        if 'can_search_users' in role and role['can_search_users']:
-            acl.users.acl['can_search_users'] = True
-
-        if 'can_see_users_emails' in role and role['can_see_users_emails']:
-            acl.users.acl['can_see_users_emails'] = True
-
-        if 'can_see_users_trails' in role and role['can_see_users_trails']:
-            acl.users.acl['can_see_users_trails'] = True
-
-        if 'can_see_hidden_users' in role and role['can_see_hidden_users']:
-            acl.users.acl['can_see_hidden_users'] = True

+ 0 - 7
notrefactored/users/context_processors.py

@@ -1,7 +0,0 @@
-def user(request):
-    try:
-        return {
-            'user': request.user,
-        }
-    except AttributeError:
-        pass

+ 0 - 13
notrefactored/users/fixtures.py

@@ -1,13 +0,0 @@
-from misago.monitor.fixtures import load_monitor_fixture
-
-monitor_fixtures = {
-                  'users': 0,
-                  'users_inactive': 0,
-                  'users_reported': 0,
-                  'last_user': None,
-                  'last_user_name': None,
-                  'last_user_slug': None,
-                  }
-
-def load_fixtures():
-    load_monitor_fixture(monitor_fixtures)

+ 0 - 209
notrefactored/users/forms.py

@@ -1,209 +0,0 @@
-from PIL import Image
-from django.conf import settings
-from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
-from django import forms
-from misago.ranks.models import Rank
-from misago.roles.models import Role
-from misago.users.models import User
-from misago.users.validators import validate_username, validate_password, validate_email
-from misago.forms import Form, YesNoSwitch
-
-class UserForm(Form):
-    username = forms.CharField(max_length=255)
-    title = forms.CharField(max_length=255, required=False)
-    rank = forms.ModelChoiceField(queryset=Rank.objects.order_by('order').all(), required=False, empty_label=_('No rank assigned'))
-    roles = False
-    email = forms.EmailField(max_length=255)
-    new_password = forms.CharField(max_length=255, required=False, widget=forms.PasswordInput)
-    signature = forms.CharField(widget=forms.Textarea, required=False)
-    avatar_custom = forms.CharField(max_length=255, required=False)
-    avatar_ban = forms.BooleanField(widget=YesNoSwitch, required=False)
-    avatar_ban_reason_user = forms.CharField(widget=forms.Textarea, required=False)
-    avatar_ban_reason_admin = forms.CharField(widget=forms.Textarea, required=False)
-    signature_ban = forms.BooleanField(widget=YesNoSwitch, required=False)
-    signature_ban_reason_user = forms.CharField(widget=forms.Textarea, required=False)
-    signature_ban_reason_admin = forms.CharField(widget=forms.Textarea, required=False)
-
-    def __init__(self, user=None, *args, **kwargs):
-        self.request = kwargs['request']
-        self.user = user
-        super(UserForm, self).__init__(*args, **kwargs)
-
-    def finalize_form(self):
-        self.layout = [
-                       [
-                        _("Basic Account Settings"),
-                        [
-                         ('username', {'label': _("Username"), 'help_text': _("Username is name under which user is known to other users. Between 3 and 15 characters, only letters and digits are allowed.")}),
-                         ('title', {'label': _("User Title"), 'help_text': _("To override user title with custom one, enter it here.")}),
-                         ('rank', {'label': _("User Rank"), 'help_text': _("This user rank.")}),
-                         ('roles', {'label': _("User Roles"), 'help_text': _("This user roles. Roles are sets of user permissions")}),
-                         ],
-                        ],
-                       [
-                        _("Sign-in Credentials"),
-                        [
-                         ('email', {'label': _("E-mail Address"), 'help_text': _("Member e-mail address.")}),
-                         ('new_password', {'label': _("Change User Password"), 'help_text': _("If you wish to change user password, enter here new password. Otherwhise leave this field blank."), 'has_value': False}),
-                         ],
-                        ],
-                       [
-                        _("User Avatar"),
-                        [
-                         ('avatar_custom', {'label': _("Set Non-Standard Avatar"), 'help_text': _("You can make this member use special avatar by entering name of image file located in avatars directory here.")}),
-                         ('avatar_ban', {'label': _("Lock Member's Avatar"), 'help_text': _("If you set this field to yes, this member's avatar will be deleted and replaced with random one selected from _removed gallery and member will not be able to change his avatar.")}),
-                         ('avatar_ban_reason_user', {'label': _("User-visible reason for lock"), 'help_text': _("You can leave message to member explaining why he or she is unable to change his avatar anymore. This message will be displayed to member in his control panel.")}),
-                         ('avatar_ban_reason_admin', {'label': _("Forum Team-visible reason for lock"), 'help_text': _("You can leave message to other forum team members exmplaining why this member's avatar has been locked.")}),
-                         ],
-                        ],
-                       [
-                        _("User Signature"),
-                        [
-                         ('signature', {'label': _("Signature"), 'help_text': _("Signature is short message attached at end of member's messages.")}),
-                         ('signature_ban', {'label': _("Lock Member's Signature"), 'help_text': _("If you set this field to yes, this member will not be able to change his signature.")}),
-                         ('signature_ban_reason_user', {'label': _("User-visible reason for lock"), 'help_text': _("You can leave message to member explaining why he or she is unable to edit his signature anymore. This message will be displayed to member in his control panel.")}),
-                         ('signature_ban_reason_admin', {'label': _("Forum Team-visible reason for lock"), 'help_text': _("You can leave message to other forum team members exmplaining why this member's signature has been locked.")}),
-                         ],
-                        ],
-                       ]
-
-        # Roles list
-        if self.request.user.is_god():
-            self.fields['roles'] = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Role.objects.order_by('name').all(), error_messages={'required': _("User must have at least one role assigned.")})
-        else:
-            self.fields['roles'] = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Role.objects.filter(protected__exact=False).order_by('name').all(), required=False)
-
-        # Keep non-gods from editing protected members sign-in credentials
-        if self.user.is_protected() and not self.request.user.is_god() and self.user.pk != self.request.user.pk:
-            del self.fields['email']
-            del self.fields['new_password']
-            del self.layout[1]
-
-    def clean_username(self):
-        org_username = self.user.username
-        validate_username(self.cleaned_data['username'], self.request.settings)
-        self.user.set_username(self.cleaned_data['username'])
-        try:
-            self.user.full_clean()
-        except ValidationError as e:
-            self.user.is_username_valid(e)
-            self.user.set_username(org_username)
-        return self.cleaned_data['username']
-
-    def clean_email(self):
-        self.user.set_email(self.cleaned_data['email'])
-        try:
-            self.user.full_clean()
-        except ValidationError as e:
-            self.user.is_email_valid(e)
-        return self.cleaned_data['email']
-
-    def clean_new_password(self):
-        if self.cleaned_data['new_password']:
-            validate_password(self.cleaned_data['new_password'], self.request.settings)
-            self.user.set_password(self.cleaned_data['new_password'])
-            try:
-                self.user.full_clean()
-            except ValidationError as e:
-                self.user.is_password_valid(e)
-            return self.cleaned_data['new_password']
-        return ''
-
-    def clean_avatar_custom(self):
-        if self.cleaned_data['avatar_custom']:
-            try:
-                avatar_image = Image.open('%s/avatars/%s' % (settings.STATICFILES_DIRS[0], self.cleaned_data['avatar_custom']))
-            except IOError:
-                raise ValidationError(_("Avatar does not exist or is not image file."))
-            return self.cleaned_data['avatar_custom']
-        return ''
-
-
-class NewUserForm(Form):
-    username = forms.CharField(max_length=255)
-    title = forms.CharField(max_length=255, required=False)
-    rank = forms.ModelChoiceField(queryset=Rank.objects.order_by('order').all(), required=False, empty_label=_('No rank assigned'))
-    roles = False
-    email = forms.EmailField(max_length=255)
-    password = forms.CharField(max_length=255, widget=forms.PasswordInput)
-
-    layout = [
-              [
-               _("Basic Account Settings"),
-               [
-                ('username', {'label': _("Username"), 'help_text': _("Username is name under which user is known to other users. Between 3 and 15 characters, only letters and digits are allowed.")}),
-                ('title', {'label': _("User Title"), 'help_text': _("To override user title with custom one, enter it here.")}),
-                ('rank', {'label': _("User Rank"), 'help_text': _("This user rank.")}),
-                ('roles', {'label': _("User Roles"), 'help_text': _("This user roles. Roles are sets of user permissions")}),
-                ],
-               ],
-              [
-               _("Sign-in Credentials"),
-               [
-                ('email', {'label': _("E-mail Address"), 'help_text': _("Member e-mail address.")}),
-                ('password', {'label': _("User Password"), 'help_text': _("Member password."), 'has_value': False}),
-                ],
-               ],
-              ]
-
-    def __init__(self, *args, **kwargs):
-        self.request = kwargs['request']
-
-        # Roles list
-        if self.request.user.is_god():
-            self.base_fields['roles'] = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Role.objects.order_by('name').all(), error_messages={'required': _("User must have at least one role assigned.")})
-        else:
-            self.base_fields['roles'] = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Role.objects.filter(protected__exact=False).order_by('name').all(), required=False)
-
-        super(NewUserForm, self).__init__(*args, **kwargs)
-
-    def clean_username(self):
-        validate_username(self.cleaned_data['username'], self.request.settings)
-        new_user = User.objects.get_blank_user()
-        new_user.set_username(self.cleaned_data['username'])
-        try:
-            new_user.full_clean()
-        except ValidationError as e:
-            new_user.is_username_valid(e)
-        return self.cleaned_data['username']
-
-    def clean_email(self):
-        new_user = User.objects.get_blank_user()
-        new_user.set_email(self.cleaned_data['email'])
-        try:
-            new_user.full_clean()
-        except ValidationError as e:
-            new_user.is_email_valid(e)
-        return self.cleaned_data['email']
-
-    def clean_password(self):
-        new_user = User.objects.get_blank_user()
-        new_user.set_password(self.cleaned_data['password'])
-        try:
-            new_user.full_clean()
-        except ValidationError as e:
-            new_user.is_password_valid(e)
-        validate_password(self.cleaned_data['password'],  self.request.settings)
-        return self.cleaned_data['password']
-
-
-class SearchUsersForm(Form):
-    username = forms.CharField(max_length=255, required=False)
-    email = forms.CharField(max_length=255, required=False)
-    activation = forms.TypedMultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=((0, _("Already Active")), (1, _("By User")), (2, _("By Administrator"))), coerce=int, required=False)
-    rank = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Rank.objects.order_by('order').all(), required=False)
-    role = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Role.objects.order_by('name').all(), required=False)
-
-    layout = (
-              (
-               _("Search Users"),
-               (
-                ('username', {'label': _("Username"), 'attrs': {'placeholder': _("Username contains...")}}),
-                ('email', {'label': _("E-mail Address"), 'attrs': {'placeholder': _("E-mail address contains...")}}),
-                ('activation', {'label': _("Activation Requirement")}),
-                ('rank', {'label': _("Rank is")}),
-                ('role', {'label': _("Has Role")}),
-                ),
-               ),
-              )

+ 0 - 0
notrefactored/users/management/__init__.py


+ 0 - 0
notrefactored/users/management/commands/__init__.py


+ 0 - 39
notrefactored/users/management/commands/adduser.py

@@ -1,39 +0,0 @@
-from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
-from django.core.management.base import BaseCommand, CommandError
-from django.utils import timezone
-from optparse import make_option
-from misago.roles.models import Role
-from misago.users.models import User
-
-class Command(BaseCommand):
-    args = 'username email password'
-    help = 'Creates new user account'
-    option_list = BaseCommand.option_list + (
-        make_option('--admin',
-            action='store_true',
-            dest='admin',
-            default=False,
-            help='Make a new user an administrator'),
-        )
-
-    def handle(self, *args, **options):
-        if len(args) < 3:
-            raise CommandError('adduser requires exactly three arguments: user name, e-mail address and password')
-
-        # Set user
-        try:
-            new_user = User.objects.create_user(args[0], args[1], args[2])
-        except ValidationError as e:
-            raise CommandError("New user cannot be created because of following errors:\n\n%s" % '\n'.join(e.messages))
-
-        # Set admin role
-        if options['admin']:
-            new_user.roles.add(Role.objects.get(token='admin'))
-            new_user.make_acl_key(True)
-            new_user.save(force_update=True)
-
-        if options['admin']:
-            self.stdout.write('Successfully created new administrator "%s"' % args[0])
-        else:
-            self.stdout.write('Successfully created new user "%s"' % args[0])
-        self.stdout.write('\n\nNew user should use "%s" e-mail address and "%s" password to sign in.\n' % (args[1], args[2]))

+ 0 - 67
notrefactored/users/management/commands/genavatars.py

@@ -1,67 +0,0 @@
-from django.core.management.base import BaseCommand, CommandError
-from django.conf import settings
-from path import path
-try:
-    from PIL import Image
-    has_pil = True
-except ImportError:
-    has_pil = False
-from misago.users.models import User
-from misago.utils.avatars import resizeimage
-
-class Command(BaseCommand):
-    help = 'Regenerates avatar images for new dimensions'
-    def handle(self, *args, **options):
-        if not has_pil:
-            raise CommandError('genavatars requires Python Imaging Library to be installed in order to run')
-        self.scale_user_avatars()
-        self.scale_gallery_avatars()
-        self.stdout.write('\n\nAvatar images have been regenerated.\n')
-
-    def scale_image(self, image_src, image_dir=None):
-        image_name = path.basename(path(image_src))
-        if not image_dir:
-            image_dir = path.dirname(path(image_src)) + '/%s_'
-        for size in settings.AVATAR_SIZES[1:]:
-            resizeimage(image_src, size, image_dir % size + image_name)
-
-    def scale_user_avatars(self):
-        for user in User.objects.filter(avatar_type='upload').iterator():
-            for image in path(settings.MEDIA_ROOT).joinpath('avatars').files('*_%s' % user.avatar_image):
-                if not image.isdir():
-                    image.remove()
-            self.scale_image(settings.MEDIA_ROOT + 'avatars/' + user.avatar_image)
-
-    def scale_gallery_avatars(self):
-        try:
-            thumb_dir = path(settings.STATICFILES_DIRS[0]).joinpath('avatars').joinpath('_thumbs')
-            items = [thumb_dir]
-            for item in thumb_dir.walk():
-                items.append(item)
-            for item in reversed(items):
-                if item.isdir():
-                    item.rmdir()
-                else:
-                    item.remove()
-        except Exception:
-            pass
-        avatars_dir = path(settings.STATICFILES_DIRS[0]).joinpath('avatars')
-        avatars_len = len(avatars_dir)
-        avatars_list = []
-        for directory in avatars_dir.dirs():
-            avatars_list += directory.files('*.gif')
-            avatars_list += directory.files('*.jpg')
-            avatars_list += directory.files('*.jpeg')
-            avatars_list += directory.files('*.png')
-        thumb_dir = path(settings.STATICFILES_DIRS[0]).joinpath('avatars').joinpath('_thumbs')
-        thumb_dir.mkdir(777)
-        for size in settings.AVATAR_SIZES[1:]:
-            thumb_dir.joinpath(str(size)).mkdir(777)
-        for directory in avatars_dir.dirs():
-            dirname = path(directory[avatars_len:]).basename()
-            if dirname != '_thumbs':
-                for size in settings.AVATAR_SIZES[1:]:
-                    thumb_dir.joinpath(str(size)).joinpath(dirname).mkdir(777)
-        for avatar in avatars_list:
-            self.scale_image(avatar,
-                             thumb_dir + '/%s' + avatar.dirname()[avatars_len:] + '/')

+ 0 - 12
notrefactored/users/management/commands/syncusermonitor.py

@@ -1,12 +0,0 @@
-from django.core.management.base import BaseCommand
-from django.utils import timezone
-from optparse import make_option
-from misago.monitor.monitor import Monitor
-from misago.users.models import User
-
-class Command(BaseCommand):
-    help = 'Updates forum monitor to contain to date user information'
-
-    def handle(self, *args, **options):
-        User.objects.resync_monitor(Monitor())
-        self.stdout.write('\nForum monitor has been updated to contain to date user information.\n')

+ 0 - 28
notrefactored/users/middleware.py

@@ -1,28 +0,0 @@
-from django.conf import settings
-from django.utils import timezone
-from django.utils.translation import ugettext_lazy as _
-from misago.messages import Message
-
-def set_timezone(new_tz):
-    if settings.USE_TZ:
-        try:
-            import pytz
-            timezone.activate(pytz.timezone(new_tz))
-        except ImportError:
-            pass
-
-
-class UserMiddleware(object):
-    def process_request(self, request):
-        if request.user.is_authenticated():
-            # Set user timezone and rank
-            request.session.rank = request.user.rank_id
-            set_timezone(request.user.timezone)
-
-            # Display "welcome back!" message
-            if request.session.remember_me:
-                request.messages.set_message(Message(_("Welcome back, %(username)s! We've signed you in automatically for your convenience.") % {'username': request.user.username}), 'info')
-        else:
-            # Set guest's timezone and empty rank
-            set_timezone(request.settings['default_timezone'])
-            request.session.rank = None

+ 0 - 192
notrefactored/users/migrations/0001_initial.py

@@ -1,192 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'User'
-        db.create_table(u'users_user', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('username', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('username_slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=255)),
-            ('email', self.gf('django.db.models.fields.EmailField')(max_length=255)),
-            ('email_hash', self.gf('django.db.models.fields.CharField')(unique=True, max_length=32)),
-            ('password', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('password_date', self.gf('django.db.models.fields.DateTimeField')()),
-            ('avatar_type', self.gf('django.db.models.fields.CharField')(max_length=10, null=True, blank=True)),
-            ('avatar_image', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('avatar_original', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('avatar_temp', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('signature', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('signature_preparsed', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('join_date', self.gf('django.db.models.fields.DateTimeField')()),
-            ('join_ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39)),
-            ('join_agent', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('last_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-            ('last_ip', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39, null=True, blank=True)),
-            ('last_agent', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('hide_activity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('allow_pms', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('subscribe_start', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('subscribe_reply', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('receive_newsletters', self.gf('django.db.models.fields.BooleanField')(default=True)),
-            ('threads', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('posts', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('votes', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('karma_given_p', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('karma_given_n', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('karma_p', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('karma_n', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('following', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('followers', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('score', self.gf('django.db.models.fields.IntegerField')(default=0)),
-            ('ranking', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('rank', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ranks.Rank'], null=True, on_delete=models.SET_NULL, blank=True)),
-            ('last_sync', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-            ('title', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
-            ('last_post', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-            ('last_search', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-            ('alerts', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
-            ('alerts_date', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
-            ('activation', self.gf('django.db.models.fields.IntegerField')(default=0)),
-            ('token', self.gf('django.db.models.fields.CharField')(max_length=12, null=True, blank=True)),
-            ('avatar_ban', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('avatar_ban_reason_user', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('avatar_ban_reason_admin', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('signature_ban', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('signature_ban_reason_user', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('signature_ban_reason_admin', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
-            ('timezone', self.gf('django.db.models.fields.CharField')(default='utc', max_length=255)),
-            ('is_team', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('acl_key', self.gf('django.db.models.fields.CharField')(max_length=12, null=True, blank=True)),
-        ))
-        db.send_create_signal(u'users', ['User'])
-
-        # Adding M2M table for field follows on 'User'
-        db.create_table(u'users_user_follows', (
-            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
-            ('from_user', models.ForeignKey(orm[u'users.user'], null=False)),
-            ('to_user', models.ForeignKey(orm[u'users.user'], null=False))
-        ))
-        db.create_unique(u'users_user_follows', ['from_user_id', 'to_user_id'])
-
-        # Adding M2M table for field ignores on 'User'
-        db.create_table(u'users_user_ignores', (
-            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
-            ('from_user', models.ForeignKey(orm[u'users.user'], null=False)),
-            ('to_user', models.ForeignKey(orm[u'users.user'], null=False))
-        ))
-        db.create_unique(u'users_user_ignores', ['from_user_id', 'to_user_id'])
-
-        # Adding M2M table for field roles on 'User'
-        db.create_table(u'users_user_roles', (
-            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
-            ('user', models.ForeignKey(orm[u'users.user'], null=False)),
-            ('role', models.ForeignKey(orm[u'roles.role'], null=False))
-        ))
-        db.create_unique(u'users_user_roles', ['user_id', 'role_id'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'User'
-        db.delete_table(u'users_user')
-
-        # Removing M2M table for field follows on 'User'
-        db.delete_table('users_user_follows')
-
-        # Removing M2M table for field ignores on 'User'
-        db.delete_table('users_user_ignores')
-
-        # Removing M2M table for field roles on 'User'
-        db.delete_table('users_user_roles')
-
-
-    models = {
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        }
-    }
-
-    complete_apps = ['users']

+ 0 - 0
notrefactored/users/migrations/__init__.py


+ 0 - 537
notrefactored/users/models.py

@@ -1,537 +0,0 @@
-import hashlib
-import math
-from random import choice
-from path import path
-from django.conf import settings
-from django.contrib.auth.hashers import (
-    check_password, make_password, is_password_usable, UNUSABLE_PASSWORD)
-from django.core.cache import cache, InvalidCacheBackendError
-from django.core.exceptions import ValidationError
-from django.core.mail import EmailMultiAlternatives
-from django.db import models
-from django.template import RequestContext
-from django.utils import timezone as tz_util
-from django.utils.translation import ugettext_lazy as _
-from misago.acl.builder import build_acl
-from misago.monitor.monitor import Monitor
-from misago.roles.models import Role
-from misago.settings.settings import Settings as DBSettings
-from misago.users.signals import delete_user_content, rename_user
-from misago.users.validators import validate_username, validate_password, validate_email
-from misago.utils import get_random_string, slugify
-from misago.utils.avatars import avatar_size
-
-class UserManager(models.Manager):
-    """
-    User Manager provides us with some additional methods for users
-    """
-    def get_blank_user(self):
-        blank_user = User(
-                        join_date=tz_util.now(),
-                        join_ip='127.0.0.1'
-                        )
-        return blank_user
-
-    def resync_monitor(self, monitor):
-        monitor['users'] = self.filter(activation=0).count()
-        monitor['users_inactive'] = self.filter(activation__gt=0).count()
-        last_user = self.filter(activation=0).latest('id')
-        monitor['last_user'] = last_user.pk
-        monitor['last_user_name'] = last_user.username
-        monitor['last_user_slug'] = last_user.username_slug
-
-    def create_user(self, username, email, password, timezone=False, ip='127.0.0.1', agent='', no_roles=False, activation=0, request=False):
-        token = ''
-        if activation > 0:
-            token = get_random_string(12)
-
-        try:
-            db_settings = request.settings
-        except AttributeError:
-            db_settings = DBSettings()
-
-        if timezone == False:
-            timezone = db_settings['default_timezone']
-
-        # Get first rank
-        try:
-            from misago.ranks.models import Rank
-            default_rank = Rank.objects.filter(special=0).order_by('order')[0]
-        except IndexError:
-            default_rank = None
-
-        # Store user in database
-        new_user = User(
-                        last_sync=tz_util.now(),
-                        join_date=tz_util.now(),
-                        join_ip=ip,
-                        join_agent=agent,
-                        activation=activation,
-                        token=token,
-                        timezone=timezone,
-                        rank=default_rank,
-                        subscribe_start=db_settings['subscribe_start'],
-                        subscribe_reply=db_settings['subscribe_reply'],
-                        )
-
-        validate_username(username, db_settings)
-        validate_password(password, db_settings)
-        new_user.set_username(username)
-        new_user.set_email(email)
-        new_user.set_password(password)
-        new_user.full_clean()
-        new_user.default_avatar(db_settings)
-        new_user.save(force_insert=True)
-
-        # Set user roles?
-        if not no_roles:
-            from misago.roles.models import Role
-            new_user.roles.add(Role.objects.get(token='registered'))
-            new_user.make_acl_key()
-            new_user.save(force_update=True)
-
-        # Load monitor
-        try:
-            monitor = request.monitor
-        except AttributeError:
-            monitor = Monitor()
-
-        # Update forum stats
-        if activation == 0:
-            monitor['users'] = int(monitor['users']) + 1
-            monitor['last_user'] = new_user.pk
-            monitor['last_user_name'] = new_user.username
-            monitor['last_user_slug'] = new_user.username_slug
-        else:
-            monitor['users_inactive'] = int(monitor['users_inactive']) + 1
-
-        # Return new user
-        return new_user
-
-    def get_by_email(self, email):
-        return self.get(email_hash=hashlib.md5(email).hexdigest())
-
-    def filter_stats(self, start, end):
-        return self.filter(join_date__gte=start).filter(join_date__lte=end)
-
-
-class User(models.Model):
-    """
-    Misago User model
-    """
-    username = models.CharField(max_length=255)
-    username_slug = models.SlugField(max_length=255, unique=True,
-                                     error_messages={'unique': _("This user name is already in use by another user.")})
-    email = models.EmailField(max_length=255, validators=[validate_email])
-    email_hash = models.CharField(max_length=32, unique=True,
-                                     error_messages={'unique': _("This email address is already in use by another user.")})
-    password = models.CharField(max_length=255)
-    password_date = models.DateTimeField()
-    avatar_type = models.CharField(max_length=10, null=True, blank=True)
-    avatar_image = models.CharField(max_length=255, null=True, blank=True)
-    avatar_original = models.CharField(max_length=255, null=True, blank=True)
-    avatar_temp = models.CharField(max_length=255, null=True, blank=True)
-    signature = models.TextField(null=True, blank=True)
-    signature_preparsed = models.TextField(null=True, blank=True)
-    join_date = models.DateTimeField()
-    join_ip = models.GenericIPAddressField()
-    join_agent = models.TextField(null=True, blank=True)
-    last_date = models.DateTimeField(null=True, blank=True)
-    last_ip = models.GenericIPAddressField(null=True, blank=True)
-    last_agent = models.TextField(null=True, blank=True)
-    hide_activity = models.PositiveIntegerField(default=0)
-    allow_pms = models.PositiveIntegerField(default=0)
-    subscribe_start = models.PositiveIntegerField(default=0)
-    subscribe_reply = models.PositiveIntegerField(default=0)
-    receive_newsletters = models.BooleanField(default=True)
-    threads = models.PositiveIntegerField(default=0)
-    posts = models.PositiveIntegerField(default=0)
-    votes = models.PositiveIntegerField(default=0)
-    karma_given_p = models.PositiveIntegerField(default=0)
-    karma_given_n = models.PositiveIntegerField(default=0)
-    karma_p = models.PositiveIntegerField(default=0)
-    karma_n = models.PositiveIntegerField(default=0)
-    following = models.PositiveIntegerField(default=0)
-    followers = models.PositiveIntegerField(default=0)
-    score = models.IntegerField(default=0)
-    ranking = models.PositiveIntegerField(default=0)
-    rank = models.ForeignKey('ranks.Rank', null=True, blank=True, on_delete=models.SET_NULL)
-    last_sync = models.DateTimeField(null=True, blank=True)
-    follows = models.ManyToManyField('self', related_name='follows_set', symmetrical=False)
-    ignores = models.ManyToManyField('self', related_name='ignores_set', symmetrical=False)
-    title = models.CharField(max_length=255, null=True, blank=True)
-    last_post = models.DateTimeField(null=True, blank=True)
-    last_search = models.DateTimeField(null=True, blank=True)
-    alerts = models.PositiveIntegerField(default=0)
-    alerts_date = models.DateTimeField(null=True, blank=True)
-    activation = models.IntegerField(default=0)
-    token = models.CharField(max_length=12, null=True, blank=True)
-    avatar_ban = models.BooleanField(default=False)
-    avatar_ban_reason_user = models.TextField(null=True, blank=True)
-    avatar_ban_reason_admin = models.TextField(null=True, blank=True)
-    signature_ban = models.BooleanField(default=False)
-    signature_ban_reason_user = models.TextField(null=True, blank=True)
-    signature_ban_reason_admin = models.TextField(null=True, blank=True)
-    timezone = models.CharField(max_length=255, default='utc')
-    roles = models.ManyToManyField('roles.Role')
-    is_team = models.BooleanField(default=False)
-    acl_key = models.CharField(max_length=12, null=True, blank=True)
-
-    objects = UserManager()
-
-    ACTIVATION_NONE = 0
-    ACTIVATION_USER = 1
-    ACTIVATION_ADMIN = 2
-    ACTIVATION_CREDENTIALS = 3
-
-    statistics_name = _('Users Registrations')
-
-    def is_god(self):
-        try:
-            return self.is_god_cache
-        except AttributeError:
-            for user in settings.ADMINS:
-                if user[1].lower() == self.email:
-                    self.is_god_cache = True
-                    return True
-            self.is_god_cache = False
-            return False
-
-    def is_anonymous(self):
-        return False
-
-    def is_authenticated(self):
-        return True
-
-    def is_crawler(self):
-        return False
-
-    def is_protected(self):
-        for role in self.roles.all():
-            if role.protected:
-                return True
-        return False
-
-    def lock_avatar(self):
-        # Kill existing avatar and lock our ability to change it
-        self.delete_avatar()
-        self.avatar_ban = True
-
-        # Pick new one from _locked gallery
-        galleries = path(settings.STATICFILES_DIRS[0]).joinpath('avatars').joinpath('_locked')
-        avatars_list = galleries.files('*.gif')
-        avatars_list += galleries.files('*.jpg')
-        avatars_list += galleries.files('*.jpeg')
-        avatars_list += galleries.files('*.png')
-        self.avatar_type = 'gallery'
-        self.avatar_image = '/'.join(path(choice(avatars_list)).splitall()[-2:])
-
-    def default_avatar(self, db_settings):
-        if db_settings['default_avatar'] == 'gallery':
-            try:
-                avatars_list = []
-                try:
-                    # First try, _default path
-                    galleries = path(settings.STATICFILES_DIRS[0]).joinpath('avatars').joinpath('_default')
-                    avatars_list += galleries.files('*.gif')
-                    avatars_list += galleries.files('*.jpg')
-                    avatars_list += galleries.files('*.jpeg')
-                    avatars_list += galleries.files('*.png')
-                except Exception as e:
-                    pass
-                # Second try, all paths
-                if not avatars_list:
-                    avatars_list = []
-                    for directory in path(settings.STATICFILES_DIRS[0]).joinpath('avatars').dirs():
-                        if not directory[-7:] == '_locked' and not directory[-7:] == '_thumbs':
-                            avatars_list += directory.files('*.gif')
-                            avatars_list += directory.files('*.jpg')
-                            avatars_list += directory.files('*.jpeg')
-                            avatars_list += directory.files('*.png')
-                if avatars_list:
-                    # Pick random avatar from list
-                    self.avatar_type = 'gallery'
-                    self.avatar_image = '/'.join(path(choice(avatars_list)).splitall()[-2:])
-                    return True
-            except Exception as e:
-                pass
-
-        self.avatar_type = 'gravatar'
-        self.avatar_image = None
-        return True
-
-    def delete_avatar_temp(self):
-        if self.avatar_temp:
-            try:
-                av_file = path(settings.MEDIA_ROOT + 'avatars/' + self.avatar_temp)
-                if not av_file.isdir():
-                    av_file.remove()
-            except Exception:
-                pass
-
-        self.avatar_temp = None
-
-    def delete_avatar_original(self):
-        if self.avatar_original:
-            try:
-                av_file = path(settings.MEDIA_ROOT + 'avatars/' + self.avatar_original)
-                if not av_file.isdir():
-                    av_file.remove()
-            except Exception:
-                pass
-
-        self.avatar_original = None
-
-    def delete_avatar_image(self):
-        if self.avatar_image:
-            for size in settings.AVATAR_SIZES[1:]:
-                try:
-                    av_file = path(settings.MEDIA_ROOT + 'avatars/' + str(size) + '_' + self.avatar_image)
-                    if not av_file.isdir():
-                        av_file.remove()
-                except Exception:
-                    pass
-            try:
-                av_file = path(settings.MEDIA_ROOT + 'avatars/' + self.avatar_image)
-                if not av_file.isdir():
-                    av_file.remove()
-            except Exception:
-                pass
-
-        self.avatar_image = None
-
-    def delete_avatar(self):
-        self.delete_avatar_temp()
-        self.delete_avatar_original()
-        self.delete_avatar_image()
-
-    def delete_content(self):
-        delete_user_content.send(sender=self)
-
-    def delete(self, *args, **kwargs):
-        self.delete_avatar()
-        super(User, self).delete(*args, **kwargs)
-
-    def set_username(self, username):
-        self.username = username.strip()
-        self.username_slug = slugify(username)
-
-    def sync_username(self):
-        print 'SYNCING NAME CACHES!'
-        rename_user.send(sender=self)
-
-    def is_username_valid(self, e):
-        try:
-            raise ValidationError(e.message_dict['username'])
-        except KeyError:
-            pass
-        try:
-            raise ValidationError(e.message_dict['username_slug'])
-        except KeyError:
-            pass
-
-    def is_email_valid(self, e):
-        try:
-            raise ValidationError(e.message_dict['email'])
-        except KeyError:
-            pass
-        try:
-            raise ValidationError(e.message_dict['email_hash'])
-        except KeyError:
-            pass
-
-    def is_password_valid(self, e):
-        try:
-            raise ValidationError(e.message_dict['password'])
-        except KeyError:
-            pass
-
-    def set_email(self, email):
-        self.email = email.strip().lower()
-        self.email_hash = hashlib.md5(self.email).hexdigest()
-
-    def set_password(self, raw_password):
-        self.password_date = tz_util.now()
-        self.password = make_password(raw_password.strip())
-
-    def set_last_visit(self, ip, agent, hidden=False):
-        self.last_date = tz_util.now()
-        self.last_ip = ip
-        self.last_agent = agent
-        self.last_hide = hidden
-
-    def check_password(self, raw_password, mobile=False):
-        """
-        Returns a boolean of whether the raw_password was correct. Handles
-        hashing formats behind the scenes.
-        """
-        def setter(raw_password):
-            self.set_password(raw_password)
-            self.save()
-
-        # Is standard password allright?
-        if check_password(raw_password, self.password, setter):
-            return True
-
-        # Check mobile password?
-        if mobile:
-            raw_password = raw_password[:1].lower() + raw_password[1:]
-        else:
-            password_reversed = u''
-            for c in raw_password:
-                r = c.upper()
-                if r == c:
-                    r = c.lower()
-                password_reversed += r
-            raw_password = password_reversed
-        return check_password(raw_password, self.password, setter)
-
-    def is_following(self, user):
-        try:
-            return self.follows.filter(id=user.pk).count() > 0
-        except AttributeError:
-            return self.follows.filter(id=user).count() > 0
-
-    def is_ignoring(self, user):
-        try:
-            return self.ignores.filter(id=user.pk).count() > 0
-        except AttributeError:
-            return self.ignores.filter(id=user).count() > 0
-        
-    def ignored_users(self):
-        return [item['id'] for item in self.ignores.values('id')]
-
-    def get_roles(self):
-        return self.roles.all()
-
-    def make_acl_key(self, force=False):
-        if not force and self.acl_key:
-            return self.acl_key
-        roles_ids = []
-        for role in self.roles.all():
-            roles_ids.append(str(role.pk))
-        self.acl_key = 'acl_%s' % hashlib.md5('_'.join(roles_ids)).hexdigest()[0:8]
-        return self.acl_key
-
-    def get_acl(self, request):
-        try:
-            acl = cache.get(self.acl_key)
-            if acl.version != request.monitor.acl_version:
-                raise InvalidCacheBackendError()
-        except AttributeError, InvalidCacheBackendError:
-            # build acl cache
-            acl = build_acl(request, self.get_roles())
-            cache.set(self.acl_key, acl, 2592000)
-        return acl
-
-    def get_avatar(self, size=None):
-        image_size = avatar_size(size) if size else None
-
-        # Get uploaded avatar
-        if self.avatar_type == 'upload':
-            image_prefix = '%s_' % image_size if image_size else ''
-            return settings.MEDIA_URL + 'avatars/' + image_prefix + self.avatar_image
-
-        # Get gallery avatar
-        if self.avatar_type == 'gallery':
-            image_prefix = '_thumbs/%s/' % image_size if image_size else ''
-            return settings.STATIC_URL + 'avatars/' + image_prefix + self.avatar_image
-
-        # No avatar found, get gravatar
-        if not image_size:
-            image_size = settings.AVATAR_SIZES[0]
-        return 'http://www.gravatar.com/avatar/%s?s=%s' % (hashlib.md5(self.email).hexdigest(), image_size)
-
-    def get_ranking(self):
-        if not self.ranking:
-            self.ranking = User.objects.filter(score__gt=self.score).count() + 1
-            self.save(force_update=True)
-        return self.ranking
-
-    def get_title(self):
-        if self.title:
-            return self.title
-        if self.rank:
-            return self.rank.title
-        return None
-
-    def get_style(self):
-        if self.rank:
-            return self.rank.style
-        return ''
-
-    def email_user(self, request, template, subject, context={}):
-        templates = request.theme.get_email_templates(template)
-        context = RequestContext(request, context)
-        context['author'] = context['user']
-        context['user'] = self
-
-        # Set message recipient
-        if settings.DEBUG and settings.CATCH_ALL_EMAIL_ADDRESS:
-            recipient = settings.CATCH_ALL_EMAIL_ADDRESS
-        else:
-            recipient = self.email
-
-        # Build and send message
-        email = EmailMultiAlternatives(subject, templates[0].render(context), settings.EMAIL_HOST_USER, [recipient])
-        email.attach_alternative(templates[1].render(context), "text/html")
-        email.send()
-
-    def get_activation(self):
-        activations = ['none', 'user', 'admin', 'credentials']
-        return activations[self.activation]
-
-    def alert(self, message):
-        from misago.alerts.models import Alert
-        self.alerts += 1
-        return Alert(user=self, message=message, date=tz_util.now())
-
-    def get_date(self):
-        return self.join_date
-
-    def sync_user(self):
-        pass
-
-
-class Guest(object):
-    """
-    Misago Guest dummy
-    """
-    id = -1
-    pk = -1
-    is_team = False
-
-    def is_anonymous(self):
-        return True
-
-    def is_authenticated(self):
-        return False
-
-    def is_crawler(self):
-        return False
-
-    def get_roles(self):
-        return Role.objects.filter(token='guest')
-
-    def make_acl_key(self):
-        return 'acl_guest'
-
-
-class Crawler(Guest):
-    """
-    Misago Crawler dummy
-    """
-    is_team = False
-
-    def __init__(self, username):
-        self.username = username
-
-    def is_anonymous(self):
-        return True
-
-    def is_authenticated(self):
-        return False
-
-    def is_crawler(self):
-        return True
-

+ 0 - 4
notrefactored/users/signals.py

@@ -1,4 +0,0 @@
-import django.dispatch
-
-delete_user_content = django.dispatch.Signal()
-rename_user = django.dispatch.Signal()

+ 0 - 64
notrefactored/users/validators.py

@@ -1,64 +0,0 @@
-import re
-from django.conf import settings
-from django.core.exceptions import ValidationError
-from django.utils.translation import ungettext, ugettext_lazy as _
-from misago.banning.models import check_ban
-from misago.settings.settings import Settings as DBSettings
-
-def validate_username(value, db_settings):
-    value = unicode(value).strip()
-    if len(value) < db_settings['username_length_min']:
-        raise ValidationError(ungettext(
-            'Username must be at least one character long.',
-            'Username must be at least %(count)d characters long.',
-            db_settings['username_length_min']
-        ) % {
-            'count': db_settings['username_length_min'],
-        })
-    if len(value) > db_settings['username_length_max']:
-        raise ValidationError(ungettext(
-            'Username cannot be longer than one characters.',
-            'Username cannot be longer than %(count)d characters.',
-            db_settings['username_length_max']
-        ) % {
-            'count': db_settings['username_length_max'],
-        })
-    if settings.UNICODE_USERNAMES:
-        if not re.search('^[^\W_]+$', value, re.UNICODE):
-            raise ValidationError(_("Username can only contain letters and digits."))
-    else:
-        if not re.search('^[^\W_]+$', value):
-            raise ValidationError(_("Username can only contain latin alphabet letters and digits."))
-    if check_ban(username=value):
-        raise ValidationError(_("This username is forbidden."))
-
-
-def validate_password(value, db_settings):
-    value = unicode(value).strip()
-    if len(value) < db_settings['password_length']:
-        raise ValidationError(ungettext(
-            'Correct password has to be at least one character long.',
-            'Correct password has to be at least %(count)d characters long.',
-            db_settings['password_length']
-        ) % {
-            'count': db_settings['password_length'],
-        })
-    for test in db_settings['password_complexity']:
-        if test in ('case', 'digits', 'special'):
-            if not re.search('[a-zA-Z]', value):
-                raise ValidationError(_("Password must contain alphabetical characters."))
-            if test == 'case':
-                if not (re.search('[a-z]', value) and re.search('[A-Z]', value)):
-                    raise ValidationError(_("Password must contain characters that have different case."))
-            if test == 'digits':
-                if not re.search('[0-9]', value):
-                    raise ValidationError(_("Password must contain digits in addition to characters."))
-            if test == 'special':
-                if not re.search('[^0-9a-zA-Z]', value):
-                    raise ValidationError(_("Password must contain special (non alphanumerical) characters."))
-
-
-def validate_email(value):
-    value = unicode(value).strip()
-    if check_ban(email=value):
-        raise ValidationError(_("This board forbids registrations using this e-mail address."))

+ 0 - 374
notrefactored/users/views.py

@@ -1,374 +0,0 @@
-from django.core.urlresolvers import reverse as django_reverse
-from django.db.models import Q
-from django.shortcuts import redirect
-from django.utils.translation import ugettext as _
-from misago.admin import site
-from misago.admin.widgets import *
-from misago.forums.models import Forum
-from misago.markdown import signature_markdown
-from misago.users.forms import UserForm, NewUserForm, SearchUsersForm
-from misago.users.models import User
-from misago.utils import get_random_string
-
-def reverse(route, target=None):
-    if target:
-        return django_reverse(route, kwargs={'target': target.pk, 'slug': target.username_slug})
-    return django_reverse(route)
-
-"""
-Views
-"""
-class List(ListWidget):
-    admin = site.get_action('users')
-    id = 'list'
-    columns = (
-               ('username_slug', _("User Name"), 35),
-               ('join_date', _("Join Date")),
-               )
-    default_sorting = 'username'
-    sortables = {
-                 'username_slug': 1,
-                 'join_date': 0,
-                }
-    pagination = 25
-    search_form = SearchUsersForm
-    nothing_checked_message = _('You have to check at least one user.')
-    actions = (
-               ('activate', _("Activate users"), _("Are you sure you want to activate selected members?")),
-               ('deactivate', _("Request e-mail validation"), _("Are you sure you want to deactivate selected members and request them to revalidate their e-mail addresses?")),
-               ('remove_av', _("Remove and lock avatars"), _("Are you sure you want to remove selected members avatars and their ability to change them?")),
-               ('remove_sig', _("Remove and lock signatures"), _("Are you sure you want to remove selected members signatures and their ability to edit them?")),
-               ('remove_locks', _("Remove locks from avatars and signatures"), _("Are you sure you want to remove locks from selected members avatars and signatures?")),
-               ('reset', _("Reset passwords"), _("Are you sure you want to reset selected members passwords?")),
-               ('delete_content', _("Delete users with content"), _("Are you sure you want to delete selected users and their content?")),
-               ('delete', _("Delete users"), _("Are you sure you want to delete selected users?")),
-               )
-
-    def set_filters(self, model, filters):
-        if 'role' in filters:
-            model = model.filter(roles__in=filters['role']).distinct()
-        if 'rank' in filters:
-            model = model.filter(rank__in=filters['rank'])
-        if 'username' in filters:
-            if ',' in filters['username']:
-                qs = None
-                for name in filters['username'].split(','):
-                    name = name.strip().lower()
-                    if name:
-                        if qs:
-                            qs = qs | Q(username_slug__contains=name)
-                        else:
-                            qs = Q(username_slug__contains=name)
-                if qs:
-                    model = model.filter(qs)
-            else:
-                model = model.filter(username_slug__contains=filters['username'])
-        if 'email' in filters:
-            if ',' in filters['email']:
-                qs = None
-                for name in filters['email'].split(','):
-                    name = name.strip().lower()
-                    if name:
-                        if qs:
-                            qs = qs | Q(email__contains=name)
-                        else:
-                            qs = Q(email__contains=name)
-                if qs:
-                    model = model.filter(qs)
-            else:
-                model = model.filter(email__contains=filters['email'])
-        if 'activation' in filters:
-            model = model.filter(activation__in=filters['activation'])
-        return model
-
-    def prefetch_related(self, items):
-        return items.prefetch_related('roles')
-
-    def get_item_actions(self, item):
-        return (
-                self.action('pencil', _("Edit User Details"), reverse('admin_users_edit', item)),
-                self.action('remove', _("Delete User"), reverse('admin_users_delete', item), post=True, prompt=_("Are you sure you want to delete this user account?")),
-                )
-
-    def action_activate(self, items, checked):
-        for user in items:
-            if unicode(user.pk) in checked and user.activation > 0:
-                self.request.monitor['users_inactive'] = int(self.request.monitor['users_inactive']) - 1
-                user.activation = user.ACTIVATION_NONE
-                user.save(force_update=True)
-                user.email_user(
-                                self.request,
-                                'users/activation/admin_done',
-                                _("Your Account has been activated"),
-                                )
-
-        return Message(_('Selected users accounts have been activated.'), 'success'), reverse('admin_users')
-
-    def action_deactivate(self, items, checked):
-        # First loop - check for errors
-        for user in items:
-            if unicode(user.pk) in checked:
-                if user.is_protected() and not self.request.user.is_god():
-                    return Message(_('You cannot force validation of protected members e-mails.'), 'error'), reverse('admin_users')
-
-        # Second loop - reset passwords
-        for user in items:
-            if unicode(user.pk) in checked:
-                user.activation = user.ACTIVATION_USER
-                user.token = token = get_random_string(12)
-                user.save(force_update=True)
-                user.email_user(
-                                self.request,
-                                'users/activation/invalidated',
-                                _("Account Activation"),
-                                )
-
-        return Message(_('Selected users accounts have been deactivated and new activation links have been sent to them.'), 'success'), reverse('admin_users')
-
-    def action_remove_av(self, items, checked):
-        # First loop - check for errors
-        for user in items:
-            if unicode(user.pk) in checked:
-                if user.is_protected() and not self.request.user.is_god():
-                    return Message(_('You cannot remove and block protected members avatars.'), 'error'), reverse('admin_users')
-
-        # Second loop - reset passwords
-        for user in items:
-            if unicode(user.pk) in checked:
-                user.lock_avatar()
-                user.save(force_update=True)
-
-        return Message(_('Selected users avatars were deleted and locked.'), 'success'), reverse('admin_users')
-
-    def action_remove_sig(self, items, checked):
-        # First loop - check for errors
-        for user in items:
-            if unicode(user.pk) in checked:
-                if user.is_protected() and not self.request.user.is_god():
-                    return Message(_('You cannot remove and block protected members signatures.'), 'error'), reverse('admin_users')
-
-        # Second loop - reset passwords
-        for user in items:
-            if unicode(user.pk) in checked:
-                user.signature_ban = True
-                user.signature = ''
-                user.signature_preparsed = ''
-                user.save(force_update=True)
-
-        return Message(_('Selected users signatures were deleted and locked.'), 'success'), reverse('admin_users')
-
-    def action_remove_locks(self, items, checked):
-        for user in items:
-            if unicode(user.pk) in checked:
-                user.default_avatar(self.request.settings)
-                user.avatar_ban = False
-                user.signature_ban = False
-                user.save(force_update=True)
-
-        return Message(_('Selected users can now edit their avatars and signatures.'), 'success'), reverse('admin_users')
-
-    def action_reset(self, items, checked):
-        # First loop - check for errors
-        for user in items:
-            if unicode(user.pk) in checked:
-                if user.is_protected() and not self.request.user.is_god():
-                    return Message(_('You cannot reset protected members passwords.'), 'error'), reverse('admin_users')
-
-        # Second loop - reset passwords
-        for user in items:
-            if unicode(user.pk) in checked:
-                new_password = get_random_string(8)
-                user.set_password(new_password)
-                user.save(force_update=True)
-                user.email_user(
-                                self.request,
-                                'users/password/new_admin',
-                                _("Your New Password"),
-                                {
-                                 'password': new_password,
-                                 },
-                                )
-
-        return Message(_('Selected users passwords have been reset successfully.'), 'success'), reverse('admin_users')
-
-    def action_delete_content(self, items, checked):
-        for user in items:
-            if unicode(user.pk) in checked:
-                if user.pk == self.request.user.id:
-                    return Message(_('You cannot delete yourself.'), 'error'), reverse('admin_users')
-                if user.is_protected():
-                    return Message(_('You cannot delete protected members.'), 'error'), reverse('admin_users')
-
-        for user in items:
-            if unicode(user.pk) in checked:
-                user.delete_content()
-                user.delete()
-
-        for forum in Forum.objects.all():
-            forum.sync()
-            forum.save(force_update=True)
-        
-        User.objects.resync_monitor(self.request.monitor)
-        return Message(_('Selected users and their content have been deleted successfully.'), 'success'), reverse('admin_users')
-
-    def action_delete(self, items, checked):
-        for user in items:
-            if unicode(user.pk) in checked:
-                if user.pk == self.request.user.id:
-                    return Message(_('You cannot delete yourself.'), 'error'), reverse('admin_users')
-                if user.is_protected():
-                    return Message(_('You cannot delete protected members.'), 'error'), reverse('admin_users')
-
-        for user in items:
-            if unicode(user.pk) in checked:
-                user.delete()
-
-        User.objects.resync_monitor(self.request.monitor)
-        return Message(_('Selected users have been deleted successfully.'), 'success'), reverse('admin_users')
-
-
-class New(FormWidget):
-    admin = site.get_action('users')
-    id = 'new'
-    fallback = 'admin_users'
-    form = NewUserForm
-    submit_button = _("Save User")
-
-    def get_new_url(self, model):
-        return reverse('admin_users_new')
-
-    def get_edit_url(self, model):
-        return reverse('admin_users_edit', model)
-
-    def submit_form(self, form, target):
-        new_user = User.objects.create_user(
-                                            form.cleaned_data['username'],
-                                            form.cleaned_data['email'],
-                                            form.cleaned_data['password'],
-                                            self.request.settings['default_timezone'],
-                                            self.request.META['REMOTE_ADDR'],
-                                            no_roles=True,
-                                            request=self.request,
-                                            )
-        new_user.title = form.cleaned_data['title']
-        new_user.rank = form.cleaned_data['rank']
-
-        for role in form.cleaned_data['roles']:
-            new_user.roles.add(role)
-        new_user.make_acl_key(True)
-        new_user.save(force_update=True)
-
-        return new_user, Message(_('New User has been created.'), 'success')
-
-
-class Edit(FormWidget):
-    admin = site.get_action('users')
-    id = 'edit'
-    name = _("Edit User")
-    fallback = 'admin_users'
-    form = UserForm
-    tabbed = True
-    target_name = 'username'
-    notfound_message = _('Requested User could not be found.')
-    submit_fallback = True
-
-    def get_form_instance(self, form, model, initial, post=False):
-        if post:
-            return form(model, self.request.POST, request=self.request, initial=self.get_initial_data(model))
-        return form(model, request=self.request, initial=self.get_initial_data(model))
-
-    def get_url(self, model):
-        return reverse('admin_users_edit', model)
-
-    def get_edit_url(self, model):
-        return self.get_url(model)
-
-    def get_initial_data(self, model):
-        return {
-                'username': model.username,
-                'title': model.title,
-                'email': model.email,
-                'rank': model.rank,
-                'roles': model.roles.all(),
-                'avatar_ban': model.avatar_ban,
-                'avatar_ban_reason_user': model.avatar_ban_reason_user,
-                'avatar_ban_reason_admin': model.avatar_ban_reason_admin,
-                'signature': model.signature,
-                'signature_ban': model.signature_ban,
-                'signature_ban_reason_user': model.signature_ban_reason_user,
-                'signature_ban_reason_admin': model.signature_ban_reason_admin,
-                }
-
-    def submit_form(self, form, target):
-        target.title = form.cleaned_data['title']
-        target.rank = form.cleaned_data['rank']
-        target.avatar_ban_reason_user = form.cleaned_data['avatar_ban_reason_user']
-        target.avatar_ban_reason_admin = form.cleaned_data['avatar_ban_reason_admin']
-        target.signature_ban = form.cleaned_data['signature_ban']
-        target.signature_ban_reason_user = form.cleaned_data['signature_ban_reason_user']
-        target.signature_ban_reason_admin = form.cleaned_data['signature_ban_reason_admin']
-
-        # Sync username?
-        if target.username != self.original_name:
-            target.sync_username()
-
-        # Do signature mumbo-jumbo
-        if form.cleaned_data['signature']:
-            target.signature = form.cleaned_data['signature']
-            target.signature_preparsed = signature_markdown(target.get_acl(self.request),
-                                                            form.cleaned_data['signature'])
-        else:
-            target.signature = None
-            target.signature_preparsed = None
-
-        # Do avatar ban mumbo-jumbo
-        if target.avatar_ban != form.cleaned_data['avatar_ban']:
-            if form.cleaned_data['avatar_ban']:
-                target.lock_avatar()
-            else:
-                target.default_avatar(self.request.settings)
-        target.avatar_ban = form.cleaned_data['avatar_ban']
-
-        # Set custom avatar
-        if form.cleaned_data['avatar_custom']:
-            target.delete_avatar()
-            target.avatar_image = form.cleaned_data['avatar_custom']
-            target.avatar_type = 'gallery'
-
-        # Update user roles
-        if self.request.user.is_god():
-            target.roles.clear()
-            for role in form.cleaned_data['roles']:
-                target.roles.add(role)
-        else:
-            for role in target.roles.all():
-                if not role.protected:
-                    target.roles.remove(role)
-            for role in form.cleaned_data['roles']:
-                target.roles.add(role)
-
-        target.make_acl_key(True)
-        target.save(force_update=True)
-        return target, Message(_('Changes in user\'s "%(name)s" account have been saved.') % {'name': self.original_name}, 'success')
-
-
-class Delete(ButtonWidget):
-    admin = site.get_action('users')
-    id = 'delete'
-    fallback = 'admin_users'
-    notfound_message = _('Requested User account could not be found.')
-
-    def action(self, target):
-        if target.pk == self.request.user.id:
-            return Message(_('You cannot delete yourself.'), 'error'), False
-        if target.is_protected():
-            return Message(_('You cannot delete protected member.'), 'error'), False
-        target.delete()
-        User.objects.resync_monitor(self.request.monitor)
-        return Message(_('User "%(name)s" has been deleted.') % {'name': target.username}, 'success'), False
-
-
-def inactive(request):
-    token = 'list_filter_misago.users.models.User'
-    request.session[token] = {'activation': ['1', '2', '3']}
-    return redirect(reverse('admin_users'))

+ 0 - 94
notrefactored/utils/__init__.py

@@ -1,94 +0,0 @@
-"""
-Smart slugify
-"""
-import django.template.defaultfilters
-
-use_unidecode = True
-try:
-    from unidecode import unidecode
-except ImportError:
-    use_unidecode = False
-
-def slugify(string):
-    if use_unidecode:
-        string = unidecode(string)
-    return django.template.defaultfilters.slugify(string)
-
-
-"""
-Lazy translate that allows us to access original message
-"""
-from django.utils import translation
-
-def ugettext_lazy(str):
-    t = translation.ugettext_lazy(str)
-    t.message = str
-    return t
-def get_msgid(gettext):
-    try:
-        return gettext.message
-    except AttributeError:
-        return None
-
-
-"""
-Random string
-"""
-from django.utils import crypto
-
-def get_random_string(length):
-    return crypto.get_random_string(length, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM")
-
-
-"""
-Date formats
-"""
-from django.utils.formats import get_format
-
-formats = {
-    'DATE_FORMAT': '',
-    'DATETIME_FORMAT': '',
-    'TIME_FORMAT': '',
-    'YEAR_MONTH_FORMAT': '',
-    'MONTH_DAY_FORMAT': '',
-    'SHORT_DATE_FORMAT': '',
-    'SHORT_DATETIME_FORMAT': '',
-}
-
-for key in formats:
-    formats[key] = get_format(key).replace('P', 'g:i a')
-
-
-"""
-Build pagination list
-"""
-import math
-
-def make_pagination(page, total, max):
-    pagination = {'start': 0, 'stop': 0, 'prev':-1, 'next':-1}
-    page = int(page)
-    if page > 0:
-        pagination['start'] = (page - 1) * max
-
-    # Set page and total stat
-    pagination['page'] = int(pagination['start'] / max) + 1
-    pagination['total'] = int(math.ceil(total / float(max)))
-
-    # Fix too large offset
-    if pagination['start'] > total:
-        pagination['start'] = 0
-
-    # Allow prev/next?
-    if total > max:
-        if pagination['page'] > 1:
-            pagination['prev'] = pagination['page'] - 1
-        if pagination['page'] < pagination['total']:
-            pagination['next'] = pagination['page'] + 1
-
-    # Fix empty pagers
-    if not pagination['total']:
-        pagination['total'] = 1
-
-    # Set stop offset
-    pagination['stop'] = pagination['start'] + max
-    return pagination

+ 0 - 46
notrefactored/utils/avatars.py

@@ -1,46 +0,0 @@
-from django.conf import settings
-try:
-    from PIL import Image
-    has_pil = True
-except ImportError:
-    has_pil = False
-
-avatar_sizes = {}
-def avatar_size(size):
-    if not has_pil:
-        return None
-    try:
-        return avatar_sizes[size]
-    except KeyError:
-        avatar_sizes[size] = None
-        for i in settings.AVATAR_SIZES[1:]:
-            if size <= i:
-                avatar_sizes[size] = i
-    return avatar_sizes[size]
-
-
-def resizeimage(image, size, target, info=None, format=None):
-    if isinstance(image, basestring):
-        image = Image.open(image)
-    if not info:
-        info = image.info
-    if not format:
-        format = image.format
-    if format == "GIF":
-        if 'transparency' in info:
-            image = image.resize((size, size), Image.ANTIALIAS)
-            image.save(target, image.format, transparency=info['transparency'])
-        else:
-            image = image.convert("RGB")
-            image = image.resize((size, size), Image.ANTIALIAS)
-            image = image.convert('P', palette=Image.ADAPTIVE)
-            image.save(target, image.format)
-    if format == "PNG":
-        image = image.resize((size, size), Image.ANTIALIAS)
-        image.save(target, quality=95)
-    if format == "JPEG":
-        image = image.convert("RGB")
-        image = image.resize((size, size), Image.ANTIALIAS)
-        image = image.convert('P', palette=Image.ADAPTIVE)
-        image = image.convert("RGB", dither=None)
-        image.save(target, image.format, quality=95)

+ 0 - 11
notrefactored/utils/slugify.py

@@ -1,11 +0,0 @@
-import django.template.defaultfilters
-try:
-    from unidecode import unidecode
-    use_unidecode = True
-except ImportError:
-    use_unidecode = False
-
-def slugify(string):
-    if use_unidecode:
-        string = unidecode(string)
-    return django.template.defaultfilters.slugify(string)

+ 0 - 15
notrefactored/utils/validators.py

@@ -1,15 +0,0 @@
-from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
-from misago.utils import slugify
-
-class validate_sluggable(object):
-    def __init__(self, error_short=None, error_long=None):
-        self.error_short = error_short if error_short else _("Value has to contain alpha-numerical characters.")
-        self.error_long = error_long if error_long else _("Value is too long.")
-
-    def __call__(self, value):
-        slug = slugify(value)
-        if not slug:
-            raise ValidationError(self.error_short)
-        if len(slug) > 255:
-            raise ValidationError(self.error_long)

+ 0 - 203
notrefactored/views.py

@@ -1,203 +0,0 @@
-from datetime import timedelta
-from django.core.cache import cache
-from django.core.urlresolvers import reverse
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils import timezone
-from django.utils.translation import ugettext as _
-from misago.authn.decorators import block_guest
-from misago.csrf.decorators import check_csrf
-from misago.forums.models import Forum
-from misago.messages import Message
-from misago.readstracker.models import ForumRecord, ThreadRecord
-from misago.readstracker.trackers import ForumsTracker
-from misago.ranks.models import Rank
-from misago.sessions.models import Session
-from misago.threads.models import Thread, Post
-from misago.utils import make_pagination
-
-def home(request):
-    # Threads ranking
-    popular_threads = []
-    if request.settings['thread_ranking_size'] > 0:
-        popular_threads = cache.get('thread_ranking_%s' % request.user.make_acl_key(), 'nada')
-        if popular_threads == 'nada':
-            popular_threads = []
-            for thread in Thread.objects.filter(moderated=False).filter(deleted=False).filter(forum__in=request.acl.threads.get_readable_forums(request.acl)).prefetch_related('forum').order_by('-score')[:request.settings['thread_ranking_size']]:
-                thread.forum_name = thread.forum.name
-                thread.forum_slug = thread.forum.slug
-                popular_threads.append(thread)
-            cache.set('thread_ranking_%s' % request.user.make_acl_key(), popular_threads, 60 * request.settings['thread_ranking_refresh'])
-
-    # Ranks online
-    ranks_list = cache.get('ranks_online', 'nada')
-    if ranks_list == 'nada':
-        ranks_dict = {}
-        ranks_list = []
-        users_list = []
-        for rank in Rank.objects.filter(on_index=True).order_by('order'):
-            rank_entry = {'id':rank.id, 'name': rank.name, 'style': rank.style, 'title': rank.title, 'online': []}
-            ranks_list.append(rank_entry)
-            ranks_dict[rank.pk] = rank_entry
-        if ranks_dict:
-            for session in Session.objects.select_related('user').filter(rank__in=ranks_dict.keys()).filter(last__gte=timezone.now() - timedelta(minutes=10)).filter(user__isnull=False):
-                if not session.user_id in users_list:
-                    ranks_dict[session.user.rank_id]['online'].append(session.user)
-                    users_list.append(session.user_id)
-            # Assert we are on list
-            if (request.user.is_authenticated() and request.user.rank_id in ranks_dict.keys()
-                and not request.user.id in users_list):
-                    ranks_dict[request.user.rank_id]['online'].append(request.user)
-            del ranks_dict
-            del users_list
-        cache.set('ranks_online', ranks_list, 300)
-
-    # Users online
-    users_online = cache.get('users_online', 'nada')
-    if users_online == 'nada':
-        users_online = Session.objects.filter(matched=True).filter(crawler__isnull=True).filter(last__gte=timezone.now() - timedelta(seconds=300)).count()
-        cache.set('users_online', users_online, 300)
-    if not users_online and not request.user.is_crawler():
-        # Cheatey trick to make sure we'll never display
-        # zero users online to human client
-        users_online = 1
-
-    # Load reads tracker and build forums list
-    reads_tracker = ForumsTracker(request.user)
-    forums_list = Forum.objects.treelist(request.acl.forums, tracker=reads_tracker)
-    
-    # Whitelist ignored members
-    Forum.objects.ignored_users(request.user, forums_list)
-        
-    # Render page 
-    return request.theme.render_to_response('index.html',
-                                            {
-                                             'forums_list': forums_list,
-                                             'ranks_online': ranks_list,
-                                             'users_online': users_online,
-                                             'popular_threads': popular_threads,
-                                             },
-                                            context_instance=RequestContext(request));
-
-
-def category(request, forum, slug):
-    if not request.acl.forums.can_see(forum):
-        return error404(request)
-    try:
-        forum = Forum.objects.get(pk=forum, type='category')
-        if not request.acl.forums.can_browse(forum):
-            return error403(request, _("You don't have permission to browse this category."))
-    except Forum.DoesNotExist:
-        return error404(request)
-
-    forum.subforums = Forum.objects.treelist(request.acl.forums, forum, tracker=ForumsTracker(request.user))
-    return request.theme.render_to_response('category.html',
-                                            {
-                                             'category': forum,
-                                             'parents': Forum.objects.forum_parents(forum.pk),
-                                             },
-                                            context_instance=RequestContext(request));
-
-
-def redirection(request, forum, slug):
-    if not request.acl.forums.can_see(forum):
-        return error404(request)
-    try:
-        forum = Forum.objects.get(pk=forum, type='redirect')
-        if not request.acl.forums.can_browse(forum):
-            return error403(request, _("You don't have permission to follow this redirect."))
-        redirects_tracker = request.session.get('redirects', [])
-        if forum.pk not in redirects_tracker:
-            redirects_tracker.append(forum.pk)
-            request.session['redirects'] = redirects_tracker
-            forum.redirects += 1
-            forum.save(force_update=True)
-        return redirect(forum.redirect)
-    except Forum.DoesNotExist:
-        return error404(request)
-
-
-@block_guest
-@check_csrf
-def read_all(request):
-    ForumRecord.objects.filter(user=request.user).delete()
-    ThreadRecord.objects.filter(user=request.user).delete()
-    now = timezone.now()
-    bulk = []
-    for forum in request.acl.forums.known_forums():
-        new_record = ForumRecord(user=request.user, forum_id=forum, updated=now, cleared=now)
-        bulk.append(new_record)
-    if bulk:
-        ForumRecord.objects.bulk_create(bulk)
-    request.messages.set_flash(Message(_("All forums have been marked as read.")), 'success')
-    return redirect(reverse('index'))
-
-
-def forum_map(request):
-    return request.theme.render_to_response('forum_map.html',
-                                            {
-                                             'ranks': Rank.objects.filter(as_tab=1).order_by('order'),
-                                             'forums': Forum.objects.treelist(request.acl.forums),
-                                             },
-                                            context_instance=RequestContext(request));
-
-
-def popular_threads(request, page=0):
-    queryset = Thread.objects.filter(forum_id__in=request.acl.threads.get_readable_forums(request.acl)).filter(deleted=False).filter(moderated=False)
-    items_total = queryset.count();
-    pagination = make_pagination(page, items_total, 30)
-
-    queryset = queryset.order_by('-score').prefetch_related('forum')[pagination['start']:pagination['stop']];
-    if request.settings['avatars_on_threads_list']:
-        queryset = queryset.prefetch_related('start_poster', 'last_poster')
-
-    return request.theme.render_to_response('popular_threads.html',
-                                            {
-                                             'items_total': items_total,
-                                             'threads': Thread.objects.with_reads(queryset, request.user),
-                                             'pagination': pagination,
-                                             },
-                                            context_instance=RequestContext(request));
-
-
-def new_threads(request, page=0):
-    queryset = Thread.objects.filter(forum_id__in=request.acl.threads.get_readable_forums(request.acl)).filter(deleted=False).filter(moderated=False).filter(start__gte=(timezone.now() - timedelta(days=2)))
-    items_total = queryset.count();
-    pagination = make_pagination(page, items_total, 30)
-
-    queryset = queryset.order_by('-start').prefetch_related('forum')[pagination['start']:pagination['stop']];
-    if request.settings['avatars_on_threads_list']:
-        queryset = queryset.prefetch_related('start_poster', 'last_poster')
-
-    return request.theme.render_to_response('new_threads.html',
-                                            {
-                                             'items_total': items_total,
-                                             'threads': Thread.objects.with_reads(queryset, request.user),
-                                             'pagination': pagination,
-                                             },
-                                            context_instance=RequestContext(request));
-
-
-def redirect_message(request, message, type='info', owner=None):
-    request.messages.set_flash(message, type, owner)
-    return redirect(reverse('index'))
-
-
-def error403(request, message=None):
-    return error_view(request, 403, message)
-
-
-def error404(request, message=None):
-    return error_view(request, 404, message)
-
-
-def error_view(request, error, message):
-    response = request.theme.render_to_response(('error%s.html' % error),
-                                                {
-                                                 'message': message,
-                                                 'hide_signin': True,
-                                                 'exception_response': True,
-                                                 },
-                                                context_instance=RequestContext(request));
-    response.status_code = error
-    return response

+ 0 - 0
notrefactored/watcher/__init__.py


+ 0 - 217
notrefactored/watcher/migrations/0001_initial.py

@@ -1,217 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
-    def forwards(self, orm):
-        # Adding model 'ThreadWatch'
-        db.create_table(u'watcher_threadwatch', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['users.User'])),
-            ('forum', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['forums.Forum'])),
-            ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['threads.Thread'])),
-            ('last_read', self.gf('django.db.models.fields.DateTimeField')()),
-            ('email', self.gf('django.db.models.fields.BooleanField')(default=False)),
-        ))
-        db.send_create_signal(u'watcher', ['ThreadWatch'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'ThreadWatch'
-        db.delete_table(u'watcher_threadwatch')
-
-
-    models = {
-        u'forums.forum': {
-            'Meta': {'object_name': 'Forum'},
-            'attrs': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'description_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Thread']"}),
-            'last_thread_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_thread_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_thread_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'parent': ('mptt.fields.TreeForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': u"orm['forums.Forum']"}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'posts_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'prune_last': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'prune_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirect': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'redirects': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'redirects_delta': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'show_details': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads_delta': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
-            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'})
-        },
-        u'ranks.rank': {
-            'Meta': {'object_name': 'Rank'},
-            'as_tab': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'criteria': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name_slug': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'on_index': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'special': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'roles.role': {
-            'Meta': {'object_name': 'Role'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
-        },
-        u'threads.post': {
-            'Meta': {'object_name': 'Post'},
-            'agent': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'checkpoints': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'date': ('django.db.models.fields.DateTimeField', [], {}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'edit_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'edit_reason': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'edit_user_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edit_user_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'edits': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'mentions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'mention_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'merge': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'post': ('django.db.models.fields.TextField', [], {}),
-            'post_preparsed': ('django.db.models.fields.TextField', [], {}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'reported': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'user_name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
-        },
-        u'threads.thread': {
-            'Meta': {'object_name': 'Thread'},
-            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'downvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last': ('django.db.models.fields.DateTimeField', [], {}),
-            'last_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'last_poster': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['users.User']"}),
-            'last_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'last_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'merges': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'replies': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_deleted': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_moderated': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'replies_reported': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'score': ('django.db.models.fields.PositiveIntegerField', [], {'default': '30'}),
-            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start': ('django.db.models.fields.DateTimeField', [], {}),
-            'start_post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['threads.Post']"}),
-            'start_poster': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'start_poster_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'start_poster_slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
-            'start_poster_style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'type': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'upvotes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'weight': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        },
-        u'users.user': {
-            'Meta': {'object_name': 'User'},
-            'acl_key': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'activation': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'alerts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'alerts_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'allow_pms': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'avatar_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'avatar_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'avatar_image': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_original': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_temp': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'avatar_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
-            'email_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
-            'followers': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'following': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'follows': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'follows_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'hide_activity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'ignores': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ignores_set'", 'symmetrical': 'False', 'to': u"orm['users.User']"}),
-            'is_team': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'join_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'join_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'join_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
-            'karma_given_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_given_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_n': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'karma_p': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'last_agent': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'last_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
-            'last_post': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_search': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'last_sync': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
-            'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'password_date': ('django.db.models.fields.DateTimeField', [], {}),
-            'posts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'rank': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['ranks.Rank']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
-            'ranking': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'receive_newsletters': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
-            'roles': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['roles.Role']", 'symmetrical': 'False'}),
-            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
-            'signature': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'signature_ban_reason_admin': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_ban_reason_user': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'signature_preparsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
-            'subscribe_reply': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'subscribe_start': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'timezone': ('django.db.models.fields.CharField', [], {'default': "'utc'", 'max_length': '255'}),
-            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '12', 'null': 'True', 'blank': 'True'}),
-            'username': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'username_slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
-            'votes': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
-        },
-        u'watcher.threadwatch': {
-            'Meta': {'object_name': 'ThreadWatch'},
-            'email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'forum': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['forums.Forum']"}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last_read': ('django.db.models.fields.DateTimeField', [], {}),
-            'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['threads.Thread']"}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['users.User']"})
-        }
-    }
-
-    complete_apps = ['watcher']

+ 0 - 0
notrefactored/watcher/migrations/__init__.py


+ 0 - 33
notrefactored/watcher/models.py

@@ -1,33 +0,0 @@
-from django.db import models
-from misago.forums.signals import move_forum_content
-from misago.threads.signals import move_thread, merge_thread
-
-class ThreadWatch(models.Model):
-    user = models.ForeignKey('users.User')
-    forum = models.ForeignKey('forums.Forum')
-    thread = models.ForeignKey('threads.Thread')
-    last_read = models.DateTimeField()
-    email = models.BooleanField(default=False)
-    deleted = False
-    
-    def save(self, *args, **kwargs):
-        if not self.deleted:
-            super(ThreadWatch, self).save(*args, **kwargs)
-            
-
-def move_forum_content_handler(sender, **kwargs):
-    ThreadWatch.objects.filter(forum=sender).update(forum=kwargs['move_to'])
-
-move_forum_content.connect(move_forum_content_handler, dispatch_uid="move_forum_threads_watchers")
-
-
-def move_thread_handler(sender, **kwargs):
-    ThreadWatch.objects.filter(forum=sender.forum_id).update(forum=kwargs['move_to'])
-
-move_thread.connect(move_thread_handler, dispatch_uid="move_thread_watchers")
-
-
-def merge_thread_handler(sender, **kwargs):
-    ThreadWatch.objects.filter(thread=sender).delete()
-
-merge_thread.connect(merge_thread_handler, dispatch_uid="merge_threads_watchers")

+ 0 - 8
notrefactored/watcher/urls.py

@@ -1,8 +0,0 @@
-from django.conf.urls import patterns, url
-
-urlpatterns = patterns('misago.watcher.views',
-    url(r'^watched/$', 'watched_threads', name="watched_threads"),
-    url(r'^watched/(?P<page>\d+)/$', 'watched_threads', name="watched_threads"),
-    url(r'^watched/new/$', 'watched_threads', name="watched_threads_new", kwargs={'new': True}),
-    url(r'^watched/new/(?P<page>\d+)/$', 'watched_threads', name="watched_threads_new", kwargs={'new': True}),
-)

+ 0 - 40
notrefactored/watcher/views.py

@@ -1,40 +0,0 @@
-from django import forms
-from django.core.urlresolvers import reverse
-from django.db.models import F
-from django.shortcuts import redirect
-from django.template import RequestContext
-from django.utils.translation import ugettext as _
-from misago.authn.decorators import block_guest
-from misago.forms import Form, FormLayout, FormFields
-from misago.messages import Message
-from misago.watcher.models import ThreadWatch
-from misago.utils import make_pagination
-
-@block_guest
-def watched_threads(request, page=0, new=False):
-    # Find mode and fetch threads
-    queryset = ThreadWatch.objects.filter(user=request.user).filter(forum_id__in=request.acl.threads.get_readable_forums(request.acl)).select_related('thread').filter(thread__moderated=False).filter(thread__deleted=False)
-    if new:
-        queryset = queryset.filter(last_read__lt=F('thread__last'))
-    count = queryset.count()
-    pagination = make_pagination(page, count, request.settings.threads_per_page)
-    queryset = queryset.order_by('-thread__last')
-    if request.settings.threads_per_page < count:
-        queryset = queryset[pagination['start']:pagination['stop']]
-    queryset.prefetch_related('thread__forum', 'thread__start_poster', 'thread__last_poster')
-    threads = []
-    for thread in queryset:
-        thread.thread.send_email = thread.email
-        thread.thread.is_read = thread.thread.last <= thread.last_read             
-        threads.append(thread.thread)
-            
-    # Display page
-    return request.theme.render_to_response('watched.html',
-                                            {
-                                             'items_total': count,
-                                             'pagination': pagination,
-                                             'new': new,
-                                             'threads': threads,
-                                             'message': request.messages.get_message('threads'),
-                                             },
-                                            context_instance=RequestContext(request))

+ 0 - 273
refactoring.md

@@ -1,273 +0,0 @@
-Refactored Code Layout
-======================
-
-Directory Tree
---------------
-
-```
-misago/                        App root structure
-+-admin/                       Admin apps
-+-shared/                      Shared (Admin/Front) apps
-+-fixtures/                    Starting data
-  +-basicsettings.py           "Basic Settings" group fixture
-  +-captchasettings.py         "Captcha Settings" group fixture
-  +-usersmonitor.py            Users Monitor fixture
-+-forms/                     Misago forms
-  +-fields.py                Custom fields
-  +-forms.py                 Custom form base class
-  +-layouts.py               Forums layouts (wrapper around Django forms that enables templating)
-  +-widgets.py               Custom widgets
-+-front/                       Frontend apps
-+-management/                  manage.py commands
-+-migrations/                  South DB migrations
-+-models/                      Models
-+-middleware/                  Middlewares
-  +-monitor.py                 Middleware that makes Monitor accessible from request.monitor
-  +-settings.py                Middleware that makes DB Settings accessible from request.settings
-  +-stopwatch.py               Middleware that makes Stopwatch accessible from request.stopwatch
-+-templatetags/                Template tags
-+-utils/                       Small helpers that are imported by models/views
-  +-avatars.py                 Functions for working with avatars sizes
-  +-datesformats.py            Functions for formatting dates and times
-  +-fixtures.py                Fixture loaders
-  +-pagination.py              Pagination helper
-  +-strings.py                 Strings utilities (make slug from string, generate random string, etc. ect.)
-  +-timezones.py               Generate fancy timezones list
-  +-translation.py             Functions for working with translation strings
-+-__init__.py                  Misago init, contains Misago version
-+-context_processors.py        Misago context processors
-+-cookiejar.py                 CookieJar allows for easy setting and removing cookies without direct access to response object
-+-dbsettings.py                DB based settings controller
-+-monitor.py                   Monitor controller that tracks forum stats
-+-settingsbase.py              Base configuration
-+-signals.py                   Misago's signals
-+-urls.py                      Default urls
-+-validators.py                Misago's validators
-+-stopwatch.py                 Stopwatch controller for measuring request processing time
-```
-
-
-ACL
----
-
-
-Activation
-----------
-
-
-Admin
------
-
-
-Alerts
-------
-
-
-Authn
------
-
-
-Banning
--------
-* Moved Ban model to models package.
-
-
-Bruteforce
-----------
-* Moved SignInAttempt model to models package.
-
-
-Captcha
--------
-* Turned into module and moved to core.forms package
-
-
-CookieJar
----------
-* Moved controller to core package.
-* Moved middleware to middleware package.
-
-
-Crawlers
---------
-
-
-CSRF
-----
-
-
-Firewalls
----------
-
-
-Forms
------
-* Moved package under core package.
-* Split __init__.py into three modules.
-
-
-ForumRoles
-----------
-* Moved ForumRole model to models package.
-
-
-Forums
-------
-* Moved Forum model to models package.
-
-
-Heartbeat
----------
-
-
-Markdown
---------
-
-
-Messages
---------
-
-
-Monitor
--------
-* Moved controller to core package.
-* Moved context processor to main context processor.
-* Moved fixture utils to fixtures.py module in utils package.
-* Moved middleware to middleware package.
-* Renamed model Item to MonitorItem and moved it to models package.
-
-
-Newsfeed
---------
-
-
-Newsletters
------------
-* Moved Newsletter model to models package.
-
-
-Profiles
---------
-
-
-Prune
------
-* Renamed "Policy" model to "PruningPolicy" and moved to models package.
-
-
-Ranks
------
-* Moved Rank model to models package.
-
-
-Readstracker
-------------
-* Renamed "ForumRecord" model to "ForumRead" and moved to models package.
-* Renamed "ThreadRecord" model to "ThreadRead" and moved to models package.
-
-
-Register
---------
-
-
-ResetPswd
----------
-
-
-Roles
------
-* Moved Role model to models package.
-
-
-Search
-------
-
-
-Sessions
---------
-* Moved Session model to models package.
-
-
-Settings
---------
-* Moved controller to core package.
-* Moved context processor to main context processor.
-* Moved fixture utils to fixtures.py module in utils package.
-* Moved middleware to middleware package.
-* Moved Setting model to models package.
-* Renamed "type" attribute on Setting model to "normalizes_to".
-* Renamed "input" attribute on Setting model to "field".
-* Renamed model "Group" to "SettingsGroup" and moved it to models package.
-
-
-Setup
------
-* Moved management commands to management package.
-* Renamed "initdata" command to "syncfixtures".
-* Moved fixture utils to fixtures.py module in utils package.
-* Moved Fixture model to models package.
-* Renamed "app_name" attribute on Fixture model to "name".
-
-
-Stats
------
-
-
-Stopwatch
----------
-* Moved controller to core package.
-* Moved middleware to middleware package.
-* Added "stopwatch" to template context.
-
-
-Team
-----
-
-
-Template
---------
-
-
-Themes
-------
-
-
-Threads
--------
-* Moved Thread model to models package.
-* Moved Post model to models package.
-* Moved Karma model to models package.
-* Moved Change model to models package.
-* Moved Checkpoint model to models package.
-
-
-Timezones
----------
-* Turned into module in utils package.
-
-
-ToS
----
-
-
-UserCP
-------
-* Moved UsernameChange model to models package.
-
-
-Users
------
-* Moved User model to models package.
-* Moved Guest model to models package.
-* Moved Crawler model to models package.
-
-
-Utils
------
-* Split __init__.py module into datesformat, pagination, translation and strings modules.
-* Renamed "get_random_string" function to "random_String" in strings module.
-
-
-Watcher
--------
-* Renamed "ThreadWatch" model to "WatchedThread" and moved to models package.