1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
class AgendaItem < ActiveRecord::Base
hobo_model # Don't put anything above this
fields do
title :string
discussion :string
body :text
rejected :boolean, :default => false
timelimits :text, :null => false, :default => ''
discussion_time :string, :null => false, :default => ''
timestamps
end
belongs_to :user, :creator => true
belongs_to :agenda
has_many :voting_options
validate :timelimits_entered_properly
# --- Permissions --- #
def create_permitted?
return false if acting_user.guest?
return false if user != acting_user
true
end
def update_permitted?
return false if discussion_time_changed?
return false if agenda._?.state == 'old'
return false if user_changed?
return true if acting_user.council_member?
return true if acting_user.administrator?
return false unless agenda.nil?
return true if acting_user == user
false
end
def destroy_permitted?
acting_user.administrator?
end
def view_permitted?(field)
true
end
# Not deduced properly
def edit_permitted?(field)
return false if field == :rejected && !agenda.nil?
return false if field == :agenda && rejected?
return false if agenda._?.state == 'old'
return false if field == :user
return true if acting_user.administrator?
return true if acting_user.council_member?
return false unless agenda.nil?
return acting_user == user if [nil, :title, :discussion, :body].include?(field)
end
protected
# Updated discussion time for a single agenda item
# protected because we want to call it only from
# AgendaItem.update_discussion_times
# or similar methods in children classes (if there will be any)
def update_discussion_time
link_regexp = /^(https?:\/\/)?archives.gentoo.org\/([a-zA-Z-]+)\/(msg_[a-fA-F0-9]+.xml)$/
uri_match = link_regexp.match(discussion)
return unless uri_match
group = uri_match[2]
msg = uri_match[3]
message_info = get_message(group, msg)
first_date = Time.parse message_info[:date]
last_date = first_date
to_visit = []
visited = Set.new([msg])
to_visit += message_info[:links]
until to_visit.empty?
msg = to_visit.pop()
next if visited.include? msg
visited.add msg
message_info = get_message(group, msg)
current_date = Time.parse message_info[:date]
first_date = current_date if first_date > current_date
last_date = current_date if last_date < current_date
to_visit += message_info[:links]
end
duration = ((last_date - first_date) / 1.day).floor
first_date = first_date.strftime '%Y.%m.%d'
last_date = last_date.strftime '%Y.%m.%d'
self.discussion_time = "From #{first_date} to #{last_date}, #{duration} full days"
self.save!
end
def get_message(group, msg)
Net::HTTP.start("archives.gentoo.org") { |http|
resp = http.get("/#{group}/#{msg}?passthru=1")
doc = REXML::Document.new(resp.body)
table = REXML::XPath.match(doc, '//table/tr[th=\'Replies:\']/../tr')
in_replies = false
reply_links = []
table.each do |row|
th = REXML::XPath.first(row, "th")
if th
in_replies = (th.text == 'Replies:')
else
next unless in_replies
reply = REXML::XPath.first(row, "ti/uri")
reply_link = reply.attribute(:link).to_s
reply_links.push(reply_link)
end
end
date = resp.body.match(/\<\!--X-Date: (.*) --\>/)[1]
{:date => date, :links => reply_links}
}
end
def timelimits_entered_properly
regexp = /^\d+:\d+( .*)?$/
for line in timelimits.split("\n")
unless line.match regexp
errors.add(:timelimits, "Line '#{line}' doensn't match '<minutes>:<seconds> <message>'")
end
end
end
end
|