parlement 0.9 → 0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +20 -1
- data/MEMORY +51 -0
- data/README +11 -38
- data/Rakefile +2 -2
- data/app/controllers/account_controller.rb +83 -50
- data/app/controllers/application.rb +3 -0
- data/app/controllers/elt_controller.rb +14 -3
- data/app/controllers/subscriber_controller.rb +25 -9
- data/app/helpers/elt_helper.rb +1 -1
- data/app/models/elt.rb +23 -13
- data/app/models/mail.rb +37 -17
- data/app/models/mail_notify.rb +6 -5
- data/app/models/person.rb +6 -5
- data/app/models/person_mail.rb +4 -0
- data/app/models/person_notify.rb +13 -0
- data/app/models/subscription.rb +4 -0
- data/app/views/account/_login.rhtml +9 -12
- data/app/views/account/_show.rhtml +35 -16
- data/app/views/elt/_elt.rhtml +8 -20
- data/app/views/elt/_listByVote.rhtml +9 -9
- data/app/views/elt/show.rhtml +6 -33
- data/app/views/layouts/top.rhtml +6 -0
- data/app/views/person_notify/setEmail.rhtml +24 -0
- data/app/views/subscriber/_list.rhtml +18 -0
- data/config/environment.rb +6 -4
- data/config/environments/development.rb +2 -0
- data/db/ROOT/parlement/{news → News}/Version_01.txt +0 -0
- data/db/ROOT/parlement/{news → News}/Version_02.txt +0 -0
- data/db/ROOT/parlement/{news → News}/Version_03.txt +0 -0
- data/db/ROOT/parlement/{news → News}/Version_04.txt +0 -0
- data/db/ROOT/parlement/{news → News}/Version_05.txt +0 -0
- data/db/ROOT/parlement/{news → News}/Version_06.txt +0 -0
- data/db/ROOT/parlement/{news → News}/Version_07.txt +0 -0
- data/db/ROOT/parlement/{news → News}/Version_08.txt +0 -0
- data/db/ROOT/parlement/{security → Security}/anonymity.txt +0 -0
- data/db/ROOT/parlement.txt +1 -1
- data/db/development_structure.sql +49 -34
- data/db/migrate/003_elt_children_count.rb +1 -1
- data/db/migrate/005_filter_mail.rb +22 -0
- data/public/javascripts/mybehaviour.js +10 -2
- data/public/stylesheets/default.css +21 -15
- data/test/unit/choice_test.rb +1 -1
- data/test/unit/elt_test.rb +1 -1
- data/test/unit/mail_notify_test.rb +24 -8
- data/test/unit/mail_test.rb +61 -6
- data/test/unit/{notifier_test.rb → person_notify_test.rb} +2 -2
- data/test/unit/person_test.rb +1 -1
- data/test/unit/subscriber_test.rb +12 -12
- metadata +24 -20
- data/app/models/notifier.rb +0 -13
- data/app/views/notifier/changeEmail.rhtml +0 -10
- data/public/images/comments.gif +0 -0
data/CHANGES
CHANGED
@@ -1,9 +1,28 @@
|
|
1
1
|
- parlement changelog
|
2
2
|
|
3
|
+
== Version 0.10
|
4
|
+
|
5
|
+
Democratically moderated mails.
|
6
|
+
|
7
|
+
Elements are displayed on the web page or sent by mail when they reach a user
|
8
|
+
chosen voting threshold.
|
9
|
+
|
10
|
+
* one element threads are not automatically displayed anymore
|
11
|
+
* better spam fighting
|
12
|
+
* unsubscribe now also works when user is subscribed on a parent elt
|
13
|
+
* correcting a badly managed reply_to in mails
|
14
|
+
* setEmail and setPassword
|
15
|
+
* small threads automatically displayed (SUB_THREAD_LENGTH = 5)
|
16
|
+
* colored logs
|
17
|
+
* persistent cookies for authentication
|
18
|
+
* fighting the bacon spammer :-(
|
19
|
+
* easier rss auto discovery (html/head/link)
|
20
|
+
* moderated mails
|
21
|
+
|
3
22
|
== Version 0.9
|
4
23
|
|
5
24
|
Improved look, particularly the voting and writing part. Long posts and lists
|
6
|
-
now truncated. Permanent login. Positioned elements. Search form (
|
25
|
+
now truncated. Permanent login. Positioned elements. Search form (through
|
7
26
|
google).
|
8
27
|
|
9
28
|
* now asking to choose a pseudo
|
data/MEMORY
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
What is below is just for future personal reference...
|
2
|
+
|
3
|
+
http://www.ajaxchat.org/chat/
|
4
|
+
|
5
|
+
|
6
|
+
# Here is my console code to reset threads from their original mails:
|
7
|
+
>> elts=Mail.find_all.select{|m|m.file and mail=TMail::Mail.parse(m.file) and reply=mail.in_reply_to and mailObject=Mail.find_by_message(reply) and mailObject.elt.id!=m.elt.parent_id}.collect{|m| {:elt=>m.elt.id, :parent=>Mail.find_by_message(TMail::Mail.parse(m.file).in_reply_to).elt.id}}; puts elts.size
|
8
|
+
>> elts.each{|e|print e[:elt], ' ', e[:parent], ' '; puts Elt.update_all("parent_id='#{e[:parent]}'", "id='#{e[:elt]}'")}; puts elts.size
|
9
|
+
|
10
|
+
# To get and remove duplicate messages
|
11
|
+
>> messages=Mail.find_by_sql "select message from mails group by message having count(message) > 1"; puts messages.length
|
12
|
+
>> messages.each{ |m| mail=Mail.find_all_by_message m.message; mail.each{|m| print m.elt.id, ' ', m.elt.subject, ' ', m.elt.children.size; puts } }; puts messages.length
|
13
|
+
>> messages.each{ |m| mail=Mail.find_all_by_message m.message; mail.each_index{|i| m=mail[i]; print i, ' ', m.elt.id, ' ', m.elt.subject, ' ', m.elt.children.size; m.elt.destroy if i>0 and m.elt.children.size==0; puts } }; puts messages.length
|
14
|
+
|
15
|
+
# To get all existing votes
|
16
|
+
elts=Elt.find(:all, :conditions => ["body LIKE '%%+1%%' OR body LIKE '%%0%%' OR body LIKE '%%-1%%'"]); puts elts.size
|
17
|
+
elts.each { |e| print '(', Regexp.last_match(1), ')' if e.body =~ /^\s*(-1|0|\+1)(\s*|$)/ }; puts; puts elts.size
|
18
|
+
elts.each { |e| e.vote(Regexp.last_match(1), e.person) if e.body =~ /^\s*(-1|0|\+1)(\s*|$)/ }; puts; puts elts.size
|
19
|
+
|
20
|
+
|
21
|
+
UPDATE elts SET elts_count = (SELECT COUNT(*) FROM elts e2 WHERE e2.parent_id = elts.id);
|
22
|
+
|
23
|
+
# To reconstruct the nested tree set
|
24
|
+
def construction(e, counter)
|
25
|
+
e.lft = counter
|
26
|
+
counter += 1
|
27
|
+
e.children.each { |c|
|
28
|
+
counter = construction(c, counter)
|
29
|
+
}
|
30
|
+
e.rgt = counter
|
31
|
+
counter += 1
|
32
|
+
e.save
|
33
|
+
counter
|
34
|
+
end
|
35
|
+
e=Elt.find('ROOT')
|
36
|
+
construction(e, 0)
|
37
|
+
|
38
|
+
UPDATE elts SET lft = NULL, rgt = NULL;
|
39
|
+
ALTER TABLE elts ADD CONSTRAINT elts_unique_lft UNIQUE (lft);
|
40
|
+
ALTER TABLE elts ADD CONSTRAINT elts_unique_rgt UNIQUE (rgt);
|
41
|
+
|
42
|
+
SELECT * FROM person_mails;
|
43
|
+
INSERT INTO person_mails (person_id, mail_id, created_on) VALUES ('first', 'aGaGwUHxCr25c5aaVnmTrI', now());
|
44
|
+
|
45
|
+
select id from mails;
|
46
|
+
select count(*) from mails;
|
47
|
+
select * from people;
|
48
|
+
select * from subscriptions;
|
49
|
+
select * from person_mails;
|
50
|
+
\dt
|
51
|
+
|
data/README
CHANGED
@@ -5,10 +5,11 @@
|
|
5
5
|
| .__/ \__,_|_| |_|\___|_| |_| |_|\___|_| |_|\__|
|
6
6
|
|_|
|
7
7
|
|
8
|
-
|
8
|
+
On debian, here are the commands used to setup the parlement machine:
|
9
9
|
# apt-get install postgresql
|
10
10
|
# sudo su - postgres
|
11
|
-
|
11
|
+
~ createuser /your_login/
|
12
|
+
~ exit
|
12
13
|
# apt-get install ruby
|
13
14
|
# apt-get install libpgsql-ruby
|
14
15
|
# apt-get install irb
|
@@ -22,6 +23,7 @@ You need to install "ruby gems":http://docs.rubygems.org
|
|
22
23
|
And then:
|
23
24
|
# gem install rails
|
24
25
|
# gem install redcloth
|
26
|
+
# gem install term-ansicolor
|
25
27
|
|
26
28
|
Only if you expect to develop and do any release:
|
27
29
|
# gem install meta_project
|
@@ -40,54 +42,25 @@ filtering tool), define this kind of rule:
|
|
40
42
|
* ^TO parlement|leparlement.org
|
41
43
|
| /home/manu/parlement/trunk/script/runner 'Mailman.receive STDIN.read'
|
42
44
|
|
43
|
-
|
44
45
|
Once you have everything set up (ruby, postgresql, redcloth, irb), you can
|
45
46
|
initialise and launch parlement this way:
|
46
47
|
|
47
|
-
|
48
|
-
~ cd parlement/trunk
|
49
|
-
|
50
|
-
|
51
|
-
~
|
52
|
-
|
53
|
-
|
54
|
-
~ ruby lib/data_import.rb
|
55
|
-
|
56
|
-
Migrate the db to its last version
|
57
|
-
~ rake migrate
|
58
|
-
|
59
|
-
Launch the developement web server
|
60
|
-
~ ruby ./script/server
|
48
|
+
~ svn checkout svn://rubyforge.org/var/svn/parlement # Get the code source
|
49
|
+
~ cd parlement/trunk # Go into the right folder
|
50
|
+
~ createdb parlement_development # Create database
|
51
|
+
~ psql -q template1 -f db/schema.sql # Initiate the db schema
|
52
|
+
~ rake migrate # Get the db to its last version
|
53
|
+
~ ruby lib/data_import.rb # Populate the db
|
54
|
+
~ ruby ./script/server # Launch the server
|
61
55
|
|
62
56
|
Now you can go to http://localhost:3000 with your browser.
|
63
57
|
|
64
58
|
You can check that everything works all right on your machine with the testing suite:
|
65
59
|
~ rake
|
66
60
|
|
67
|
-
|
68
61
|
__ __ _
|
69
62
|
\ \ / /__| | ___ ___ _ __ ___ ___
|
70
63
|
\ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \
|
71
64
|
\ V V / __/ | (_| (_) | | | | | | __/
|
72
65
|
\_/\_/ \___|_|\___\___/|_| |_| |_|\___|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
What is below is just for future personal reference...
|
79
|
-
|
80
|
-
|
81
|
-
# Here is my console code to reset threads from their original mails:
|
82
|
-
>> elts=Mail.find_all.select{|m|m.file and mail=TMail::Mail.parse(m.file) and reply=mail.in_reply_to and mailObject=Mail.find_by_message(reply) and mailObject.elt.id!=m.elt.parent_id}.collect{|m| {:elt=>m.elt.id, :parent=>Mail.find_by_message(TMail::Mail.parse(m.file).in_reply_to).elt.id}}; puts elts.size
|
83
|
-
>> elts.each{|e|print e[:elt], ' ', e[:parent], ' '; puts Elt.update_all("parent_id='#{e[:parent]}'", "id='#{e[:elt]}'")}; puts elts.size
|
84
|
-
|
85
|
-
# To get and remove duplicate messages
|
86
|
-
>> messages=Mail.find_by_sql "select message from mails group by message having count(message) > 1"; puts messages.length
|
87
|
-
>> messages.each{ |m| mail=Mail.find_all_by_message m.message; mail.each{|m| print m.elt.id, ' ', m.elt.subject, ' ', m.elt.children.size; puts } }; puts messages.length
|
88
|
-
>> messages.each{ |m| mail=Mail.find_all_by_message m.message; mail.each_index{|i| m=mail[i]; print i, ' ', m.elt.id, ' ', m.elt.subject, ' ', m.elt.children.size; m.elt.destroy if i>0 and m.elt.children.size==0; puts } }; puts messages.length
|
89
66
|
|
90
|
-
# To get all existing votes
|
91
|
-
elts=Elt.find(:all, :conditions => ["body LIKE '%%+1%%' OR body LIKE '%%0%%' OR body LIKE '%%-1%%'"]); puts elts.size
|
92
|
-
elts.each { |e| print '(', Regexp.last_match(1), ')' if e.body =~ /^\s*(-1|0|\+1)(\s*|$)/ }; puts; puts elts.size
|
93
|
-
elts.each { |e| e.vote(Regexp.last_match(1), e.person) if e.body =~ /^\s*(-1|0|\+1)(\s*|$)/ }; puts; puts elts.size
|
data/Rakefile
CHANGED
@@ -56,7 +56,7 @@ spec = Gem::Specification.new do |s|
|
|
56
56
|
EOF
|
57
57
|
s.files = PKG_FILES
|
58
58
|
s.require_path = 'lib'
|
59
|
-
s.autorequire = 'rails redcloth'
|
59
|
+
s.autorequire = 'rails redcloth term-ansicolor'
|
60
60
|
s.has_rdoc = false
|
61
61
|
s.requirements << 'none'
|
62
62
|
s.test_files = Dir.glob('test/unit/*')
|
@@ -72,7 +72,7 @@ EOF
|
|
72
72
|
#s.signing_key = File.join(ENV['CERT_DIR'], 'gem-private_key.pem')
|
73
73
|
#s.cert_chain = [File.join(ENV['CERT_DIR'], 'gem-public_cert.pem')]
|
74
74
|
#end
|
75
|
-
s.add_dependency('rails')
|
75
|
+
s.add_dependency('rails redcloth term-ansicolor')
|
76
76
|
end
|
77
77
|
|
78
78
|
desc "Build Gem"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
#
|
2
2
|
# This class manages users inscription, login and logout
|
3
3
|
#
|
4
4
|
class AccountController < UserController
|
@@ -25,7 +25,7 @@ class AccountController < UserController
|
|
25
25
|
Person.transaction(@person) do
|
26
26
|
@person = Person.new :id => login.gsub(/\s/, '_'), :name => login
|
27
27
|
if @person.save
|
28
|
-
logger.info "
|
28
|
+
logger.info yellow { bold { "Person: #{@person.name}, id: #{@person.id}" } }
|
29
29
|
flash.now[:notice] = "Pseudo created"
|
30
30
|
session[:person] = @person
|
31
31
|
else
|
@@ -34,12 +34,12 @@ class AccountController < UserController
|
|
34
34
|
end
|
35
35
|
rescue Exception => e
|
36
36
|
flash.now[:error] = 'Error creating account'
|
37
|
-
logger.error e
|
37
|
+
logger.error red { e }
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
# We record the password or try to authenticate
|
41
42
|
if @person and @person.errors.empty?
|
42
|
-
# Second we record the password or try to authenticate
|
43
43
|
if password.empty?
|
44
44
|
if not @user or not @user.salted_password \
|
45
45
|
or @user.salted_password.empty?
|
@@ -48,42 +48,28 @@ class AccountController < UserController
|
|
48
48
|
flash.now[:error] = "This pseudo is protected with a password"
|
49
49
|
end
|
50
50
|
elsif not @user
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
@user.login = login
|
55
|
-
@user.change_password(password)
|
56
|
-
# To make sure even a non email protected user can use a password
|
57
|
-
@user.email = login+'@nomailyet'
|
58
|
-
# This is a hack, to make sure this user can login even if he
|
59
|
-
# didn't verify his email
|
60
|
-
@user.verified = true
|
61
|
-
if @user.save
|
62
|
-
flash['notice 2'] = 'Password recorded'
|
63
|
-
|
64
|
-
session[:person] = @person
|
65
|
-
session[:user] = @user
|
66
|
-
end
|
67
|
-
end
|
68
|
-
rescue
|
69
|
-
flash.now[:error] = 'Error with password'
|
70
|
-
end
|
71
|
-
|
51
|
+
# Record password
|
52
|
+
session[:person] = @person
|
53
|
+
mngPassword
|
72
54
|
elsif User.authenticate(login, password)
|
73
|
-
|
55
|
+
logger.info yellow { bold { "#{@person.name} logged in" } }
|
56
|
+
# Authenticate
|
74
57
|
session[:person] = @person
|
75
58
|
session[:user] = @user
|
76
|
-
|
77
|
-
|
59
|
+
elsif email and not email.empty?
|
60
|
+
# There is a check key, used to change the password
|
78
61
|
begin
|
79
62
|
User.transaction(@user) do
|
80
63
|
if User.authenticate_by_token(@user.id, email)
|
81
64
|
@user.change_password(password)
|
82
65
|
@user.security_token = nil
|
83
66
|
if @user.save
|
67
|
+
logger.info yellow { "Person: #{@person.name} changed its password" }
|
84
68
|
flash.now['notice 2'] = 'Password successfully modified!'
|
85
69
|
session[:person] = @person
|
86
70
|
session[:user] = @user
|
71
|
+
else
|
72
|
+
@user.errors.each_full { |msg| logger.error msg }
|
87
73
|
end
|
88
74
|
end
|
89
75
|
end
|
@@ -94,45 +80,50 @@ class AccountController < UserController
|
|
94
80
|
flash.now[:error] = "Wrong password"
|
95
81
|
end
|
96
82
|
|
97
|
-
#
|
98
|
-
if not email.empty?
|
83
|
+
# Record the email or send a check_key for a password reset
|
84
|
+
if email and not email.empty?
|
99
85
|
if session[:person]
|
100
86
|
if email == @person.email
|
101
87
|
flash.now['notice 3'] = "Email already recorded and verified"
|
102
88
|
else
|
103
|
-
|
89
|
+
mngEmail
|
104
90
|
end
|
105
|
-
|
106
91
|
elsif email == @person.email
|
107
92
|
# User protected by password and with the same email as entered
|
108
93
|
key = @user.generate_security_token
|
109
94
|
url = url_for(:action => 'check_key')
|
110
95
|
url += "?user[id]=#{@user.id}&key=#{key}"
|
111
96
|
UserNotify::deliver_forgot_password(@user, url)
|
112
|
-
flash.now['notice 3'] = "Email with a check key sent to "
|
97
|
+
flash.now['notice 3'] = "Email with a check key sent to #{email}"
|
113
98
|
end
|
114
99
|
end
|
115
100
|
end
|
116
101
|
|
117
102
|
# Record cookies for re authentication
|
118
103
|
if session[:person]
|
119
|
-
cookies[:person_name] = session[:person].name
|
120
|
-
cookies[:salted_password] = @user.salted_password if @user
|
104
|
+
cookies[:person_name] = { :value => session[:person].name, :expires => 3.years.from_now }
|
105
|
+
cookies[:salted_password] = { :value => @user.salted_password, :expires => 3.years.from_now } if @user
|
121
106
|
end
|
122
107
|
|
108
|
+
# To make sure the logout knows which elt's choices to update
|
109
|
+
@elt = Elt.find(params[:elt]) if params[:elt]
|
110
|
+
|
123
111
|
render :partial => 'show',
|
124
|
-
:locals => { :
|
112
|
+
:locals => { :choices => getAllVotes },
|
125
113
|
:status => (session[:person] ? 200 : 403)
|
126
114
|
end
|
127
115
|
|
128
116
|
def logout
|
117
|
+
logger.info yellow { bold { "Bye bye" } }
|
129
118
|
# Cleaning up
|
130
119
|
session[:person] = @person = session[:user] = @user = nil
|
131
120
|
cookies.delete :person_name
|
132
121
|
cookies.delete :salted_password
|
133
122
|
|
134
|
-
|
135
|
-
|
123
|
+
# To make sure the logout knows which elt's choices to update
|
124
|
+
@elt = Elt.find(params[:elt]) if params[:elt]
|
125
|
+
|
126
|
+
render :partial => 'show', :locals => { :choices => getAllVotes }
|
136
127
|
end
|
137
128
|
|
138
129
|
def check_key
|
@@ -158,10 +149,26 @@ class AccountController < UserController
|
|
158
149
|
end
|
159
150
|
end
|
160
151
|
|
152
|
+
def setPassword
|
153
|
+
logger.info yellow { "Person #{session[:person].name} sets/changes his password" } if session[:person]
|
154
|
+
@person = session[:person]
|
155
|
+
@user = session[:user]
|
156
|
+
mngPassword
|
157
|
+
render :partial => 'show'
|
158
|
+
end
|
159
|
+
|
160
|
+
def setEmail
|
161
|
+
logger.info yellow { "Person #{session[:person].name} set his email to #{params[:person][:email]}" } if session[:person]
|
162
|
+
@person = session[:person]
|
163
|
+
@user = session[:user]
|
164
|
+
mngEmail
|
165
|
+
render :partial => 'show'
|
166
|
+
end
|
167
|
+
|
161
168
|
def setAvatar
|
162
169
|
return render(:text => "Not logged in", :status => 403) \
|
163
170
|
unless session[:person]
|
164
|
-
logger.info "Setting up an avatar for person #{session[:person].name}"
|
171
|
+
logger.info yellow { "Setting up an avatar for person #{session[:person].name}" }
|
165
172
|
|
166
173
|
@elt = Elt.find_by_id 'people'
|
167
174
|
if !@elt
|
@@ -192,8 +199,34 @@ class AccountController < UserController
|
|
192
199
|
|
193
200
|
protected
|
194
201
|
|
202
|
+
def mngPassword
|
203
|
+
if @person and password = @params[:user][:password] and !password.empty?
|
204
|
+
@user = @person.user || User.new()
|
205
|
+
begin
|
206
|
+
User.transaction(@user) do
|
207
|
+
@user.login = @person.name
|
208
|
+
# To make sure even a non email protected user can use a password
|
209
|
+
@user.email ||= @person.name+'@nomailyet'
|
210
|
+
# This is a hack, to make sure this user can login even if he
|
211
|
+
# didn't verify his email
|
212
|
+
@user.verified = true
|
213
|
+
@user.change_password(password)
|
214
|
+
if @user.save
|
215
|
+
logger.info yellow { "Password changed" }
|
216
|
+
flash['notice 2'] = 'Password recorded'
|
217
|
+
session[:user] = @user
|
218
|
+
else
|
219
|
+
@user.errors.each_full { |msg| logger.error msg }
|
220
|
+
end
|
221
|
+
end
|
222
|
+
rescue
|
223
|
+
flash.now[:error] = 'Error with password'
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
195
228
|
# Mostly copied from the login engine
|
196
|
-
def
|
229
|
+
def mngEmail
|
197
230
|
if @person and not @user
|
198
231
|
@user = User.new
|
199
232
|
@user.login = @person.name
|
@@ -207,31 +240,31 @@ class AccountController < UserController
|
|
207
240
|
end
|
208
241
|
if @user.save
|
209
242
|
key = @user.generate_security_token
|
210
|
-
|
211
|
-
url =
|
212
|
-
url += "?user[id]=#{@user.id}&key=#{key}"
|
243
|
+
url = url_for(:action => 'check_key', 'user[id]' => @user.id, :key => key)
|
244
|
+
#url = url_for(:action => 'check_key')
|
245
|
+
#url += "?user[id]=#{@user.id}&key=#{key}"
|
213
246
|
#flash[:notice] = 'Signup successful!'
|
214
|
-
flash.now['notice 3'] = 'Confirmation email sent to '+@user.email
|
215
247
|
if LoginEngine.config(:use_email_notification)
|
216
|
-
|
217
|
-
flash['notice
|
248
|
+
PersonNotify.deliver_setEmail(@person, url)
|
249
|
+
flash.now['notice 3'] = "Confirmation email sent to #{@user.email}"
|
218
250
|
end
|
219
251
|
#redirect_to :action => 'login'
|
220
252
|
end
|
221
253
|
end
|
222
254
|
rescue Exception => e
|
223
255
|
flash.now[:notice] = nil
|
256
|
+
flash.now['notice 2'] = nil
|
257
|
+
flash.now['notice 3'] = nil
|
224
258
|
flash.now[:warning] = 'Error creating account: confirmation email not sent'
|
225
|
-
logger.error
|
259
|
+
e.backtrace.each { |m| logger.error m }
|
226
260
|
end
|
227
261
|
end
|
228
262
|
|
229
263
|
def getAllVotes
|
230
|
-
return
|
231
|
-
elt = Elt.find params[:divId].gsub(/author_/, '')
|
264
|
+
return unless @elt
|
232
265
|
Choice.find_all_by_person_id((session[:person] ? session[:person].id : nil),
|
233
266
|
:include => 'elt',
|
234
|
-
:conditions => "elts.lft >= '#{elt.lft}' AND elts.rgt <= '#{elt.rgt}'")
|
267
|
+
:conditions => "elts.lft >= '#{@elt.lft}' AND elts.rgt <= '#{@elt.rgt}'")
|
235
268
|
end
|
236
269
|
end
|
237
270
|
|
@@ -2,9 +2,11 @@
|
|
2
2
|
# Likewese will all the methods added be available for all controllers.
|
3
3
|
|
4
4
|
require 'login_engine'
|
5
|
+
require 'term/ansicolor'
|
5
6
|
|
6
7
|
class ApplicationController < ActionController::Base
|
7
8
|
include LoginEngine
|
9
|
+
include Term::ANSIColor
|
8
10
|
model :user
|
9
11
|
|
10
12
|
before_filter :set_charset
|
@@ -32,6 +34,7 @@ class ApplicationController < ActionController::Base
|
|
32
34
|
((!person.user and !cookies[:salted_password]) \
|
33
35
|
or (person.user \
|
34
36
|
and person.user.salted_password == cookies[:salted_password]))
|
37
|
+
logger.info yellow { bold { "#{person.name} is back" } }
|
35
38
|
session[:person] = person
|
36
39
|
session[:user] = person.user
|
37
40
|
end
|
@@ -66,10 +66,13 @@ class EltController < ApplicationController
|
|
66
66
|
@elt = Elt.new(params[:elt])
|
67
67
|
@elt.person = @session[:person]
|
68
68
|
|
69
|
-
if @elt.subject
|
70
|
-
|
69
|
+
if @elt.subject =~ /([<>\/]|href)/ \
|
70
|
+
or @elt.body =~ /(.*([<>\/]|href).*){3}/ \
|
71
|
+
or @elt.body =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i \
|
72
|
+
or @elt.body =~ /([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,}.*){3}/i
|
73
|
+
logger.error red { underline { "SPAM! '#{@elt.subject}'" } }
|
71
74
|
logger.error "SPAM! '#{@elt.body}'"
|
72
|
-
flash[:error] = 'Sorry, to fight spam "<" ">" or "href" are forbidden in the subject!'
|
75
|
+
flash[:error] = 'Sorry, to fight spam "<" ">" or "href" are forbidden in the subject, and there can not be more than 3 links in the body, you also can\'t input one simple email or more than 3 emails!'
|
73
76
|
headers["Status"] = "404 Post considered as spam"
|
74
77
|
render :controller => 'elt', :action => 'new', :status => 404
|
75
78
|
elsif params[:submit] == "preview" or (@elt.publish and @elt.parent.add_child(@elt)) then
|
@@ -89,6 +92,14 @@ class EltController < ApplicationController
|
|
89
92
|
|
90
93
|
def vote
|
91
94
|
@elt = Elt.find params[:id]
|
95
|
+
unless params[:choice][:value] =~ /^\s*(-1|0|\+1)(\s|$)/ then
|
96
|
+
logger.error red { underline { "SPAM! through the vote" } }
|
97
|
+
logger.error params[:choice][:value]
|
98
|
+
flash[:error] = 'Sorry, you can only vote here!'
|
99
|
+
render :partial => '/elt/choice', :locals => { :elt => @elt }
|
100
|
+
return
|
101
|
+
end
|
102
|
+
|
92
103
|
vote = @elt.children.build
|
93
104
|
vote.person = session[:person]
|
94
105
|
vote.subject = @elt.subject
|
@@ -1,21 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# Mailing list management
|
3
|
+
#
|
4
|
+
# This is to add or remove subscribers
|
5
|
+
#
|
1
6
|
class SubscriberController < ApplicationController
|
2
|
-
|
3
7
|
def subscribe
|
4
|
-
@elt = Elt.find
|
8
|
+
@elt = Elt.find params[:id]
|
5
9
|
|
6
10
|
if @session[:person]
|
7
11
|
if @elt.subscribers.include?(@session[:person])
|
8
|
-
|
9
|
-
logger.info "
|
10
|
-
|
12
|
+
Subscription.find_by_person_id_and_elt_id(@session[:person].id, @elt.id).destroy
|
13
|
+
logger.info yellow { "User #{@session[:person].name} unsubscribed from #{@elt.subject}..." }
|
14
|
+
elsif @elt.all_recipients.include?(@session[:person])
|
15
|
+
elt2 = @elt
|
16
|
+
elt2 = elt2.parent until elt2.subscribers.include?(@session[:person])
|
17
|
+
Subscription.find_by_person_id_and_elt_id(@session[:person].id, elt2.id).destroy
|
18
|
+
logger.info yellow { "User #{@session[:person].name} unsubscribed from #{elt2.subject}..." }
|
11
19
|
else
|
12
|
-
|
13
|
-
|
14
|
-
|
20
|
+
if cookies[:filter]
|
21
|
+
filter = cookies[:filter].to_i - 1
|
22
|
+
filter = nil unless filter >= 0
|
23
|
+
else
|
24
|
+
filter = 0
|
25
|
+
end
|
26
|
+
@elt.subscriptions.create :person => @session[:person], :filter => filter
|
27
|
+
logger.info yellow { "User #{@session[:person].name} subscribed to #{@elt.id} with filter #{filter}..." }
|
15
28
|
end
|
16
29
|
else
|
17
30
|
puts "Not logged in!"
|
18
|
-
render :inline => "First you need to login... it's easy, type a pseudo with at least 3 characters. Then
|
31
|
+
#render :inline => "First you need to login... it's easy, type a pseudo with at least 3 characters. Then OK"
|
32
|
+
flash.now[:error] = 'First you need to login!'
|
19
33
|
end
|
34
|
+
render :partial => 'list'
|
20
35
|
end
|
21
36
|
end
|
37
|
+
|
data/app/helpers/elt_helper.rb
CHANGED
@@ -66,7 +66,7 @@ module EltHelper
|
|
66
66
|
and elt.subject != elt.parent.subject \
|
67
67
|
and elt.parent.subject \
|
68
68
|
and elt.subject.downcase != elt.parent.subject.downcase \
|
69
|
-
and not elt.subject.sub(/(Re|r�f|re|sv|aw):\s*/, '') == elt.parent.subject
|
69
|
+
and not elt.subject.sub(/(Re|RE|r�f|re|sv|aw):\s*/, '') == elt.parent.subject
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
data/app/models/elt.rb
CHANGED
@@ -16,12 +16,14 @@
|
|
16
16
|
# normal characters are used)
|
17
17
|
#
|
18
18
|
class Elt < ActiveRecord::Base
|
19
|
-
has_one :mail, :dependent => true
|
20
19
|
belongs_to :person
|
20
|
+
has_one :mail, :dependent => :destroy
|
21
|
+
|
22
|
+
has_many :choices, :dependent => :destroy, :order => "choices.created_on"
|
21
23
|
has_many :voters, :through => :choices, :source => :person
|
22
|
-
has_many :
|
23
|
-
has_many :
|
24
|
-
|
24
|
+
has_many :attachments, :dependent => :destroy
|
25
|
+
has_many :subscriptions, :dependent => :destroy
|
26
|
+
has_many :subscribers, :through => :subscriptions, :source => :person
|
25
27
|
|
26
28
|
acts_as_nested_set :order => "position is not null, position, created_on"
|
27
29
|
acts_as_tree :order => "position is not null, position, created_on", :counter_cache => true
|
@@ -35,11 +37,20 @@ class Elt < ActiveRecord::Base
|
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
40
|
+
def all_subscriptions
|
41
|
+
if parent
|
42
|
+
(subscriptions + parent.all_subscriptions).uniq
|
43
|
+
else
|
44
|
+
subscriptions
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
38
48
|
def vote(value = 1, person = self.person)
|
39
49
|
logger.info "#{person.name if person} vote #{value} on #{subject} #{self.choices}"
|
40
50
|
choices.each{ |c| c.destroy if c.person == person }
|
41
51
|
choice = choices.build :value => value, :person => person
|
42
52
|
choice.save!
|
53
|
+
mail.publish if mail
|
43
54
|
end
|
44
55
|
|
45
56
|
# Get the vote results
|
@@ -54,10 +65,10 @@ class Elt < ActiveRecord::Base
|
|
54
65
|
def publish
|
55
66
|
logger.info "Publish #{subject}"
|
56
67
|
|
68
|
+
self.position = Regexp.last_match(1) if body =~ /^\s*position:\s*(\d+(\.\d+)?)(\s|$)/
|
69
|
+
|
57
70
|
build_mail(:elt => self) unless mail
|
58
71
|
mail.publish
|
59
|
-
|
60
|
-
self.position = Regexp.last_match(1) if body =~ /^\s*position:\s*(\d+(\.\d+)?)(\s|$)/
|
61
72
|
save!
|
62
73
|
|
63
74
|
parent.vote Regexp.last_match(1), person if body =~ /^\s*(-1|0|\+1)(\s|$)/
|
@@ -73,15 +84,14 @@ class Elt < ActiveRecord::Base
|
|
73
84
|
def save
|
74
85
|
if new_record?
|
75
86
|
# Let's generate a nice looking id
|
76
|
-
self.id = new_id =
|
77
|
-
.gsub(/\
|
78
|
-
.gsub(
|
79
|
-
if subject
|
87
|
+
self.id = new_id =
|
88
|
+
subject.gsub(/\[[\w-]*\]/, '').strip \
|
89
|
+
.gsub(/\s/, '_').gsub(/[^\w]+/, '') \
|
90
|
+
.gsub(/_+/, '_').gsub(/(^_|_$)/, '') if subject
|
80
91
|
self.id ||= "elt"
|
81
92
|
|
82
|
-
|
83
|
-
self.id = "#{new_id}_#{
|
84
|
-
while discrim += 1 and self.class.find_by_id self.id
|
93
|
+
i = 0
|
94
|
+
self.id = "#{new_id}_#{i+=1}" while self.class.find_by_id self.id
|
85
95
|
end
|
86
96
|
|
87
97
|
super
|