]> git.openstreetmap.org Git - osqa.git/blob - forum/actions/node.py
fix breach in award points that allows user to award infinite points
[osqa.git] / forum / actions / node.py
1 from django.utils.html import strip_tags
2 from django.utils.translation import ugettext as _
3 from forum.models.action import ActionProxy
4 from forum.models import Comment, Question, Answer, NodeRevision
5 from forum import settings, REQUEST_HOLDER
6
7 from django.contrib import messages
8
9 class NodeEditAction(ActionProxy):
10     def create_revision_data(self, initial=False, **data):
11         revision_data = dict(summary=data.get('summary', (initial and _('Initial revision') or '')), body=data['text'])
12
13         if data.get('title', None):
14             revision_data['title'] = strip_tags(data['title'].strip())
15
16         if data.get('tags', None):
17             revision_data['tagnames'] = data['tags'].strip()
18
19         return revision_data
20
21 class AskAction(NodeEditAction):
22     verb = _("asked")
23
24     def process_data(self, **data):
25         processed_data = self.create_revision_data(True, **data)
26         if 'added_at' in data:
27             processed_data['added_at'] = data['added_at']
28
29         question = Question(author=self.user, **processed_data)
30         question.save()
31         self.node = question
32
33         messages.info(REQUEST_HOLDER.request, self.describe(self.user))
34
35     def describe(self, viewer=None):
36         return _("%(user)s asked %(question)s") % {
37             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
38             'question': self.hyperlink(self.node.get_absolute_url(), self.node.title)
39         }
40
41 class AnswerAction(NodeEditAction):
42     verb = _("answered")
43
44     def process_data(self, **data):
45         answer = Answer(author=self.user, parent=data['question'], **self.create_revision_data(True, **data))
46         answer.save()
47         self.node = answer
48
49     def process_action(self):
50         self.node.question.reset_answer_count_cache()
51
52         messages.info(REQUEST_HOLDER.request, self.describe(self.user))
53
54
55     def describe(self, viewer=None):
56         question = self.node.parent
57         return _("%(user)s answered %(asker)s on %(question)s") % {
58             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
59             'asker': self.hyperlink(question.author.get_profile_url(), self.friendly_username(viewer, question.author)),
60             'question': self.hyperlink(self.node.get_absolute_url(), question.title)
61         }
62
63 class CommentAction(ActionProxy):
64     verb = _("commented")
65
66     def process_data(self, text='', parent=None):
67         comment = Comment(author=self.user, parent=parent, body=text)
68         comment.save()
69         self.node = comment
70
71     def describe(self, viewer=None):
72         return _("%(user)s commented on %(post_desc)s") % {
73             'user': self.hyperlink(self.node.author.get_profile_url(), self.friendly_username(viewer, self.node.author)),
74             'post_desc': self.describe_node(viewer, self.node.parent)
75         }
76
77 class ReviseAction(NodeEditAction):
78     verb = _("edited")
79
80     def process_data(self, **data):
81         revision_data = self.create_revision_data(**data)
82         revision = self.node.create_revision(self.user, **revision_data)
83         self.extra = revision.revision
84
85     def process_action(self):
86         self.node.last_edited = self
87         self.node.save()
88
89     def describe(self, viewer=None):
90         return _("%(user)s edited %(post_desc)s") % {
91             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
92             'post_desc': self.describe_node(viewer, self.node)
93         }
94
95     def get_absolute_url(self):
96         return self.node.get_revisions_url()
97
98 class RetagAction(ActionProxy):
99     verb = _("retagged")
100
101     def process_data(self, tagnames=''):
102         active = self.node.active_revision
103         revision_data = dict(summary=_('Retag'), title=active.title, tagnames=strip_tags(tagnames.strip()), body=active.body)
104         revision = self.node.create_revision(self.user, **revision_data)
105         self.extra = revision.revision
106
107     def process_action(self):
108         self.node.last_edited = self
109         self.node.save()
110
111     def describe(self, viewer=None):
112         return _("%(user)s retagged %(post_desc)s") % {
113             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
114             'post_desc': self.describe_node(viewer, self.node)
115         }
116
117     def get_absolute_url(self):
118         return self.node.get_revisions_url()
119
120 class RollbackAction(ActionProxy):
121     verb = _("reverted")
122
123     def process_data(self, activate=None):
124         previous = self.node.active_revision
125         self.node.activate_revision(self.user, activate)
126         self.extra = "%d:%d" % (previous.revision, activate.revision)
127
128     def process_action(self):
129         self.node.last_edited = self
130         self.node.save()
131
132     def describe(self, viewer=None):
133         revisions = [NodeRevision.objects.get(node=self.node, revision=int(n)) for n in self.extra.split(':')]
134
135         return _("%(user)s reverted %(post_desc)s from revision %(initial)d (%(initial_sum)s) to revision %(final)d (%(final_sum)s)") % {
136             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
137             'post_desc': self.describe_node(viewer, self.node),
138             'initial': revisions[0].revision, 'initial_sum': revisions[0].summary,
139             'final': revisions[1].revision, 'final_sum': revisions[1].summary,
140         }
141
142     def get_absolute_url(self):
143         return self.node.get_revisions_url()
144
145 class CloseAction(ActionProxy):
146     verb = _("closed")
147
148     def process_action(self):
149         self.node.marked = True
150         self.node.nstate.closed = self
151         self.node.last_edited = self
152         self.node.update_last_activity(self.user, save=True)
153
154     def cancel_action(self):
155         self.node.marked = False
156         self.node.nstate.closed = None
157         self.node.update_last_activity(self.user, save=True)
158
159     def describe(self, viewer=None):
160         return _("%(user)s closed %(post_desc)s: %(reason)s") % {
161             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
162             'post_desc': self.describe_node(viewer, self.node),
163             'reason': self.extra
164         }
165
166 class AnswerToCommentAction(ActionProxy):
167     verb = _("converted")
168
169     def process_data(self, new_parent=None):
170         self.node.parent = new_parent
171         self.node.node_type = "comment"
172
173         for comment in self.node.comments.all():
174             comment.parent = new_parent
175             comment.save()
176
177         self.node.last_edited = self
178         self.node.update_last_activity(self.user, save=True)
179         try:
180             self.node.abs_parent.reset_answer_count_cache()
181         except AttributeError:
182             pass
183
184     def describe(self, viewer=None):
185         return _("%(user)s converted an answer to %(question)s into a comment") % {
186             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
187             'question': self.describe_node(viewer, self.node.abs_parent),
188         }
189
190 class CommentToAnswerAction(ActionProxy):
191     verb = _("converted")
192
193     def process_data(self, question):
194         self.node.parent = question
195         self.node.node_type = "answer"
196         self.node.last_edited = self
197         self.node.update_last_activity(self.user, save=True)
198
199         # Now updated the cached data
200         question.reset_answer_count_cache()
201
202     def describe(self, viewer=None):
203         return _("%(user)s converted comment on %(question)s into an answer") % {
204             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
205             'question': self.describe_node(viewer, self.node.abs_parent),
206         }
207 class CommentToQuestionAction(NodeEditAction):
208     verb = _("converted")
209
210     def process_data(self, **data):
211         revision_data = self.create_revision_data(**data)
212         revision = self.node.create_revision(self.user, **revision_data)
213
214         self.extra = {
215             'covert_revision': revision.revision,
216         }
217
218         self.node.node_type = "question"
219         self.node.parent = None
220         self.node.abs_parent = None
221
222     def process_action(self):
223         self.node.last_edited = self
224         self.node.save()
225
226     def describe(self, viewer=None):
227         return _("%(user)s converted comment on %(question)s to a new question") % {
228             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
229             'question': self.describe_node(viewer, self.node.abs_parent),
230         }
231
232 class AnswerToQuestionAction(NodeEditAction):
233     verb = _("converted to question")
234
235     def process_data(self,  **data):
236         revision_data = self.create_revision_data(**data)
237         revision = self.node.create_revision(self.user, **revision_data)
238
239         original_question = self.node.question
240
241         self.extra = {
242             'covert_revision': revision.revision,
243             'original_question': original_question
244         }
245
246         self.node.node_type = "question"
247         self.node.parent = None
248         self.node.abs_parent = None
249
250         original_question.reset_answer_count_cache()
251
252     def process_action(self):
253         self.node.last_edited = self
254         self.node.save()
255
256
257     def describe(self, viewer=None):
258         return _("%(user)s converted an answer to %(question)s into a separate question") % {
259             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
260             'question': self.describe_node(viewer, self.node.abs_parent),
261         }
262
263 class WikifyAction(ActionProxy):
264     verb = _("wikified")
265
266     def process_action(self):
267         self.node.nstate.wiki = self
268         self.node.last_edited = self
269         self.node.update_last_activity(self.user, save=True)
270
271     def cancel_action(self):
272         self.node.nstate.wiki = None
273         self.node.update_last_activity(self.user, save=True)
274
275     def describe(self, viewer=None):
276         return _("%(user)s marked %(node)s as community wiki.") % {
277             'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
278             'node': self.describe_node(viewer, self.node),
279         }
280