Commit cd4eff3c40cb9834e9a7673f3b4b2bc02f9d1036

Authored by Francisco Júnior
2 parents 15a4ca5f 3a392608

Merge branch 'staging' into security-search

Showing 1968 changed files with 192212 additions and 85052 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 1968 files displayed.

.gitlab-ci.yml 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +before_script:
  2 + - mkdir -p tmp/pids log
  3 + - bundle check || bundle install
  4 +# workaround for plugins with Gemfile
  5 + - perl -pi -e 's/--local //' script/noosfero-plugins
  6 + - script/noosfero-plugins disableall
  7 + - bundle exec rake makemo &>/dev/null
  8 +# database
  9 + - cp config/database.yml.gitlab-ci config/database.yml
  10 + - createdb gitlab_ci_test || true
  11 + - bundle exec rake db:schema:load &>/dev/null
  12 + - bundle exec rake db:migrate &>/dev/null
  13 +
  14 +units:
  15 + script: bundle exec rake test:units
  16 +functionals:
  17 + script: bundle exec rake test:functionals
  18 +integration:
  19 + script: bundle exec rake test:integration
  20 +cucumber:
  21 + script: bundle exec rake cucumber
  22 +selenium:
  23 + script: bundle exec rake selenium
  24 +plugins:
  25 + script: bundle exec rake test:noosfero_plugins
  26 +
.gitmodules 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +[submodule "plugins/pairwise"]
  2 + path = plugins/pairwise
  3 + url = https://gitlab.com/noosfero-plugins/pairwise.git
  4 +[submodule "plugins/proposals_discussion"]
  5 + path = plugins/proposals_discussion
  6 + url = https://gitlab.com/noosfero-plugins/proposals_discussion.git
  7 +[submodule "plugins/site_tour"]
  8 + path = plugins/site_tour
  9 + url = https://gitlab.com/noosfero-plugins/site_tour.git
  10 +[submodule "plugins/gamification"]
  11 + path = plugins/gamification
  12 + url = https://gitlab.com/noosfero-plugins/gamification.git
  13 +[submodule "plugins/comment_paragraph"]
  14 + path = plugins/comment_paragraph
  15 + url = https://gitlab.com/noosfero-plugins/comment-paragraph.git
  16 +[submodule "plugins/notification"]
  17 + path = plugins/notification
  18 + url = https://gitlab.com/noosfero-plugins/notification.git
  19 +[submodule "plugins/email_article"]
  20 + path = plugins/email_article
  21 + url = https://gitlab.com/noosfero-plugins/email_article.git
  22 +[submodule "public/proposal-app"]
  23 + path = public/proposal-app
  24 + url = https://gitlab.com/participa/proposal-app.git
  25 +[submodule "plugins/gravatar_provider"]
  26 + path = plugins/gravatar_provider
  27 + url = https://gitlab.com/noosfero-plugins/gravatar-provider.git
  28 +[submodule "plugins/juventude"]
  29 + path = plugins/juventude
  30 + url = https://gitlab.com/noosfero-plugins/juventude.git
  31 +[submodule "plugins/dialoga"]
  32 + path = plugins/dialoga
  33 + url = https://gitlab.com/participa/dialoga-plugin.git
  34 +[submodule "rest-clients/confjuvapp"]
  35 + path = rest-clients/confjuvapp
  36 + url = https://gitlab.com/participa/confjuvapp.git
  37 +[submodule "rest-clients/proposal-app"]
  38 + path = rest-clients/proposal-app
  39 + url = https://gitlab.com/participa/proposal-app.git
.travis.yml 0 → 100644
@@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
  1 +language: ruby
  2 +rvm:
  3 +# for 2.2 support we need to upgrade the pg gem
  4 + - 2.1.6
  5 +
  6 +sudo: false
  7 +addons:
  8 + apt:
  9 + packages:
  10 + - po4a
  11 + - iso-codes
  12 + - tango-icon-theme
  13 + - pidgin-data
  14 + # for gem extensions
  15 + - libmagickwand-dev
  16 + - libpq-dev
  17 + - libreadline-dev
  18 + - libsqlite3-dev
  19 + - libxslt1-dev
  20 +
  21 +before_install:
  22 + - gem env
  23 +
  24 +# workaround for https://github.com/travis-ci/travis-ci/issues/4536
  25 +before_install:
  26 + - export GEM_HOME=$PWD/vendor/bundle/ruby/2.1.0
  27 + - gem install bundler
  28 +cache: bundler
  29 +
  30 +before_script:
  31 + - mkdir -p tmp/pids log
  32 +# workaround for plugins with Gemfile
  33 + - perl -pi -e 's/cat .+ > \$gemfile/echo "source \\"https:\/\/rubygems.org\\"" > \$gemfile && cat \$source\/Gemfile >> \$gemfile/' script/noosfero-plugins
  34 + - perl -pi -e 's/--local --quiet/install --jobs=3 --retry=3/' script/noosfero-plugins
  35 + - script/noosfero-plugins disableall
  36 + - bundle exec rake makemo &>/dev/null
  37 +# database
  38 + - cp config/database.yml.travis config/database.yml
  39 + - psql -c 'create database myapp_test;' -U postgres
  40 + - bundle exec rake db:schema:load &>/dev/null
  41 + - bundle exec rake db:migrate &>/dev/null
  42 +
  43 +env:
  44 + - TASK=test:units
  45 + - TASK=test:functionals
  46 + - TASK=test:integration
  47 + - TASK=cucumber
  48 + - TASK=selenium
  49 + - TASK=test:noosfero_plugins
  50 +
  51 +script:
  52 + - bundle exec rake $TASK
  53 +
  1 +This list is automatically generated at release time. Please do not change it.
  2 +
1 If you are not listed here, but should be, please write to the noosfero mailing 3 If you are not listed here, but should be, please write to the noosfero mailing
2 list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev 4 list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev
3 (this list requires subscription to post, but since you are an author of 5 (this list requires subscription to post, but since you are an author of
@@ -8,256 +10,120 @@ Developers @@ -8,256 +10,120 @@ Developers
8 10
9 Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br> 11 Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>
10 Alan Freihof Tygel <alantygel@gmail.com> 12 Alan Freihof Tygel <alantygel@gmail.com>
11 -alcampelo <alcampelo@alcampelo.(none)>  
12 Alessandro Palmeira <alessandro.palmeira@gmail.com> 13 Alessandro Palmeira <alessandro.palmeira@gmail.com>
13 -Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com>  
14 -Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com>  
15 -Alessandro Palmeira + Caio Salgado <caio.csalgado@gmail.com>  
16 -Alessandro Palmeira + Caio Salgado + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
17 -Alessandro Palmeira + Carlos Morais <alessandro.palmeira@gmail.com>  
18 -Alessandro Palmeira + Daniel Alves <alessandro.palmeira@gmail.com>  
19 -Alessandro Palmeira + Daniel Alves + Diego Araújo <diegoamc90@gmail.com>  
20 -Alessandro Palmeira + Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>  
21 -Alessandro Palmeira + Diego Araujo <alessandro.palmeira@gmail.com>  
22 -Alessandro Palmeira + Diego Araújo <alessandro.palmeira@gmail.com>  
23 -Alessandro Palmeira + Diego Araujo + Daniela Feitosa <alessandro.palmeira@gmail.com>  
24 -Alessandro Palmeira + Diego Araujo <diegoamc90@gmail.com>  
25 -Alessandro Palmeira + Diego Araújo <diegoamc90@gmail.com>  
26 -Alessandro Palmeira + Diego Araujo + Eduardo Morais <alessandro.palmeira@gmail.com>  
27 -Alessandro Palmeira + Diego Araújo + João M. M. da Silva <alessandro.palmeira@gmail.com>  
28 -Alessandro Palmeira + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
29 -Alessandro Palmeira + Diego Araujo + João M. M. da Silva + Paulo Meirelles <alessandro.palmeira@gmail.com>  
30 -Alessandro Palmeira + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
31 -Alessandro Palmeira + Diego Araújo + Pedro Leal + João M. M. da Silva <diegoamc90@gmail.com>  
32 -Alessandro Palmeira + Diego Araujo + Rafael Manzo <alessandro.palmeira@gmail.com>  
33 -Alessandro Palmeira + Eduardo Morais <alessandro.palmeira@gmail.com>  
34 -Alessandro Palmeira + Guilherme Rojas <alessandro.palmeira@gmail.com>  
35 -Alessandro Palmeira + Jefferson Fernandes <alessandro.palmeira@gmail.com>  
36 -Alessandro Palmeira + João M. M. da Silva <alessandro.palmeira@gmail.com>  
37 -Alessandro Palmeira + Joao M. M. da Silva + Diego Araujo <alessandro.palmeira@gmail.com>  
38 -Alessandro Palmeira + João M. M. da Silva + Renan Teruo <alessandro.palmeira@gmail.com>  
39 -Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com>  
40 -Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>  
41 -Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>  
42 -Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>  
43 -analosnak <analosnak@gmail.com> 14 +Alex Campelo <campelo.al1@gmail.com>
  15 +Álvaro Fernando <alvarofernandoms@gmail.com>
44 Ana Losnak <analosnak@gmail.com> 16 Ana Losnak <analosnak@gmail.com>
45 -Andre Bernardes <andrebsguedes@gmail.com>  
46 -Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>  
47 -Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> 17 +Ana Paula Vargas <anapaulavnoronha@gmail.com>
  18 +Andre Bedran <bedran.fleck@gmail.com>
  19 +André Guedes <andrebsguedes@gmail.com>
  20 +Andrey Aleksanyants <aaleksanyants@yahoo.com>
48 Antonio Terceiro <terceiro@colivre.coop.br> 21 Antonio Terceiro <terceiro@colivre.coop.br>
49 Arthur Del Esposte <arthurmde@gmail.com> 22 Arthur Del Esposte <arthurmde@gmail.com>
50 -Arthur Del Esposte <arthurmde@yahoo.com.br> 23 +Athos Ribeiro <athoscribeiro@gmail.com>
51 Aurelio A. Heckert <aurelio@colivre.coop.br> 24 Aurelio A. Heckert <aurelio@colivre.coop.br>
52 -Braulio Bhavamitra <brauliobo@gmail.com>  
53 -Bráulio Bhavamitra <brauliobo@gmail.com>  
54 Braulio Bhavamitra <braulio@eita.org.br> 25 Braulio Bhavamitra <braulio@eita.org.br>
55 -Caio <caio.csalgado@gmail.com>  
56 -Caio + Diego + Pedro + João <caio.csalgado@gmail.com> 26 +Brenddon Gontijo <brenddongontijo@msn.com>
57 Caio Formiga <caio.formiga@gmail.com> 27 Caio Formiga <caio.formiga@gmail.com>
58 -Caio, Pedro <caio.csalgado@gmail.com>  
59 -Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com>  
60 Caio Salgado <caio.csalgado@gmail.com> 28 Caio Salgado <caio.csalgado@gmail.com>
61 -Caio Salgado + Carlos Morais + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
62 -Caio Salgado + Diego Araujo <caio.csalgado@gmail.com>  
63 -Caio Salgado + Diego Araújo <caio.csalgado@gmail.com>  
64 -Caio Salgado + Diego Araújo <diegoamc90@gmail.com>  
65 -Caio Salgado + Diego Araújo + Jefferson Fernandes <caio.csalgado@gmail.com>  
66 -Caio Salgado + Diego Araújo + João M. M. da Silva <caio.csalgado@gmail.com>  
67 -Caio Salgado + Diego Araújo + Pedro Leal <caio.csalgado@gmail.com>  
68 -Caio Salgado + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
69 -Caio Salgado + Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>  
70 -Caio Salgado + Jefferson Fernandes <caio.csalgado@gmail.com>  
71 -Caio Salgado + Jefferson Fernandes <jeffs.fernandes@gmail.com>  
72 -Caio Salgado + Rafael Manzo <caio.csalgado@gmail.com>  
73 -Caio Salgado + Renan Teruo <caio.csalgado@gmail.com>  
74 -Caio Salgado + Renan Teruo <caio.salgado@gmail.com>  
75 -Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com>  
76 -Caio Salgado + Renan Teruo <renanteruoc@gmail.com>  
77 Caio SBA <caio@colivre.coop.br> 29 Caio SBA <caio@colivre.coop.br>
78 Caio Tiago Oliveira <caiotiago@colivre.coop.br> 30 Caio Tiago Oliveira <caiotiago@colivre.coop.br>
79 Carlos Andre de Souza <carlos.andre.souza@msn.com> 31 Carlos Andre de Souza <carlos.andre.souza@msn.com>
80 Carlos Morais <carlos88morais@gmail.com> 32 Carlos Morais <carlos88morais@gmail.com>
81 -Carlos Morais + Diego Araújo <diegoamc90@gmail.com>  
82 -Carlos Morais + Eduardo Morais <carlos88morais@gmail.com>  
83 -Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com>  
84 -Carlos Morais + Pedro Leal <carlos88morais@gmail.com>  
85 -Daniel Alves + Diego Araújo <danpaulalves@gmail.com>  
86 -Daniel Alves + Diego Araújo <diegoamc90@gmail.com>  
87 -Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>  
88 -Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>  
89 -Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com>  
90 -Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com>  
91 -Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> 33 +Christophe DANIEL <papaeng@gmail.com>
  34 +Daniela Feitosa <alessandro.palmeira@gmail.com>
  35 +Daniel Alves <danpaulalves@gmail.com>
92 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> 36 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
93 Daniel Bucher <daniel.bucher88@gmail.com> 37 Daniel Bucher <daniel.bucher88@gmail.com>
94 Daniel Cunha <daniel@colivre.coop.br> 38 Daniel Cunha <daniel@colivre.coop.br>
  39 +Daniel Tygel <dtygel@eita.org.br>
95 David Carlos <ddavidcarlos1392@gmail.com> 40 David Carlos <ddavidcarlos1392@gmail.com>
96 -diegoamc <diegoamc90@gmail.com>  
97 -Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>  
98 -Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com>  
99 -Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com>  
100 -Diego Araujo + Caio Salgado <diegoamc90@gmail.com>  
101 -Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>  
102 -Diego Araújo <diegoamc90@gmail.com>  
103 -Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com>  
104 -Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>  
105 -Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com>  
106 -Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com>  
107 -Diego Araújo + João Machini <diegoamc90@gmail.com>  
108 -Diego Araújo + João Machini <digoamc90@gmail.com>  
109 -Diego Araújo + João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
110 -Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
111 -Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com>  
112 -Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com>  
113 -Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com>  
114 -Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
115 -Diego Araujo + Rafael Manzo <diegoamc90@gmail.com>  
116 -Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>  
117 -Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com>  
118 -Diego Araújo + Renan Teruo <diegoamc90@gmail.com>  
119 -Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>  
120 -Diego + Jefferson <diegoamc90@gmail.com>  
121 -Diego Martinez <diegoamc90@gmail.com>  
122 -Diego + Renan <renanteruoc@gmail.com>  
123 -DylanGuedes <djmgguedes@gmail.com>  
124 -Eduardo Passos <eduardo@risa.localdomain.localhost> 41 +Diego Araujo <diegoamc90@gmail.com>
  42 +Dylan Guedes <djmgguedes@gmail.com>
  43 +Eduardo Morais
125 Eduardo Passos <eduardosteps@gmail.com> 44 Eduardo Passos <eduardosteps@gmail.com>
126 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> 45 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
127 -Evandro Jr <evandrojr@gmail.com>  
128 -Evandro Junior <evandrojr@gmail.com> 46 +Eduardo Vital <vitaldu@gmail.com>
  47 +Evandro Magalhaes Leite Junior <evandro.leite@serpro.gov.br>
129 Fabio Teixeira <fabio1079@gmail.com> 48 Fabio Teixeira <fabio1079@gmail.com>
130 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com> 49 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com>
131 Fernanda Lopes <nanda.listas+psl@gmail.com> 50 Fernanda Lopes <nanda.listas+psl@gmail.com>
132 -Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br>  
133 -Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> 51 +Filipe Ribeiro <firibeiro77@live.com>
134 Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br> 52 Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br>
135 -Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com>  
136 Gabriela Navarro <navarro1703@gmail.com> 53 Gabriela Navarro <navarro1703@gmail.com>
137 Gonzalo Exequiel Pedone <hipersayan.x@gmail.com> 54 Gonzalo Exequiel Pedone <hipersayan.x@gmail.com>
138 Grazieno Pellegrino <grazieno@gmail.com> 55 Grazieno Pellegrino <grazieno@gmail.com>
139 -Gust <darksshades@hotmail.com> 56 +Guilherme C. Muniz <guilherme.cmuniz@gmail.com>
  57 +Guilherme Rojas <guilhermehrojas@gmail.com>
  58 +Gustavo Jaruga <darksshades@gmail.com>
140 Hebert Douglas <hebertdougl@gmail.com> 59 Hebert Douglas <hebertdougl@gmail.com>
141 Hugo Melo <hugo@riseup.net> 60 Hugo Melo <hugo@riseup.net>
  61 +Iolane Andrade <andrade.icaa@gmail.com>
142 Isaac Canan <isaac@intelletto.com.br> 62 Isaac Canan <isaac@intelletto.com.br>
143 Italo Valcy <italo@dcc.ufba.br> 63 Italo Valcy <italo@dcc.ufba.br>
144 -Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com>  
145 -Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com>  
146 -Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com>  
147 -João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com>  
148 -João da Silva <jaodsilv@linux.ime.usp.br>  
149 -João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br>  
150 -João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br>  
151 -João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br>  
152 -Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
153 -João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
154 -João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br>  
155 -João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
156 -João M. M. da Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>  
157 -João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br>  
158 -João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com>  
159 -João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>  
160 -João M. M. da Silva + Diego Araújo + Pedro Leal <jaodsilv@linux.ime.usp.br> 64 +Jefferson Fernandes <jeffs.fernandes@gmail.com>
  65 +Jérôme Jutteau <j.jutteau@gmail.com>
  66 +João Machini
161 João M. M. da Silva <jaodsilv@linux.ime.usp.br> 67 João M. M. da Silva <jaodsilv@linux.ime.usp.br>
162 -Joao M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
163 -João M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
164 -João M. M. da Silva + João M. Miranda <jaodsilv@linux.ime.usp.br>  
165 -João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>  
166 -João M. M. da Silva + Pedro Leal <jaodsilv@linux.ime.usp.br>  
167 -João M. M. da Silva + Rafael Manzo + Diego Araújo <jaodsilv@linux.ime.usp.br>  
168 -João M. M. da Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>  
169 -João M. M. da Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>  
170 -João M. M. Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>  
171 -João M. M. Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>  
172 -Joao M. M. Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
173 -João M. M. Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>  
174 -João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>  
175 -João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>  
176 Joenio Costa <joenio@colivre.coop.br> 68 Joenio Costa <joenio@colivre.coop.br>
177 Josef Spillner <josef.spillner@tu-dresden.de> 69 Josef Spillner <josef.spillner@tu-dresden.de>
178 Jose Pedro <1jpsneto@gmail.com> 70 Jose Pedro <1jpsneto@gmail.com>
179 -Junior Silva <junior@bajor.localhost.localdomain>  
180 -Junior Silva <junior@sedeantigo.colivre.coop.br>  
181 Junior Silva <juniorsilva1001@gmail.com> 71 Junior Silva <juniorsilva1001@gmail.com>
182 -Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)>  
183 -Junior Silva <juniorsilva@colivre.coop.br>  
184 -juniorsilva <juniorsilva@QonoS.localhost.localdomain>  
185 Keilla Menezes <keilla@colivre.coop.br> 72 Keilla Menezes <keilla@colivre.coop.br>
186 Larissa Reis <larissa@colivre.coop.br> 73 Larissa Reis <larissa@colivre.coop.br>
187 -Larissa Reis <reiss.larissa@gmail.com>  
188 Leandro Alves <leandrosustenido@gmail.com> 74 Leandro Alves <leandrosustenido@gmail.com>
189 -Leandro Nunes dos Santos <81665687568@serpro-1541727.Home>  
190 -Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)>  
191 -Leandro Nunes dos Santos <leandronunes@gmail.com>  
192 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> 75 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br>
  76 +Leandro Veloso <leandrovelosorodrigues@gmail.com>
193 LinguÁgil 2010 <linguagil.bahia@gmail.com> 77 LinguÁgil 2010 <linguagil.bahia@gmail.com>
  78 +Lucas Couto <loc.unb@gmail.com>
194 Lucas Kanashiro <kanashiro.duarte@gmail.com> 79 Lucas Kanashiro <kanashiro.duarte@gmail.com>
195 -Lucas Melo <lucas@colivre.coop.br>  
196 Lucas Melo <lucaspradomelo@gmail.com> 80 Lucas Melo <lucaspradomelo@gmail.com>
197 -Luciano <lucianopcbr@gmail.com>  
198 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com> 81 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com>
199 Luis David Aguilar Carlos <ludwig9003@gmail.com> 82 Luis David Aguilar Carlos <ludwig9003@gmail.com>
200 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> 83 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com>
201 -Marcos <marcos.rpj2@gmail.com> 84 +Luiz Matos <luizff.matos@gmail.com>
202 Marcos Ramos <ms.ramos@outlook.com> 85 Marcos Ramos <ms.ramos@outlook.com>
  86 +Marcos Ronaldo <marcos.rpj2@gmail.com>
  87 +Mariel Zasso <noosfero-br@listas.softwarelivre.org>
203 Martín Olivera <molivera@solar.org.ar> 88 Martín Olivera <molivera@solar.org.ar>
  89 +Matheus Faria <matheus.sousa.faria@gmail.com>
204 Maurilio Atila <cabelotaina@gmail.com> 90 Maurilio Atila <cabelotaina@gmail.com>
205 M for Momo <mo@rtnp.org> 91 M for Momo <mo@rtnp.org>
206 Michal Čihař <michal@cihar.com> 92 Michal Čihař <michal@cihar.com>
  93 +Michel Felipe <mfelipeof@gmail.com>
207 Moises Machado <moises@colivre.coop.br> 94 Moises Machado <moises@colivre.coop.br>
208 Naíla Alves <naila@colivre.coop.br> 95 Naíla Alves <naila@colivre.coop.br>
209 Nanda Lopes <nanda.listas+psl@gmail.com> 96 Nanda Lopes <nanda.listas+psl@gmail.com>
210 Niemand Jedermann <predatorix@web.de> 97 Niemand Jedermann <predatorix@web.de>
211 Parley Martins <parleypachecomartins@gmail.com> 98 Parley Martins <parleypachecomartins@gmail.com>
212 -Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>  
213 -Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>  
214 -Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>  
215 -Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org>  
216 -Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org>  
217 Paulo Meirelles <paulo@softwarelivre.org> 99 Paulo Meirelles <paulo@softwarelivre.org>
218 -Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org> 100 +Pedro de Lyra <pedrodelyra@gmail.com>
  101 +Pedro Leal
  102 +Rafael de Souza Queiroz <querafael@live.com>
219 Rafael Gomes <rafaelgomes@techfree.com.br> 103 Rafael Gomes <rafaelgomes@techfree.com.br>
220 -Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com>  
221 -Rafael Manzo + Daniel Alves <danpaulalves@gmail.com>  
222 -Rafael Manzo + Diego Araújo <rr.manzo@gmail.com>  
223 -Rafael Manzo + João M. M. Silva <rr.manzo@gmail.com>  
224 -Rafael Manzo + Paulo Meirelles <rr.manzo@gmail.com>  
225 Rafael Martins <rmmartins@gmail.com> 104 Rafael Martins <rmmartins@gmail.com>
226 -Rafael Reggiani Manzo + Caio Salgado + Jefferson Fernandes <rr.manzo@gmail.com>  
227 -Rafael Reggiani Manzo + Diego Araujo <diegoamc90@gmail.com>  
228 -Rafael Reggiani Manzo + Diego Araujo <rr.manzo@gmail.com>  
229 -Rafael Reggiani Manzo + Diego Araújo <rr.manzo@gmail.com>  
230 -Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com>  
231 Rafael Reggiani Manzo <rr.manzo@gmail.com> 105 Rafael Reggiani Manzo <rr.manzo@gmail.com>
232 Raphaël Rousseau <raph@r4f.org> 106 Raphaël Rousseau <raph@r4f.org>
233 Raquel Lira <raquel.lira@gmail.com> 107 Raquel Lira <raquel.lira@gmail.com>
234 Raquel <rcordioli@gmail.com> 108 Raquel <rcordioli@gmail.com>
235 -Renan Teruo + Caio Salgado <renanteruoc@gmail.com>  
236 -Renan Teruoc + Diego Araujo <renanteruoc@gmail.com>  
237 -Renan Teruo + Diego Araujo <renanteruoc@gmail.com>  
238 -Renan Teruo + Diego Araújo <renanteruoc@gmail.com>  
239 -Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>  
240 -Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>  
241 -Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org> 109 +Renan Costa <renan2727@hotmail.com>
  110 +Renan Teruo <renanteruoc@gmail.com>
  111 +Rodrigo Medeiros <rodrigo.mss01@gmail.com>
242 Rodrigo Souto <rodrigo@colivre.coop.br> 112 Rodrigo Souto <rodrigo@colivre.coop.br>
243 Ronny Kursawe <kursawe.ronny@googlemail.com> 113 Ronny Kursawe <kursawe.ronny@googlemail.com>
244 -root <root@debian.sdr.serpro>  
245 Samuel R. C. Vale <srcvale@holoscopio.com> 114 Samuel R. C. Vale <srcvale@holoscopio.com>
246 -Tallys Martins <tallysmartins@gmail.com>  
247 Tallys Martins <tallysmartins@yahoo.com.br> 115 Tallys Martins <tallysmartins@yahoo.com.br>
248 -tallys <tallys@tallys>  
249 -tallys <tallys@tallys.(none)> 116 +Thiago Casotti <thiago.casotti@uol.com.br>
  117 +Thiago Kairala <thiagor.kairala@gmail.com>
  118 +Thiago Ribeiro <thiagitosouza@hotmail.com>
250 Thiago Zoroastro <thiago.zoroastro@bol.com.br> 119 Thiago Zoroastro <thiago.zoroastro@bol.com.br>
251 Tuux <tuxa@galaxie.eu.org> 120 Tuux <tuxa@galaxie.eu.org>
  121 +TWS <tablettws@gmail.com>
252 Valessio Brito <contato@valessiobrito.com.br> 122 Valessio Brito <contato@valessiobrito.com.br>
253 -Valessio Brito <contato@valessiobrito.info>  
254 -Valessio Brito <valessio@gmail.com>  
255 -vfcosta <vfcosta@gmail.com>  
256 -Victor Carvalho <victorhugodf.ac@gmail.com>  
257 Victor Costa <vfcosta@gmail.com> 123 Victor Costa <vfcosta@gmail.com>
258 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com> 124 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>
259 Vinicius Cubas Brand <viniciuscb@gmail.com> 125 Vinicius Cubas Brand <viniciuscb@gmail.com>
260 -Visita <visita@debian.(none)> 126 +Wilton Rodrigues <braynwilton@gmail.com>
261 Yann Lugrin <yann.lugrin@liquid-concept.ch> 127 Yann Lugrin <yann.lugrin@liquid-concept.ch>
262 128
263 Ideas, specifications and incentive 129 Ideas, specifications and incentive
1 source "https://rubygems.org" 1 source "https://rubygems.org"
2 -gem 'rails', '~> 3.2.21' 2 +gem 'rails', '~> 3.2.22'
3 gem 'minitest', '~> 3.2.0' 3 gem 'minitest', '~> 3.2.0'
4 gem 'fast_gettext', '~> 0.6.8' 4 gem 'fast_gettext', '~> 0.6.8'
5 gem 'acts-as-taggable-on', '~> 3.4.2' 5 gem 'acts-as-taggable-on', '~> 3.4.2'
@@ -11,27 +11,46 @@ gem &#39;will_paginate&#39;, &#39;~&gt; 3.0.3&#39; @@ -11,27 +11,46 @@ gem &#39;will_paginate&#39;, &#39;~&gt; 3.0.3&#39;
11 gem 'ruby-feedparser', '~> 0.7' 11 gem 'ruby-feedparser', '~> 0.7'
12 gem 'daemons', '~> 1.1.5' 12 gem 'daemons', '~> 1.1.5'
13 gem 'thin', '~> 1.3.1' 13 gem 'thin', '~> 1.3.1'
14 -gem 'nokogiri', '~> 1.5.5' 14 +gem 'nokogiri', '~> 1.6.0'
15 gem 'rake', :require => false 15 gem 'rake', :require => false
16 gem 'rest-client', '~> 1.6.7' 16 gem 'rest-client', '~> 1.6.7'
17 gem 'exception_notification', '~> 4.0.1' 17 gem 'exception_notification', '~> 4.0.1'
18 gem 'gettext', '~> 2.2.1', :require => false 18 gem 'gettext', '~> 2.2.1', :require => false
19 gem 'locale', '~> 2.0.5' 19 gem 'locale', '~> 2.0.5'
20 gem 'whenever', :require => false 20 gem 'whenever', :require => false
21 -gem 'eita-jrails', '>= 0.9.5', :require => 'jrails' 21 +gem 'eita-jrails', '~> 0.9.5', require: 'jrails'
22 22
23 -group :assets do  
24 - gem 'uglifier', '>= 1.0.3'  
25 - gem 'sass-rails'  
26 -end 23 +# API dependencies
  24 +gem 'grape', '~> 0.12'
  25 +gem 'grape-entity'
  26 +#FIXME Get the Grape Loggin from master yo solve this issue https://github.com/intridea/grape/issues/1059
  27 +#We have to remove this commit referenve code when update the next release of grape_logging. Actualy we are using (1.1.2)
  28 +gem 'grape_logging', :git => 'https://github.com/aceunreal/grape_logging.git', :ref => 'f1755ae'
  29 +gem 'rack-cors'
  30 +gem 'rack-contrib'
  31 +gem 'liquid', '~> 3.0.3'
  32 +#gem 'grape-swagger-rails'
  33 +gem 'rubyzip'
  34 +
  35 +gem 'execjs'
  36 +gem 'therubyracer'
  37 +
  38 +# FIXME list here all actual dependencies (i.e. the ones in debian/control),
  39 +# with their GEM names (not the Debian package names)
  40 +
  41 +gem 'api-pagination', '~> 4.1.1'
  42 +
  43 +# asset pipeline
  44 +gem 'uglifier', '>= 1.0.3'
  45 +gem 'sass-rails'
27 46
28 group :production do 47 group :production do
29 gem 'dalli', '~> 2.7.0' 48 gem 'dalli', '~> 2.7.0'
30 end 49 end
31 50
32 group :test do 51 group :test do
33 - gem 'rspec', '~> 2.10.0'  
34 - gem 'rspec-rails', '~> 2.10.1' 52 + gem 'rspec', '~> 2.14.0'
  53 + gem 'rspec-rails', '~> 2.14.1'
35 gem 'mocha', '~> 1.1.0', :require => false 54 gem 'mocha', '~> 1.1.0', :require => false
36 end 55 end
37 56
Gemfile.lock 0 → 100644
@@ -0,0 +1,281 @@ @@ -0,0 +1,281 @@
  1 +GIT
  2 + remote: https://github.com/aceunreal/grape_logging.git
  3 + revision: f1755ae4e1d897a65b20218d40681f59a9630f1b
  4 + ref: f1755ae
  5 + specs:
  6 + grape_logging (1.1.2)
  7 + grape
  8 +
  9 +GEM
  10 + remote: https://rubygems.org/
  11 + specs:
  12 + RedCloth (4.2.9)
  13 + actionmailer (3.2.22)
  14 + actionpack (= 3.2.22)
  15 + mail (~> 2.5.4)
  16 + actionpack (3.2.22)
  17 + activemodel (= 3.2.22)
  18 + activesupport (= 3.2.22)
  19 + builder (~> 3.0.0)
  20 + erubis (~> 2.7.0)
  21 + journey (~> 1.0.4)
  22 + rack (~> 1.4.5)
  23 + rack-cache (~> 1.2)
  24 + rack-test (~> 0.6.1)
  25 + sprockets (~> 2.2.1)
  26 + activemodel (3.2.22)
  27 + activesupport (= 3.2.22)
  28 + builder (~> 3.0.0)
  29 + activerecord (3.2.22)
  30 + activemodel (= 3.2.22)
  31 + activesupport (= 3.2.22)
  32 + arel (~> 3.0.2)
  33 + tzinfo (~> 0.3.29)
  34 + activeresource (3.2.22)
  35 + activemodel (= 3.2.22)
  36 + activesupport (= 3.2.22)
  37 + activesupport (3.2.22)
  38 + i18n (~> 0.6, >= 0.6.4)
  39 + multi_json (~> 1.0)
  40 + acts-as-taggable-on (3.4.4)
  41 + activerecord (>= 3.2, < 5)
  42 + api-pagination (4.1.1)
  43 + arel (3.0.3)
  44 + axiom-types (0.1.1)
  45 + descendants_tracker (~> 0.0.4)
  46 + ice_nine (~> 0.11.0)
  47 + thread_safe (~> 0.3, >= 0.3.1)
  48 + builder (3.0.4)
  49 + capybara (2.1.0)
  50 + mime-types (>= 1.16)
  51 + nokogiri (>= 1.3.3)
  52 + rack (>= 1.0.0)
  53 + rack-test (>= 0.5.4)
  54 + xpath (~> 2.0)
  55 + childprocess (0.5.6)
  56 + ffi (~> 1.0, >= 1.0.11)
  57 + chronic (0.10.2)
  58 + coercible (1.0.0)
  59 + descendants_tracker (~> 0.0.1)
  60 + cucumber (1.0.6)
  61 + builder (>= 2.1.2)
  62 + diff-lcs (>= 1.1.2)
  63 + gherkin (~> 2.4.18)
  64 + json (>= 1.4.6)
  65 + term-ansicolor (>= 1.0.6)
  66 + cucumber-rails (1.0.6)
  67 + capybara (>= 1.1.1)
  68 + cucumber (>= 1.0.6)
  69 + nokogiri (>= 1.5.0)
  70 + daemons (1.1.9)
  71 + dalli (2.7.4)
  72 + database_cleaner (1.2.0)
  73 + descendants_tracker (0.0.4)
  74 + thread_safe (~> 0.3, >= 0.3.1)
  75 + diff-lcs (1.2.5)
  76 + eita-jrails (0.9.5)
  77 + actionpack (~> 3.2, >= 3.1.0)
  78 + activesupport (~> 3.2, >= 3.0.0)
  79 + equalizer (0.0.11)
  80 + erubis (2.7.0)
  81 + eventmachine (1.0.7)
  82 + exception_notification (4.0.1)
  83 + actionmailer (>= 3.0.4)
  84 + activesupport (>= 3.0.4)
  85 + execjs (2.5.2)
  86 + fast_gettext (0.6.12)
  87 + ffi (1.9.10)
  88 + gettext (2.2.1)
  89 + locale
  90 + gherkin (2.4.21)
  91 + json (>= 1.4.6)
  92 + git-version-bump (0.15.1)
  93 + grape (0.12.0)
  94 + activesupport
  95 + builder
  96 + hashie (>= 2.1.0)
  97 + multi_json (>= 1.3.2)
  98 + multi_xml (>= 0.5.2)
  99 + rack (>= 1.3.0)
  100 + rack-accept
  101 + rack-mount
  102 + virtus (>= 1.0.0)
  103 + grape-entity (0.4.5)
  104 + activesupport
  105 + multi_json (>= 1.3.2)
  106 + hashie (2.1.2)
  107 + hike (1.2.3)
  108 + i18n (0.7.0)
  109 + ice_nine (0.11.1)
  110 + journey (1.0.4)
  111 + json (1.8.3)
  112 + libv8 (3.16.14.11)
  113 + liquid (3.0.6)
  114 + locale (2.0.9)
  115 + magic (0.2.9)
  116 + ffi (>= 0.6.3)
  117 + mail (2.5.4)
  118 + mime-types (~> 1.16)
  119 + treetop (~> 1.4.8)
  120 + metaclass (0.0.4)
  121 + mime-types (1.25.1)
  122 + mini_portile (0.6.2)
  123 + minitest (3.2.0)
  124 + mocha (1.1.0)
  125 + metaclass (~> 0.0.1)
  126 + multi_json (1.11.2)
  127 + multi_xml (0.5.5)
  128 + nokogiri (1.6.6.2)
  129 + mini_portile (~> 0.6.0)
  130 + pg (0.13.2)
  131 + polyglot (0.3.5)
  132 + rack (1.4.7)
  133 + rack-accept (0.4.5)
  134 + rack (>= 0.4)
  135 + rack-cache (1.2)
  136 + rack (>= 0.4)
  137 + rack-contrib (1.3.0)
  138 + git-version-bump (~> 0.15)
  139 + rack (~> 1.4)
  140 + rack-cors (0.4.0)
  141 + rack-mount (0.8.3)
  142 + rack (>= 1.0.0)
  143 + rack-ssl (1.3.4)
  144 + rack
  145 + rack-test (0.6.3)
  146 + rack (>= 1.0)
  147 + rails (3.2.22)
  148 + actionmailer (= 3.2.22)
  149 + actionpack (= 3.2.22)
  150 + activerecord (= 3.2.22)
  151 + activeresource (= 3.2.22)
  152 + activesupport (= 3.2.22)
  153 + bundler (~> 1.0)
  154 + railties (= 3.2.22)
  155 + rails_autolink (1.1.6)
  156 + rails (> 3.1)
  157 + railties (3.2.22)
  158 + actionpack (= 3.2.22)
  159 + activesupport (= 3.2.22)
  160 + rack-ssl (~> 1.3.2)
  161 + rake (>= 0.8.7)
  162 + rdoc (~> 3.4)
  163 + thor (>= 0.14.6, < 2.0)
  164 + rake (10.4.2)
  165 + rdoc (3.12.2)
  166 + json (~> 1.4)
  167 + ref (2.0.0)
  168 + rest-client (1.6.9)
  169 + mime-types (~> 1.16)
  170 + rmagick (2.13.4)
  171 + rspec (2.14.1)
  172 + rspec-core (~> 2.14.0)
  173 + rspec-expectations (~> 2.14.0)
  174 + rspec-mocks (~> 2.14.0)
  175 + rspec-core (2.14.8)
  176 + rspec-expectations (2.14.5)
  177 + diff-lcs (>= 1.1.3, < 2.0)
  178 + rspec-mocks (2.14.6)
  179 + rspec-rails (2.14.2)
  180 + actionpack (>= 3.0)
  181 + activemodel (>= 3.0)
  182 + activesupport (>= 3.0)
  183 + railties (>= 3.0)
  184 + rspec-core (~> 2.14.0)
  185 + rspec-expectations (~> 2.14.0)
  186 + rspec-mocks (~> 2.14.0)
  187 + ruby-feedparser (0.9.3)
  188 + magic
  189 + rubyzip (1.1.7)
  190 + sass (3.4.15)
  191 + sass-rails (3.2.6)
  192 + railties (~> 3.2.0)
  193 + sass (>= 3.1.10)
  194 + tilt (~> 1.3)
  195 + selenium-webdriver (2.39.0)
  196 + childprocess (>= 0.2.5)
  197 + multi_json (~> 1.0)
  198 + rubyzip (~> 1.0)
  199 + websocket (~> 1.0.4)
  200 + sprockets (2.2.3)
  201 + hike (~> 1.2)
  202 + multi_json (~> 1.0)
  203 + rack (~> 1.0)
  204 + tilt (~> 1.1, != 1.3.0)
  205 + term-ansicolor (1.3.2)
  206 + tins (~> 1.0)
  207 + therubyracer (0.12.2)
  208 + libv8 (~> 3.16.14.0)
  209 + ref
  210 + thin (1.3.1)
  211 + daemons (>= 1.0.9)
  212 + eventmachine (>= 0.12.6)
  213 + rack (>= 1.0.0)
  214 + thor (0.19.1)
  215 + thread_safe (0.3.5)
  216 + tilt (1.4.1)
  217 + tins (1.5.4)
  218 + treetop (1.4.15)
  219 + polyglot
  220 + polyglot (>= 0.3.1)
  221 + tzinfo (0.3.44)
  222 + uglifier (2.7.1)
  223 + execjs (>= 0.3.0)
  224 + json (>= 1.8.0)
  225 + virtus (1.0.5)
  226 + axiom-types (~> 0.1)
  227 + coercible (~> 1.0)
  228 + descendants_tracker (~> 0.0, >= 0.0.3)
  229 + equalizer (~> 0.0, >= 0.0.9)
  230 + websocket (1.0.7)
  231 + whenever (0.9.4)
  232 + chronic (>= 0.6.3)
  233 + will_paginate (3.0.7)
  234 + xpath (2.0.0)
  235 + nokogiri (~> 1.3)
  236 +
  237 +PLATFORMS
  238 + ruby
  239 +
  240 +DEPENDENCIES
  241 + RedCloth (~> 4.2.9)
  242 + acts-as-taggable-on (~> 3.4.2)
  243 + api-pagination (~> 4.1.1)
  244 + capybara (~> 2.1.0)
  245 + cucumber (~> 1.0.6)
  246 + cucumber-rails (~> 1.0.6)
  247 + daemons (~> 1.1.5)
  248 + dalli (~> 2.7.0)
  249 + database_cleaner (~> 1.2.0)
  250 + eita-jrails (~> 0.9.5)
  251 + exception_notification (~> 4.0.1)
  252 + execjs
  253 + fast_gettext (~> 0.6.8)
  254 + gettext (~> 2.2.1)
  255 + grape (~> 0.12)
  256 + grape-entity
  257 + grape_logging!
  258 + liquid (~> 3.0.3)
  259 + locale (~> 2.0.5)
  260 + minitest (~> 3.2.0)
  261 + mocha (~> 1.1.0)
  262 + nokogiri (~> 1.6.0)
  263 + pg (~> 0.13.2)
  264 + rack-contrib
  265 + rack-cors
  266 + rails (~> 3.2.22)
  267 + rails_autolink (~> 1.1.5)
  268 + rake
  269 + rest-client (~> 1.6.7)
  270 + rmagick (~> 2.13.1)
  271 + rspec (~> 2.14.0)
  272 + rspec-rails (~> 2.14.1)
  273 + ruby-feedparser (~> 0.7)
  274 + rubyzip
  275 + sass-rails
  276 + selenium-webdriver (~> 2.39.0)
  277 + therubyracer
  278 + thin (~> 1.3.1)
  279 + uglifier (>= 1.0.3)
  280 + whenever
  281 + will_paginate (~> 3.0.3)
INSTALL.chat.md
1 -XMPP/Chat Setup  
2 -=============== 1 +Automatic XMPP/Chat Setup
  2 +=========================
  3 +
  4 +Since Noosfero 1.2, the XMPP/Chat can be installed via `noosfero-chat` Debian
  5 +package. So you don't need to follow the manual instructions here if you
  6 +already have it installed on your system.
  7 +
  8 +But if you are going to install the `noosfero-chat` package on a system that
  9 +already has `noosfero` older 1.2 installed then you need to check if apache's
  10 +configuration file `/etc/apache2/sites-available/noosfero` has this line below:
  11 +
  12 + Include /usr/share/noosfero/util/chat/apache/xmpp.conf
  13 +
  14 +Manual XMPP/Chat Setup
  15 +======================
3 16
4 The samples of config file to configure a XMPP/BOSH server with ejabberd, 17 The samples of config file to configure a XMPP/BOSH server with ejabberd,
5 postgresql and apache2 can be found at util/chat directory. 18 postgresql and apache2 can be found at util/chat directory.
@@ -8,7 +21,7 @@ This setup supposes that you are using Noosfero installed via Debian package @@ -8,7 +21,7 @@ This setup supposes that you are using Noosfero installed via Debian package
8 in a production environment. 21 in a production environment.
9 22
10 Steps 23 Steps
11 -===== 24 +-----
12 25
13 This is a step-by-step guide to get a XMPP service working, in a Debian system. 26 This is a step-by-step guide to get a XMPP service working, in a Debian system.
14 27
@@ -144,15 +157,8 @@ You should see a page with a message like that: @@ -144,15 +157,8 @@ You should see a page with a message like that:
144 157
145 ## 9. Test chat session 158 ## 9. Test chat session
146 159
147 -Open Noosfero console and execute:  
148 -  
149 ->> environment = Environment.default  
150 ->> user = Person['guest']  
151 ->> password = user.user.crypted_password  
152 ->> login = user.jid  
153 ->> RubyBOSH.initialize_session(login, password, "http://#{environment.default_hostname}/http-bind", :wait => 30, :hold => 1, :window => 5  
154 -  
155 -If you have luck, should see something like that: 160 +Run `./script/noosfero-test-chat-session`. If you have luck, should see
  161 +something like that:
156 162
157 Ruby-BOSH - SEND 163 Ruby-BOSH - SEND
158 <body window="5" rid="60265" xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" to="vagrant-debian-squeeze.vagrantup.com" wait="30" xmpp:version="1.0" hold="1"/> 164 <body window="5" rid="60265" xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" to="vagrant-debian-squeeze.vagrantup.com" wait="30" xmpp:version="1.0" hold="1"/>
INSTALL.https.md
@@ -11,8 +11,8 @@ as below: @@ -11,8 +11,8 @@ as below:
11 11
12 # mkdir /etc/noosfero/ssl 12 # mkdir /etc/noosfero/ssl
13 # cd /etc/noosfero/ssl 13 # cd /etc/noosfero/ssl
14 - # openssl genrsa 1024 > noosfero.key  
15 - # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert 14 + # openssl genrsa 2048 > noosfero.key
  15 + # openssl req -new -x509 -sha256 -nodes -days $[10*365] -key noosfero.key > noosfero.cert
16 # cat noosfero.key noosfero.cert > noosfero.pem 16 # cat noosfero.key noosfero.cert > noosfero.pem
17 17
18 ## Web server configuration 18 ## Web server configuration
@@ -74,7 +74,7 @@ downloading from git @@ -74,7 +74,7 @@ downloading from git
74 74
75 Here we are cloning the noosfero repository from git. Note: you will need to install git before. 75 Here we are cloning the noosfero repository from git. Note: you will need to install git before.
76 76
77 - $ git clone git://gitorious.org/noosfero/noosfero.git current 77 + $ git clone https://gitlab.com/noosfero/noosfero.git current
78 $ cd current 78 $ cd current
79 $ git checkout -b stable origin/stable 79 $ git checkout -b stable origin/stable
80 80
@@ -15,4 +15,21 @@ Noosfero::Application.load_tasks @@ -15,4 +15,21 @@ Noosfero::Application.load_tasks
15 Dir.glob(pattern).sort 15 Dir.glob(pattern).sort
16 end.flatten.each do |taskfile| 16 end.flatten.each do |taskfile|
17 load taskfile 17 load taskfile
  18 +end
  19 +
  20 +# plugins' tasks
  21 +plugins_tasks = Dir.glob("config/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake").sort +
  22 + Dir.glob("config/plugins/*/vendor/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake").sort
  23 +plugins_tasks.each{ |ext| load ext }
  24 +
  25 +
  26 +desc "Print out grape routes"
  27 +task :grape_routes => :environment do
  28 + #require 'api/api.rb'
  29 + Noosfero::API::API.routes.each do |route|
  30 + puts route
  31 + method = route.route_method
  32 + path = route.route_path
  33 + puts " #{method} #{path}"
  34 + end
18 end 35 end
app/controllers/admin/admin_panel_controller.rb
@@ -71,22 +71,4 @@ class AdminPanelController &lt; AdminController @@ -71,22 +71,4 @@ class AdminPanelController &lt; AdminController
71 end 71 end
72 end 72 end
73 end 73 end
74 -  
75 - def manage_organizations_status  
76 - scope = environment.organizations  
77 - @filter = params[:filter] || 'any'  
78 - @title = "Organization profiles"  
79 - @title = @title+" - "+@filter if @filter != 'any'  
80 -  
81 - if @filter == 'enabled'  
82 - scope = scope.visible  
83 - elsif @filter == 'disabled'  
84 - scope = scope.disabled  
85 - end  
86 -  
87 - scope = scope.order('name ASC')  
88 -  
89 - @q = params[:q]  
90 - @collection = find_by_contents(:organizations, environment, scope, @q, {:per_page => 10, :page => params[:npage]})[:results]  
91 - end  
92 end 74 end
app/controllers/admin/environment_design_controller.rb
1 class EnvironmentDesignController < BoxOrganizerController 1 class EnvironmentDesignController < BoxOrganizerController
2 - 2 +
3 protect 'edit_environment_design', :environment 3 protect 'edit_environment_design', :environment
4 4
  5 + def filtered_available_blocks(blocks=nil)
  6 + filtered_available_blocks = []
  7 + blocks.each { |block| filtered_available_blocks << block unless @environment.disabled_blocks.include?(block.name) }
  8 + filtered_available_blocks
  9 + end
  10 +
5 def available_blocks 11 def available_blocks
6 @available_blocks ||= [ ArticleBlock, LoginBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] 12 @available_blocks ||= [ ArticleBlock, LoginBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
7 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) 13 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment)
8 end 14 end
9 15
  16 + def index
  17 + available_blocks
  18 + end
  19 +
10 end 20 end
app/controllers/admin/environment_email_templates_controller.rb 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +class EnvironmentEmailTemplatesController < EmailTemplatesController
  2 +
  3 + protect 'manage_email_templates', :environment
  4 +
  5 + protected
  6 +
  7 + def owner
  8 + environment
  9 + end
  10 +
  11 + before_filter :only => :index do
  12 + @back_to = url_for(:controller => :admin_panel)
  13 + end
  14 +
  15 +end
app/controllers/admin/features_controller.rb
1 class FeaturesController < AdminController 1 class FeaturesController < AdminController
  2 +
2 protect 'edit_environment_features', :environment 3 protect 'edit_environment_features', :environment
3 - 4 +
4 def index 5 def index
5 @features = Environment.available_features.sort_by{|k,v|v} 6 @features = Environment.available_features.sort_by{|k,v|v}
6 end 7 end
7 8
  9 + def manage_blocks
  10 + @blocks = [ ArticleBlock,
  11 + TagsBlock,
  12 + RecentDocumentsBlock,
  13 + ProfileInfoBlock,
  14 + LinkListBlock,
  15 + MyNetworkBlock,
  16 + FeedReaderBlock,
  17 + ProfileImageBlock,
  18 + LocationBlock,
  19 + SlideshowBlock,
  20 + ProfileSearchBlock,
  21 + HighlightsBlock,
  22 + FriendsBlock,
  23 + FavoriteEnterprisesBlock,
  24 + CommunitiesBlock,
  25 + EnterprisesBlock,
  26 + MembersBlock,
  27 + DisabledEnterpriseMessageBlock,
  28 + ProductCategoriesBlock,
  29 + FeaturedProductsBlock,
  30 + FansBlock,
  31 + ProductsBlock ]
  32 +
  33 + @blocks += plugins.dispatch(:extra_blocks)
  34 + @blocks.sort_by! { |block| block.name }
  35 + end
  36 +
8 post_only :update 37 post_only :update
9 def update 38 def update
10 if @environment.update_attributes(params[:environment]) 39 if @environment.update_attributes(params[:environment])
@@ -15,6 +44,17 @@ class FeaturesController &lt; AdminController @@ -15,6 +44,17 @@ class FeaturesController &lt; AdminController
15 end 44 end
16 end 45 end
17 46
  47 + post_only :update_blocks
  48 + def update_blocks
  49 + params[:environment].delete(:available_blocks)
  50 + if @environment.update_attributes(params[:environment])
  51 + session[:notice] = _('Blocks updated successfully.')
  52 + redirect_to :action => 'manage_blocks'
  53 + else
  54 + render :action => 'manage_blocks'
  55 + end
  56 + end
  57 +
18 def manage_fields 58 def manage_fields
19 @person_fields = Person.fields 59 @person_fields = Person.fields
20 @enterprise_fields = Enterprise.fields 60 @enterprise_fields = Enterprise.fields
app/controllers/admin/organizations_controller.rb 0 → 100644
@@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
  1 +class OrganizationsController < AdminController
  2 +
  3 + protect 'manage_environment_organizations', :environment
  4 +
  5 + def index
  6 + @filter = params[:filter] || 'any'
  7 + @title = _('Organization profiles')
  8 + @type = params[:type] || "any"
  9 + @types_filter = [[_('All'), 'any'], [_('Community'), 'Community'], [_('Enterprise'), 'Enterprise']]
  10 + @types_filter = @types_filter | @plugins.dispatch(:organization_types_filter_options)
  11 +
  12 + scope = @plugins.dispatch_first(:filter_manage_organization_scope, @type)
  13 + if scope.blank?
  14 + scope = environment.organizations
  15 + scope = scope.where(:type => @type) if @type != 'any'
  16 + end
  17 +
  18 + if @filter == 'enabled'
  19 + scope = scope.visible
  20 + elsif @filter == 'disabled'
  21 + scope = scope.disabled
  22 + end
  23 +
  24 + scope = scope.order('name ASC')
  25 +
  26 + @q = params[:q]
  27 + @collection = find_by_contents(:organizations, environment, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results]
  28 + end
  29 +
  30 + def activate
  31 + organization = environment.organizations.find(params[:id])
  32 + if organization.enable
  33 + render :text => (_('%s enabled') % organization.name).to_json
  34 + else
  35 + render :text => (_('%s could not be enabled') % organization.name).to_json
  36 + end
  37 + end
  38 +
  39 + def deactivate
  40 + organization = environment.organizations.find(params[:id])
  41 + if organization.disable
  42 + render :text => (_('%s disabled') % organization.name).to_json
  43 + else
  44 + render :text => (_('%s could not be disable') % organization.name).to_json
  45 + end
  46 + end
  47 +
  48 + def destroy
  49 + if request.post?
  50 + organization = environment.organizations.find(params[:id])
  51 + if organization && organization.destroy
  52 + render :text => (_('%s removed') % organization.name).to_json
  53 + else
  54 + render :text => (_('%s could not be removed') % organization.name).to_json
  55 + end
  56 + else
  57 + render :nothing => true
  58 + end
  59 + end
  60 +
  61 + private
  62 +
  63 + def per_page
  64 + 10
  65 + end
  66 +end
app/controllers/admin/role_controller.rb
@@ -2,7 +2,7 @@ class RoleController &lt; AdminController @@ -2,7 +2,7 @@ class RoleController &lt; AdminController
2 protect 'manage_environment_roles', :environment 2 protect 'manage_environment_roles', :environment
3 3
4 def index 4 def index
5 - @roles = environment.roles.find(:all) 5 + @roles = environment.roles.find(:all, :conditions => {:profile_id => nil})
6 end 6 end
7 7
8 def new 8 def new
app/controllers/application_controller.rb
@@ -7,8 +7,17 @@ class ApplicationController &lt; ActionController::Base @@ -7,8 +7,17 @@ class ApplicationController &lt; ActionController::Base
7 before_filter :detect_stuff_by_domain 7 before_filter :detect_stuff_by_domain
8 before_filter :init_noosfero_plugins 8 before_filter :init_noosfero_plugins
9 before_filter :allow_cross_domain_access 9 before_filter :allow_cross_domain_access
  10 +
  11 + before_filter :login_from_cookie
10 before_filter :login_required, :if => :private_environment? 12 before_filter :login_required, :if => :private_environment?
  13 +
11 before_filter :verify_members_whitelist, :if => [:private_environment?, :user] 14 before_filter :verify_members_whitelist, :if => [:private_environment?, :user]
  15 + before_filter :log_user
  16 +
  17 + def log_user
  18 + Rails.logger.info "Logged in: #{user.identifier}" if user
  19 + end
  20 + before_filter :redirect_to_current_user
12 21
13 def verify_members_whitelist 22 def verify_members_whitelist
14 render_access_denied unless user.is_admin? || environment.in_whitelist?(user) 23 render_access_denied unless user.is_admin? || environment.in_whitelist?(user)
@@ -71,8 +80,8 @@ class ApplicationController &lt; ActionController::Base @@ -71,8 +80,8 @@ class ApplicationController &lt; ActionController::Base
71 FastGettext.available_locales = environment.available_locales 80 FastGettext.available_locales = environment.available_locales
72 FastGettext.default_locale = environment.default_locale 81 FastGettext.default_locale = environment.default_locale
73 FastGettext.locale = (params[:lang] || session[:lang] || environment.default_locale || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en') 82 FastGettext.locale = (params[:lang] || session[:lang] || environment.default_locale || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
74 - I18n.locale = FastGettext.locale  
75 - I18n.default_locale = FastGettext.default_locale 83 + I18n.locale = FastGettext.locale.to_s.gsub '_', '-'
  84 + I18n.default_locale = FastGettext.default_locale.to_s.gsub '_', '-'
76 if params[:lang] 85 if params[:lang]
77 session[:lang] = params[:lang] 86 session[:lang] = params[:lang]
78 end 87 end
@@ -192,4 +201,15 @@ class ApplicationController &lt; ActionController::Base @@ -192,4 +201,15 @@ class ApplicationController &lt; ActionController::Base
192 def private_environment? 201 def private_environment?
193 @environment.enabled?(:restrict_to_members) 202 @environment.enabled?(:restrict_to_members)
194 end 203 end
  204 +
  205 + def redirect_to_current_user
  206 + if params[:profile] == '~'
  207 + if logged_in?
  208 + redirect_to params.merge(:profile => user.identifier)
  209 + else
  210 + render_not_found
  211 + end
  212 + end
  213 + end
  214 +
195 end 215 end
app/controllers/box_organizer_controller.rb
@@ -3,12 +3,11 @@ class BoxOrganizerController &lt; ApplicationController @@ -3,12 +3,11 @@ class BoxOrganizerController &lt; ApplicationController
3 before_filter :login_required 3 before_filter :login_required
4 4
5 def index 5 def index
  6 + @available_blocks = available_blocks.uniq.sort_by(&:pretty_name)
6 end 7 end
7 8
8 def move_block 9 def move_block
9 - @block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))  
10 -  
11 - @source_box = @block.box 10 + @block = params[:id] ? boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) : nil
12 11
13 target_position = nil 12 target_position = nil
14 13
@@ -20,9 +19,12 @@ class BoxOrganizerController &lt; ApplicationController @@ -20,9 +19,12 @@ class BoxOrganizerController &lt; ApplicationController
20 else 19 else
21 (params[:target] =~ /end-of-box-([0-9]+)/) 20 (params[:target] =~ /end-of-box-([0-9]+)/)
22 21
23 - @target_box = boxes_holder.boxes.find($1) 22 + @target_box = boxes_holder.boxes.find_by_id($1)
24 end 23 end
25 24
  25 + @block = new_block(params[:type], @target_box) if @block.nil?
  26 + @source_box = @block.box
  27 +
26 if (@source_box != @target_box) 28 if (@source_box != @target_box)
27 @block.remove_from_list 29 @block.remove_from_list
28 @block.box = @target_box 30 @block.box = @target_box
@@ -58,23 +60,6 @@ class BoxOrganizerController &lt; ApplicationController @@ -58,23 +60,6 @@ class BoxOrganizerController &lt; ApplicationController
58 redirect_to :action => 'index' 60 redirect_to :action => 'index'
59 end 61 end
60 62
61 - def add_block  
62 - type = params[:type]  
63 - if ! type.blank?  
64 - if available_blocks.map(&:name).include?(type)  
65 - boxes_holder.boxes.find(params[:box_id]).blocks << type.constantize.new  
66 - redirect_to :action => 'index'  
67 - else  
68 - raise ArgumentError.new("Type %s is not allowed. Go away." % type)  
69 - end  
70 - else  
71 - @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1)  
72 - @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3])  
73 - @boxes = boxes_holder.boxes.with_position  
74 - render :action => 'add_block', :layout => false  
75 - end  
76 - end  
77 -  
78 def edit 63 def edit
79 @block = boxes_holder.blocks.find(params[:id]) 64 @block = boxes_holder.blocks.find(params[:id])
80 render :action => 'edit', :layout => false 65 render :action => 'edit', :layout => false
@@ -98,8 +83,12 @@ class BoxOrganizerController &lt; ApplicationController @@ -98,8 +83,12 @@ class BoxOrganizerController &lt; ApplicationController
98 83
99 def save 84 def save
100 @block = boxes_holder.blocks.find(params[:id]) 85 @block = boxes_holder.blocks.find(params[:id])
101 - @block.update_attributes(params[:block])  
102 - redirect_to :action => 'index' 86 + if @block.kind_of?(RawHTMLBlock) && !user.is_admin?(environment)
  87 + render_access_denied
  88 + else
  89 + @block.update_attributes(params[:block])
  90 + redirect_to :action => 'index'
  91 + end
103 end 92 end
104 93
105 def boxes_editor? 94 def boxes_editor?
@@ -121,6 +110,27 @@ class BoxOrganizerController &lt; ApplicationController @@ -121,6 +110,27 @@ class BoxOrganizerController &lt; ApplicationController
121 redirect_to :action => 'index' 110 redirect_to :action => 'index'
122 end 111 end
123 112
  113 + def show_block_type_info
  114 + type = params[:type]
  115 + if type.blank? || !available_blocks.map(&:name).include?(type)
  116 + raise ArgumentError.new("Type %s is not allowed. Go away." % type)
  117 + end
  118 + @block = type.constantize.new
  119 + @block.box = Box.new(:owner => boxes_holder)
  120 + render :action => 'show_block_type_info', :layout => false
  121 + end
  122 +
124 protected :boxes_editor? 123 protected :boxes_editor?
125 124
  125 + protected
  126 +
  127 + def new_block(type, box)
  128 + if !available_blocks.map(&:name).include?(type)
  129 + raise ArgumentError.new("Type %s is not allowed. Go away." % type)
  130 + end
  131 + block = type.constantize.new
  132 + box.blocks << block
  133 + block
  134 + end
  135 +
126 end 136 end
app/controllers/email_templates_controller.rb 0 → 100644
@@ -0,0 +1,62 @@ @@ -0,0 +1,62 @@
  1 +class EmailTemplatesController < ApplicationController
  2 +
  3 + def index
  4 + @email_templates = owner.email_templates
  5 + end
  6 +
  7 + def show
  8 + @email_template = owner.email_templates.find(params[:id])
  9 +
  10 + respond_to do |format|
  11 + format.html # show.html.erb
  12 + format.json { render json: @email_template }
  13 + end
  14 + end
  15 +
  16 + def show_parsed
  17 + @email_template = owner.email_templates.find(params[:id])
  18 + template_params = {:profile => owner, :environment => environment}
  19 + render json: {:parsed_body => @email_template.parsed_body(template_params), :parsed_subject => @email_template.parsed_subject(template_params)}
  20 + end
  21 +
  22 + def new
  23 + @email_template = owner.email_templates.build(:owner => owner)
  24 + end
  25 +
  26 + def edit
  27 + @email_template = owner.email_templates.find(params[:id])
  28 + end
  29 +
  30 + def create
  31 + @email_template = owner.email_templates.build(params[:email_template])
  32 + @email_template.owner = owner
  33 +
  34 + if @email_template.save
  35 + session[:notice] = _('Email template was successfully created.')
  36 + redirect_to url_for(:action => :index)
  37 + else
  38 + render action: "new"
  39 + end
  40 + end
  41 +
  42 + def update
  43 + @email_template = owner.email_templates.find(params[:id])
  44 +
  45 + if @email_template.update_attributes(params[:email_template])
  46 + session[:notice] = _('Email template was successfully updated.')
  47 + redirect_to url_for(:action => :index)
  48 + else
  49 + render action: "edit"
  50 + end
  51 + end
  52 +
  53 + def destroy
  54 + @email_template = owner.email_templates.find(params[:id])
  55 + @email_template.destroy
  56 +
  57 + respond_to do |format|
  58 + format.html { redirect_to url_for(:action => :index)}
  59 + format.json { head :no_content }
  60 + end
  61 + end
  62 +end
app/controllers/my_profile/cms_controller.rb
@@ -6,7 +6,7 @@ class CmsController &lt; MyProfileController @@ -6,7 +6,7 @@ class CmsController &lt; MyProfileController
6 6
7 def search_tags 7 def search_tags
8 arg = params[:term].downcase 8 arg = params[:term].downcase
9 - result = ActsAsTaggableOn::Tag.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"]) 9 + result = ActsAsTaggableOn::Tag.where('name ILIKE ?', "%#{arg}%").limit(10)
10 render :text => prepare_to_token_input_by_label(result).to_json, :content_type => 'application/json' 10 render :text => prepare_to_token_input_by_label(result).to_json, :content_type => 'application/json'
11 end 11 end
12 12
@@ -27,20 +27,13 @@ class CmsController &lt; MyProfileController @@ -27,20 +27,13 @@ class CmsController &lt; MyProfileController
27 27
28 helper_method :file_types 28 helper_method :file_types
29 29
30 - protect_if :only => :upload_files do |c, user, profile|  
31 - article_id = c.params[:parent_id]  
32 - (!article_id.blank? && profile.articles.find(article_id).allow_create?(user)) ||  
33 - (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)))  
34 - end  
35 -  
36 - protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :publish_on_portal_community, :publish_on_communities, :search_communities_to_publish, :upload_files, :new] do |c, user, profile| 30 + protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files, :new] do |c, user, profile|
37 user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) 31 user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))
38 end 32 end
39 33
40 - protect_if :only => :new do |c, user, profile|  
41 - article = profile.articles.find_by_id(c.params[:parent_id])  
42 - (!article.nil? && (article.allow_create?(user) || article.parent.allow_create?(user))) ||  
43 - (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) 34 + protect_if :only => [:new, :upload_files] do |c, user, profile|
  35 + parent = profile.articles.find_by_id(c.params[:parent_id])
  36 + user && user.can_post_content?(profile, parent)
44 end 37 end
45 38
46 protect_if :only => :destroy do |c, user, profile| 39 protect_if :only => :destroy do |c, user, profile|
@@ -101,6 +94,11 @@ class CmsController &lt; MyProfileController @@ -101,6 +94,11 @@ class CmsController &lt; MyProfileController
101 record_coming 94 record_coming
102 if request.post? 95 if request.post?
103 @article.image = nil if params[:remove_image] == 'true' 96 @article.image = nil if params[:remove_image] == 'true'
  97 + if @article.image.present? && params[:article][:image_builder] &&
  98 + params[:article][:image_builder][:label]
  99 + @article.image.label = params[:article][:image_builder][:label]
  100 + @article.image.save!
  101 + end
104 @article.last_changed_by = user 102 @article.last_changed_by = user
105 if @article.update_attributes(params[:article]) 103 if @article.update_attributes(params[:article])
106 if !continue 104 if !continue
@@ -112,6 +110,11 @@ class CmsController &lt; MyProfileController @@ -112,6 +110,11 @@ class CmsController &lt; MyProfileController
112 end 110 end
113 end 111 end
114 end 112 end
  113 +
  114 + unless @article.kind_of?(RssFeed)
  115 + @escaped_body = CGI::escapeHTML(@article.body || '')
  116 + @escaped_abstract = CGI::escapeHTML(@article.abstract || '')
  117 + end
115 end 118 end
116 119
117 def new 120 def new
@@ -143,7 +146,14 @@ class CmsController &lt; MyProfileController @@ -143,7 +146,14 @@ class CmsController &lt; MyProfileController
143 klass = @type.constantize 146 klass = @type.constantize
144 article_data = environment.enabled?('articles_dont_accept_comments_by_default') ? { :accept_comments => false } : {} 147 article_data = environment.enabled?('articles_dont_accept_comments_by_default') ? { :accept_comments => false } : {}
145 article_data.merge!(params[:article]) if params[:article] 148 article_data.merge!(params[:article]) if params[:article]
146 - @article = klass.new(article_data) 149 + article_data.merge!(:profile => profile) if profile
  150 +
  151 + @article = if params[:clone]
  152 + current_article = profile.articles.find(params[:id])
  153 + current_article.copy_without_save
  154 + else
  155 + klass.new(article_data)
  156 + end
147 157
148 parent = check_parent(params[:parent_id]) 158 parent = check_parent(params[:parent_id])
149 if parent 159 if parent
@@ -220,7 +230,7 @@ class CmsController &lt; MyProfileController @@ -220,7 +230,7 @@ class CmsController &lt; MyProfileController
220 if @errors.any? 230 if @errors.any?
221 render :action => 'upload_files', :parent_id => @parent_id 231 render :action => 'upload_files', :parent_id => @parent_id
222 else 232 else
223 - session[:notice] = _('File(s) successfully uploaded') 233 + session[:notice] = _('File(s) successfully uploaded')
224 if @back_to 234 if @back_to
225 redirect_to @back_to 235 redirect_to @back_to
226 elsif @parent 236 elsif @parent
@@ -357,7 +367,8 @@ class CmsController &lt; MyProfileController @@ -357,7 +367,8 @@ class CmsController &lt; MyProfileController
357 @task.ip_address = request.remote_ip 367 @task.ip_address = request.remote_ip
358 @task.user_agent = request.user_agent 368 @task.user_agent = request.user_agent
359 @task.referrer = request.referrer 369 @task.referrer = request.referrer
360 - if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save 370 + @task.requestor = current_person if logged_in?
  371 + if (logged_in? || verify_recaptcha(:model => @task, :message => _('Please type the words correctly'))) && @task.save
361 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') 372 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.')
362 redirect_to @back_to 373 redirect_to @back_to
363 end 374 end
@@ -453,7 +464,8 @@ class CmsController &lt; MyProfileController @@ -453,7 +464,8 @@ class CmsController &lt; MyProfileController
453 end 464 end
454 465
455 def refuse_blocks 466 def refuse_blocks
456 - if ['TinyMceArticle', 'TextileArticle', 'Event', 'EnterpriseHomepage'].include?(@type) 467 + article_types = ['TinyMceArticle', 'TextileArticle', 'Event', 'EnterpriseHomepage'] + @plugins.dispatch(:content_types).map {|type| type.name}
  468 + if article_types.include?(@type)
457 @no_design_blocks = true 469 @no_design_blocks = true
458 end 470 end
459 end 471 end
app/controllers/my_profile/enterprise_validation_controller.rb
1 class EnterpriseValidationController < MyProfileController 1 class EnterpriseValidationController < MyProfileController
2 2
3 protect 'validate_enterprise', :profile 3 protect 'validate_enterprise', :profile
4 - 4 +
5 def index 5 def index
6 @pending_validations = profile.pending_validations 6 @pending_validations = profile.pending_validations
7 end 7 end
@@ -27,7 +27,7 @@ class EnterpriseValidationController &lt; MyProfileController @@ -27,7 +27,7 @@ class EnterpriseValidationController &lt; MyProfileController
27 post_only :reject 27 post_only :reject
28 def reject 28 def reject
29 @pending = profile.find_pending_validation(params[:id]) 29 @pending = profile.find_pending_validation(params[:id])
30 - if @pending 30 + if @pending
31 @pending.reject_explanation = params[:reject_explanation] 31 @pending.reject_explanation = params[:reject_explanation]
32 begin 32 begin
33 @pending.reject 33 @pending.reject
app/controllers/my_profile/favorite_enterprises_controller.rb
1 class FavoriteEnterprisesController < MyProfileController 1 class FavoriteEnterprisesController < MyProfileController
2 -  
3 -# protect 'manage_favorite_enteprises', :profile 2 +
  3 +# protect 'manage_favorite_enterprises', :profile
4 4
5 requires_profile_class Person 5 requires_profile_class Person
6 - 6 +
7 def index 7 def index
8 @favorite_enterprises = profile.favorite_enterprises 8 @favorite_enterprises = profile.favorite_enterprises
9 end 9 end
@@ -12,7 +12,7 @@ class FavoriteEnterprisesController &lt; MyProfileController @@ -12,7 +12,7 @@ class FavoriteEnterprisesController &lt; MyProfileController
12 @favorite_enterprise = Enterprise.find(params[:id]) 12 @favorite_enterprise = Enterprise.find(params[:id])
13 if request.post? && params[:confirmation] 13 if request.post? && params[:confirmation]
14 profile.favorite_enterprises << @favorite_enterprise 14 profile.favorite_enterprises << @favorite_enterprise
15 - redirect_to :action => 'index' 15 + redirect_to :action => 'index'
16 end 16 end
17 end 17 end
18 18
app/controllers/my_profile/friends_controller.rb
1 class FriendsController < MyProfileController 1 class FriendsController < MyProfileController
2 - 2 +
3 protect 'manage_friends', :profile 3 protect 'manage_friends', :profile
4 - 4 +
5 def index 5 def index
6 - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) 6 + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page)
7 if is_cache_expired?(profile.manage_friends_cache_key(params)) 7 if is_cache_expired?(profile.manage_friends_cache_key(params))
8 @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage]) 8 @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage])
9 end 9 end
@@ -18,7 +18,7 @@ class FriendsController &lt; MyProfileController @@ -18,7 +18,7 @@ class FriendsController &lt; MyProfileController
18 end 18 end
19 19
20 def suggest 20 def suggest
21 - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) 21 + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page)
22 end 22 end
23 23
24 def remove_suggestion 24 def remove_suggestion
@@ -26,13 +26,13 @@ class FriendsController &lt; MyProfileController @@ -26,13 +26,13 @@ class FriendsController &lt; MyProfileController
26 redirect_to :action => 'suggest' unless @person 26 redirect_to :action => 'suggest' unless @person
27 if @person && request.post? 27 if @person && request.post?
28 profile.remove_suggestion(@person) 28 profile.remove_suggestion(@person)
29 - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) 29 + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page)
30 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => params[:per_page] || per_page } 30 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => params[:per_page] || per_page }
31 end 31 end
32 end 32 end
33 33
34 def connections 34 def connections
35 - @suggestion = profile.profile_suggestions.of_person.enabled.find_by_suggestion_id(params[:id]) 35 + @suggestion = profile.suggested_profiles.of_person.enabled.find_by_suggestion_id(params[:id])
36 if @suggestion 36 if @suggestion
37 @tags = @suggestion.tag_connections 37 @tags = @suggestion.tag_connections
38 @profiles = @suggestion.profile_connections 38 @profiles = @suggestion.profile_connections
app/controllers/my_profile/manage_products_controller.rb
@@ -35,7 +35,7 @@ class ManageProductsController &lt; ApplicationController @@ -35,7 +35,7 @@ class ManageProductsController &lt; ApplicationController
35 end 35 end
36 36
37 def categories_for_selection 37 def categories_for_selection
38 - @category = Category.find(params[:category_id]) if params[:category_id] 38 + @category = environment.categories.find_by_id params[:category_id]
39 @object_name = params[:object_name] 39 @object_name = params[:object_name]
40 if @category 40 if @category
41 @categories = @category.children 41 @categories = @category.children
@@ -95,6 +95,20 @@ class ManageProductsController &lt; ApplicationController @@ -95,6 +95,20 @@ class ManageProductsController &lt; ApplicationController
95 end 95 end
96 end 96 end
97 97
  98 + def show_category_tree
  99 + @category = environment.categories.find params[:category_id]
  100 + render :partial => 'selected_category_tree'
  101 + end
  102 +
  103 + def search_categories
  104 + @term = params[:term].downcase
  105 + conditions = ['LOWER(name) LIKE ? OR LOWER(name) LIKE ?', "#{@term}%", "% #{@term}%"]
  106 + @categories = ProductCategory.all :conditions => conditions, :limit => 10
  107 + render :json => (@categories.map do |category|
  108 + {:label => category.name, :value => category.id}
  109 + end)
  110 + end
  111 +
98 def add_input 112 def add_input
99 @product = @profile.products.find(params[:id]) 113 @product = @profile.products.find(params[:id])
100 @input = @product.inputs.build 114 @input = @product.inputs.build
@@ -192,7 +206,8 @@ class ManageProductsController &lt; ApplicationController @@ -192,7 +206,8 @@ class ManageProductsController &lt; ApplicationController
192 end 206 end
193 207
194 def certifiers_for_selection 208 def certifiers_for_selection
195 - @qualifier = Qualifier.exists?(params[:id]) ? Qualifier.find(params[:id]) : nil 209 + # updated to use hash as argument to exists? to avoid sql injection vunerabillity (http://brakemanscanner.org/docs/warning_types/sql_injection/)
  210 + @qualifier = Qualifier.exists?(:id => params[:id]) ? Qualifier.find(params[:id]) : nil
196 render :update do |page| 211 render :update do |page|
197 page.replace_html params[:certifier_area], :partial => 'certifiers_for_selection' 212 page.replace_html params[:certifier_area], :partial => 'certifiers_for_selection'
198 end 213 end
app/controllers/my_profile/maps_controller.rb
@@ -16,6 +16,7 @@ class MapsController &lt; MyProfileController @@ -16,6 +16,7 @@ class MapsController &lt; MyProfileController
16 16
17 Profile.transaction do 17 Profile.transaction do
18 if profile.update_attributes!(params[:profile_data]) 18 if profile.update_attributes!(params[:profile_data])
  19 + BlockSweeper.expire_blocks profile.blocks.select{ |b| b.class == LocationBlock }
19 session[:notice] = _('Address was updated successfully!') 20 session[:notice] = _('Address was updated successfully!')
20 redirect_to :action => 'edit_location' 21 redirect_to :action => 'edit_location'
21 end 22 end
app/controllers/my_profile/memberships_controller.rb
@@ -40,7 +40,7 @@ class MembershipsController &lt; MyProfileController @@ -40,7 +40,7 @@ class MembershipsController &lt; MyProfileController
40 end 40 end
41 41
42 def suggest 42 def suggest
43 - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(per_page) 43 + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(per_page)
44 end 44 end
45 45
46 def remove_suggestion 46 def remove_suggestion
@@ -49,13 +49,13 @@ class MembershipsController &lt; MyProfileController @@ -49,13 +49,13 @@ class MembershipsController &lt; MyProfileController
49 redirect_to :action => 'suggest' unless @community 49 redirect_to :action => 'suggest' unless @community
50 if @community && request.post? 50 if @community && request.post?
51 profile.remove_suggestion(@community) 51 profile.remove_suggestion(@community)
52 - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(custom_per_page) 52 + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(custom_per_page)
53 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => custom_per_page} 53 render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => custom_per_page}
54 end 54 end
55 end 55 end
56 56
57 def connections 57 def connections
58 - @suggestion = profile.profile_suggestions.of_community.enabled.find_by_suggestion_id(params[:id]) 58 + @suggestion = profile.suggested_profiles.of_community.enabled.find_by_suggestion_id(params[:id])
59 if @suggestion 59 if @suggestion
60 @tags = @suggestion.tag_connections 60 @tags = @suggestion.tag_connections
61 @profiles = @suggestion.profile_connections 61 @profiles = @suggestion.profile_connections
app/controllers/my_profile/profile_design_controller.rb
@@ -4,11 +4,20 @@ class ProfileDesignController &lt; BoxOrganizerController @@ -4,11 +4,20 @@ class ProfileDesignController &lt; BoxOrganizerController
4 4
5 protect 'edit_profile_design', :profile 5 protect 'edit_profile_design', :profile
6 6
7 - before_filter :protect_fixed_block, :only => [:save, :move_block] 7 + before_filter :protect_uneditable_block, :only => [:save]
  8 + before_filter :protect_fixed_block, :only => [:move_block]
  9 +
  10 + def protect_uneditable_block
  11 + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
  12 + if !current_person.is_admin? && !block.editable?
  13 + render_access_denied
  14 + end
  15 + end
8 16
9 def protect_fixed_block 17 def protect_fixed_block
  18 + return if params[:id].blank?
10 block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) 19 block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
11 - if block.fixed && !current_person.is_admin? 20 + if block.present? && !current_person.is_admin? && !block.movable?
12 render_access_denied 21 render_access_denied
13 end 22 end
14 end 23 end
app/controllers/my_profile/profile_editor_controller.rb
@@ -5,6 +5,7 @@ class ProfileEditorController &lt; MyProfileController @@ -5,6 +5,7 @@ class ProfileEditorController &lt; MyProfileController
5 5
6 before_filter :access_welcome_page, :only => [:welcome_page] 6 before_filter :access_welcome_page, :only => [:welcome_page]
7 before_filter :back_to 7 before_filter :back_to
  8 + before_filter :forbid_destroy_profile, :only => [:destroy_profile]
8 helper_method :has_welcome_page 9 helper_method :has_welcome_page
9 10
10 def index 11 def index
@@ -18,7 +19,10 @@ class ProfileEditorController &lt; MyProfileController @@ -18,7 +19,10 @@ class ProfileEditorController &lt; MyProfileController
18 @profile_data = profile 19 @profile_data = profile
19 @possible_domains = profile.possible_domains 20 @possible_domains = profile.possible_domains
20 if request.post? 21 if request.post?
21 - params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash) 22 + if profile.person? && params[:profile_data].is_a?(Hash)
  23 + params[:profile_data][:fields_privacy] ||= {}
  24 + params[:profile_data][:custom_fields] ||= {}
  25 + end
22 Profile.transaction do 26 Profile.transaction do
23 Image.transaction do 27 Image.transaction do
24 begin 28 begin
@@ -109,7 +113,7 @@ class ProfileEditorController &lt; MyProfileController @@ -109,7 +113,7 @@ class ProfileEditorController &lt; MyProfileController
109 profile = environment.profiles.find(params[:id]) 113 profile = environment.profiles.find(params[:id])
110 if profile.disable 114 if profile.disable
111 profile.save 115 profile.save
112 - session[:notice] = _("The profile '#{profile.name}' was deactivated.") 116 + session[:notice] = _("The profile '%s' was deactivated.") % profile.name
113 else 117 else
114 session[:notice] = _('Could not deactivate profile.') 118 session[:notice] = _('Could not deactivate profile.')
115 end 119 end
@@ -123,7 +127,7 @@ class ProfileEditorController &lt; MyProfileController @@ -123,7 +127,7 @@ class ProfileEditorController &lt; MyProfileController
123 profile = environment.profiles.find(params[:id]) 127 profile = environment.profiles.find(params[:id])
124 128
125 if profile.enable 129 if profile.enable
126 - session[:notice] = _("The profile '#{profile.name}' was activated.") 130 + session[:notice] = _("The profile '%s' was activated.") % profile.name
127 else 131 else
128 session[:notice] = _('Could not activate the profile.') 132 session[:notice] = _('Could not activate the profile.')
129 end 133 end
@@ -155,4 +159,10 @@ class ProfileEditorController &lt; MyProfileController @@ -155,4 +159,10 @@ class ProfileEditorController &lt; MyProfileController
155 end 159 end
156 end 160 end
157 161
  162 + def forbid_destroy_profile
  163 + if environment.enabled?('forbid_destroy_profile') && !current_person.is_admin?(environment)
  164 + session[:notice] = _('You can not destroy the profile.')
  165 + redirect_to_previous_location
  166 + end
  167 + end
158 end 168 end
app/controllers/my_profile/profile_email_templates_controller.rb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +class ProfileEmailTemplatesController < EmailTemplatesController
  2 +
  3 + needs_profile
  4 + protect 'manage_email_templates', :profile
  5 +
  6 + protected
  7 +
  8 + def owner
  9 + profile
  10 + end
  11 +
  12 + before_filter :only => :index do
  13 + @back_to = url_for(:controller => :profile_editor)
  14 + end
  15 +
  16 +end
app/controllers/my_profile/profile_members_controller.rb
@@ -58,6 +58,7 @@ class ProfileMembersController &lt; MyProfileController @@ -58,6 +58,7 @@ class ProfileMembersController &lt; MyProfileController
58 58
59 def change_role 59 def change_role
60 @roles = Profile::Roles.organization_member_roles(environment.id) 60 @roles = Profile::Roles.organization_member_roles(environment.id)
  61 + @custom_roles = profile.custom_roles
61 begin 62 begin
62 @member = profile.members.find(params[:id]) 63 @member = profile.members.find(params[:id])
63 rescue ActiveRecord::RecordNotFound 64 rescue ActiveRecord::RecordNotFound
app/controllers/my_profile/profile_roles_controller.rb 0 → 100644
@@ -0,0 +1,116 @@ @@ -0,0 +1,116 @@
  1 +class ProfileRolesController < MyProfileController
  2 +
  3 + protect 'manage_custom_roles', :profile
  4 +
  5 + def index
  6 + @roles = profile.custom_roles
  7 + end
  8 +
  9 + def new
  10 + @role = Role.new
  11 + end
  12 +
  13 + def create
  14 + @role = Role.new({:name => params[:role][:name], :permissions => params[:role][:permissions], :environment => environment }, :without_protection => true)
  15 + if @role.save
  16 + profile.custom_roles << @role
  17 + redirect_to :action => 'show', :id => @role
  18 + else
  19 + session[:notice] = _('Failed to create role')
  20 + render :action => 'new'
  21 + end
  22 + end
  23 +
  24 + def show
  25 + @role = environment.roles.find(params[:id])
  26 + end
  27 +
  28 + def edit
  29 + @role = environment.roles.find(params[:id])
  30 + end
  31 +
  32 + def assign_role_by_members
  33 + return redirect_to "/" if params[:q].nil? or !request.xhr?
  34 + arg = params[:q].downcase
  35 + result = find_by_contents(:people, environment, profile.members, params[:q])[:results]
  36 + render :text => prepare_to_token_input(result).to_json
  37 + end
  38 +
  39 + def destroy
  40 + @role = environment.roles.find(params[:id])
  41 + @members = profile.members_by_role(@role)
  42 + @roles_list = all_roles(environment, profile)
  43 + @roles_list.delete(@role)
  44 + end
  45 +
  46 + def remove
  47 + @role = environment.roles.find(params[:id])
  48 + @members = profile.members_by_role(@role)
  49 + member_roles = params[:roles] ? environment.roles.find(params[:roles].select{|r|!r.to_i.zero?}) : []
  50 + append_roles(@members, member_roles, profile)
  51 + if @role.destroy
  52 + session[:notice] = _('Role successfuly removed!')
  53 + else
  54 + session[:notice] = _('Failed to remove role!')
  55 + end
  56 + redirect_to :action => 'index'
  57 + end
  58 +
  59 + def update
  60 + @role = environment.roles.find(params[:id])
  61 + if @role.update_attributes(params[:role])
  62 + redirect_to :action => 'show', :id => @role
  63 + else
  64 + session[:notice] = _('Failed to edit role')
  65 + render :action => 'edit'
  66 + end
  67 + end
  68 +
  69 + def assign
  70 + @role = environment.roles.find(params[:id])
  71 + @roles_list = all_roles(environment, profile)
  72 + @roles_list.delete(@role)
  73 + end
  74 +
  75 + def define
  76 + @role = environment.roles.find(params[:id])
  77 + selected_role = params[:selected_role] ? environment.roles.find(params[:selected_role].to_i) : nil
  78 + if params[:assign_role_by].eql? "members"
  79 + members_list = params[:person_id].split(',').collect {|id| environment.profiles.find(id.to_i)}
  80 + members_list.collect{|person| person.add_role(@role, profile)}
  81 + elsif params[:assign_role_by].eql? "roles"
  82 + members = profile.members_by_role(selected_role)
  83 + replace_role(members, selected_role, @role, profile)
  84 + else
  85 + session[:notice] = _("Error")
  86 + end
  87 + redirect_to :action => 'index'
  88 + end
  89 +
  90 + protected
  91 +
  92 + def append_roles(members, roles, profile)
  93 + members.each do |person|
  94 + all_roles = person.find_roles(profile).map(&:role) + roles
  95 + person.define_roles(all_roles, profile)
  96 + end
  97 + end
  98 +
  99 + def all_roles(environment, profile)
  100 + Profile::Roles.organization_member_roles(environment.id) + profile.custom_roles
  101 + end
  102 +
  103 + def replace_roles(members, roles, profile)
  104 + members.each do |person|
  105 + person.define_roles(roles, profile)
  106 + end
  107 + end
  108 +
  109 + def replace_role(members, role, new_role, profile)
  110 + members.each do |person|
  111 + person.remove_role(role, profile)
  112 + person.add_role(new_role, profile)
  113 + end
  114 + end
  115 +
  116 +end
app/controllers/my_profile/tasks_controller.rb
1 class TasksController < MyProfileController 1 class TasksController < MyProfileController
2 2
3 - protect 'perform_task', :profile  
4 - 3 + protect [:perform_task, :view_tasks], :profile, :only => [:index, :save_tags, :search_tags]
  4 + protect :perform_task, :profile, :only => [:processed, :change_responsible, :close, :new, :list_requested, :ticket_details, :search_tags]
  5 +
5 def index 6 def index
6 - @filter = params[:filter_type].blank? ? nil : params[:filter_type] 7 + @rejection_email_templates = profile.email_templates.find_all_by_template_type(:task_rejection)
  8 + @acceptance_email_templates = profile.email_templates.find_all_by_template_type(:task_acceptance)
  9 +
  10 + @filter_type = params[:filter_type].presence
  11 + @filter_text = params[:filter_text].presence
  12 + @filter_responsible = params[:filter_responsible]
  13 + @filter_tags = params[:filter_tags]
  14 +
7 @task_types = Task.pending_types_for(profile) 15 @task_types = Task.pending_types_for(profile)
8 - @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) 16 + @task_tags = [OpenStruct.new(:name => _('All'), :id => nil) ] + Task.all_tags
  17 +
  18 + @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc')
  19 + @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present?
  20 + @tasks = @tasks.tagged_with(@filter_tags, any: true) if @filter_tags.present?
  21 + @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page])
  22 +
9 @failed = params ? params[:failed] : {} 23 @failed = params ? params[:failed] : {}
  24 +
  25 + @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task') && !r.has_permission?('view_tasks')}) if profile.organization?
  26 +
  27 + @view_only = !current_person.has_permission?(:perform_task, profile)
10 end 28 end
11 29
12 def processed 30 def processed
13 - @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) 31 + @tasks = Task.to(profile).without_spam.closed.order('tasks.created_at DESC')
  32 + @filter = params[:filter] || {}
  33 + @tasks = filter_tasks(@filter, @tasks)
  34 + @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page])
  35 + @task_types = Task.closed_types_for(profile)
  36 + end
  37 +
  38 + def change_responsible
  39 + task = profile.tasks.find(params[:task_id])
  40 +
  41 + if task.responsible.present? && task.responsible.id != params[:old_responsible_id].to_i
  42 + return render :json => {:notice => _('Task already assigned!'), :success => false, :current_responsible => task.responsible.id}
  43 + end
  44 +
  45 + responsible = profile.members.find(params[:responsible_id]) if params[:responsible_id].present?
  46 + task.responsible = responsible
  47 + task.save!
  48 + render :json => {:notice => _('Task responsible successfully updated!'), :success => true, :new_responsible => {:id => responsible.present? ? responsible.id : nil}}
14 end 49 end
15 50
16 VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] 51 VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ]
17 52
18 def close 53 def close
19 failed = {} 54 failed = {}
  55 + save = false
20 56
21 if params[:tasks] 57 if params[:tasks]
22 params[:tasks].each do |id, value| 58 params[:tasks].each do |id, value|
23 decision = value[:decision] 59 decision = value[:decision]
24 - if request.post? && VALID_DECISIONS.include?(decision) && id && decision != 'skip' 60 +
  61 + if value[:task].is_a?(Hash) && value[:task][:tag_list]
  62 +
25 task = profile.find_in_all_tasks(id) 63 task = profile.find_in_all_tasks(id)
26 - begin  
27 - task.update_attributes(value[:task])  
28 - task.send(decision)  
29 - rescue Exception => ex  
30 - message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})"  
31 - failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message] 64 + task.tag_list = value[:task][:tag_list]
  65 + value[:task].delete('tag_list')
  66 +
  67 + save = true
  68 + end
  69 +
  70 + if request.post?
  71 + if VALID_DECISIONS.include?(decision) && id && decision != 'skip'
  72 + task ||= profile.find_in_all_tasks(id)
  73 + begin
  74 + task.update_attributes(value[:task])
  75 + task.send(decision, current_person)
  76 + rescue Exception => ex
  77 + message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})"
  78 + failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message]
  79 + end
  80 + elsif save
  81 + task.save!
32 end 82 end
33 end 83 end
34 end 84 end
35 end 85 end
36 86
37 url = { :action => 'index' } 87 url = { :action => 'index' }
  88 +
38 if failed.blank? 89 if failed.blank?
39 session[:notice] = _("All decisions were applied successfully.") 90 session[:notice] = _("All decisions were applied successfully.")
40 else 91 else
@@ -65,4 +116,79 @@ class TasksController &lt; MyProfileController @@ -65,4 +116,79 @@ class TasksController &lt; MyProfileController
65 @ticket = Ticket.find(:first, :conditions => ['(requestor_id = ? or target_id = ?) and id = ?', profile.id, profile.id, params[:id]]) 116 @ticket = Ticket.find(:first, :conditions => ['(requestor_id = ? or target_id = ?) and id = ?', profile.id, profile.id, params[:id]])
66 end 117 end
67 118
  119 + def search_tasks
  120 + filter_type = params[:filter_type].presence
  121 + filter_text = params[:filter_text].presence
  122 + result = Task.pending_all(profile,filter_type, filter_text)
  123 +
  124 + render :json => result.map { |task| {:label => task.data[:name], :value => task.data[:name]} }
  125 + end
  126 +
  127 + def save_tags
  128 + if request.post? && params[:tag_list]
  129 + result = {
  130 + success: false,
  131 + message: _('Error to save tags. Please, contact the system admin')
  132 + }
  133 +
  134 + ActsAsTaggableOn.remove_unused_tags = true
  135 +
  136 + task = profile.tasks.find_by_id(params[:task_id])
  137 +
  138 + if task && task.update_attributes(:tag_list => params[:tag_list])
  139 + result[:success] = true
  140 + end
  141 + end
  142 +
  143 + render json: result
  144 + end
  145 +
  146 + # FIXME make this test
  147 + # Should not search for article tasks
  148 + # Should not search for other profile tags
  149 + # Should search only task tags
  150 + # Should check the permissions
  151 +
  152 + def search_tags
  153 +
  154 + arg = params[:term].downcase
  155 +
  156 + result = ActsAsTaggableOn::Tag.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"])
  157 +
  158 + render :text => prepare_to_token_input_by_label(result).to_json, :content_type => 'application/json'
  159 + end
  160 +
  161 + protected
  162 +
  163 + def filter_by_closed_date(filter, tasks)
  164 + filter[:closed_from] = Date.parse(filter[:closed_from]) unless filter[:closed_from].blank?
  165 + filter[:closed_until] = Date.parse(filter[:closed_until]) unless filter[:closed_until].blank?
  166 +
  167 + tasks = tasks.where('tasks.end_date >= ?', filter[:closed_from].beginning_of_day) unless filter[:closed_from].blank?
  168 + tasks = tasks.where('tasks.end_date <= ?', filter[:closed_until].end_of_day) unless filter[:closed_until].blank?
  169 + tasks
  170 + end
  171 +
  172 + def filter_by_creation_date(filter, tasks)
  173 + filter[:created_from] = Date.parse(filter[:created_from]) unless filter[:created_from].blank?
  174 + filter[:created_until] = Date.parse(filter[:created_until]) unless filter[:created_until].blank?
  175 +
  176 + tasks = tasks.where('tasks.created_at >= ?', filter[:created_from].beginning_of_day) unless filter[:created_from].blank?
  177 + tasks = tasks.where('tasks.created_at <= ?', filter[:created_until].end_of_day) unless filter[:created_until].blank?
  178 + tasks
  179 + end
  180 +
  181 + def filter_tasks(filter, tasks)
  182 + tasks = tasks.includes(:requestor, :closed_by)
  183 + tasks = tasks.of(filter[:type].presence)
  184 + tasks = tasks.where(:status => filter[:status]) unless filter[:status].blank?
  185 + tasks = filter_by_creation_date(filter, tasks)
  186 + tasks = filter_by_closed_date(filter, tasks)
  187 +
  188 + tasks = tasks.like('profiles.name', filter[:requestor]) unless filter[:requestor].blank?
  189 + tasks = tasks.like('closed_bies_tasks.name', filter[:closed_by]) unless filter[:closed_by].blank?
  190 + tasks = tasks.like('tasks.data', filter[:text]) unless filter[:text].blank?
  191 + tasks
  192 + end
  193 +
68 end 194 end
app/controllers/public/account_controller.rb
@@ -16,7 +16,7 @@ class AccountController &lt; ApplicationController @@ -16,7 +16,7 @@ class AccountController &lt; ApplicationController
16 def activate 16 def activate
17 @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code] 17 @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code]
18 if @user 18 if @user
19 - unless @user.environment.enabled?('admin_must_approve_new_users') 19 + unless @user.environment.enabled?('admin_must_approve_new_users')
20 if @user.activate 20 if @user.activate
21 @message = _("Your account has been activated, now you can log in!") 21 @message = _("Your account has been activated, now you can log in!")
22 check_redirection 22 check_redirection
@@ -30,7 +30,7 @@ class AccountController &lt; ApplicationController @@ -30,7 +30,7 @@ class AccountController &lt; ApplicationController
30 @user.activation_code = nil 30 @user.activation_code = nil
31 @user.save! 31 @user.save!
32 redirect_to :controller => :home 32 redirect_to :controller => :home
33 - end 33 + end
34 end 34 end
35 else 35 else
36 session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?") 36 session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?")
@@ -50,10 +50,12 @@ class AccountController &lt; ApplicationController @@ -50,10 +50,12 @@ class AccountController &lt; ApplicationController
50 50
51 if logged_in? 51 if logged_in?
52 check_join_in_community(self.current_user) 52 check_join_in_community(self.current_user)
  53 +
53 if params[:remember_me] == "1" 54 if params[:remember_me] == "1"
54 self.current_user.remember_me 55 self.current_user.remember_me
55 - cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at } 56 + cookies[:auth_token] = {value: self.current_user.remember_token, expires: self.current_user.remember_token_expires_at}
56 end 57 end
  58 +
57 if redirect? 59 if redirect?
58 go_to_initial_page 60 go_to_initial_page
59 session[:notice] = _("Logged in successfully") 61 session[:notice] = _("Logged in successfully")
@@ -77,6 +79,13 @@ class AccountController &lt; ApplicationController @@ -77,6 +79,13 @@ class AccountController &lt; ApplicationController
77 render :text => { :ok=>true, :key=>key }.to_json 79 render :text => { :ok=>true, :key=>key }.to_json
78 end 80 end
79 81
  82 + def custom_fields_for_template
  83 + custom_fields ||= environment.people.templates.find(params[:template_id]).custom_fields.map { |k,v|
  84 + { :name => k, :title => v[:title] } if v['signup']
  85 + }.compact
  86 + render :text => {:ok => true, :custom_fields => custom_fields}.to_json
  87 + end
  88 +
80 # action to register an user to the application 89 # action to register an user to the application
81 def signup 90 def signup
82 if @plugins.dispatch(:allow_user_registration).include?(false) 91 if @plugins.dispatch(:allow_user_registration).include?(false)
@@ -92,6 +101,7 @@ class AccountController &lt; ApplicationController @@ -92,6 +101,7 @@ class AccountController &lt; ApplicationController
92 @invitation_code = params[:invitation_code] 101 @invitation_code = params[:invitation_code]
93 begin 102 begin
94 @user = User.new(params[:user]) 103 @user = User.new(params[:user])
  104 + @user.session = session
95 @user.terms_of_use = environment.terms_of_use 105 @user.terms_of_use = environment.terms_of_use
96 @user.environment = environment 106 @user.environment = environment
97 @terms_of_use = environment.terms_of_use 107 @terms_of_use = environment.terms_of_use
@@ -358,11 +368,11 @@ class AccountController &lt; ApplicationController @@ -358,11 +368,11 @@ class AccountController &lt; ApplicationController
358 end 368 end
359 369
360 def get_signup_start_time 370 def get_signup_start_time
361 - Rails.cache.read params[:signup_time_key] 371 + Rails.cache.read params[:signup_time_key] if params[:signup_time_key].present?
362 end 372 end
363 373
364 def clear_signup_start_time 374 def clear_signup_start_time
365 - Rails.cache.delete params[:signup_time_key] if params[:signup_time_key] 375 + Rails.cache.delete params[:signup_time_key] if params[:signup_time_key].present?
366 end 376 end
367 377
368 def may_be_a_bot 378 def may_be_a_bot
@@ -435,7 +445,7 @@ class AccountController &lt; ApplicationController @@ -435,7 +445,7 @@ class AccountController &lt; ApplicationController
435 end 445 end
436 446
437 def go_to_signup_initial_page 447 def go_to_signup_initial_page
438 - check_redirection_options(user, user.environment.redirection_after_signup, user.url) 448 + check_redirection_options user, user.environment.redirection_after_signup, user.url, signup: true
439 end 449 end
440 450
441 def redirect_if_logged_in 451 def redirect_if_logged_in
@@ -455,8 +465,11 @@ class AccountController &lt; ApplicationController @@ -455,8 +465,11 @@ class AccountController &lt; ApplicationController
455 465
456 protected 466 protected
457 467
458 - def check_redirection_options(user, condition, default)  
459 - case condition 468 + def check_redirection_options user, condition, default, options={}
  469 + if options[:signup] and target = session.delete(:after_signup_redirect_to)
  470 + redirect_to target
  471 + else
  472 + case condition
460 when 'keep_on_same_page' 473 when 'keep_on_same_page'
461 redirect_back_or_default(user.admin_url) 474 redirect_back_or_default(user.admin_url)
462 when 'site_homepage' 475 when 'site_homepage'
@@ -469,8 +482,11 @@ class AccountController &lt; ApplicationController @@ -469,8 +482,11 @@ class AccountController &lt; ApplicationController
469 redirect_to user.admin_url 482 redirect_to user.admin_url
470 when 'welcome_page' 483 when 'welcome_page'
471 redirect_to :controller => :home, :action => :welcome, :template_id => (user.template && user.template.id) 484 redirect_to :controller => :home, :action => :welcome, :template_id => (user.template && user.template.id)
472 - else  
473 - redirect_back_or_default(default) 485 + when 'custom_url'
  486 + if (url = user.custom_url_redirection).present? then redirect_to url else redirect_back_or_default default end
  487 + else
  488 + redirect_back_or_default(default)
  489 + end
474 end 490 end
475 end 491 end
476 492
app/controllers/public/api_controller.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +class ApiController < PublicController
  2 +
  3 + no_design_blocks
  4 +
  5 + helper_method :endpoints
  6 +
  7 + def index
  8 + end
  9 +
  10 + def playground
  11 + end
  12 +
  13 + private
  14 +
  15 + def endpoints
  16 + Noosfero::API::API.endpoints(environment)
  17 + end
  18 +
  19 +end
app/controllers/public/chat_controller.rb
@@ -2,6 +2,7 @@ class ChatController &lt; PublicController @@ -2,6 +2,7 @@ class ChatController &lt; PublicController
2 2
3 before_filter :login_required 3 before_filter :login_required
4 before_filter :check_environment_feature 4 before_filter :check_environment_feature
  5 + before_filter :can_send_message, :only => :register_message
5 6
6 def start_session 7 def start_session
7 login = user.jid 8 login = user.jid
@@ -54,6 +55,16 @@ class ChatController &lt; PublicController @@ -54,6 +55,16 @@ class ChatController &lt; PublicController
54 end 55 end
55 end 56 end
56 57
  58 + def avatars
  59 + profiles = environment.profiles.where(:identifier => params[:profiles])
  60 + avatar_map = profiles.inject({}) do |result, profile|
  61 + result[profile.identifier] = profile_icon(profile, :minor)
  62 + result
  63 + end
  64 +
  65 + render_json avatar_map
  66 + end
  67 +
57 def update_presence_status 68 def update_presence_status
58 if request.xhr? 69 if request.xhr?
59 current_user.update_attributes({:chat_status_at => DateTime.now}.merge(params[:status] || {})) 70 current_user.update_attributes({:chat_status_at => DateTime.now}.merge(params[:status] || {}))
@@ -62,11 +73,17 @@ class ChatController &lt; PublicController @@ -62,11 +73,17 @@ class ChatController &lt; PublicController
62 end 73 end
63 74
64 def save_message 75 def save_message
65 - to = environment.profiles.find_by_identifier(params[:to])  
66 - body = params[:body]  
67 -  
68 - ChatMessage.create!(:to => to, :from => user, :body => body)  
69 - render :text => 'ok' 76 + if request.post?
  77 + to = environment.profiles.where(:identifier => params[:to]).first
  78 + body = params[:body]
  79 +
  80 + begin
  81 + ChatMessage.create!(:to => to, :from => user, :body => body)
  82 + return render_json({:status => 0})
  83 + rescue Exception => exception
  84 + return render_json({:status => 3, :message => exception.to_s, :backtrace => exception.backtrace})
  85 + end
  86 + end
70 end 87 end
71 88
72 def recent_messages 89 def recent_messages
@@ -90,8 +107,9 @@ class ChatController &lt; PublicController @@ -90,8 +107,9 @@ class ChatController &lt; PublicController
90 end 107 end
91 108
92 def recent_conversations 109 def recent_conversations
93 - conversations_order = ActiveRecord::Base.connection.execute("select profiles.identifier from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc").entries.map {|e| e['identifier']}  
94 - render :json => {:order => conversations_order.reverse, :domain => environment.default_hostname.gsub('.','-')}.to_json 110 + profiles = Profile.find_by_sql("select profiles.* from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc")
  111 + jids = profiles.map(&:jid).reverse
  112 + render :json => jids.to_json
95 end 113 end
96 114
97 #TODO Ideally this is done through roster table on ejabberd. 115 #TODO Ideally this is done through roster table on ejabberd.
@@ -108,4 +126,14 @@ class ChatController &lt; PublicController @@ -108,4 +126,14 @@ class ChatController &lt; PublicController
108 end 126 end
109 end 127 end
110 128
  129 + def can_send_message
  130 + return render_json({:status => 1, :message => 'Missing parameters!'}) if params[:from].nil? || params[:to].nil? || params[:message].nil?
  131 + return render_json({:status => 2, :message => 'You can not send message as another user!'}) if params[:from] != user.jid
  132 + # TODO Maybe register the jid in a table someday to avoid this below
  133 + return render_json({:status => 3, :messsage => 'You can not send messages to strangers!'}) if user.friends.where(:identifier => params[:to].split('@').first).blank?
  134 + end
  135 +
  136 + def render_json(result)
  137 + render :text => result.to_json
  138 + end
111 end 139 end
app/controllers/public/contact_controller.rb
@@ -6,8 +6,9 @@ class ContactController &lt; PublicController @@ -6,8 +6,9 @@ class ContactController &lt; PublicController
6 def new 6 def new
7 @contact = build_contact 7 @contact = build_contact
8 if request.post? && params[:confirm] == 'true' 8 if request.post? && params[:confirm] == 'true'
9 - @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil  
10 - @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil 9 + # updated to use hash as argument to exists? to avoid sql injection vunerabillity (http://brakemanscanner.org/docs/warning_types/sql_injection/)
  10 + @contact.city = (!params[:city].blank? && City.exists?(:id => params[:city])) ? City.find(params[:city]).name : nil
  11 + @contact.state = (!params[:state].blank? && State.exists?(:id => params[:state])) ? State.find(params[:state]).name : nil
11 if @contact.deliver 12 if @contact.deliver
12 session[:notice] = _('Contact successfully sent') 13 session[:notice] = _('Contact successfully sent')
13 redirect_to :action => 'new' 14 redirect_to :action => 'new'
app/controllers/public/content_viewer_controller.rb
@@ -15,9 +15,10 @@ class ContentViewerController &lt; ApplicationController @@ -15,9 +15,10 @@ class ContentViewerController &lt; ApplicationController
15 path = get_path(params[:page], params[:format]) 15 path = get_path(params[:page], params[:format])
16 16
17 @version = params[:version].to_i 17 @version = params[:version].to_i
  18 + @npage = params[:npage] || '1'
18 19
19 if path.blank? 20 if path.blank?
20 - @page = profile.home_page 21 + @page = profile.home_page
21 return if redirected_to_profile_index 22 return if redirected_to_profile_index
22 else 23 else
23 @page = profile.articles.find_by_path(path) 24 @page = profile.articles.find_by_path(path)
@@ -74,7 +75,7 @@ class ContentViewerController &lt; ApplicationController @@ -74,7 +75,7 @@ class ContentViewerController &lt; ApplicationController
74 render :action => 'slideshow', :layout => 'slideshow' 75 render :action => 'slideshow', :layout => 'slideshow'
75 return 76 return
76 end 77 end
77 - render :view_page, :formats => [:html] 78 + render @page.view_page, :formats => [:html]
78 end 79 end
79 80
80 def versions_diff 81 def versions_diff
@@ -125,21 +126,23 @@ class ContentViewerController &lt; ApplicationController @@ -125,21 +126,23 @@ class ContentViewerController &lt; ApplicationController
125 helper_method :pass_without_comment_captcha? 126 helper_method :pass_without_comment_captcha?
126 127
127 def allow_access_to_page(path) 128 def allow_access_to_page(path)
128 - allowed = true  
129 if @page.nil? # page not found, give error 129 if @page.nil? # page not found, give error
130 render_not_found(path) 130 render_not_found(path)
131 - allowed = false  
132 - elsif !@page.display_to?(user)  
133 - if !profile.public? 131 + return false
  132 + end
  133 +
  134 + unless @page.display_to?(user)
  135 + if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank?
  136 + render_access_denied
  137 + else #!profile.public?
134 private_profile_partial_parameters 138 private_profile_partial_parameters
135 render :template => 'profile/_private_profile', :status => 403, :formats => [:html] 139 render :template => 'profile/_private_profile', :status => 403, :formats => [:html]
136 - allowed = false  
137 - else #if !profile.visible?  
138 - render_access_denied  
139 - allowed = false  
140 end 140 end
  141 +
  142 + return false
141 end 143 end
142 - allowed 144 +
  145 + return true
143 end 146 end
144 147
145 def user_is_a_bot? 148 def user_is_a_bot?
@@ -184,7 +187,7 @@ class ContentViewerController &lt; ApplicationController @@ -184,7 +187,7 @@ class ContentViewerController &lt; ApplicationController
184 if @page.forum? && @page.has_terms_of_use && terms_accepted == "true" 187 if @page.forum? && @page.has_terms_of_use && terms_accepted == "true"
185 @page.add_agreed_user(user) 188 @page.add_agreed_user(user)
186 end 189 end
187 - end 190 + end
188 191
189 def is_a_forum_topic? (page) 192 def is_a_forum_topic? (page)
190 return (!@page.parent.nil? && @page.parent.forum?) 193 return (!@page.parent.nil? && @page.parent.forum?)
app/controllers/public/home_controller.rb
@@ -12,6 +12,7 @@ class HomeController &lt; PublicController @@ -12,6 +12,7 @@ class HomeController &lt; PublicController
12 @area_news = environment.portal_folders 12 @area_news = environment.portal_folders
13 end 13 end
14 end 14 end
  15 + render :file => 'home/index', :formats => [:html]
15 end 16 end
16 17
17 def terms 18 def terms
app/controllers/public/invite_controller.rb
@@ -62,20 +62,36 @@ class InviteController &lt; PublicController @@ -62,20 +62,36 @@ class InviteController &lt; PublicController
62 redirect_to :action => 'invite_friends' 62 redirect_to :action => 'invite_friends'
63 end 63 end
64 64
  65 + #Invite or add member without create a task
  66 + #if logged user is admin of environment
65 def invite_registered_friend 67 def invite_registered_friend
  68 +
  69 + if !params['q'].present? || !request.post?
  70 +
  71 + redirect_to :action => 'invite_friends'
  72 + session[:notice] = _('Please enter a valid profile.')
  73 +
  74 + return
  75 + end
  76 +
66 contacts_to_invite = params['q'].split(',') 77 contacts_to_invite = params['q'].split(',')
67 - if !contacts_to_invite.empty? && request.post? 78 +
  79 + if user.is_admin? && profile.community?
  80 +
  81 + Delayed::Job.enqueue AddMembersJob.new contacts_to_invite, profile.id, locale
  82 +
  83 + session[:notice] = _('This friends was added!')
  84 + else
68 Delayed::Job.enqueue InvitationJob.new(user.id, contacts_to_invite, '', profile.id, nil, locale) 85 Delayed::Job.enqueue InvitationJob.new(user.id, contacts_to_invite, '', profile.id, nil, locale)
69 session[:notice] = _('Your invitations are being sent.') 86 session[:notice] = _('Your invitations are being sent.')
70 - if profile.person?  
71 - redirect_to :controller => 'profile', :action => 'friends'  
72 - else  
73 - redirect_to :controller => 'profile', :action => 'members'  
74 - end 87 + end
  88 +
  89 + if profile.person?
  90 + redirect_to :controller => 'profile', :action => 'friends'
75 else 91 else
76 - redirect_to :action => 'invite_friends'  
77 - session[:notice] = _('Please enter a valid profile.') 92 + redirect_to :controller => 'profile', :action => 'members'
78 end 93 end
  94 +
79 end 95 end
80 96
81 def search 97 def search
app/controllers/public/profile_controller.rb
@@ -6,6 +6,7 @@ class ProfileController &lt; PublicController @@ -6,6 +6,7 @@ class ProfileController &lt; PublicController
6 before_filter :login_required, :only => [:add, :join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail] 6 before_filter :login_required, :only => [:add, :join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail]
7 7
8 helper TagsHelper 8 helper TagsHelper
  9 + helper ActionTrackerHelper
9 10
10 protect 'send_mail_to_members', :profile, :only => [:send_mail] 11 protect 'send_mail_to_members', :profile, :only => [:send_mail]
11 12
@@ -201,7 +202,10 @@ class ProfileController &lt; PublicController @@ -201,7 +202,10 @@ class ProfileController &lt; PublicController
201 202
202 def more_comments 203 def more_comments
203 profile_filter = @profile.person? ? {:user_id => @profile} : {:target_id => @profile} 204 profile_filter = @profile.person? ? {:user_id => @profile} : {:target_id => @profile}
204 - activity = ActionTracker::Record.find(:first, :conditions => {:id => params[:activity]}.merge(profile_filter)) 205 + activity = ActionTracker::Record.where(:id => params[:activity])
  206 + activity = activity.where(profile_filter) if !logged_in? || !current_person.follows?(@profile)
  207 + activity = activity.first
  208 +
205 comments_count = activity.comments.count 209 comments_count = activity.comments.count
206 comment_page = (params[:comment_page] || 1).to_i 210 comment_page = (params[:comment_page] || 1).to_i
207 comments_per_page = 5 211 comments_per_page = 5
@@ -353,6 +357,7 @@ class ProfileController &lt; PublicController @@ -353,6 +357,7 @@ class ProfileController &lt; PublicController
353 357
354 def send_mail 358 def send_mail
355 @mailing = profile.mailings.build(params[:mailing]) 359 @mailing = profile.mailings.build(params[:mailing])
  360 + @email_templates = profile.email_templates.find_all_by_template_type(:organization_members)
356 if request.post? 361 if request.post?
357 @mailing.locale = locale 362 @mailing.locale = locale
358 @mailing.person = user 363 @mailing.person = user
app/controllers/public/search_controller.rb
@@ -95,10 +95,10 @@ class SearchController &lt; PublicController @@ -95,10 +95,10 @@ class SearchController &lt; PublicController
95 95
96 def events 96 def events
97 if params[:year].blank? && params[:year].blank? && params[:day].blank? 97 if params[:year].blank? && params[:year].blank? && params[:day].blank?
98 - @date = Date.today 98 + @date = DateTime.now
99 else 99 else
100 - year = (params[:year] ? params[:year].to_i : Date.today.year)  
101 - month = (params[:month] ? params[:month].to_i : Date.today.month) 100 + year = (params[:year] ? params[:year].to_i : DateTime.now.year)
  101 + month = (params[:month] ? params[:month].to_i : DateTime.now.month)
102 day = (params[:day] ? params[:day].to_i : 1) 102 day = (params[:day] ? params[:day].to_i : 1)
103 @date = build_date(year, month, day) 103 @date = build_date(year, month, day)
104 end 104 end
@@ -109,9 +109,7 @@ class SearchController &lt; PublicController @@ -109,9 +109,7 @@ class SearchController &lt; PublicController
109 @events = @category ? 109 @events = @category ?
110 environment.events.by_day(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) : 110 environment.events.by_day(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) :
111 environment.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page]) 111 environment.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page])
112 - end  
113 -  
114 - if params[:year] || params[:month] 112 + elsif params[:year] || params[:month]
115 @events = @category ? 113 @events = @category ?
116 environment.events.by_month(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) : 114 environment.events.by_month(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) :
117 environment.events.by_month(@date).paginate(:per_page => per_page, :page => params[:page]) 115 environment.events.by_month(@date).paginate(:per_page => per_page, :page => params[:page])
app/controllers/public_controller.rb
@@ -3,7 +3,7 @@ class PublicController &lt; ApplicationController @@ -3,7 +3,7 @@ class PublicController &lt; ApplicationController
3 3
4 def allow_access_to_page 4 def allow_access_to_page
5 unless profile.display_info_to?(user) 5 unless profile.display_info_to?(user)
6 - if profile.visible? 6 + if profile.visible? && !profile.secret
7 private_profile 7 private_profile
8 else 8 else
9 invisible_profile 9 invisible_profile
app/helpers/action_tracker_helper.rb 0 → 100644
@@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
  1 +module ActionTrackerHelper
  2 +
  3 + def create_article_description ta
  4 + _('published an article: %{title}') % { title: link_to(truncate(ta.get_name), ta.get_url) }
  5 + end
  6 +
  7 + def new_friendship_description ta
  8 + n_('has made 1 new friend:<br />%{name}', 'has made %{num} new friends:<br />%{name}', ta.get_friend_name.size) % {
  9 + num: ta.get_friend_name.size,
  10 + name: ta.collect_group_with_index(:friend_name) do |n,i|
  11 + link_to image_tag(ta.get_friend_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/person-icon.png")),
  12 + ta.get_friend_url[i], title: n
  13 + end.join
  14 + }
  15 + end
  16 +
  17 + def join_community_description ta
  18 + n_('has joined 1 community:<br />%{name}', 'has joined %{num} communities:<br />%{name}', ta.get_resource_name.size) % {
  19 + num: ta.get_resource_name.size,
  20 + name: ta.collect_group_with_index(:resource_name) do |n,i|
  21 + link_to image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")),
  22 + ta.get_resource_url[i], title: n
  23 + end.join
  24 + }
  25 + end
  26 +
  27 + def add_member_in_community_description ta
  28 + _('has joined the community.')
  29 + end
  30 +
  31 + def upload_image_description ta
  32 + total = ta.get_view_url.size
  33 + (n_('uploaded 1 image', 'uploaded %d images', total) % total) +
  34 + tag(:br) +
  35 + ta.collect_group_with_index(:thumbnail_path) do |t,i|
  36 + if total == 1
  37 + link_to image_tag(t), ta.get_view_url[i], class: 'upimg'
  38 + else
  39 + pos = total-i;
  40 + morethen2 = pos>2 ? 'morethen2' : ''
  41 + morethen5 = pos>5 ? 'morethen5' : ''
  42 + t = t.gsub(/(.*)(display)(.*)/, '\\1thumb\\3')
  43 +
  44 + link_to '&nbsp;'.html_safe, ta.get_view_url[i],
  45 + style: "background-image:url(#{t})",
  46 + class: "upimg pos#{pos} #{morethen2} #{morethen5}"
  47 + end
  48 + end.reverse.join +
  49 + if total <= 5 then ''.html_safe else content_tag :span, '&hellip;'.html_safe,
  50 + class: 'more', onclick: "this.parentNode.className+=' show-all'" end +
  51 + tag(:br, style: 'clear: both')
  52 + end
  53 +
  54 + def reply_scrap_description ta
  55 + _('sent a message to %{receiver}: <br /> "%{message}"') % {
  56 + receiver: link_to(ta.get_receiver_name, ta.get_receiver_url),
  57 + message: auto_link_urls(ta.get_content)
  58 + }
  59 + end
  60 +
  61 + alias :leave_scrap_description :reply_scrap_description
  62 + alias :reply_scrap_on_self_description :reply_scrap_description
  63 +
  64 + def leave_scrap_to_self_description ta
  65 + _('wrote: <br /> "%{text}"') % {
  66 + text: auto_link_urls(ta.get_content)
  67 + }
  68 + end
  69 +
  70 + def create_product_description
  71 + _('created the product %{title}') % {
  72 + title: link_to(truncate(ta.get_name), ta.get_url),
  73 + }
  74 + end
  75 +
  76 + def update_product_description
  77 + _('updated the product %{title}') % {
  78 + title: link_to(truncate(ta.get_name), ta.get_url),
  79 + }
  80 + end
  81 +
  82 + def remove_product_description
  83 + _('removed the product %{title}') % {
  84 + title: truncate(ta.get_name),
  85 + }
  86 + end
  87 +
  88 + def favorite_enterprise_description ta
  89 + _('favorited enterprise %{title}') % {
  90 + title: link_to(truncate(ta.get_enterprise_name), ta.get_enterprise_url),
  91 + }
  92 + end
  93 +
  94 +end
app/helpers/application_helper.rb
@@ -44,6 +44,8 @@ module ApplicationHelper @@ -44,6 +44,8 @@ module ApplicationHelper
44 44
45 include PluginsHelper 45 include PluginsHelper
46 46
  47 + include TaskHelper
  48 +
47 def locale 49 def locale
48 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale 50 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale
49 end 51 end
@@ -707,6 +709,24 @@ module ApplicationHelper @@ -707,6 +709,24 @@ module ApplicationHelper
707 javascript_include_tag script if script 709 javascript_include_tag script if script
708 end 710 end
709 711
  712 + def template_path
  713 + if profile.nil?
  714 + "/designs/templates/#{environment.layout_template}"
  715 + else
  716 + "/designs/templates/#{profile.layout_template}"
  717 + end
  718 + end
  719 +
  720 + def template_javascript_src
  721 + script = File.join template_path, '/javascripts/template.js'
  722 + script if File.exists? File.join(Rails.root, 'public', script)
  723 + end
  724 +
  725 + def templete_javascript_ng
  726 + script = template_javascript_src
  727 + javascript_include_tag script if script
  728 + end
  729 +
710 def file_field_or_thumbnail(label, image, i) 730 def file_field_or_thumbnail(label, image, i)
711 display_form_field label, ( 731 display_form_field label, (
712 render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'), 732 render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'),
@@ -853,7 +873,7 @@ module ApplicationHelper @@ -853,7 +873,7 @@ module ApplicationHelper
853 field_html += capture(&block) 873 field_html += capture(&block)
854 end 874 end
855 875
856 - if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') 876 + if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') || (controller.controller_name == 'home' && controller.action_name == 'index' && user.nil?)
857 if profile.signup_fields.include?(name) 877 if profile.signup_fields.include?(name)
858 result = field_html 878 result = field_html
859 end 879 end
@@ -913,6 +933,19 @@ module ApplicationHelper @@ -913,6 +933,19 @@ module ApplicationHelper
913 article_helper.cms_label_for_edit 933 article_helper.cms_label_for_edit
914 end 934 end
915 935
  936 + def label_for_clone_article(article)
  937 + translated_types = {
  938 + Folder => _('Folder'),
  939 + Blog => _('Blog'),
  940 + Event => _('Event'),
  941 + Forum => _('Forum')
  942 + }
  943 +
  944 + translated_type = translated_types[article.class] || _('Article')
  945 +
  946 + _('Clone %s') % translated_type
  947 + end
  948 +
916 def add_rss_feed_to_head(title, url) 949 def add_rss_feed_to_head(title, url)
917 content_for :feeds do 950 content_for :feeds do
918 tag(:link, :rel => 'alternate', :type => 'application/rss+xml', :title => title, :href => url_for(url)) 951 tag(:link, :rel => 'alternate', :type => 'application/rss+xml', :title => title, :href => url_for(url))
@@ -1151,10 +1184,10 @@ module ApplicationHelper @@ -1151,10 +1184,10 @@ module ApplicationHelper
1151 pending_tasks_count = '' 1184 pending_tasks_count = ''
1152 count = user ? Task.to(user).pending.count : -1 1185 count = user ? Task.to(user).pending.count : -1
1153 if count > 0 1186 if count > 0
1154 - pending_tasks_count = link_to(count.to_s, user.tasks_url, :id => 'pending-tasks-count', :title => _("Manage your pending tasks")) 1187 + pending_tasks_count = link_to("<i class=\"icon-menu-tasks\"></i><span class=\"task-count\">#{count}</span>", user.tasks_url, :id => 'pending-tasks-count', :title => _("Manage your pending tasks"))
1155 end 1188 end
1156 1189
1157 - (_("<span class='welcome'>Welcome,</span> %s") % link_to("<i style='background-image:url(#{user.profile_custom_icon(gravatar_default)})'></i><strong>#{user.identifier}</strong>", user.public_profile_url, :id => "homepage-link", :title => _('Go to your homepage'))) + 1190 + (_("<span class='welcome'>Welcome,</span> %s") % link_to("<i style='background-image:url(#{user.profile_custom_icon(gravatar_default)})'></i><strong>#{user.identifier}</strong>", user.url, :id => "homepage-link", :title => _('Go to your homepage'))) +
1158 render_environment_features(:usermenu) + 1191 render_environment_features(:usermenu) +
1159 admin_link + 1192 admin_link +
1160 manage_enterprises + 1193 manage_enterprises +
@@ -1173,7 +1206,8 @@ module ApplicationHelper @@ -1173,7 +1206,8 @@ module ApplicationHelper
1173 end 1206 end
1174 1207
1175 def expandable_text_area(object_name, method, text_area_id, options = {}) 1208 def expandable_text_area(object_name, method, text_area_id, options = {})
1176 - text_area(object_name, method, { :id => text_area_id, :onkeyup => "grow_text_area('#{text_area_id}')" }.merge(options)) 1209 + options[:class] = (options[:class] || '') + ' autogrow'
  1210 + text_area(object_name, method, { :id => text_area_id }.merge(options))
1177 end 1211 end
1178 1212
1179 def pluralize_without_count(count, singular, plural = nil) 1213 def pluralize_without_count(count, singular, plural = nil)
@@ -1184,35 +1218,6 @@ module ApplicationHelper @@ -1184,35 +1218,6 @@ module ApplicationHelper
1184 list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort 1218 list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort
1185 end 1219 end
1186 1220
1187 - #FIXME Use time_ago_in_words instead of this method if you're using Rails 2.2+  
1188 - def time_ago_as_sentence(from_time, include_seconds = false)  
1189 - to_time = Time.now  
1190 - from_time = Time.parse(from_time.to_s)  
1191 - from_time = from_time.to_time if from_time.respond_to?(:to_time)  
1192 - to_time = to_time.to_time if to_time.respond_to?(:to_time)  
1193 - distance_in_minutes = (((to_time - from_time).abs)/60).round  
1194 - distance_in_seconds = ((to_time - from_time).abs).round  
1195 - case distance_in_minutes  
1196 - when 0..1  
1197 - return (distance_in_minutes == 0) ? _('less than a minute') : _('1 minute') unless include_seconds  
1198 - case distance_in_seconds  
1199 - when 0..4 then _('less than 5 seconds')  
1200 - when 5..9 then _('less than 10 seconds')  
1201 - when 10..19 then _('less than 20 seconds')  
1202 - when 20..39 then _('half a minute')  
1203 - when 40..59 then _('less than a minute')  
1204 - else _('1 minute')  
1205 - end  
1206 -  
1207 - when 2..44 then _('%{distance} minutes ago') % { :distance => distance_in_minutes }  
1208 - when 45..89 then _('about 1 hour ago')  
1209 - when 90..1439 then _('about %{distance} hours ago') % { :distance => (distance_in_minutes.to_f / 60.0).round }  
1210 - when 1440..2879 then _('1 day ago')  
1211 - when 2880..10079 then _('%{distance} days ago') % { :distance => (distance_in_minutes / 1440).round }  
1212 - else show_time(from_time)  
1213 - end  
1214 - end  
1215 -  
1216 def comment_balloon(options = {}, &block) 1221 def comment_balloon(options = {}, &block)
1217 wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content') 1222 wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content')
1218 (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") } 1223 (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") }
@@ -1231,7 +1236,7 @@ module ApplicationHelper @@ -1231,7 +1236,7 @@ module ApplicationHelper
1231 1236
1232 def task_information(task) 1237 def task_information(task)
1233 values = {} 1238 values = {}
1234 - values.merge!({:requestor => link_to(task.requestor.name, task.requestor.public_profile_url)}) if task.requestor 1239 + values.merge!({:requestor => link_to(task.requestor.name, task.requestor.url)}) if task.requestor
1235 values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject 1240 values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject
1236 values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject 1241 values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject
1237 values.merge!(task.information[:variables]) if task.information[:variables] 1242 values.merge!(task.information[:variables]) if task.information[:variables]
@@ -1336,18 +1341,29 @@ module ApplicationHelper @@ -1336,18 +1341,29 @@ module ApplicationHelper
1336 def template_options(kind, field_name) 1341 def template_options(kind, field_name)
1337 templates = environment.send(kind).templates 1342 templates = environment.send(kind).templates
1338 return '' if templates.count == 0 1343 return '' if templates.count == 0
1339 - return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1  
1340 -  
1341 - radios = templates.map do |template|  
1342 - content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template)))  
1343 - end.join("\n")  
1344 -  
1345 - content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') +  
1346 - content_tag('p', _('Your profile will be created according to the selected template. Click on the options to view them.'), :style => 'margin: 5px 15px;padding: 0px 10px;') +  
1347 - content_tag('ul', radios, :style => 'list-style: none; padding-left: 20px; margin-top: 0.5em;'),  
1348 - :id => 'template-options',  
1349 - :style => 'margin-top: 1em'  
1350 - ) 1344 + if templates.count == 1
  1345 + if templates.first.custom_fields == {}
  1346 + return hidden_field_tag("#{field_name}[template_id]", templates.first.id)
  1347 + else
  1348 + custom_fields = ""
  1349 + templates.first.custom_fields.each { |field, value|
  1350 + custom_fields += content_tag('div', content_tag('label', value[:title].capitalize, :class => 'formlabel') +
  1351 + content_tag('div', text_field_tag( "profile_data[custom_fields][#{field}][title]", ''), :class => 'formfield type-text'), :class => "formfieldline" ) if value[:signup] == 'on'
  1352 + }
  1353 + content_tag('div', custom_fields)
  1354 + end
  1355 + else
  1356 + radios = templates.map do |template|
  1357 + content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template), :onchange => 'show_fields_for_template(this);'))
  1358 + end.join("\n")
  1359 +
  1360 + content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') +
  1361 + content_tag('p', _('Your profile will be created according to the selected template. Click on the options to view them.'), :style => 'margin: 5px 15px;padding: 0px 10px;') +
  1362 + content_tag('ul', radios, :style => 'list-style: none; padding-left: 20px; margin-top: 0.5em;'),
  1363 + :id => 'template-options',
  1364 + :style => 'margin-top: 1em'
  1365 + )
  1366 + end
1351 end 1367 end
1352 1368
1353 def expirable_content_reference(content, action, text, url, options = {}) 1369 def expirable_content_reference(content, action, text, url, options = {})
@@ -1480,4 +1496,26 @@ module ApplicationHelper @@ -1480,4 +1496,26 @@ module ApplicationHelper
1480 text_field(object_name, method, options.merge(:class => 'colorpicker_field')) 1496 text_field(object_name, method, options.merge(:class => 'colorpicker_field'))
1481 end 1497 end
1482 1498
  1499 + def fullscreen_buttons(itemId)
  1500 + content="
  1501 + <script>fullscreenPageLoad('#{itemId}')</script>
  1502 + "
  1503 + content+=content_tag('a', content_tag('span',_("Full screen")),
  1504 + { :id=>"fullscreen-btn",
  1505 + :onClick=>"toggle_fullwidth('#{itemId}')",
  1506 + :class=>"button with-text icon-fullscreen",
  1507 + :href=>"#",
  1508 + :title=>_("Go to full screen mode")
  1509 + })
  1510 +
  1511 + content+=content_tag('a', content_tag('span',_("Exit full screen")),
  1512 + { :style=>"display: none;",
  1513 + :id=>"exit-fullscreen-btn",
  1514 + :onClick=>"toggle_fullwidth('#{itemId}')",
  1515 + :class=>"button with-text icon-fullscreen",
  1516 + :href=>"#",
  1517 + :title=>_("Exit full screen mode")
  1518 + })
  1519 + end
  1520 +
1483 end 1521 end
app/helpers/article_helper.rb
@@ -12,6 +12,7 @@ module ArticleHelper @@ -12,6 +12,7 @@ module ArticleHelper
12 @article = article 12 @article = article
13 13
14 visibility_options(@article, tokenized_children) + 14 visibility_options(@article, tokenized_children) +
  15 + topic_creation(@article) +
15 content_tag('h4', _('Options')) + 16 content_tag('h4', _('Options')) +
16 content_tag('div', 17 content_tag('div',
17 (article.profile.has_members? ? 18 (article.profile.has_members? ?
@@ -55,14 +56,7 @@ module ArticleHelper @@ -55,14 +56,7 @@ module ArticleHelper
55 'div', 56 'div',
56 check_box(:article, :display_versions) + 57 check_box(:article, :display_versions) +
57 content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions') 58 content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions')
58 - ) : '') +  
59 -  
60 - (article.forum? && article.profile.community? ?  
61 - content_tag(  
62 - 'div',  
63 - check_box(:article, :allows_members_to_create_topics) +  
64 - content_tag('label', _('Allow members to create topics'), :for => 'article_allows_members_to_create_topics')  
65 - ) : '') 59 + ) : '')
66 ) 60 )
67 end 61 end
68 62
@@ -81,6 +75,22 @@ module ArticleHelper @@ -81,6 +75,22 @@ module ArticleHelper
81 ) 75 )
82 end 76 end
83 77
  78 + def topic_creation(article)
  79 + return '' unless article.forum?
  80 +
  81 + general_options = Forum::TopicCreation.general_options(article)
  82 + slider_options = {:id => 'topic-creation-slider'}
  83 + slider_options = general_options.keys.inject(slider_options) do |result, option|
  84 + result.merge!({'data-'+option => general_options[option]})
  85 + end
  86 +
  87 + content_tag('h4', _('Topic creation')) +
  88 + content_tag( 'small', _('Who will be able to create new topics on this forum?')) +
  89 + content_tag('div', '', slider_options) +
  90 + hidden_field_tag('article[topic_creation]', article.topic_creation) +
  91 + javascript_include_tag('topic-creation-config')
  92 + end
  93 +
84 def privacity_exceptions(article, tokenized_children) 94 def privacity_exceptions(article, tokenized_children)
85 content_tag('div', 95 content_tag('div',
86 content_tag('div', 96 content_tag('div',
app/helpers/blog_helper.rb
@@ -22,7 +22,9 @@ module BlogHelper @@ -22,7 +22,9 @@ module BlogHelper
22 :param_name => 'npage', 22 :param_name => 'npage',
23 :previous_label => _('&laquo; Newer posts'), 23 :previous_label => _('&laquo; Newer posts'),
24 :next_label => _('Older posts &raquo;'), 24 :next_label => _('Older posts &raquo;'),
25 - :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} 25 + :params => {:action=>"view_page",
  26 + :page=>articles.first.parent.path.split('/'),
  27 + :controller=>"content_viewer"}
26 }) if articles.present? && conf[:paginate] 28 }) if articles.present? && conf[:paginate]
27 content = [] 29 content = []
28 artic_len = articles.length 30 artic_len = articles.length
@@ -44,7 +46,7 @@ module BlogHelper @@ -44,7 +46,7 @@ module BlogHelper
44 end 46 end
45 47
46 def display_post(article, format = 'full') 48 def display_post(article, format = 'full')
47 - no_comments = (format == 'full') ? false : true 49 + no_comments = (format == 'full' || format == 'compact' ) ? false : true
48 title = article_title(article, :no_comments => no_comments) 50 title = article_title(article, :no_comments => no_comments)
49 method = "display_#{format.split('+')[0]}_format" 51 method = "display_#{format.split('+')[0]}_format"
50 html = send(method, FilePresenter.for(article)).html_safe 52 html = send(method, FilePresenter.for(article)).html_safe
@@ -55,8 +57,12 @@ module BlogHelper @@ -55,8 +57,12 @@ module BlogHelper
55 else 57 else
56 '<div class="post-pic" style="background-image:url('+img+')"></div>' 58 '<div class="post-pic" style="background-image:url('+img+')"></div>'
57 end 59 end
58 - end.to_s +  
59 - title + html 60 + end.to_s + title + html
  61 + end
  62 +
  63 + def display_compact_format(article)
  64 + render :file => 'content_viewer/_display_compact_format',
  65 + :locals => { :article => article, :format => "compact" }
60 end 66 end
61 67
62 def display_full_format(article) 68 def display_full_format(article)
app/helpers/box_organizer_helper.rb
1 module BoxOrganizerHelper 1 module BoxOrganizerHelper
2 2
  3 + def display_icon(block)
  4 + image_path = nil
  5 + plugin = @plugins.fetch_first_plugin(:has_block?, block)
  6 +
  7 + theme = Theme.new(environment.theme) # remove this
  8 + if File.exists?(File.join(theme.filesystem_path, 'images', block.icon_path))
  9 + image_path = File.join(theme.public_path, 'images', block.icon_path)
  10 + elsif plugin && File.exists?(File.join(Rails.root, 'public', plugin.public_path, 'images', block.icon_path))
  11 + image_path = File.join('/', plugin.public_path, 'images', block.icon_path)
  12 + elsif File.exists?(File.join(Rails.root, 'public', 'images', block.icon_path))
  13 + image_path = File.join('images', block.icon_path)
  14 + else
  15 + image_path = File.join('images', block.default_icon_path)
  16 + end
  17 +
  18 + image_tag(image_path, height: '48', width: '48', class: 'block-type-icon', alt: '' )
  19 + end
  20 +
  21 + def display_previews(block)
  22 + images_path = nil
  23 + plugin = @plugins.fetch_first_plugin(:has_block?, block)
  24 +
  25 + theme = Theme.new(environment.theme) # remove this
  26 +
  27 + images_path = Dir.glob(File.join(theme.filesystem_path, 'images', block.preview_path, '*'))
  28 + images_path = images_path.map{|path| path.gsub(theme.filesystem_path, theme.public_path) } unless images_path.empty?
  29 +
  30 + images_path = Dir.glob(File.join(Rails.root, 'public', plugin.public_path, 'images', block.preview_path, '*')) if plugin && images_path.empty?
  31 + images_path = images_path.map{|path| path.gsub(File.join(Rails.root, 'public'), '') } unless images_path.empty?
  32 +
  33 + images_path = Dir.glob(File.join(Rails.root, 'public', 'images', block.preview_path, '*')) if images_path.empty?
  34 + images_path = images_path.map{|path| path.gsub(File.join(Rails.root, 'public'), '') } unless images_path.empty?
  35 +
  36 + images_path = 1.upto(3).map{File.join('images', block.default_preview_path)} if images_path.empty?
  37 +
  38 + content_tag(:ul,
  39 + images_path.map do |preview|
  40 + content_tag(:li, image_tag(preview, height: '240', alt: ''))
  41 + end.join("\n")
  42 + )
  43 + end
  44 +
3 def icon_selector(icon = 'no-ico') 45 def icon_selector(icon = 'no-ico')
4 render :partial => 'icon_selector', :locals => { :icon => icon } 46 render :partial => 'icon_selector', :locals => { :icon => icon }
5 end 47 end
@@ -10,4 +52,4 @@ module BoxOrganizerHelper @@ -10,4 +52,4 @@ module BoxOrganizerHelper
10 end 52 end
11 end 53 end
12 54
13 -end  
14 \ No newline at end of file 55 \ No newline at end of file
  56 +end
app/helpers/boxes_helper.rb
@@ -122,7 +122,7 @@ module BoxesHelper @@ -122,7 +122,7 @@ module BoxesHelper
122 end 122 end
123 123
124 def wrap_main_content(content) 124 def wrap_main_content(content)
125 - (1..8).to_a.reverse.inject(content) { |acc,n| content_tag('div', acc, :id => 'main-content-wrapper-' + n.to_s) } 125 + content_tag('div', content, :class => 'main-content')
126 end 126 end
127 127
128 def extract_block_content(content) 128 def extract_block_content(content)
@@ -190,8 +190,9 @@ module BoxesHelper @@ -190,8 +190,9 @@ module BoxesHelper
190 else 190 else
191 "before-block-#{block.id}" 191 "before-block-#{block.id}"
192 end 192 end
193 - if block.nil? or modifiable?(block)  
194 - content_tag('div', '&nbsp;', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') 193 + if block.nil? || movable?(block)
  194 + url = url_for(:action => 'move_block', :target => id)
  195 + content_tag('div', _('Drop Here'), :id => id, :class => 'block-target' ) + drop_receiving_element(id, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover', :activeClass => 'block-target-active', :tolerance => 'pointer', :onDrop => "function(ev, ui) { dropBlock('#{url}', '#{_('loading...')}', ev, ui);}")
195 else 196 else
196 "" 197 ""
197 end 198 end
@@ -199,14 +200,32 @@ module BoxesHelper @@ -199,14 +200,32 @@ module BoxesHelper
199 200
200 # makes the given block draggable so it can be moved away. 201 # makes the given block draggable so it can be moved away.
201 def block_handle(block) 202 def block_handle(block)
202 - modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : "" 203 + return "" unless movable?(block)
  204 + icon = "<div><div>#{display_icon(block.class)}</div><span>#{_(block.class.pretty_name)}</span></div>"
  205 + block_draggable("block-#{block.id}",
  206 + :helper => "function() {return cloneDraggableBlock($(this), '#{icon}')}")
  207 + end
  208 +
  209 + def block_draggable(element_id, options={})
  210 + draggable_options = {
  211 + :revert => "'invalid'",
  212 + :appendTo => "'#block-store-draggables'",
  213 + :helper => '"clone"',
  214 + :revertDuration => 200,
  215 + :scroll => false,
  216 + :start => "startDragBlock",
  217 + :stop => "stopDragBlock",
  218 + :cursor => "'move'",
  219 + :cursorAt => '{ left: 0, top:0, right:0, bottom:0 }',
  220 + }.merge(options)
  221 + draggable_element(element_id, draggable_options)
203 end 222 end
204 223
205 def block_edit_buttons(block) 224 def block_edit_buttons(block)
206 buttons = [] 225 buttons = []
207 nowhere = 'javascript: return false;' 226 nowhere = 'javascript: return false;'
208 227
209 - if modifiable?(block) 228 + if movable?(block)
210 if block.first? 229 if block.first?
211 buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere) 230 buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
212 else 231 else
@@ -229,15 +248,15 @@ module BoxesHelper @@ -229,15 +248,15 @@ module BoxesHelper
229 buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' ) 248 buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
230 end 249 end
231 end 250 end
  251 + end
232 252
233 - if block.editable?  
234 - buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })  
235 - end 253 + if editable?(block)
  254 + buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
  255 + end
236 256
237 - if !block.main?  
238 - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})  
239 - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })  
240 - end 257 + if movable?(block) && !block.main?
  258 + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
  259 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
241 end 260 end
242 261
243 if block.respond_to?(:help) 262 if block.respond_to?(:help)
@@ -273,7 +292,11 @@ module BoxesHelper @@ -273,7 +292,11 @@ module BoxesHelper
273 classes 292 classes
274 end 293 end
275 294
276 - def modifiable?(block)  
277 - return !block.fixed || environment.admins.include?(user) 295 + def movable?(block)
  296 + return block.movable? || user.is_admin?
  297 + end
  298 +
  299 + def editable?(block)
  300 + return block.editable? || user.is_admin?
278 end 301 end
279 end 302 end
app/helpers/chat_helper.rb
@@ -9,12 +9,12 @@ module ChatHelper @@ -9,12 +9,12 @@ module ChatHelper
9 avatar = profile_image(user, :portrait, :class => 'avatar') 9 avatar = profile_image(user, :portrait, :class => 'avatar')
10 content_tag('span', 10 content_tag('span',
11 link_to(avatar + content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'), 11 link_to(avatar + content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'),
12 - '#', 12 + '',
13 :onclick => 'toggleMenu(this); return false', 13 :onclick => 'toggleMenu(this); return false',
14 :class => icon_class + ' simplemenu-trigger' 14 :class => icon_class + ' simplemenu-trigger'
15 ) + 15 ) +
16 content_tag('ul', 16 content_tag('ul',
17 - links.map{|link| content_tag('li', link_to(link[1], '#', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"), 17 + links.map{|link| content_tag('li', link_to(link[1], '', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"),
18 :style => 'display: none; z-index: 100', 18 :style => 'display: none; z-index: 100',
19 :class => 'simplemenu-submenu' 19 :class => 'simplemenu-submenu'
20 ), 20 ),
app/helpers/comment_helper.rb
1 module CommentHelper 1 module CommentHelper
  2 + include DatesHelper
2 3
3 def article_title(article, args = {}) 4 def article_title(article, args = {})
4 title = article.title 5 title = article.title
@@ -15,7 +16,7 @@ module CommentHelper @@ -15,7 +16,7 @@ module CommentHelper
15 content_tag('span', show_date(article.published_at), :class => 'date') + 16 content_tag('span', show_date(article.published_at), :class => 'date') +
16 content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') + 17 content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') +
17 content_tag('span', comments, :class => 'comments'), 18 content_tag('span', comments, :class => 'comments'),
18 - :class => 'created-at' 19 + :class => 'publishing-info'
19 ) 20 )
20 end 21 end
21 title 22 title
app/helpers/content_viewer_helper.rb
@@ -2,6 +2,7 @@ module ContentViewerHelper @@ -2,6 +2,7 @@ module ContentViewerHelper
2 2
3 include BlogHelper 3 include BlogHelper
4 include ForumHelper 4 include ForumHelper
  5 + include DatesHelper
5 6
6 def display_number_of_comments(n) 7 def display_number_of_comments(n)
7 base_str = "<span class='comment-count hide'>#{n}</span>" 8 base_str = "<span class='comment-count hide'>#{n}</span>"
@@ -24,16 +25,35 @@ module ContentViewerHelper @@ -24,16 +25,35 @@ module ContentViewerHelper
24 unless args[:no_comments] || !article.accept_comments 25 unless args[:no_comments] || !article.accept_comments
25 comments = (" - %s") % link_to_comments(article) 26 comments = (" - %s") % link_to_comments(article)
26 end 27 end
  28 + date_format = show_with_right_format_date article
27 title << content_tag('span', 29 title << content_tag('span',
28 - content_tag('span', show_date(article.published_at), :class => 'date') + 30 + date_format +
29 content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') + 31 content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') +
30 content_tag('span', comments, :class => 'comments'), 32 content_tag('span', comments, :class => 'comments'),
31 - :class => 'created-at' 33 + :class => 'publishing-info'
32 ) 34 )
33 end 35 end
34 title 36 title
35 end 37 end
36 38
  39 + def show_with_right_format_date article
  40 + date_format = article.environment.date_format
  41 + use_numbers = false
  42 + year = true
  43 + left_time = false
  44 + if date_format == 'numbers_with_year'
  45 + use_numbers = true
  46 + elsif date_format == 'numbers'
  47 + use_numbers = true
  48 + year = false
  49 + elsif date_format == 'month_name'
  50 + year = false
  51 + elsif date_format == 'past_time'
  52 + left_time = true
  53 + end
  54 + content_tag('span', show_time(article.published_at, use_numbers , year, left_time), :class => 'date')
  55 + end
  56 +
37 def link_to_comments(article, args = {}) 57 def link_to_comments(article, args = {})
38 return '' unless article.accept_comments? 58 return '' unless article.accept_comments?
39 reference_to_article number_of_comments(article), article, 'comments_list' 59 reference_to_article number_of_comments(article), article, 'comments_list'
app/helpers/dates_helper.rb
@@ -2,6 +2,7 @@ require &#39;noosfero/i18n&#39; @@ -2,6 +2,7 @@ require &#39;noosfero/i18n&#39;
2 2
3 module DatesHelper 3 module DatesHelper
4 4
  5 + include ActionView::Helpers::DateHelper
5 def months 6 def months
6 I18n.t('date.month_names') 7 I18n.t('date.month_names')
7 end 8 end
@@ -15,10 +16,12 @@ module DatesHelper @@ -15,10 +16,12 @@ module DatesHelper
15 end 16 end
16 17
17 # formats a date for displaying. 18 # formats a date for displaying.
18 - def show_date(date, use_numbers = false, year=true) 19 + def show_date(date, use_numbers = false, year = true, left_time = false)
19 if date && use_numbers 20 if date && use_numbers
20 date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}') 21 date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}')
21 date_format % { :day => date.day, :month => date.month, :year => date.year } 22 date_format % { :day => date.day, :month => date.month, :year => date.year }
  23 + elsif date && left_time
  24 + date_format = time_ago_in_words(date)
22 elsif date 25 elsif date
23 date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}') 26 date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}')
24 date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year } 27 date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year }
@@ -40,9 +43,14 @@ module DatesHelper @@ -40,9 +43,14 @@ module DatesHelper
40 end 43 end
41 44
42 # formats a datetime for displaying. 45 # formats a datetime for displaying.
43 - def show_time(time)  
44 - if time  
45 - _('%{day} %{month} %{year}, %{hour}:%{minutes}') % { :year => time.year, :month => month_name(time.month), :day => time.day, :hour => time.hour, :minutes => time.strftime("%M") } 46 + def show_time(time, use_numbers = false, year = true, left_time = false)
  47 + if time && use_numbers
  48 + _('%{month}/%{day}/%{year}, %{hour}:%{minutes}') % { :year => (year ? time.year : ''), :month => time.month, :day => time.day, :hour => time.hour, :minutes => time.strftime("%M") }
  49 + elsif time && left_time
  50 + date_format = time_ago_in_words(time)
  51 + elsif time
  52 + date_format = year ? _('%{month_name} %{day}, %{year} %{hour}:%{minutes}') : _('%{month_name} %{day} %{hour}:%{minutes}')
  53 + date_format % { :day => time.day, :month_name => month_name(time.month), :year => time.year, :hour => time.hour, :minutes => time.strftime("%M") }
46 else 54 else
47 '' 55 ''
48 end 56 end
@@ -50,7 +58,7 @@ module DatesHelper @@ -50,7 +58,7 @@ module DatesHelper
50 58
51 def show_period(date1, date2 = nil, use_numbers = false) 59 def show_period(date1, date2 = nil, use_numbers = false)
52 if (date1 == date2) || (date2.nil?) 60 if (date1 == date2) || (date2.nil?)
53 - show_date(date1, use_numbers) 61 + show_time(date1, use_numbers)
54 else 62 else
55 if date1.year == date2.year 63 if date1.year == date2.year
56 if date1.month == date2.month 64 if date1.month == date2.month
@@ -69,8 +77,8 @@ module DatesHelper @@ -69,8 +77,8 @@ module DatesHelper
69 end 77 end
70 else 78 else
71 _('from %{date1} to %{date2}') % { 79 _('from %{date1} to %{date2}') % {
72 - :date1 => show_date(date1, use_numbers),  
73 - :date2 => show_date(date2, use_numbers) 80 + :date1 => show_time(date1, use_numbers),
  81 + :date2 => show_time(date2, use_numbers)
74 } 82 }
75 end 83 end
76 end 84 end
@@ -103,18 +111,18 @@ module DatesHelper @@ -103,18 +111,18 @@ module DatesHelper
103 111
104 def build_date(year, month, day = 1) 112 def build_date(year, month, day = 1)
105 if year.blank? and month.blank? and day.blank? 113 if year.blank? and month.blank? and day.blank?
106 - Date.today 114 + DateTime.now
107 else 115 else
108 if year.blank? 116 if year.blank?
109 - year = Date.today.year 117 + year = DateTime.now.year
110 end 118 end
111 if month.blank? 119 if month.blank?
112 - month = Date.today.month 120 + month = DateTime.now.month
113 end 121 end
114 if day.blank? 122 if day.blank?
115 day = 1 123 day = 1
116 end 124 end
117 - Date.new(year.to_i, month.to_i, day.to_i) 125 + DateTime.new(year.to_i, month.to_i, day.to_i)
118 end 126 end
119 end 127 end
120 128
app/helpers/email_template_helper.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +module EmailTemplateHelper
  2 +
  3 + def mail_with_template(params={})
  4 + if params[:email_template].present?
  5 + params[:body] = params[:email_template].parsed_body(params[:template_params])
  6 + params[:subject] = params[:email_template].parsed_subject(params[:template_params])
  7 + params[:content_type] = "text/html"
  8 + end
  9 + mail(params.except(:email_template))
  10 + end
  11 +
  12 +end
app/helpers/events_helper.rb
1 module EventsHelper 1 module EventsHelper
2 2
  3 + include DatesHelper
3 def list_events(date, events) 4 def list_events(date, events)
4 title = _('Events for %s') % show_date_month(date) 5 title = _('Events for %s') % show_date_month(date)
5 content_tag('h2', title) + 6 content_tag('h2', title) +
@@ -15,7 +16,7 @@ module EventsHelper @@ -15,7 +16,7 @@ module EventsHelper
15 16
16 content_tag( 'tr', 17 content_tag( 'tr',
17 content_tag('td', 18 content_tag('td',
18 - content_tag('div', show_date(article.start_date) + ( article.end_date.nil? ? '' : (_(" to ") + show_date(article.end_date))),:class => 'event-date' ) + 19 + content_tag('div', show_time(article.start_date) + ( article.end_date.nil? ? '' : (_(" to ") + show_time(article.end_date))),:class => 'event-date' ) +
19 content_tag('div',link_to(article.name,article.url),:class => 'event-title') + 20 content_tag('div',link_to(article.name,article.url),:class => 'event-title') +
20 content_tag('div',(article.address.nil? or article.address == '') ? '' : (_('Place: ') + article.address),:class => 'event-place') 21 content_tag('div',(article.address.nil? or article.address == '') ? '' : (_('Place: ') + article.address),:class => 'event-place')
21 ) 22 )
@@ -29,7 +30,7 @@ module EventsHelper @@ -29,7 +30,7 @@ module EventsHelper
29 # the day itself 30 # the day itself
30 date, 31 date,
31 # is there any events in this date? 32 # is there any events in this date?
32 - events.any? {|event| event.date_range.include?(date)}, 33 + events.any? {|event| event.date_range.cover?(date)},
33 # is this date in the current month? 34 # is this date in the current month?
34 true 35 true
35 ] 36 ]
app/helpers/folder_helper.rb
1 -require 'short_filename'  
2 -  
3 module FolderHelper 1 module FolderHelper
4 2
5 - include ShortFilename  
6 include ArticleHelper 3 include ArticleHelper
7 4
8 def list_contents(configure={}) 5 def list_contents(configure={})
@@ -10,8 +7,8 @@ module FolderHelper @@ -10,8 +7,8 @@ module FolderHelper
10 configure[:list_type] ||= :folder 7 configure[:list_type] ||= :folder
11 if !configure[:contents].blank? 8 if !configure[:contents].blank?
12 configure[:contents] = configure[:contents].paginate( 9 configure[:contents] = configure[:contents].paginate(
13 - :order => "updated_at DESC",  
14 - :per_page => 10, 10 + :order => "name ASC",
  11 + :per_page => 30,
15 :page => params[:npage] 12 :page => params[:npage]
16 ) 13 )
17 14
@@ -25,49 +22,32 @@ module FolderHelper @@ -25,49 +22,32 @@ module FolderHelper
25 articles.select {|article| article.display_to?(user)} 22 articles.select {|article| article.display_to?(user)}
26 end 23 end
27 24
28 - def display_content_in_listing(configure={})  
29 - recursive = configure[:recursive] || false  
30 - list_type = configure[:list_type] || :folder  
31 - level = configure[:level] || 0  
32 - content = FilePresenter.for configure[:content] 25 + def display_content_icon(content_item)
  26 + content = FilePresenter.for content_item
33 content_link = if content.image? 27 content_link = if content.image?
34 - link_to('&nbsp;' * (level * 4) +  
35 - image_tag(icon_for_article(content)) + short_filename(content.name), 28 + link_to(
  29 + image_tag(icon_for_article(content, :bigicon)),
36 content.url.merge(:view => true) 30 content.url.merge(:view => true)
37 ) 31 )
38 else 32 else
39 - link_to('&nbsp;' * (level * 4) +  
40 - short_filename(content.name),  
41 - content.url.merge(:view => true), :class => icon_for_article(content) 33 + link_to('',
  34 + content.url.merge(:view => true),
  35 + :class => icon_for_article(content, :bigicon)
42 ) 36 )
43 end 37 end
44 - result = content_tag(  
45 - 'tr',  
46 - content_tag('td', content_link ) +  
47 - content_tag('td', show_date(content.updated_at), :class => 'last-update'),  
48 - :class => "#{list_type}-item"  
49 - )  
50 - if recursive  
51 - result + content.children.map {|item|  
52 - display_content_in_listing :content=>item, :recursive=>recursive,  
53 - :list_type=>list_type, :level=>level+1  
54 - }.join("\n")  
55 - else  
56 - result  
57 - end  
58 end 38 end
59 39
60 - def icon_for_article(article) 40 + def icon_for_article(article, size = 'icon')
61 article = FilePresenter.for article 41 article = FilePresenter.for article
62 - icon = article.respond_to?(:icon_name) ?  
63 - article.icon_name :  
64 - article.class.icon_name(article)  
65 - if (icon =~ /\//)  
66 - icon 42 + if article.respond_to?(:sized_icon)
  43 + article.sized_icon(size)
67 else 44 else
68 - klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ') 45 + icon = article.respond_to?(:icon_name) ?
  46 + article.icon_name :
  47 + article.class.icon_name(article)
  48 + klasses = "#{size} " + [icon].flatten.map{|name| "#{size}-"+name}.join(' ')
69 if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter) 49 if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter)
70 - klasses += ' icon-upload-file' 50 + klasses += " #{size}-upload-file"
71 end 51 end
72 klasses 52 klasses
73 end 53 end
app/helpers/forms_helper.rb
@@ -151,7 +151,7 @@ module FormsHelper @@ -151,7 +151,7 @@ module FormsHelper
151 datepicker_options[:close_text] ||= _('Done') 151 datepicker_options[:close_text] ||= _('Done')
152 datepicker_options[:constrain_input] ||= true 152 datepicker_options[:constrain_input] ||= true
153 datepicker_options[:current_text] ||= _('Today') 153 datepicker_options[:current_text] ||= _('Today')
154 - datepicker_options[:date_format] ||= 'mm/dd/yy' 154 + datepicker_options[:date_format] ||= 'yy/mm/dd'
155 datepicker_options[:day_names] ||= [_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')] 155 datepicker_options[:day_names] ||= [_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')]
156 datepicker_options[:day_names_min] ||= [_('Su'), _('Mo'), _('Tu'), _('We'), _('Th'), _('Fr'), _('Sa')] 156 datepicker_options[:day_names_min] ||= [_('Su'), _('Mo'), _('Tu'), _('We'), _('Th'), _('Fr'), _('Sa')]
157 datepicker_options[:day_names_short] ||= [_('Sun'), _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat')] 157 datepicker_options[:day_names_short] ||= [_('Sun'), _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat')]
@@ -236,7 +236,7 @@ module FormsHelper @@ -236,7 +236,7 @@ module FormsHelper
236 weekHeader: #{datepicker_options[:week_header].to_json}, 236 weekHeader: #{datepicker_options[:week_header].to_json},
237 yearRange: #{datepicker_options[:year_range].to_json}, 237 yearRange: #{datepicker_options[:year_range].to_json},
238 yearSuffix: #{datepicker_options[:year_suffix].to_json} 238 yearSuffix: #{datepicker_options[:year_suffix].to_json}
239 - }) 239 + }).datepicker('setDate', new Date('#{value}'))
240 </script> 240 </script>
241 ".html_safe 241 ".html_safe
242 result 242 result
app/helpers/forum_helper.rb
1 module ForumHelper 1 module ForumHelper
  2 + include ActionView::Helpers::DateHelper
2 3
3 def cms_label_for_new_children 4 def cms_label_for_new_children
4 _('New discussion topic') 5 _('New discussion topic')
@@ -42,9 +43,9 @@ module ForumHelper @@ -42,9 +43,9 @@ module ForumHelper
42 def last_topic_update(article) 43 def last_topic_update(article)
43 info = article.info_from_last_update 44 info = article.info_from_last_update
44 if info[:author_url] 45 if info[:author_url]
45 - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url]) 46 + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url])
46 else 47 else
47 - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + info[:author_name] 48 + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + info[:author_name]
48 end 49 end
49 end 50 end
50 51
app/helpers/layout_helper.rb
@@ -28,7 +28,7 @@ module LayoutHelper @@ -28,7 +28,7 @@ module LayoutHelper
28 end 28 end
29 29
30 def noosfero_javascript 30 def noosfero_javascript
31 - plugins_javascripts = @plugins.flat_map{ |plugin| plugin.js_files.map{ |js| plugin.class.public_path(js, true) } }.flatten 31 + plugins_javascripts = @plugins.flat_map{ |plugin| Array.wrap(plugin.js_files).map{ |js| plugin.class.public_path(js, true) } }.flatten
32 32
33 output = '' 33 output = ''
34 output += render 'layouts/javascript' 34 output += render 'layouts/javascript'
@@ -38,6 +38,8 @@ module LayoutHelper @@ -38,6 +38,8 @@ module LayoutHelper
38 output += theme_javascript_ng.to_s 38 output += theme_javascript_ng.to_s
39 output += javascript_tag 'render_all_jquery_ui_widgets()' 39 output += javascript_tag 'render_all_jquery_ui_widgets()'
40 40
  41 + output += templete_javascript_ng.to_s
  42 +
41 output 43 output
42 end 44 end
43 45
@@ -70,24 +72,13 @@ module LayoutHelper @@ -70,24 +72,13 @@ module LayoutHelper
70 end 72 end
71 73
72 def template_stylesheet_path 74 def template_stylesheet_path
73 - if profile.nil?  
74 - "/designs/templates/#{environment.layout_template}/stylesheets/style.css"  
75 - else  
76 - "/designs/templates/#{profile.layout_template}/stylesheets/style.css"  
77 - end 75 + File.join template_path, "/stylesheets/style.css"
78 end 76 end
79 77
80 78
81 def icon_theme_stylesheet_path 79 def icon_theme_stylesheet_path
82 - icon_themes = []  
83 theme_icon_themes = theme_option(:icon_theme) || [] 80 theme_icon_themes = theme_option(:icon_theme) || []
84 - for icon_theme in theme_icon_themes do  
85 - theme_path = "designs/icons/#{icon_theme}/style.css"  
86 - if File.exists?(Rails.root.join('public', theme_path))  
87 - icon_themes << theme_path  
88 - end  
89 - end  
90 - icon_themes 81 + theme_icon_themes.map{ |it| "designs/icons/#{it}/style.css" }
91 end 82 end
92 83
93 def jquery_ui_theme_stylesheet_path 84 def jquery_ui_theme_stylesheet_path
app/helpers/manage_products_helper.rb
@@ -75,9 +75,12 @@ module ManageProductsHelper @@ -75,9 +75,12 @@ module ManageProductsHelper
75 end 75 end
76 76
77 def categories_container(categories_selection_html, hierarchy_html = '') 77 def categories_container(categories_selection_html, hierarchy_html = '')
78 - hidden_field_tag('selected_category_id') +  
79 - content_tag('div', hierarchy_html, :id => 'hierarchy_navigation') +  
80 - content_tag('div', categories_selection_html, :id => 'categories_container_wrapper') 78 + content_tag 'div',
  79 + render('categories_autocomplete') +
  80 + hidden_field_tag('selected_category_id') +
  81 + content_tag('div', hierarchy_html, :id => 'hierarchy_navigation') +
  82 + content_tag('div', categories_selection_html, :id => 'categories_container_wrapper'),
  83 + :id => 'categories-container'
81 end 84 end
82 85
83 def select_for_categories(categories, level = 0) 86 def select_for_categories(categories, level = 0)
app/helpers/profile_editor_helper.rb
@@ -141,8 +141,9 @@ module ProfileEditorHelper @@ -141,8 +141,9 @@ module ProfileEditorHelper
141 ) 141 )
142 end 142 end
143 143
144 - def control_panel_button(title, icon, url)  
145 - link_to title, url, :class => 'control-panel-%s' % icon 144 + def control_panel_button(title, icon, url, html_options = {})
  145 + html_options ||= {}
  146 + link_to title, url, html_options.merge(:class => 'control-panel-%s' % icon)
146 end 147 end
147 148
148 def unchangeable_privacy_field(profile) 149 def unchangeable_privacy_field(profile)
app/helpers/profile_helper.rb
@@ -190,4 +190,22 @@ module ProfileHelper @@ -190,4 +190,22 @@ module ProfileHelper
190 end 190 end
191 end 191 end
192 192
  193 + def display_custom_field(title, profile, field, force = false)
  194 + unless force || profile.may_display_field_to?(field, user)
  195 + return
  196 + end
  197 + value = profile.custom_fields[field][:value]
  198 + !value.blank? ? content_tag('tr', content_tag('td', title) + content_tag('td', value)) : ''
  199 + end
  200 +
  201 + def display_custom_fields(profile)
  202 + fields = []
  203 + profile.custom_fields.each { |custom_field_key,custom_field_data|
  204 + if !profile.fields_privacy.blank? && profile.fields_privacy.include?(custom_field_key)
  205 + fields << display_custom_field(custom_field_data[:title], profile, custom_field_key) if profile.fields_privacy[custom_field_key] == 'public'
  206 + end
  207 + }
  208 + fields.size >= 1 ? content_tag('tr', content_tag('th', _('Custom Fields'), { :colspan => 2 })) + fields.join.html_safe : ''
  209 + end
  210 +
193 end 211 end
app/helpers/search_helper.rb
@@ -106,6 +106,10 @@ module SearchHelper @@ -106,6 +106,10 @@ module SearchHelper
106 end 106 end
107 end 107 end
108 108
  109 + def city_with_state_for_profile(p)
  110 + city_with_state(p.region) || [p.city, p.state].compact.reject(&:blank?).join(', ')
  111 + end
  112 +
109 def display_selector(asset, display, float = 'right') 113 def display_selector(asset, display, float = 'right')
110 display = nil if display.blank? 114 display = nil if display.blank?
111 display ||= asset_class(asset).default_search_display 115 display ||= asset_class(asset).default_search_display
app/helpers/task_helper.rb 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +module TaskHelper
  2 +
  3 + def task_email_template(description, email_templates, task, include_blank=true)
  4 + return '' unless email_templates.present?
  5 +
  6 + content_tag(
  7 + :div,
  8 + labelled_form_field(description, select_tag("tasks[#{task.id}][task][email_template_id]", options_from_collection_for_select(email_templates, :id, :name), :include_blank => include_blank, 'data-url' => url_for(:controller => 'profile_email_templates', :action => 'show_parsed', :profile => profile.identifier))),
  9 + :class => 'template-selection'
  10 + )
  11 + end
  12 +
  13 + def task_action action
  14 + base_url = { action: action }
  15 + url_for(base_url.merge(filter_params))
  16 + end
  17 +
  18 + def filter_params
  19 + filter_fields = ['filter_type', 'filter_text', 'filter_responsible', 'filter_tags']
  20 + params.select {|filter| filter if filter_fields.include? filter }
  21 + end
  22 +
  23 +end
app/helpers/tinymce_helper.rb
@@ -17,9 +17,10 @@ module TinymceHelper @@ -17,9 +17,10 @@ module TinymceHelper
17 searchreplace wordcount visualblocks visualchars code fullscreen 17 searchreplace wordcount visualblocks visualchars code fullscreen
18 insertdatetime media nonbreaking save table contextmenu directionality 18 insertdatetime media nonbreaking save table contextmenu directionality
19 emoticons template paste textcolor colorpicker textpattern], 19 emoticons template paste textcolor colorpicker textpattern],
  20 + :image_advtab => true,
20 :language => tinymce_language 21 :language => tinymce_language
21 22
22 - options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image" 23 + options[:toolbar1] = "fullscreen | insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
23 if options[:mode] == 'simple' 24 if options[:mode] == 'simple'
24 options[:menubar] = false 25 options[:menubar] = false
25 else 26 else
app/helpers/users_helper.rb
@@ -14,7 +14,7 @@ module UsersHelper @@ -14,7 +14,7 @@ module UsersHelper
14 select_field = select_tag(:filter, options, :onchange => onchange) 14 select_field = select_tag(:filter, options, :onchange => onchange)
15 content_tag('div', 15 content_tag('div',
16 content_tag('strong', _('Filter')) + ': ' + select_field, 16 content_tag('strong', _('Filter')) + ': ' + select_field,
17 - :class => "environment-users-customize-search" 17 + :class => "environment-profiles-customize-search"
18 ) 18 )
19 end 19 end
20 20
app/mailers/scrap_notifier.rb
1 class ScrapNotifier < ActionMailer::Base 1 class ScrapNotifier < ActionMailer::Base
2 def notification(scrap) 2 def notification(scrap)
3 sender, receiver = scrap.sender, scrap.receiver 3 sender, receiver = scrap.sender, scrap.receiver
  4 + # for tests
  5 + return unless receiver.email
  6 +
4 @recipient = receiver.name 7 @recipient = receiver.name
5 @sender = sender.name 8 @sender = sender.name
6 @sender_link = sender.url 9 @sender_link = sender.url
app/mailers/task_mailer.rb
1 class TaskMailer < ActionMailer::Base 1 class TaskMailer < ActionMailer::Base
2 2
  3 + include EmailTemplateHelper
  4 +
3 def target_notification(task, message) 5 def target_notification(task, message)
4 @message = extract_message(message) 6 @message = extract_message(message)
5 @target = task.target.name 7 @target = task.target.name
6 @environment = task.environment.name 8 @environment = task.environment.name
7 @url = generate_environment_url(task, :controller => 'home') 9 @url = generate_environment_url(task, :controller => 'home')
8 - url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.tasks_url) 10 + url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.tasks_url.merge(:script_name => Noosfero.root('/')))
9 @tasks_url = url_for_tasks_list 11 @tasks_url = url_for_tasks_list
10 12
11 mail( 13 mail(
@@ -34,10 +36,12 @@ class TaskMailer &lt; ActionMailer::Base @@ -34,10 +36,12 @@ class TaskMailer &lt; ActionMailer::Base
34 @environment = task.requestor.environment.name 36 @environment = task.requestor.environment.name
35 @url = url_for(:host => task.requestor.environment.default_hostname, :controller => 'home') 37 @url = url_for(:host => task.requestor.environment.default_hostname, :controller => 'home')
36 38
37 - mail( 39 + mail_with_template(
38 to: task.requestor.notification_emails, 40 to: task.requestor.notification_emails,
39 from: self.class.generate_from(task), 41 from: self.class.generate_from(task),
40 - subject: '[%s] %s' % [task.requestor.environment.name, task.target_notification_description] 42 + subject: '[%s] %s' % [task.requestor.environment.name, task.target_notification_description],
  43 + email_template: task.email_template,
  44 + template_params: {:environment => task.requestor.environment, :task => task, :message => @message, :url => @url, :requestor => task.requestor}
41 ) 45 )
42 end 46 end
43 47
@@ -56,7 +60,7 @@ class TaskMailer &lt; ActionMailer::Base @@ -56,7 +60,7 @@ class TaskMailer &lt; ActionMailer::Base
56 end 60 end
57 61
58 def generate_environment_url(task, url = {}) 62 def generate_environment_url(task, url = {})
59 - url_for(Noosfero.url_options.merge(:host => task.environment.default_hostname).merge(url)) 63 + url_for(Noosfero.url_options.merge(:host => task.environment.default_hostname).merge(url).merge(:script_name => Noosfero.root('/')))
60 end 64 end
61 65
62 end 66 end
app/mailers/user_mailer.rb
1 class UserMailer < ActionMailer::Base 1 class UserMailer < ActionMailer::Base
  2 +
  3 + include EmailTemplateHelper
  4 +
2 def activation_email_notify(user) 5 def activation_email_notify(user)
3 user_email = "#{user.login}@#{user.email_domain}" 6 user_email = "#{user.login}@#{user.email_domain}"
4 @name = user.name 7 @name = user.name
@@ -22,10 +25,12 @@ class UserMailer &lt; ActionMailer::Base @@ -22,10 +25,12 @@ class UserMailer &lt; ActionMailer::Base
22 @redirection = (true if user.return_to) 25 @redirection = (true if user.return_to)
23 @join = (user.community_to_join if user.community_to_join) 26 @join = (user.community_to_join if user.community_to_join)
24 27
25 - mail( 28 + mail_with_template(
26 from: "#{user.environment.name} <#{user.environment.contact_email}>", 29 from: "#{user.environment.name} <#{user.environment.contact_email}>",
27 to: user.email, 30 to: user.email,
28 subject: _("[%s] Activate your account") % [user.environment.name], 31 subject: _("[%s] Activate your account") % [user.environment.name],
  32 + template_params: {:environment => user.environment, :activation_code => @activation_code, :redirection => @redirection, :join => @join},
  33 + email_template: user.environment.email_templates.find_by_template_type(:user_activation),
29 ) 34 )
30 end 35 end
31 36
app/models/abuse_complaint.rb
@@ -40,10 +40,6 @@ class AbuseComplaint &lt; Task @@ -40,10 +40,6 @@ class AbuseComplaint &lt; Task
40 true 40 true
41 end 41 end
42 42
43 - def reject_details  
44 - true  
45 - end  
46 -  
47 def icon 43 def icon
48 {:type => :profile_image, :profile => reported, :url => reported.url} 44 {:type => :profile_image, :profile => reported, :url => reported.url}
49 end 45 end
app/models/add_friend.rb
@@ -14,6 +14,9 @@ class AddFriend &lt; Task @@ -14,6 +14,9 @@ class AddFriend &lt; Task
14 alias :friend :target 14 alias :friend :target
15 alias :friend= :target= 15 alias :friend= :target=
16 16
  17 + validates :requestor, :kind_of => { :kind => Person }
  18 + validates :target, :kind_of => { :kind => Person }
  19 +
17 after_create do |task| 20 after_create do |task|
18 TaskMailer.invitation_notification(task).deliver unless task.friend 21 TaskMailer.invitation_notification(task).deliver unless task.friend
19 remove_from_suggestion_list(task) 22 remove_from_suggestion_list(task)
@@ -54,7 +57,7 @@ class AddFriend &lt; Task @@ -54,7 +57,7 @@ class AddFriend &lt; Task
54 end 57 end
55 58
56 def remove_from_suggestion_list(task) 59 def remove_from_suggestion_list(task)
57 - suggestion = task.requestor.profile_suggestions.find_by_suggestion_id task.target.id 60 + suggestion = task.requestor.suggested_profiles.find_by_suggestion_id task.target.id
58 suggestion.disable if suggestion 61 suggestion.disable if suggestion
59 end 62 end
60 end 63 end
app/models/add_member.rb
@@ -2,6 +2,9 @@ class AddMember &lt; Task @@ -2,6 +2,9 @@ class AddMember &lt; Task
2 2
3 validates_presence_of :requestor_id, :target_id 3 validates_presence_of :requestor_id, :target_id
4 4
  5 + validates :requestor, kind_of: {kind: Person}
  6 + validates :target, kind_of: {kind: Organization}
  7 +
5 alias :person :requestor 8 alias :person :requestor
6 alias :person= :requestor= 9 alias :person= :requestor=
7 10
@@ -26,7 +29,8 @@ class AddMember &lt; Task @@ -26,7 +29,8 @@ class AddMember &lt; Task
26 end 29 end
27 30
28 def information 31 def information
29 - {:message => _('%{requestor} wants to be a member of this community.')} 32 + {:message => _("%{requestor} wants to be a member of '%{organization}'."),
  33 + variables: {requestor: requestor.name, organization: organization.name}}
30 end 34 end
31 35
32 def accept_details 36 def accept_details
@@ -42,7 +46,7 @@ class AddMember &lt; Task @@ -42,7 +46,7 @@ class AddMember &lt; Task
42 end 46 end
43 47
44 def target_notification_description 48 def target_notification_description
45 - _('%{requestor} wants to be a member of this community.') % {:requestor => requestor.name} 49 + _("%{requestor} wants to be a member of '%{organization}'.") % {:requestor => requestor.name, :organization => organization.name}
46 end 50 end
47 51
48 def target_notification_message 52 def target_notification_message
app/models/approve_article.rb
1 class ApproveArticle < Task 1 class ApproveArticle < Task
2 validates_presence_of :requestor_id, :target_id 2 validates_presence_of :requestor_id, :target_id
3 3
  4 + validates :requestor, kind_of: {kind: Person}
  5 + validate :allowed_requestor
  6 +
  7 + def allowed_requestor
  8 + if target
  9 + if target.person? && requestor != target
  10 + self.errors.add(:requestor, _('You can not post articles to other users.'))
  11 + end
  12 + if target.organization? && !target.members.include?(requestor) && target.environment.portal_community != target
  13 + self.errors.add(:requestor, _('Only members can post articles on communities.'))
  14 + end
  15 + end
  16 + end
  17 +
4 def article_title 18 def article_title
5 article ? article.title : _('(The original text was removed)') 19 article ? article.title : _('(The original text was removed)')
6 end 20 end
7 - 21 +
8 def article 22 def article
9 Article.find_by_id data[:article_id] 23 Article.find_by_id data[:article_id]
10 end 24 end
@@ -82,10 +96,6 @@ class ApproveArticle &lt; Task @@ -82,10 +96,6 @@ class ApproveArticle &lt; Task
82 true 96 true
83 end 97 end
84 98
85 - def reject_details  
86 - true  
87 - end  
88 -  
89 def default_decision 99 def default_decision
90 if article 100 if article
91 'skip' 101 'skip'
@@ -128,4 +138,9 @@ class ApproveArticle &lt; Task @@ -128,4 +138,9 @@ class ApproveArticle &lt; Task
128 message 138 message
129 end 139 end
130 140
  141 + def request_is_member_of_target
  142 + unless requestor.is_member_of?(target)
  143 + errors.add(:approve_article, N_('Requestor must be a member of target.'))
  144 + end
  145 + end
131 end 146 end
app/models/approve_comment.rb
@@ -60,10 +60,6 @@ class ApproveComment &lt; Task @@ -60,10 +60,6 @@ class ApproveComment &lt; Task
60 true 60 true
61 end 61 end
62 62
63 - def reject_details  
64 - true  
65 - end  
66 -  
67 def default_decision 63 def default_decision
68 if article 64 if article
69 'skip' 65 'skip'
app/models/article.rb
1 -  
2 class Article < ActiveRecord::Base 1 class Article < ActiveRecord::Base
3 2
4 attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, 3 attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent,
5 :allow_members_to_edit, :translation_of_id, :language, 4 :allow_members_to_edit, :translation_of_id, :language,
6 :license_id, :parent_id, :display_posts_in_current_language, 5 :license_id, :parent_id, :display_posts_in_current_language,
7 :category_ids, :posts_per_page, :moderate_comments, 6 :category_ids, :posts_per_page, :moderate_comments,
8 - :accept_comments, :feed, :published, :source, 7 + :accept_comments, :feed, :published, :source, :source_name,
9 :highlighted, :notify_comments, :display_hits, :slug, 8 :highlighted, :notify_comments, :display_hits, :slug,
10 :external_feed_builder, :display_versions, :external_link, 9 :external_feed_builder, :display_versions, :external_link,
11 - :image_builder, :show_to_followers 10 + :author, :published_at, :person_followers, :show_to_followers, :image_builder
12 11
13 acts_as_having_image 12 acts_as_having_image
14 13
@@ -25,6 +24,16 @@ class Article &lt; ActiveRecord::Base @@ -25,6 +24,16 @@ class Article &lt; ActiveRecord::Base
25 :display => %w[full] 24 :display => %w[full]
26 } 25 }
27 26
  27 + def initialize(*params)
  28 + super
  29 +
  30 + if !params.blank? && params.first.has_key?(:profile) && !params.first[:profile].blank?
  31 + profile = params.first[:profile]
  32 + self.published = false unless profile.public?
  33 + end
  34 +
  35 + end
  36 +
28 def self.default_search_display 37 def self.default_search_display
29 'full' 38 'full'
30 end 39 end
@@ -61,6 +70,10 @@ class Article &lt; ActiveRecord::Base @@ -61,6 +70,10 @@ class Article &lt; ActiveRecord::Base
61 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' 70 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id'
62 belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id' 71 belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id'
63 72
  73 + #Article followers relation
  74 + has_many :article_followers, :dependent => :destroy
  75 + has_many :person_followers, :class_name => 'Person', :through => :article_followers, :source => :person
  76 +
64 has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' 77 has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc'
65 78
66 has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ] 79 has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ]
@@ -86,6 +99,8 @@ class Article &lt; ActiveRecord::Base @@ -86,6 +99,8 @@ class Article &lt; ActiveRecord::Base
86 belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id 99 belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id
87 before_destroy :rotate_translations 100 before_destroy :rotate_translations
88 101
  102 + acts_as_voteable
  103 +
89 before_create do |article| 104 before_create do |article|
90 article.published_at ||= Time.now 105 article.published_at ||= Time.now
91 if article.reference_article && !article.parent 106 if article.reference_article && !article.parent
@@ -117,9 +132,11 @@ class Article &lt; ActiveRecord::Base @@ -117,9 +132,11 @@ class Article &lt; ActiveRecord::Base
117 {:include => 'categories_including_virtual', :conditions => { 'categories.id' => category.id }} 132 {:include => 'categories_including_virtual', :conditions => { 'categories.id' => category.id }}
118 } 133 }
119 134
  135 + include TimeScopes
  136 +
120 scope :by_range, lambda { |range| { 137 scope :by_range, lambda { |range| {
121 :conditions => [ 138 :conditions => [
122 - 'published_at BETWEEN :start_date AND :end_date', { :start_date => range.first, :end_date => range.last } 139 + 'articles.published_at BETWEEN :start_date AND :end_date', { :start_date => range.first, :end_date => range.last }
123 ] 140 ]
124 }} 141 }}
125 142
@@ -248,7 +265,7 @@ class Article &lt; ActiveRecord::Base @@ -248,7 +265,7 @@ class Article &lt; ActiveRecord::Base
248 } 265 }
249 266
250 scope :public, 267 scope :public,
251 - :conditions => [ "advertise = ? AND published = ? AND profiles.visible = ? AND profiles.public_profile = ?", true, true, true, true ], :joins => [:profile] 268 + :conditions => [ "articles.advertise = ? AND articles.published = ? AND profiles.visible = ? AND profiles.public_profile = ?", true, true, true, true ], :joins => [:profile]
252 269
253 scope :more_recent, 270 scope :more_recent,
254 :conditions => [ "advertise = ? AND published = ? AND profiles.visible = ? AND profiles.public_profile = ? AND 271 :conditions => [ "advertise = ? AND published = ? AND profiles.visible = ? AND profiles.public_profile = ? AND
@@ -491,11 +508,11 @@ class Article &lt; ActiveRecord::Base @@ -491,11 +508,11 @@ class Article &lt; ActiveRecord::Base
491 return [] if user.nil? || (profile && !profile.public? && !user.follows?(profile)) 508 return [] if user.nil? || (profile && !profile.public? && !user.follows?(profile))
492 where( 509 where(
493 [ 510 [
494 - "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ?  
495 - OR (show_to_followers = ? AND ?)", true, user.id, user.id, 511 + "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ?
  512 + OR (show_to_followers = ? AND ? AND profile_id IN (?))", true, user.id, user.id,
496 profile.nil? ? false : user.has_permission?(:view_private_content, profile), 513 profile.nil? ? false : user.has_permission?(:view_private_content, profile),
497 - true, user.follows?(profile)  
498 - ] 514 + true, (profile.nil? ? true : user.follows?(profile)), ( profile.nil? ? (user.friends.select('profiles.id')) : [profile.id])
  515 + ]
499 ) 516 )
500 } 517 }
501 518
@@ -509,7 +526,7 @@ class Article &lt; ActiveRecord::Base @@ -509,7 +526,7 @@ class Article &lt; ActiveRecord::Base
509 526
510 def display_to?(user = nil) 527 def display_to?(user = nil)
511 if published? 528 if published?
512 - profile.display_info_to?(user) 529 + (profile.secret? || !profile.visible?) ? profile.display_info_to?(user) : true
513 else 530 else
514 if !user 531 if !user
515 false 532 false
@@ -567,25 +584,24 @@ class Article &lt; ActiveRecord::Base @@ -567,25 +584,24 @@ class Article &lt; ActiveRecord::Base
567 profile.visible? && profile.public? && published? 584 profile.visible? && profile.public? && published?
568 end 585 end
569 586
570 -  
571 - def copy(options = {}) 587 + def copy_without_save(options = {})
572 attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) } 588 attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) }
573 attrs.merge!(options) 589 attrs.merge!(options)
574 object = self.class.new 590 object = self.class.new
575 attrs.each do |key, value| 591 attrs.each do |key, value|
576 object.send(key.to_s+'=', value) 592 object.send(key.to_s+'=', value)
577 end 593 end
  594 + object
  595 + end
  596 +
  597 + def copy(options = {})
  598 + object = copy_without_save(options)
578 object.save 599 object.save
579 object 600 object
580 end 601 end
581 602
582 def copy!(options = {}) 603 def copy!(options = {})
583 - attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) }  
584 - attrs.merge!(options)  
585 - object = self.class.new  
586 - attrs.each do |key, value|  
587 - object.send(key.to_s+'=', value)  
588 - end 604 + object = copy_without_save(options)
589 object.save! 605 object.save!
590 object 606 object
591 end 607 end
@@ -615,6 +631,11 @@ class Article &lt; ActiveRecord::Base @@ -615,6 +631,11 @@ class Article &lt; ActiveRecord::Base
615 self.hits += 1 631 self.hits += 1
616 end 632 end
617 633
  634 + def self.hit(articles)
  635 + Article.where(:id => articles.map(&:id)).update_all('hits = hits + 1')
  636 + articles.each { |a| a.hits += 1 }
  637 + end
  638 +
618 def can_display_hits? 639 def can_display_hits?
619 true 640 true
620 end 641 end
@@ -623,6 +644,14 @@ class Article &lt; ActiveRecord::Base @@ -623,6 +644,14 @@ class Article &lt; ActiveRecord::Base
623 can_display_hits? && display_hits 644 can_display_hits? && display_hits
624 end 645 end
625 646
  647 + def display_media_panel?
  648 + can_display_media_panel? && environment.enabled?('media_panel')
  649 + end
  650 +
  651 + def can_display_media_panel?
  652 + false
  653 + end
  654 +
626 def image? 655 def image?
627 false 656 false
628 end 657 end
@@ -692,6 +721,11 @@ class Article &lt; ActiveRecord::Base @@ -692,6 +721,11 @@ class Article &lt; ActiveRecord::Base
692 person ? person.id : nil 721 person ? person.id : nil
693 end 722 end
694 723
  724 + #FIXME make this test
  725 + def author_custom_image(size = :icon)
  726 + author ? author.profile_custom_image(size) : nil
  727 + end
  728 +
695 def version_license(version_number = nil) 729 def version_license(version_number = nil)
696 return license if version_number.nil? 730 return license if version_number.nil?
697 profile.environment.licenses.find_by_id(get_version(version_number).license_id) 731 profile.environment.licenses.find_by_id(get_version(version_number).license_id)
@@ -713,8 +747,9 @@ class Article &lt; ActiveRecord::Base @@ -713,8 +747,9 @@ class Article &lt; ActiveRecord::Base
713 paragraphs.empty? ? '' : paragraphs.first.to_html 747 paragraphs.empty? ? '' : paragraphs.first.to_html
714 end 748 end
715 749
716 - def lead  
717 - abstract.blank? ? first_paragraph.html_safe : abstract.html_safe 750 + def lead(length = nil)
  751 + content = abstract.blank? ? first_paragraph.html_safe : abstract.html_safe
  752 + length.present? ? content.truncate(length) : content
718 end 753 end
719 754
720 def short_lead 755 def short_lead
@@ -781,6 +816,14 @@ class Article &lt; ActiveRecord::Base @@ -781,6 +816,14 @@ class Article &lt; ActiveRecord::Base
781 true 816 true
782 end 817 end
783 818
  819 + def view_page
  820 + "content_viewer/view_page"
  821 + end
  822 +
  823 + def to_liquid
  824 + HashWithIndifferentAccess.new :name => name, :abstract => abstract, :body => body, :id => id, :parent_id => parent_id, :author => author
  825 + end
  826 +
784 private 827 private
785 828
786 def sanitize_tag_list 829 def sanitize_tag_list
app/models/article_block.rb
@@ -3,7 +3,15 @@ class ArticleBlock &lt; Block @@ -3,7 +3,15 @@ class ArticleBlock &lt; Block
3 attr_accessible :article_id 3 attr_accessible :article_id
4 4
5 def self.description 5 def self.description
6 - _('Display one of your contents') 6 + _('Display one of your contents.')
  7 + end
  8 +
  9 + def self.short_description
  10 + _('Show one article')
  11 + end
  12 +
  13 + def self.pretty_name
  14 + _('Article')
7 end 15 end
8 16
9 def help 17 def help
app/models/article_follower.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class ArticleFollower < ActiveRecord::Base
  2 + attr_accessible :article_id, :person_id, :since
  3 + belongs_to :article
  4 + belongs_to :person
  5 +end
app/models/block.rb
1 class Block < ActiveRecord::Base 1 class Block < ActiveRecord::Base
2 2
3 - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed 3 + attr_accessible :title, :display, :limit, :box_id, :posts_per_page,
  4 + :visualization_format, :language, :display_user,
  5 + :box, :edit_modes, :move_modes, :mirror
4 6
5 # to be able to generate HTML 7 # to be able to generate HTML
6 include ActionView::Helpers::UrlHelper 8 include ActionView::Helpers::UrlHelper
@@ -13,17 +15,29 @@ class Block &lt; ActiveRecord::Base @@ -13,17 +15,29 @@ class Block &lt; ActiveRecord::Base
13 15
14 acts_as_list :scope => :box 16 acts_as_list :scope => :box
15 belongs_to :box 17 belongs_to :box
  18 + belongs_to :mirror_block, :class_name => "Block"
  19 + has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id"
16 20
17 acts_as_having_settings 21 acts_as_having_settings
18 22
19 scope :enabled, :conditions => { :enabled => true } 23 scope :enabled, :conditions => { :enabled => true }
20 24
  25 + after_save do |block|
  26 + if block.owner.kind_of?(Profile) && block.owner.is_template? && block.mirror?
  27 + block.observers.each do |observer|
  28 + observer.copy_from(block)
  29 + observer.title = block.title
  30 + observer.save
  31 + end
  32 + end
  33 + end
  34 +
21 def embedable? 35 def embedable?
22 false 36 false
23 end 37 end
24 38
25 def get_limit 39 def get_limit
26 - [0,limit].max 40 + [0,limit.to_i].max
27 end 41 end
28 42
29 def embed_code 43 def embed_code
@@ -110,8 +124,13 @@ class Block &lt; ActiveRecord::Base @@ -110,8 +124,13 @@ class Block &lt; ActiveRecord::Base
110 # * <tt>'all'</tt>: the block is always displayed 124 # * <tt>'all'</tt>: the block is always displayed
111 settings_items :language, :type => :string, :default => 'all' 125 settings_items :language, :type => :string, :default => 'all'
112 126
113 - # The block can be configured to be fixed. Only can be edited by environment admins  
114 - settings_items :fixed, :type => :boolean, :default => false 127 + # The block can be configured to define the edition modes options. Only can be edited by environment admins
  128 + # It can assume the following values:
  129 + #
  130 + # * <tt>'all'</tt>: the block owner has all edit options for this block
  131 + # * <tt>'none'</tt>: the block owner can't do anything with the block
  132 + settings_items :edit_modes, :type => :string, :default => 'all'
  133 + settings_items :move_modes, :type => :string, :default => 'all'
115 134
116 # returns the description of the block, used when the user sees a list of 135 # returns the description of the block, used when the user sees a list of
117 # blocks to choose one to include in the design. 136 # blocks to choose one to include in the design.
@@ -122,6 +141,36 @@ class Block &lt; ActiveRecord::Base @@ -122,6 +141,36 @@ class Block &lt; ActiveRecord::Base
122 '(dummy)' 141 '(dummy)'
123 end 142 end
124 143
  144 + def self.short_description
  145 + self.pretty_name
  146 + end
  147 +
  148 + def self.icon
  149 + "/images/icon_block.png"
  150 + end
  151 +
  152 + def self.icon_path
  153 + basename = self.name.split('::').last.underscore
  154 + File.join('blocks', basename, 'icon.png')
  155 + end
  156 +
  157 + def self.pretty_name
  158 + self.name.split('::').last.gsub('Block','')
  159 + end
  160 +
  161 + def self.default_icon_path
  162 + 'icon_block.png'
  163 + end
  164 +
  165 + def self.preview_path
  166 + base_name = self.name.split('::').last.underscore
  167 + File.join('blocks', base_name,'previews')
  168 + end
  169 +
  170 + def self.default_preview_path
  171 + "block_preview.png"
  172 + end
  173 +
125 # Returns the content to be used for this block. 174 # Returns the content to be used for this block.
126 # 175 #
127 # This method can return several types of objects: 176 # This method can return several types of objects:
@@ -148,7 +197,11 @@ class Block &lt; ActiveRecord::Base @@ -148,7 +197,11 @@ class Block &lt; ActiveRecord::Base
148 197
149 # Is this block editable? (Default to <tt>false</tt>) 198 # Is this block editable? (Default to <tt>false</tt>)
150 def editable? 199 def editable?
151 - true 200 + self.edit_modes == "all"
  201 + end
  202 +
  203 + def movable?
  204 + self.move_modes == "all"
152 end 205 end
153 206
154 # must always return false, except on MainBlock clas. 207 # must always return false, except on MainBlock clas.
@@ -228,6 +281,21 @@ class Block &lt; ActiveRecord::Base @@ -228,6 +281,21 @@ class Block &lt; ActiveRecord::Base
228 } 281 }
229 end 282 end
230 283
  284 + def edit_block_options
  285 + @edit_options ||= {
  286 + 'all' => _('Can be modified'),
  287 + 'none' => _('Cannot be modified')
  288 + }
  289 + end
  290 +
  291 + def move_block_options
  292 + @move_options ||= {
  293 + 'all' => _('Can be moved'),
  294 + 'none' => _('Cannot be moved')
  295 + }
  296 + end
  297 +
  298 +
231 def duplicate 299 def duplicate
232 duplicated_block = self.dup 300 duplicated_block = self.dup
233 duplicated_block.display = 'never' 301 duplicated_block.display = 'never'
@@ -243,6 +311,10 @@ class Block &lt; ActiveRecord::Base @@ -243,6 +311,10 @@ class Block &lt; ActiveRecord::Base
243 self.position = block.position 311 self.position = block.position
244 end 312 end
245 313
  314 + def add_observer(block)
  315 + self.observers << block
  316 + end
  317 +
246 private 318 private
247 319
248 def home_page_path 320 def home_page_path
app/models/blog.rb
@@ -76,9 +76,12 @@ class Blog &lt; Folder @@ -76,9 +76,12 @@ class Blog &lt; Folder
76 end 76 end
77 77
78 settings_items :visualization_format, :type => :string, :default => 'full' 78 settings_items :visualization_format, :type => :string, :default => 'full'
79 - validates_inclusion_of :visualization_format, :in => [ 'full', 'short', 'short+pic' ], :if => :visualization_format 79 + validates_inclusion_of :visualization_format,
  80 + :in => [ 'full', 'short', 'short+pic', 'compact'],
  81 + :if => :visualization_format
80 82
81 - settings_items :display_posts_in_current_language, :type => :boolean, :default => false 83 + settings_items :display_posts_in_current_language,
  84 + :type => :boolean, :default => false
82 85
83 alias :display_posts_in_current_language? :display_posts_in_current_language 86 alias :display_posts_in_current_language? :display_posts_in_current_language
84 87
app/models/change_password.rb
@@ -18,6 +18,8 @@ class ChangePassword &lt; Task @@ -18,6 +18,8 @@ class ChangePassword &lt; Task
18 18
19 validates_presence_of :requestor 19 validates_presence_of :requestor
20 20
  21 + validates :requestor, kind_of: {kind: Person}
  22 +
21 ################################################### 23 ###################################################
22 # validations for updating a ChangePassword task 24 # validations for updating a ChangePassword task
23 25
@@ -26,6 +28,13 @@ class ChangePassword &lt; Task @@ -26,6 +28,13 @@ class ChangePassword &lt; Task
26 validates_presence_of :password_confirmation, :on => :update, :if => lambda { |change| change.status != Task::Status::CANCELLED } 28 validates_presence_of :password_confirmation, :on => :update, :if => lambda { |change| change.status != Task::Status::CANCELLED }
27 validates_confirmation_of :password, :if => lambda { |change| change.status != Task::Status::CANCELLED } 29 validates_confirmation_of :password, :if => lambda { |change| change.status != Task::Status::CANCELLED }
28 30
  31 + before_save :set_email_template
  32 +
  33 + def set_email_template
  34 + template = environment.email_templates.find_by_template_type(:user_change_password)
  35 + data[:email_template_id] = template.id unless template.nil?
  36 + end
  37 +
29 def environment 38 def environment
30 requestor.environment unless requestor.nil? 39 requestor.environment unless requestor.nil?
31 end 40 end
app/models/chat_message.rb
@@ -4,4 +4,5 @@ class ChatMessage &lt; ActiveRecord::Base @@ -4,4 +4,5 @@ class ChatMessage &lt; ActiveRecord::Base
4 belongs_to :to, :class_name => 'Profile' 4 belongs_to :to, :class_name => 'Profile'
5 belongs_to :from, :class_name => 'Profile' 5 belongs_to :from, :class_name => 'Profile'
6 6
  7 + validates_presence_of :from, :to
7 end 8 end
app/models/comment.rb
@@ -20,6 +20,8 @@ class Comment &lt; ActiveRecord::Base @@ -20,6 +20,8 @@ class Comment &lt; ActiveRecord::Base
20 20
21 scope :without_reply, :conditions => ['reply_of_id IS NULL'] 21 scope :without_reply, :conditions => ['reply_of_id IS NULL']
22 22
  23 + include TimeScopes
  24 +
23 # unauthenticated authors: 25 # unauthenticated authors:
24 validates_presence_of :name, :if => (lambda { |record| !record.email.blank? }) 26 validates_presence_of :name, :if => (lambda { |record| !record.email.blank? })
25 validates_presence_of :email, :if => (lambda { |record| !record.name.blank? }) 27 validates_presence_of :email, :if => (lambda { |record| !record.name.blank? })
@@ -32,11 +34,13 @@ class Comment &lt; ActiveRecord::Base @@ -32,11 +34,13 @@ class Comment &lt; ActiveRecord::Base
32 rec.errors.add(:name, _('{fn} can only be informed for unauthenticated authors').fix_i18n) 34 rec.errors.add(:name, _('{fn} can only be informed for unauthenticated authors').fix_i18n)
33 end 35 end
34 end 36 end
35 - 37 +
36 acts_as_having_settings 38 acts_as_having_settings
37 39
38 xss_terminate :only => [ :body, :title, :name ], :on => 'validation' 40 xss_terminate :only => [ :body, :title, :name ], :on => 'validation'
39 41
  42 + acts_as_voteable
  43 +
40 def comment_root 44 def comment_root
41 (reply_of && reply_of.comment_root) || self 45 (reply_of && reply_of.comment_root) || self
42 end 46 end
@@ -65,6 +69,11 @@ class Comment &lt; ActiveRecord::Base @@ -65,6 +69,11 @@ class Comment &lt; ActiveRecord::Base
65 author ? author.url : nil 69 author ? author.url : nil
66 end 70 end
67 71
  72 + #FIXME make this test
  73 + def author_custom_image(size = :icon)
  74 + author ? author.profile_custom_image(size) : nil
  75 + end
  76 +
68 def url 77 def url
69 article.view_url.merge(:anchor => anchor) 78 article.view_url.merge(:anchor => anchor)
70 end 79 end
app/models/communities_block.rb
@@ -3,9 +3,17 @@ class CommunitiesBlock &lt; ProfileListBlock @@ -3,9 +3,17 @@ class CommunitiesBlock &lt; ProfileListBlock
3 attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type 3 attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type
4 4
5 def self.description 5 def self.description
  6 + _("<p>Display all of your communities.</p><p>You could choose the amount of communities will be displayed and you could priorize that profiles with images.</p> <p>The view all button is always present in the block.</p>")
  7 + end
  8 +
  9 + def self.short_description
6 _('Communities') 10 _('Communities')
7 end 11 end
8 12
  13 + def self.pretty_name
  14 + _('Communities Block')
  15 + end
  16 +
9 def default_title 17 def default_title
10 n_('{#} community', '{#} communities', profile_count) 18 n_('{#} community', '{#} communities', profile_count)
11 end 19 end
app/models/community.rb
@@ -86,8 +86,8 @@ class Community &lt; Organization @@ -86,8 +86,8 @@ class Community &lt; Organization
86 {:title => _('Community Info and settings'), :icon => 'edit-profile-group'} 86 {:title => _('Community Info and settings'), :icon => 'edit-profile-group'}
87 end 87 end
88 88
89 - def activities  
90 - Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.target_id = #{self.id} and action_tracker.verb != 'join_community' and action_tracker.verb != 'leave_scrap' UNION SELECT at.id, at.updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} at INNER JOIN articles a ON at.target_id = a.id WHERE a.profile_id = #{self.id} AND at.target_type = 'Article' ORDER BY updated_at DESC") 89 + def exclude_verbs_on_activities
  90 + %w[join_community leave_scrap]
91 end 91 end
92 92
93 end 93 end
app/models/create_community.rb
@@ -3,6 +3,9 @@ class CreateCommunity &lt; Task @@ -3,6 +3,9 @@ class CreateCommunity &lt; Task
3 validates_presence_of :requestor_id, :target_id 3 validates_presence_of :requestor_id, :target_id
4 validates_presence_of :name 4 validates_presence_of :name
5 5
  6 + validates :requestor, kind_of: {kind: Person}
  7 + validates :target, kind_of: {kind: Environment}
  8 +
6 alias :environment :target 9 alias :environment :target
7 alias :environment= :target= 10 alias :environment= :target=
8 11
@@ -56,10 +59,6 @@ class CreateCommunity &lt; Task @@ -56,10 +59,6 @@ class CreateCommunity &lt; Task
56 end 59 end
57 end 60 end
58 61
59 - def reject_details  
60 - true  
61 - end  
62 -  
63 # tells if this request was rejected 62 # tells if this request was rejected
64 def rejected? 63 def rejected?
65 self.status == Task::Status::CANCELLED 64 self.status == Task::Status::CANCELLED
app/models/create_enterprise.rb
@@ -27,6 +27,8 @@ class CreateEnterprise &lt; Task @@ -27,6 +27,8 @@ class CreateEnterprise &lt; Task
27 # checks for actual attributes 27 # checks for actual attributes
28 validates_presence_of :requestor_id, :target_id 28 validates_presence_of :requestor_id, :target_id
29 29
  30 + validates :requestor, kind_of: {kind: Person}
  31 +
30 # checks for admins required attributes 32 # checks for admins required attributes
31 DATA_FIELDS.each do |attribute| 33 DATA_FIELDS.each do |attribute|
32 validates_presence_of attribute, :if => lambda { |obj| obj.environment.required_enterprise_fields.include?(attribute) } 34 validates_presence_of attribute, :if => lambda { |obj| obj.environment.required_enterprise_fields.include?(attribute) }
@@ -164,10 +166,6 @@ class CreateEnterprise &lt; Task @@ -164,10 +166,6 @@ class CreateEnterprise &lt; Task
164 {:message => _('%{requestor} wants to create enterprise %{subject}.')} 166 {:message => _('%{requestor} wants to create enterprise %{subject}.')}
165 end 167 end
166 168
167 - def reject_details  
168 - true  
169 - end  
170 -  
171 def task_created_message 169 def task_created_message
172 _('Your request for registering enterprise "%{enterprise}" at %{environment} was just received. It will be reviewed by the validator organization of your choice, according to its methods and criteria. 170 _('Your request for registering enterprise "%{enterprise}" at %{environment} was just received. It will be reviewed by the validator organization of your choice, according to its methods and criteria.
173 171
app/models/email_activation.rb
1 class EmailActivation < Task 1 class EmailActivation < Task
2 2
3 validates_presence_of :requestor_id, :target_id 3 validates_presence_of :requestor_id, :target_id
  4 +
  5 + validates :requestor, kind_of: {kind: Person}
  6 + validates :target, kind_of: {kind: Environment}
  7 +
4 validate :already_requested, :on => :create 8 validate :already_requested, :on => :create
5 9
6 alias :environment :target 10 alias :environment :target
7 alias :person :requestor 11 alias :person :requestor
8 12
9 def already_requested 13 def already_requested
10 - if !self.requestor.nil? && self.requestor.user.email_activation_pending? 14 + if !self.requestor.nil? && self.requestor.person? && self.requestor.user.email_activation_pending?
11 self.errors.add(:base, _('You have already requested activation of your mailbox.')) 15 self.errors.add(:base, _('You have already requested activation of your mailbox.'))
12 end 16 end
13 end 17 end
app/models/email_template.rb 0 → 100644
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +class EmailTemplate < ActiveRecord::Base
  2 +
  3 + belongs_to :owner, :polymorphic => true
  4 +
  5 + attr_accessible :template_type, :subject, :body, :owner, :name
  6 +
  7 + validates_presence_of :name
  8 +
  9 + validates :name, uniqueness: { scope: [:owner_type, :owner_id] }
  10 +
  11 + validates :template_type, uniqueness: { scope: [:owner_type, :owner_id] }, if: :unique_by_type?
  12 +
  13 + def parsed_body(params)
  14 + @parsed_body ||= parse(body, params)
  15 + end
  16 +
  17 + def parsed_subject(params)
  18 + @parsed_subject ||= parse(subject, params)
  19 + end
  20 +
  21 + def self.available_types
  22 + {
  23 + :task_rejection => {:description => _('Task Rejection'), :owner_type => Profile},
  24 + :task_acceptance => {:description => _('Task Acceptance'), :owner_type => Profile},
  25 + :organization_members => {:description => _('Organization Members'), :owner_type => Profile},
  26 + :user_activation => {:description => _('User Activation'), :unique => true, :owner_type => Environment},
  27 + :user_change_password => {:description => _('Change User Password'), :unique => true, :owner_type => Environment}
  28 + }
  29 + end
  30 +
  31 + def available_types
  32 + HashWithIndifferentAccess.new EmailTemplate.available_types.select {|k, v| owner.kind_of?(v[:owner_type])}
  33 + end
  34 +
  35 + def type_description
  36 + available_types.fetch(template_type, {})[:description]
  37 + end
  38 +
  39 + def unique_by_type?
  40 + available_types.fetch(template_type, {})[:unique]
  41 + end
  42 +
  43 + protected
  44 +
  45 + def parse(source, params)
  46 + template = Liquid::Template.parse(source)
  47 + template.render(HashWithIndifferentAccess.new(params))
  48 + end
  49 +
  50 +end
app/models/enterprise.rb
@@ -15,12 +15,15 @@ class Enterprise &lt; Organization @@ -15,12 +15,15 @@ class Enterprise &lt; Organization
15 15
16 N_('Enterprise') 16 N_('Enterprise')
17 17
18 - has_many :products, :foreign_key => :profile_id, :dependent => :destroy, :order => 'name ASC' 18 + acts_as_trackable after_add: proc{ |p, t| notify_activity t }
  19 +
  20 + has_many :products, :foreign_key => :profile_id, :dependent => :destroy
  21 + has_many :product_categories, :through => :products
19 has_many :inputs, :through => :products 22 has_many :inputs, :through => :products
20 has_many :production_costs, :as => :owner 23 has_many :production_costs, :as => :owner
21 24
22 has_many :favorite_enterprise_people 25 has_many :favorite_enterprise_people
23 - has_many :fans, through: :favorite_enterprise_people, source: :person 26 + has_many :fans, source: :person, through: :favorite_enterprise_people
24 27
25 def product_categories 28 def product_categories
26 ProductCategory.by_enterprise(self) 29 ProductCategory.by_enterprise(self)
@@ -194,10 +197,6 @@ class Enterprise &lt; Organization @@ -194,10 +197,6 @@ class Enterprise &lt; Organization
194 true 197 true
195 end 198 end
196 199
197 - def activities  
198 - Scrap.find_by_sql("SELECT id, updated_at, 'Scrap' AS klass FROM scraps WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, 'ActionTracker::Record' AS klass FROM action_tracker WHERE action_tracker.target_id = #{self.id} UNION SELECT action_tracker.id, action_tracker.updated_at, 'ActionTracker::Record' AS klass FROM action_tracker INNER JOIN articles ON action_tracker.target_id = articles.id WHERE articles.profile_id = #{self.id} AND action_tracker.target_type = 'Article' ORDER BY updated_at DESC")  
199 - end  
200 -  
201 def catalog_url 200 def catalog_url
202 { :profile => identifier, :controller => 'catalog'} 201 { :profile => identifier, :controller => 'catalog'}
203 end 202 end
@@ -206,4 +205,9 @@ class Enterprise &lt; Organization @@ -206,4 +205,9 @@ class Enterprise &lt; Organization
206 '' 205 ''
207 end 206 end
208 207
  208 + def followed_by? person
  209 + super or self.fans.where(id: person.id).count > 0
  210 + end
  211 +
  212 +
209 end 213 end
app/models/enterprise_activation.rb
@@ -8,6 +8,8 @@ class EnterpriseActivation &lt; Task @@ -8,6 +8,8 @@ class EnterpriseActivation &lt; Task
8 8
9 validates_presence_of :enterprise 9 validates_presence_of :enterprise
10 10
  11 + validates :target, kind_of: {kind: Enterprise}
  12 +
11 def perform 13 def perform
12 self.enterprise.enable self.requestor 14 self.enterprise.enable self.requestor
13 end 15 end
app/models/enterprise_homepage.rb
@@ -35,4 +35,8 @@ class EnterpriseHomepage &lt; Article @@ -35,4 +35,8 @@ class EnterpriseHomepage &lt; Article
35 false 35 false
36 end 36 end
37 37
  38 + def can_display_media_panel?
  39 + true
  40 + end
  41 +
38 end 42 end
app/models/environment.rb
@@ -3,7 +3,17 @@ @@ -3,7 +3,17 @@
3 # domains. 3 # domains.
4 class Environment < ActiveRecord::Base 4 class Environment < ActiveRecord::Base
5 5
6 - attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body, :members_whitelist_enabled, :members_whitelist, :highlighted_news_amount, :portal_news_amount 6 + attr_accessible :name, :is_default, :signup_welcome_text_subject,
  7 + :signup_welcome_text_body, :terms_of_use,
  8 + :message_for_disabled_enterprise, :news_amount_by_folder,
  9 + :default_language, :languages, :description,
  10 + :organization_approval_method, :enabled_plugins,
  11 + :enabled_features, :redirection_after_login,
  12 + :redirection_after_signup, :contact_email, :theme,
  13 + :reports_lower_bound, :noreply_email,
  14 + :signup_welcome_screen_body, :members_whitelist_enabled,
  15 + :members_whitelist, :highlighted_news_amount,
  16 + :portal_news_amount, :date_format
7 17
8 has_many :users 18 has_many :users
9 19
@@ -11,14 +21,23 @@ class Environment &lt; ActiveRecord::Base @@ -11,14 +21,23 @@ class Environment &lt; ActiveRecord::Base
11 21
12 has_many :tasks, :dependent => :destroy, :as => 'target' 22 has_many :tasks, :dependent => :destroy, :as => 'target'
13 has_many :search_terms, :as => :context 23 has_many :search_terms, :as => :context
  24 + has_many :email_templates, :foreign_key => :owner_id
14 25
15 IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ 26 IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/
16 27
  28 + validates_inclusion_of :date_format,
  29 + :in => [ 'numbers_with_year', 'numbers',
  30 + 'month_name_with_year', 'month_name',
  31 + 'past_time'],
  32 + :if => :date_format
  33 +
17 def self.verify_filename(filename) 34 def self.verify_filename(filename)
18 filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS 35 filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS
19 filename 36 filename
20 end 37 end
21 38
  39 + NUMBER_OF_BOXES = 4
  40 +
22 PERMISSIONS['Environment'] = { 41 PERMISSIONS['Environment'] = {
23 'view_environment_admin_panel' => N_('View environment admin panel'), 42 'view_environment_admin_panel' => N_('View environment admin panel'),
24 'edit_environment_features' => N_('Edit environment features'), 43 'edit_environment_features' => N_('Edit environment features'),
@@ -27,10 +46,12 @@ class Environment &lt; ActiveRecord::Base @@ -27,10 +46,12 @@ class Environment &lt; ActiveRecord::Base
27 'manage_environment_roles' => N_('Manage environment roles'), 46 'manage_environment_roles' => N_('Manage environment roles'),
28 'manage_environment_validators' => N_('Manage environment validators'), 47 'manage_environment_validators' => N_('Manage environment validators'),
29 'manage_environment_users' => N_('Manage environment users'), 48 'manage_environment_users' => N_('Manage environment users'),
  49 + 'manage_environment_organizations' => N_('Manage environment organizations'),
30 'manage_environment_templates' => N_('Manage environment templates'), 50 'manage_environment_templates' => N_('Manage environment templates'),
31 'manage_environment_licenses' => N_('Manage environment licenses'), 51 'manage_environment_licenses' => N_('Manage environment licenses'),
32 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'), 52 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'),
33 'edit_appearance' => N_('Edit appearance'), 53 'edit_appearance' => N_('Edit appearance'),
  54 + 'manage_email_templates' => N_('Manage Email Templates'),
34 } 55 }
35 56
36 module Roles 57 module Roles
@@ -72,7 +93,8 @@ class Environment &lt; ActiveRecord::Base @@ -72,7 +93,8 @@ class Environment &lt; ActiveRecord::Base
72 'edit_profile_design', 93 'edit_profile_design',
73 'manage_products', 94 'manage_products',
74 'manage_friends', 95 'manage_friends',
75 - 'perform_task' 96 + 'perform_task',
  97 + 'view_tasks'
76 ] 98 ]
77 ) 99 )
78 end 100 end
@@ -108,6 +130,7 @@ class Environment &lt; ActiveRecord::Base @@ -108,6 +130,7 @@ class Environment &lt; ActiveRecord::Base
108 'disable_select_city_for_contact' => _('Disable state/city select for contact form'), 130 'disable_select_city_for_contact' => _('Disable state/city select for contact form'),
109 'disable_contact_person' => _('Disable contact for people'), 131 'disable_contact_person' => _('Disable contact for people'),
110 'disable_contact_community' => _('Disable contact for groups/communities'), 132 'disable_contact_community' => _('Disable contact for groups/communities'),
  133 + 'forbid_destroy_profile' => _('Forbid users of removing profiles'),
111 134
112 'products_for_enterprises' => _('Enable products for enterprises'), 135 'products_for_enterprises' => _('Enable products for enterprises'),
113 'enterprise_registration' => _('Enterprise registration'), 136 'enterprise_registration' => _('Enterprise registration'),
@@ -147,7 +170,8 @@ class Environment &lt; ActiveRecord::Base @@ -147,7 +170,8 @@ class Environment &lt; ActiveRecord::Base
147 'site_homepage' => _('Redirects the user to the environment homepage.'), 170 'site_homepage' => _('Redirects the user to the environment homepage.'),
148 'user_profile_page' => _('Redirects the user to his profile page.'), 171 'user_profile_page' => _('Redirects the user to his profile page.'),
149 'user_homepage' => _('Redirects the user to his homepage.'), 172 'user_homepage' => _('Redirects the user to his homepage.'),
150 - 'user_control_panel' => _('Redirects the user to his control panel.') 173 + 'user_control_panel' => _('Redirects the user to his control panel.'),
  174 + 'custom_url' => _('Specify the URL to redirect to:'),
151 } 175 }
152 end 176 end
153 validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true 177 validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true
@@ -172,7 +196,7 @@ class Environment &lt; ActiveRecord::Base @@ -172,7 +196,7 @@ class Environment &lt; ActiveRecord::Base
172 acts_as_having_boxes 196 acts_as_having_boxes
173 197
174 after_create do |env| 198 after_create do |env|
175 - 3.times do 199 + NUMBER_OF_BOXES.times do
176 env.boxes << Box.new 200 env.boxes << Box.new
177 end 201 end
178 202
@@ -228,6 +252,9 @@ class Environment &lt; ActiveRecord::Base @@ -228,6 +252,9 @@ class Environment &lt; ActiveRecord::Base
228 # store the Environment settings as YAML-serialized Hash. 252 # store the Environment settings as YAML-serialized Hash.
229 acts_as_having_settings :field => :settings 253 acts_as_having_settings :field => :settings
230 254
  255 + # introduce and explain to users something about the signup
  256 + settings_items :signup_intro, :type => String
  257 +
231 # the environment's terms of use: every user must accept them before registering. 258 # the environment's terms of use: every user must accept them before registering.
232 settings_items :terms_of_use, :type => String 259 settings_items :terms_of_use, :type => String
233 260
@@ -262,7 +289,20 @@ class Environment &lt; ActiveRecord::Base @@ -262,7 +289,20 @@ class Environment &lt; ActiveRecord::Base
262 settings_items :activation_blocked_text, :type => String 289 settings_items :activation_blocked_text, :type => String
263 settings_items :message_for_disabled_enterprise, :type => String, 290 settings_items :message_for_disabled_enterprise, :type => String,
264 :default => _('This enterprise needs to be enabled.') 291 :default => _('This enterprise needs to be enabled.')
265 - settings_items :location, :type => String 292 +
  293 + settings_items :contact_phone, type: String
  294 + settings_items :address, type: String
  295 + settings_items :city, type: String
  296 + settings_items :state, type: String
  297 + settings_items :country_name, type: String
  298 + settings_items :lat, type: Float
  299 + settings_items :lng, type: Float
  300 + settings_items :postal_code, type: String
  301 + settings_items :location, type: String
  302 +
  303 + alias_method :zip_code=, :postal_code
  304 + alias_method :zip_code, :postal_code
  305 +
266 settings_items :layout_template, :type => String, :default => 'default' 306 settings_items :layout_template, :type => String, :default => 'default'
267 settings_items :homepage, :type => String 307 settings_items :homepage, :type => String
268 settings_items :description, :type => String, :default => '<div style="text-align: center"><a href="http://noosfero.org/"><img src="/images/noosfero-network.png" alt="Noosfero"/></a></div>' 308 settings_items :description, :type => String, :default => '<div style="text-align: center"><a href="http://noosfero.org/"><img src="/images/noosfero-network.png" alt="Noosfero"/></a></div>'
@@ -306,6 +346,9 @@ class Environment &lt; ActiveRecord::Base @@ -306,6 +346,9 @@ class Environment &lt; ActiveRecord::Base
306 346
307 settings_items :signup_welcome_screen_body, :type => String 347 settings_items :signup_welcome_screen_body, :type => String
308 348
  349 + #Captcha settings
  350 + settings_items :api_captcha_settings, :type => ActiveSupport::HashWithIndifferentAccess, :default => {}
  351 +
309 def has_custom_welcome_screen? 352 def has_custom_welcome_screen?
310 settings[:signup_welcome_screen_body].present? 353 settings[:signup_welcome_screen_body].present?
311 end 354 end
@@ -337,6 +380,16 @@ class Environment &lt; ActiveRecord::Base @@ -337,6 +380,16 @@ class Environment &lt; ActiveRecord::Base
337 self.save! 380 self.save!
338 end 381 end
339 382
  383 + def enable_all_plugins
  384 + Noosfero::Plugin.available_plugin_names.each do |plugin|
  385 + plugin_name = plugin.to_s + "Plugin"
  386 + unless self.enabled_plugins.include?(plugin_name)
  387 + self.enabled_plugins += [plugin_name]
  388 + end
  389 + end
  390 + self.save!
  391 + end
  392 +
340 # Disables a feature identified by its name 393 # Disables a feature identified by its name
341 def disable(feature, must_save=true) 394 def disable(feature, must_save=true)
342 self.settings["#{feature}_enabled".to_sym] = false 395 self.settings["#{feature}_enabled".to_sym] = false
@@ -439,7 +492,8 @@ class Environment &lt; ActiveRecord::Base @@ -439,7 +492,8 @@ class Environment &lt; ActiveRecord::Base
439 end 492 end
440 493
441 def custom_person_fields 494 def custom_person_fields
442 - self.settings[:custom_person_fields].nil? ? {} : self.settings[:custom_person_fields] 495 + self.settings[:custom_person_fields] = {} if self.settings[:custom_person_fields].nil?
  496 + self.settings[:custom_person_fields]
443 end 497 end
444 498
445 def custom_person_fields=(values) 499 def custom_person_fields=(values)
@@ -737,8 +791,8 @@ class Environment &lt; ActiveRecord::Base @@ -737,8 +791,8 @@ class Environment &lt; ActiveRecord::Base
737 end 791 end
738 792
739 def is_default_template?(template) 793 def is_default_template?(template)
740 - is_default = template == community_default_template  
741 - is_default = is_default || template == person_default_template 794 + is_default = template == community_default_template
  795 + is_default = is_default || template == person_default_template
742 is_default = is_default || template == enterprise_default_template 796 is_default = is_default || template == enterprise_default_template
743 is_default 797 is_default
744 end 798 end
@@ -952,6 +1006,10 @@ class Environment &lt; ActiveRecord::Base @@ -952,6 +1006,10 @@ class Environment &lt; ActiveRecord::Base
952 self.licenses.any? 1006 self.licenses.any?
953 end 1007 end
954 1008
  1009 + def to_liquid
  1010 + HashWithIndifferentAccess.new :name => name
  1011 + end
  1012 +
955 private 1013 private
956 1014
957 def default_language_available 1015 def default_language_available
app/models/event.rb
@@ -3,13 +3,14 @@ require &#39;builder&#39; @@ -3,13 +3,14 @@ require &#39;builder&#39;
3 3
4 class Event < Article 4 class Event < Article
5 5
6 - attr_accessible :start_date, :end_date, :link, :address 6 + attr_accessible :start_date, :end_date, :link, :address, :presenter
7 7
8 def self.type_name 8 def self.type_name
9 _('Event') 9 _('Event')
10 end 10 end
11 11
12 settings_items :address, :type => :string 12 settings_items :address, :type => :string
  13 + settings_items :presenter, :type => :string
13 14
14 def link=(value) 15 def link=(value)
15 self.setting[:link] = maybe_add_http(value) 16 self.setting[:link] = maybe_add_http(value)
@@ -23,7 +24,7 @@ class Event &lt; Article @@ -23,7 +24,7 @@ class Event &lt; Article
23 24
24 def initialize(*args) 25 def initialize(*args)
25 super(*args) 26 super(*args)
26 - self.start_date ||= Date.today 27 + self.start_date ||= DateTime.now
27 end 28 end
28 29
29 validates_presence_of :title, :start_date 30 validates_presence_of :title, :start_date
@@ -35,7 +36,7 @@ class Event &lt; Article @@ -35,7 +36,7 @@ class Event &lt; Article
35 end 36 end
36 37
37 scope :by_day, lambda { |date| 38 scope :by_day, lambda { |date|
38 - { :conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}], 39 + { :conditions => [' start_date >= :start_date AND start_date <= :end_date AND end_date IS NULL OR (start_date <= :end_date AND end_date >= :start_date)', {:start_date => date.beginning_of_day, :end_date => date.end_of_day}],
39 :order => 'start_date ASC' 40 :order => 'start_date ASC'
40 } 41 }
41 } 42 }
@@ -80,7 +81,7 @@ class Event &lt; Article @@ -80,7 +81,7 @@ class Event &lt; Article
80 81
81 def self.date_range(year, month) 82 def self.date_range(year, month)
82 if year.nil? || month.nil? 83 if year.nil? || month.nil?
83 - today = Date.today 84 + today = DateTime.now
84 year = today.year 85 year = today.year
85 month = today.month 86 month = today.month
86 else 87 else
@@ -88,7 +89,7 @@ class Event &lt; Article @@ -88,7 +89,7 @@ class Event &lt; Article
88 month = month.to_i 89 month = month.to_i
89 end 90 end
90 91
91 - first_day = Date.new(year, month, 1) 92 + first_day = DateTime.new(year, month, 1)
92 last_day = first_day + 1.month - 1.day 93 last_day = first_day + 1.month - 1.day
93 94
94 first_day..last_day 95 first_day..last_day
@@ -98,51 +99,23 @@ class Event &lt; Article @@ -98,51 +99,23 @@ class Event &lt; Article
98 start_date..(end_date||start_date) 99 start_date..(end_date||start_date)
99 end 100 end
100 101
101 - # FIXME this shouldn't be needed  
102 - include ActionView::Helpers::TagHelper  
103 - include ActionView::Helpers::UrlHelper  
104 - include DatesHelper 102 + def first_paragraph
  103 + paragraphs = Nokogiri::HTML.fragment(self.body).css('p')
  104 + paragraphs.empty? ? '' : paragraphs.first.to_html
  105 + end
105 106
106 def to_html(options = {}) 107 def to_html(options = {})
  108 + event = self
  109 + format = options[:format]
107 110
108 - result = ''  
109 - html = ::Builder::XmlMarkup.new(:target => result)  
110 -  
111 - html.div(:class => 'event-info' ) {  
112 - html.ul(:class => 'event-data' ) {  
113 - html.li(:class => 'event-dates' ) {  
114 - html.span _('When:')  
115 - html.text! show_period(start_date, end_date)  
116 - } if start_date.present? || end_date.present?  
117 - html.li {  
118 - html.span _('URL:')  
119 - html.a(self.link || "", 'href' => self.link || "")  
120 - } if self.link.present?  
121 - html.li {  
122 - html.span _('Address:')  
123 - html.text! self.address || ""  
124 - } if self.address.present?  
125 - }  
126 -  
127 - # TODO: some good soul, please clean this ugly hack:  
128 - if self.body  
129 - html.div('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', :class => 'event-description')  
130 - end  
131 - }  
132 -  
133 - if self.body  
134 - if options[:format] == 'short'  
135 - result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', display_short_format(self))  
136 - else  
137 - result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', self.body)  
138 - end 111 + proc do
  112 + render :file => 'content_viewer/event_page', :locals => { :event => event,
  113 + :format => format }
139 end 114 end
140 -  
141 - result  
142 end 115 end
143 116
144 def duration 117 def duration
145 - ((self.end_date || self.start_date) - self.start_date).to_i 118 + (((self.end_date || self.start_date) - self.start_date).to_i/60/60/24)
146 end 119 end
147 120
148 alias_method :article_lead, :lead 121 alias_method :article_lead, :lead
@@ -162,6 +135,10 @@ class Event &lt; Article @@ -162,6 +135,10 @@ class Event &lt; Article
162 true 135 true
163 end 136 end
164 137
  138 + def can_display_media_panel?
  139 + true
  140 + end
  141 +
165 include Noosfero::TranslatableContent 142 include Noosfero::TranslatableContent
166 include MaybeAddHttp 143 include MaybeAddHttp
167 144
app/models/favorite_enterprise_person.rb
1 class FavoriteEnterprisePerson < ActiveRecord::Base 1 class FavoriteEnterprisePerson < ActiveRecord::Base
2 2
3 - self.table_name = :favorite_enteprises_people 3 + attr_accessible :person, :enterprise
  4 +
  5 + track_actions :favorite_enterprise, :after_create, keep_params: [:enterprise_name, :enterprise_url], if: proc{ |f| f.is_trackable? }
4 6
5 belongs_to :enterprise 7 belongs_to :enterprise
6 belongs_to :person 8 belongs_to :person
7 9
  10 + protected
  11 +
  12 + def is_trackable?
  13 + self.enterprise.public?
  14 + end
  15 +
  16 + def enterprise_name
  17 + self.enterprise.short_name(nil)
  18 + end
  19 + def enterprise_url
  20 + self.enterprise.url
  21 + end
  22 +
8 end 23 end
app/models/featured_products_block.rb
@@ -20,6 +20,10 @@ class FeaturedProductsBlock &lt; Block @@ -20,6 +20,10 @@ class FeaturedProductsBlock &lt; Block
20 _('Featured Products') 20 _('Featured Products')
21 end 21 end
22 22
  23 + def self.pretty_name
  24 + _('Featured Products')
  25 + end
  26 +
23 def products 27 def products
24 Product.find(self.product_ids) || [] 28 Product.find(self.product_ids) || []
25 end 29 end
app/models/feed_reader_block.rb
@@ -40,6 +40,10 @@ class FeedReaderBlock &lt; Block @@ -40,6 +40,10 @@ class FeedReaderBlock &lt; Block
40 _('Feed reader') 40 _('Feed reader')
41 end 41 end
42 42
  43 + def self.pretty_name
  44 + _('Feed Reader')
  45 + end
  46 +
43 def help 47 def help
44 _('This block can be used to list the latest new from any site you want. You just need to inform the address of a RSS feed.') 48 _('This block can be used to list the latest new from any site you want. You just need to inform the address of a RSS feed.')
45 end 49 end
app/models/forum.rb
@@ -3,11 +3,11 @@ class Forum &lt; Folder @@ -3,11 +3,11 @@ class Forum &lt; Folder
3 acts_as_having_posts :order => 'updated_at DESC' 3 acts_as_having_posts :order => 'updated_at DESC'
4 include PostsLimit 4 include PostsLimit
5 5
6 - attr_accessible :has_terms_of_use, :terms_of_use, :allows_members_to_create_topics 6 + attr_accessible :has_terms_of_use, :terms_of_use, :topic_creation
7 7
8 settings_items :terms_of_use, :type => :string, :default => "" 8 settings_items :terms_of_use, :type => :string, :default => ""
9 settings_items :has_terms_of_use, :type => :boolean, :default => false 9 settings_items :has_terms_of_use, :type => :boolean, :default => false
10 - settings_items :allows_members_to_create_topics, :type => :boolean, :default => false 10 + settings_items :topic_creation, :type => :string, :default => 'self'
11 has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people' 11 has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people'
12 12
13 before_save do |forum| 13 before_save do |forum|
@@ -33,6 +33,23 @@ class Forum &lt; Folder @@ -33,6 +33,23 @@ class Forum &lt; Folder
33 _('An internet forum, also called message board, where discussions can be held.') 33 _('An internet forum, also called message board, where discussions can be held.')
34 end 34 end
35 35
  36 + module TopicCreation
  37 + BASE = ActiveSupport::OrderedHash.new
  38 + BASE['users'] = _('Logged users')
  39 +
  40 + PERSON = ActiveSupport::OrderedHash.new
  41 + PERSON['self'] = _('Me')
  42 + PERSON['related'] = _('Friends')
  43 +
  44 + GROUP = ActiveSupport::OrderedHash.new
  45 + GROUP['self'] = _('Administrators')
  46 + GROUP['related'] = _('Members')
  47 +
  48 + def self.general_options(forum)
  49 + forum.profile.person? ? PERSON.merge(BASE) : GROUP.merge(BASE)
  50 + end
  51 + end
  52 +
36 include ActionView::Helpers::TagHelper 53 include ActionView::Helpers::TagHelper
37 def to_html(options = {}) 54 def to_html(options = {})
38 proc do 55 proc do
@@ -69,11 +86,17 @@ class Forum &lt; Folder @@ -69,11 +86,17 @@ class Forum &lt; Folder
69 self.users_with_agreement.exists? user 86 self.users_with_agreement.exists? user
70 end 87 end
71 88
72 - def can_create_topic?(user, profile)  
73 - return profile.community? && profile.members.include?(user) && self.allows_members_to_create_topics 89 + def can_create_topic?(user)
  90 + return true if user == profile || profile.admins.include?(user) || profile.environment.admins.include?(user)
  91 + case topic_creation
  92 + when 'related'
  93 + profile.person? ? profile.friends.include?(user) : profile.members.include?(user)
  94 + when 'users'
  95 + user.present?
  96 + end
74 end 97 end
75 98
76 def allow_create?(user) 99 def allow_create?(user)
77 - super || can_create_topic?(user, profile) 100 + super || can_create_topic?(user)
78 end 101 end
79 end 102 end
app/models/highlights_block.rb
@@ -12,6 +12,7 @@ class HighlightsBlock &lt; Block @@ -12,6 +12,7 @@ class HighlightsBlock &lt; Block
12 block.images.each do |i| 12 block.images.each do |i|
13 i[:image_id] = i[:image_id].to_i 13 i[:image_id] = i[:image_id].to_i
14 i[:position] = i[:position].to_i 14 i[:position] = i[:position].to_i
  15 + i[:address] = Noosfero.root + i[:address] unless Noosfero.root.nil?
15 begin 16 begin
16 file = UploadedFile.find(i[:image_id]) 17 file = UploadedFile.find(i[:image_id])
17 i[:image_src] = file.public_filename 18 i[:image_src] = file.public_filename
@@ -22,12 +23,20 @@ class HighlightsBlock &lt; Block @@ -22,12 +23,20 @@ class HighlightsBlock &lt; Block
22 end 23 end
23 24
24 def self.description 25 def self.description
25 - _('Highlights') 26 + _('Creates image slideshow')
26 end 27 end
27 28
28 def featured_images 29 def featured_images
29 - block_images = images.select{|i| !i[:image_src].nil? }.sort { |x, y| x[:position] <=> y[:position] }  
30 - shuffle ? block_images.shuffle : block_images 30 + images = get_images
  31 + shuffle ? images.shuffle : images
  32 + end
  33 +
  34 + def get_images
  35 + images.select do |i|
  36 + !i[:image_src].nil?
  37 + end.sort do |x, y|
  38 + x[:position] <=> y[:position]
  39 + end
31 end 40 end
32 41
33 def content(args={}) 42 def content(args={})
app/models/image.rb
@@ -23,7 +23,7 @@ class Image &lt; ActiveRecord::Base @@ -23,7 +23,7 @@ class Image &lt; ActiveRecord::Base
23 23
24 postgresql_attachment_fu 24 postgresql_attachment_fu
25 25
26 - attr_accessible :uploaded_data 26 + attr_accessible :uploaded_data, :label
27 27
28 def current_data 28 def current_data
29 File.file?(full_filename) ? File.read(full_filename) : nil 29 File.file?(full_filename) ? File.read(full_filename) : nil
app/models/invitation.rb
@@ -6,6 +6,8 @@ class Invitation &lt; Task @@ -6,6 +6,8 @@ class Invitation &lt; Task
6 6
7 validates_presence_of :target_id, :if => Proc.new{|invite| invite.friend_email.blank?} 7 validates_presence_of :target_id, :if => Proc.new{|invite| invite.friend_email.blank?}
8 8
  9 + validates :requestor, kind_of: {kind: Person}
  10 +
9 validates_presence_of :friend_email, :if => Proc.new{|invite| invite.target_id.blank?} 11 validates_presence_of :friend_email, :if => Proc.new{|invite| invite.target_id.blank?}
10 validates_format_of :friend_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => Proc.new{|invite| invite.target_id.blank?} 12 validates_format_of :friend_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => Proc.new{|invite| invite.target_id.blank?}
11 13
@@ -34,7 +36,7 @@ class Invitation &lt; Task @@ -34,7 +36,7 @@ class Invitation &lt; Task
34 end 36 end
35 37
36 def not_invite_yourself 38 def not_invite_yourself
37 - email = friend ? friend.user.email : friend_email 39 + email = friend && friend.person? ? friend.user.email : friend_email
38 if person && email && person.user.email == email 40 if person && email && person.user.email == email
39 self.errors.add(:base, _("You can't invite youself")) 41 self.errors.add(:base, _("You can't invite youself"))
40 end 42 end
@@ -136,7 +138,11 @@ class Invitation &lt; Task @@ -136,7 +138,11 @@ class Invitation &lt; Task
136 end 138 end
137 139
138 def environment 140 def environment
139 - self.requestor.environment 141 + if self.requestor
  142 + self.requestor.environment
  143 + else
  144 + nil
  145 + end
140 end 146 end
141 147
142 end 148 end
app/models/link_list_block.rb
@@ -55,6 +55,10 @@ class LinkListBlock &lt; Block @@ -55,6 +55,10 @@ class LinkListBlock &lt; Block
55 _('This block can be used to create a menu of links. You can add, remove and update the links as you wish.') 55 _('This block can be used to create a menu of links. You can add, remove and update the links as you wish.')
56 end 56 end
57 57
  58 + def self.pretty_name
  59 + _('Link list')
  60 + end
  61 +
58 def content(args={}) 62 def content(args={})
59 block_title(title) + 63 block_title(title) +
60 content_tag('ul', 64 content_tag('ul',