Commit db0d70fc0eb48b5508f6b8a52daad9ada1a18a9e

Authored by Antonio Terceiro
2 parents 24913d87 ef2f9593

Merge branch 'master' into api

Showing 897 changed files with 40376 additions and 10326 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 897 files displayed.

  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
@@ -6,280 +8,123 @@ noosfero, that's not a problem). @@ -6,280 +8,123 @@ noosfero, that's not a problem).
6 Developers 8 Developers
7 ========== 9 ==========
8 10
  11 +Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>
9 Alan Freihof Tygel <alantygel@gmail.com> 12 Alan Freihof Tygel <alantygel@gmail.com>
10 -Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com>  
11 -Alessandro Palmeira + Caio Salgado + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
12 -Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com>  
13 -Alessandro Palmeira + Caio Salgado <caio.csalgado@gmail.com>  
14 -Alessandro Palmeira + Carlos Morais <alessandro.palmeira@gmail.com>  
15 -Alessandro Palmeira + Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>  
16 -Alessandro Palmeira + Daniel Alves + Diego Araújo <diegoamc90@gmail.com>  
17 -Alessandro Palmeira + Daniel Alves <alessandro.palmeira@gmail.com>  
18 -Alessandro Palmeira + Diego Araujo + Daniela Feitosa <alessandro.palmeira@gmail.com>  
19 -Alessandro Palmeira + Diego Araujo + Eduardo Morais <alessandro.palmeira@gmail.com>  
20 -Alessandro Palmeira + Diego Araujo + João M. M. da Silva + Paulo Meirelles <alessandro.palmeira@gmail.com>  
21 -Alessandro Palmeira + Diego Araujo + Rafael Manzo <alessandro.palmeira@gmail.com>  
22 -Alessandro Palmeira + Diego Araujo <alessandro.palmeira@gmail.com>  
23 -Alessandro Palmeira + Diego Araujo <diegoamc90@gmail.com>  
24 -Alessandro Palmeira + Diego Araújo + João M. M. da Silva <alessandro.palmeira@gmail.com>  
25 -Alessandro Palmeira + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
26 -Alessandro Palmeira + Diego Araújo + Pedro Leal + João M. M. da Silva <diegoamc90@gmail.com>  
27 -Alessandro Palmeira + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
28 -Alessandro Palmeira + Diego Araújo <alessandro.palmeira@gmail.com>  
29 -Alessandro Palmeira + Diego Araújo <diegoamc90@gmail.com>  
30 -Alessandro Palmeira + Eduardo Morais <alessandro.palmeira@gmail.com>  
31 -Alessandro Palmeira + Guilherme Rojas <alessandro.palmeira@gmail.com>  
32 -Alessandro Palmeira + Jefferson Fernandes <alessandro.palmeira@gmail.com>  
33 -Alessandro Palmeira + Joao M. M. da Silva + Diego Araujo <alessandro.palmeira@gmail.com>  
34 -Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com>  
35 -Alessandro Palmeira + João M. M. da Silva + Renan Teruo <alessandro.palmeira@gmail.com>  
36 -Alessandro Palmeira + João M. M. da Silva <alessandro.palmeira@gmail.com>  
37 -Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>  
38 -Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>  
39 -Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>  
40 Alessandro Palmeira <alessandro.palmeira@gmail.com> 13 Alessandro Palmeira <alessandro.palmeira@gmail.com>
  14 +Alex Campelo <campelo.al1@gmail.com>
  15 +Álvaro Fernando <alvarofernandoms@gmail.com>
41 Ana Losnak <analosnak@gmail.com> 16 Ana Losnak <analosnak@gmail.com>
42 -Andre Bernardes <andrebsguedes@gmail.com>  
43 -André Bernardes <andrebsguedes@gmail.com>  
44 -André Guedes <andrebsguedes@fedora.local> 17 +Ana Paula Vargas <anapaulavnoronha@gmail.com>
  18 +Andre Bedran <bedran.fleck@gmail.com>
45 André Guedes <andrebsguedes@gmail.com> 19 André Guedes <andrebsguedes@gmail.com>
46 -Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>  
47 -Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> 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>  
51 Athos Ribeiro <athoscribeiro@gmail.com> 23 Athos Ribeiro <athoscribeiro@gmail.com>
52 Aurelio A. Heckert <aurelio@colivre.coop.br> 24 Aurelio A. Heckert <aurelio@colivre.coop.br>
53 Braulio Bhavamitra <braulio@eita.org.br> 25 Braulio Bhavamitra <braulio@eita.org.br>
54 -Braulio Bhavamitra <brauliobo@gmail.com>  
55 -Bráulio Bhavamitra <brauliobo@gmail.com>  
56 -Caio + Diego + Pedro + João <caio.csalgado@gmail.com>  
57 -Caio <caio.csalgado@gmail.com> 26 +Brenddon Gontijo <brenddongontijo@msn.com>
58 Caio Formiga <caio.formiga@gmail.com> 27 Caio Formiga <caio.formiga@gmail.com>
59 -Caio SBA <caio@colivre.coop.br>  
60 -Caio Salgado + Alessandro Palmeira <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 + Jefferson Fernandes <caio.csalgado@gmail.com>  
64 -Caio Salgado + Diego Araújo + João M. M. da Silva <caio.csalgado@gmail.com>  
65 -Caio Salgado + Diego Araújo + Pedro Leal <caio.csalgado@gmail.com>  
66 -Caio Salgado + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
67 -Caio Salgado + Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>  
68 -Caio Salgado + Diego Araújo <caio.csalgado@gmail.com>  
69 -Caio Salgado + Diego Araújo <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 + Jefferson Fernandes <jeffs.fernandes@gmail.com>  
74 -Caio Salgado + Renan Teruo <caio.csalgado@gmail.com>  
75 -Caio Salgado + Renan Teruo <caio.salgado@gmail.com>  
76 -Caio Salgado + Renan Teruo <renanteruoc@gmail.com>  
77 Caio Salgado <caio.csalgado@gmail.com> 28 Caio Salgado <caio.csalgado@gmail.com>
  29 +Caio SBA <caio@colivre.coop.br>
78 Caio Tiago Oliveira <caiotiago@colivre.coop.br> 30 Caio Tiago Oliveira <caiotiago@colivre.coop.br>
79 -Caio, Pedro <caio.csalgado@gmail.com>  
80 Carlos Andre de Souza <carlos.andre.souza@msn.com> 31 Carlos Andre de Souza <carlos.andre.souza@msn.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 Carlos Morais <carlos88morais@gmail.com> 32 Carlos Morais <carlos88morais@gmail.com>
86 Christophe DANIEL <papaeng@gmail.com> 33 Christophe DANIEL <papaeng@gmail.com>
87 -Daniel Alves + Diego Araújo <danpaulalves@gmail.com>  
88 -Daniel Alves + Diego Araújo <diegoamc90@gmail.com>  
89 -Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>  
90 -Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>  
91 -Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com>  
92 -Daniel Alves + Diego Araújo <danpaulalves@gmail.com>  
93 -Daniel Alves + Diego Araújo <diegoamc90@gmail.com>  
94 -Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com>  
95 -Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> 34 +Daniela Feitosa <alessandro.palmeira@gmail.com>
  35 +Daniel Alves <danpaulalves@gmail.com>
  36 +Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
96 Daniel Bucher <daniel.bucher88@gmail.com> 37 Daniel Bucher <daniel.bucher88@gmail.com>
97 Daniel Cunha <daniel@colivre.coop.br> 38 Daniel Cunha <daniel@colivre.coop.br>
98 -Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> 39 +Daniel Tygel <dtygel@eita.org.br>
99 David Carlos <ddavidcarlos1392@gmail.com> 40 David Carlos <ddavidcarlos1392@gmail.com>
100 -Diego + Jefferson <diegoamc90@gmail.com>  
101 -Diego + Renan <renanteruoc@gmail.com>  
102 -Diego Araujo + Caio Salgado <diegoamc90@gmail.com>  
103 -Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com>  
104 -Diego Araujo + Rafael Manzo <diegoamc90@gmail.com>  
105 -Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>  
106 -Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com>  
107 -Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com>  
108 -Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>  
109 -Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>  
110 -Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com>  
111 -Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>  
112 -Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com>  
113 -Diego Araújo + João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
114 -Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com>  
115 -Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com>  
116 -Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
117 -Diego Araújo + João Machini <diegoamc90@gmail.com>  
118 -Diego Araújo + João Machini <digoamc90@gmail.com>  
119 -Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com>  
120 -Diego Araújo + Pedro Leal <diegoamc90@gmail.com>  
121 -Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>  
122 -Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com>  
123 -Diego Araújo + Renan Teruo <diegoamc90@gmail.com>  
124 -Diego Araújo <diegoamc90@gmail.com>  
125 -Diego Martinez <diegoamc90@gmail.com>  
126 -DylanGuedes <djmgguedes@gmail.com>  
127 -Eduardo Passos <eduardo@risa.localdomain.localhost> 41 +Diego Araujo <diegoamc90@gmail.com>
  42 +Dylan Guedes <djmgguedes@gmail.com>
  43 +Eduardo Morais
128 Eduardo Passos <eduardosteps@gmail.com> 44 Eduardo Passos <eduardosteps@gmail.com>
129 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> 45 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
130 Eduardo Vital <vitaldu@gmail.com> 46 Eduardo Vital <vitaldu@gmail.com>
131 -Evandro Jr <evandrojr@gmail.com>  
132 -Evandro Junior <evandrojr@gmail.com>  
133 Evandro Magalhaes Leite Junior <evandro.leite@serpro.gov.br> 47 Evandro Magalhaes Leite Junior <evandro.leite@serpro.gov.br>
134 Fabio Teixeira <fabio1079@gmail.com> 48 Fabio Teixeira <fabio1079@gmail.com>
135 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com> 49 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com>
136 -Fabio Teixeira <fabio1079@gmail.com>  
137 Fernanda Lopes <nanda.listas+psl@gmail.com> 50 Fernanda Lopes <nanda.listas+psl@gmail.com>
138 Filipe Ribeiro <firibeiro77@live.com> 51 Filipe Ribeiro <firibeiro77@live.com>
139 -Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br>  
140 -Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)>  
141 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>
142 -Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com>  
143 Gabriela Navarro <navarro1703@gmail.com> 53 Gabriela Navarro <navarro1703@gmail.com>
144 Gonzalo Exequiel Pedone <hipersayan.x@gmail.com> 54 Gonzalo Exequiel Pedone <hipersayan.x@gmail.com>
145 Grazieno Pellegrino <grazieno@gmail.com> 55 Grazieno Pellegrino <grazieno@gmail.com>
146 -Gust <darksshades@hotmail.com> 56 +Guilherme C. Muniz <guilherme.cmuniz@gmail.com>
  57 +Guilherme Rojas <guilhermehrojas@gmail.com>
  58 +Gustavo Jaruga <darksshades@gmail.com>
147 Hebert Douglas <hebertdougl@gmail.com> 59 Hebert Douglas <hebertdougl@gmail.com>
148 Hugo Melo <hugo@riseup.net> 60 Hugo Melo <hugo@riseup.net>
  61 +Iolane Andrade <andrade.icaa@gmail.com>
149 Isaac Canan <isaac@intelletto.com.br> 62 Isaac Canan <isaac@intelletto.com.br>
150 Italo Valcy <italo@dcc.ufba.br> 63 Italo Valcy <italo@dcc.ufba.br>
151 -Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com>  
152 -Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com>  
153 -Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com>  
154 -Joao M. M. Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
155 -Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
156 -Joao M. M. da Silva + Jefferson Fernandes <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
  67 +João M. M. da Silva <jaodsilv@linux.ime.usp.br>
157 Joenio Costa <joenio@colivre.coop.br> 68 Joenio Costa <joenio@colivre.coop.br>
158 -Jose Pedro <1jpsneto@gmail.com>  
159 Josef Spillner <josef.spillner@tu-dresden.de> 69 Josef Spillner <josef.spillner@tu-dresden.de>
160 -João M. M. Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>  
161 -João M. M. Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>  
162 -João M. M. Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>  
163 -João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>  
164 -João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>  
165 -João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br>  
166 -João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br>  
167 -João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br>  
168 -João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
169 -João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
170 -João M. M. da Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>  
171 -João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br>  
172 -João M. M. da Silva + Diego Araújo + Pedro Leal <jaodsilv@linux.ime.usp.br>  
173 -João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com>  
174 -João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>  
175 -João M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
176 -João M. M. da Silva + João M. Miranda <jaodsilv@linux.ime.usp.br>  
177 -João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>  
178 -João M. M. da Silva + Pedro Leal <jaodsilv@linux.ime.usp.br>  
179 -João M. M. da Silva + Rafael Manzo + Diego Araújo <jaodsilv@linux.ime.usp.br>  
180 -João M. M. da Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>  
181 -João M. M. da Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>  
182 -João M. M. da Silva <jaodsilv@linux.ime.usp.br>  
183 -João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br>  
184 -João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com>  
185 -João da Silva <jaodsilv@linux.ime.usp.br>  
186 -Junior Silva <junior@bajor.localhost.localdomain>  
187 -Junior Silva <junior@sedeantigo.colivre.coop.br> 70 +Jose Pedro <1jpsneto@gmail.com>
188 Junior Silva <juniorsilva1001@gmail.com> 71 Junior Silva <juniorsilva1001@gmail.com>
189 -Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)>  
190 -Junior Silva <juniorsilva@colivre.coop.br>  
191 -Jérôme Jutteau <j.jutteau@gmail.com>  
192 Keilla Menezes <keilla@colivre.coop.br> 72 Keilla Menezes <keilla@colivre.coop.br>
193 Larissa Reis <larissa@colivre.coop.br> 73 Larissa Reis <larissa@colivre.coop.br>
194 -Larissa Reis <reiss.larissa@gmail.com>  
195 Leandro Alves <leandrosustenido@gmail.com> 74 Leandro Alves <leandrosustenido@gmail.com>
196 -Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)>  
197 -Leandro Nunes dos Santos <81665687568@serpro-1541727.Home>  
198 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> 75 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br>
199 -Leandro Nunes dos Santos <leandronunes@gmail.com> 76 +Leandro Veloso <leandrovelosorodrigues@gmail.com>
200 LinguÁgil 2010 <linguagil.bahia@gmail.com> 77 LinguÁgil 2010 <linguagil.bahia@gmail.com>
  78 +Lucas Couto <loc.unb@gmail.com>
201 Lucas Kanashiro <kanashiro.duarte@gmail.com> 79 Lucas Kanashiro <kanashiro.duarte@gmail.com>
202 -Lucas Melo <lucas@colivre.coop.br>  
203 Lucas Melo <lucaspradomelo@gmail.com> 80 Lucas Melo <lucaspradomelo@gmail.com>
204 -Luciano <lucianopcbr@gmail.com>  
205 -Luciano Prestes Cavacanti <lucianopcbr@gmail.com>  
206 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com> 81 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com>
207 Luis David Aguilar Carlos <ludwig9003@gmail.com> 82 Luis David Aguilar Carlos <ludwig9003@gmail.com>
208 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> 83 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com>
209 -M for Momo <mo@rtnp.org>  
210 -Marcelo Júnior <maljunior@gmail.com>  
211 -Marcos <marcos.rpj2@gmail.com> 84 +Luiz Matos <luizff.matos@gmail.com>
212 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>
213 Martín Olivera <molivera@solar.org.ar> 88 Martín Olivera <molivera@solar.org.ar>
  89 +Matheus Faria <matheus.sousa.faria@gmail.com>
214 Maurilio Atila <cabelotaina@gmail.com> 90 Maurilio Atila <cabelotaina@gmail.com>
  91 +M for Momo <mo@rtnp.org>
215 Michal Čihař <michal@cihar.com> 92 Michal Čihař <michal@cihar.com>
216 Michel Felipe <mfelipeof@gmail.com> 93 Michel Felipe <mfelipeof@gmail.com>
217 Moises Machado <moises@colivre.coop.br> 94 Moises Machado <moises@colivre.coop.br>
218 -Nanda Lopes <nanda.listas+psl@gmail.com>  
219 Naíla Alves <naila@colivre.coop.br> 95 Naíla Alves <naila@colivre.coop.br>
  96 +Nanda Lopes <nanda.listas+psl@gmail.com>
220 Niemand Jedermann <predatorix@web.de> 97 Niemand Jedermann <predatorix@web.de>
221 Parley Martins <parleypachecomartins@gmail.com> 98 Parley Martins <parleypachecomartins@gmail.com>
222 -Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>  
223 -Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>  
224 -Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>  
225 -Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org>  
226 -Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org>  
227 -Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org>  
228 Paulo Meirelles <paulo@softwarelivre.org> 99 Paulo Meirelles <paulo@softwarelivre.org>
  100 +Pedro de Lyra <pedrodelyra@gmail.com>
  101 +Pedro Leal
  102 +Rafael de Souza Queiroz <querafael@live.com>
229 Rafael Gomes <rafaelgomes@techfree.com.br> 103 Rafael Gomes <rafaelgomes@techfree.com.br>
230 -Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com>  
231 -Rafael Manzo + Daniel Alves <danpaulalves@gmail.com>  
232 -Rafael Manzo + Diego Araújo <rr.manzo@gmail.com>  
233 -Rafael Manzo + João M. M. Silva <rr.manzo@gmail.com>  
234 -Rafael Manzo + Paulo Meirelles <rr.manzo@gmail.com>  
235 Rafael Martins <rmmartins@gmail.com> 104 Rafael Martins <rmmartins@gmail.com>
236 -Rafael Reggiani Manzo + Caio Salgado + Jefferson Fernandes <rr.manzo@gmail.com>  
237 -Rafael Reggiani Manzo + Diego Araujo <diegoamc90@gmail.com>  
238 -Rafael Reggiani Manzo + Diego Araujo <rr.manzo@gmail.com>  
239 -Rafael Reggiani Manzo + Diego Araújo <rr.manzo@gmail.com>  
240 -Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com>  
241 Rafael Reggiani Manzo <rr.manzo@gmail.com> 105 Rafael Reggiani Manzo <rr.manzo@gmail.com>
242 Raphaël Rousseau <raph@r4f.org> 106 Raphaël Rousseau <raph@r4f.org>
243 -Raquel <rcordioli@gmail.com>  
244 Raquel Lira <raquel.lira@gmail.com> 107 Raquel Lira <raquel.lira@gmail.com>
245 -Renan Teruo + Caio Salgado <renanteruoc@gmail.com>  
246 -Renan Teruo + Diego Araujo <renanteruoc@gmail.com>  
247 -Renan Teruo + Diego Araújo <renanteruoc@gmail.com>  
248 -Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>  
249 -Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>  
250 -Renan Teruoc + Diego Araujo <renanteruoc@gmail.com>  
251 -Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org> 108 +Raquel <rcordioli@gmail.com>
  109 +Renan Costa <renan2727@hotmail.com>
  110 +Renan Teruo <renanteruoc@gmail.com>
  111 +Rodrigo Medeiros <rodrigo.mss01@gmail.com>
252 Rodrigo Souto <rodrigo@colivre.coop.br> 112 Rodrigo Souto <rodrigo@colivre.coop.br>
253 Ronny Kursawe <kursawe.ronny@googlemail.com> 113 Ronny Kursawe <kursawe.ronny@googlemail.com>
254 Samuel R. C. Vale <srcvale@holoscopio.com> 114 Samuel R. C. Vale <srcvale@holoscopio.com>
255 -TWS <tablettws@gmail.com>  
256 -Tallys Martins <tallysmartins@gmail.com>  
257 Tallys Martins <tallysmartins@yahoo.com.br> 115 Tallys Martins <tallysmartins@yahoo.com.br>
258 Thiago Casotti <thiago.casotti@uol.com.br> 116 Thiago Casotti <thiago.casotti@uol.com.br>
  117 +Thiago Kairala <thiagor.kairala@gmail.com>
259 Thiago Ribeiro <thiagitosouza@hotmail.com> 118 Thiago Ribeiro <thiagitosouza@hotmail.com>
260 Thiago Zoroastro <thiago.zoroastro@bol.com.br> 119 Thiago Zoroastro <thiago.zoroastro@bol.com.br>
261 Tuux <tuxa@galaxie.eu.org> 120 Tuux <tuxa@galaxie.eu.org>
  121 +TWS <tablettws@gmail.com>
262 Valessio Brito <contato@valessiobrito.com.br> 122 Valessio Brito <contato@valessiobrito.com.br>
263 -Valessio Brito <contato@valessiobrito.info>  
264 -Valessio Brito <valessio@gmail.com>  
265 -Victor Carvalho <victorhugodf.ac@gmail.com>  
266 Victor Costa <vfcosta@gmail.com> 123 Victor Costa <vfcosta@gmail.com>
267 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com> 124 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>
268 Vinicius Cubas Brand <viniciuscb@gmail.com> 125 Vinicius Cubas Brand <viniciuscb@gmail.com>
269 -Visita <visita@debian.(none)> 126 +Wilton Rodrigues <braynwilton@gmail.com>
270 Yann Lugrin <yann.lugrin@liquid-concept.ch> 127 Yann Lugrin <yann.lugrin@liquid-concept.ch>
271 -alcampelo <alcampelo@alcampelo.(none)>  
272 -analosnak <analosnak@gmail.com>  
273 -daniel <dtygel@eita.org.br>  
274 -diegoamc <diegoamc90@gmail.com>  
275 -dtygel <dtygel@gmail.com>  
276 -juniorsilva <juniorsilva@QonoS.localhost.localdomain>  
277 -root <root@17edebf1ae91>  
278 -root <root@debian.sdr.serpro>  
279 -tallys <tallys@tallys.(none)>  
280 -tallys <tallys@tallys>  
281 -vfcosta <vfcosta@gmail.com>  
282 -Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>  
283 128
284 Ideas, specifications and incentive 129 Ideas, specifications and incentive
285 =================================== 130 ===================================
app/controllers/application_controller.rb
@@ -7,7 +7,10 @@ class ApplicationController &lt; ActionController::Base @@ -7,7 +7,10 @@ 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]
12 before_filter :redirect_to_current_user 15 before_filter :redirect_to_current_user
13 16
app/controllers/my_profile/cms_controller.rb
@@ -111,10 +111,7 @@ class CmsController &lt; MyProfileController @@ -111,10 +111,7 @@ class CmsController &lt; MyProfileController
111 end 111 end
112 end 112 end
113 113
114 - unless @article.kind_of?(RssFeed)  
115 - @escaped_body = CGI::escapeHTML(@article.body || '')  
116 - @escaped_abstract = CGI::escapeHTML(@article.abstract || '')  
117 - end 114 + escape_fields @article
118 end 115 end
119 116
120 def new 117 def new
@@ -185,6 +182,8 @@ class CmsController &lt; MyProfileController @@ -185,6 +182,8 @@ class CmsController &lt; MyProfileController
185 end 182 end
186 end 183 end
187 184
  185 + escape_fields @article
  186 +
188 render :action => 'edit' 187 render :action => 'edit'
189 end 188 end
190 189
@@ -534,4 +533,10 @@ class CmsController &lt; MyProfileController @@ -534,4 +533,10 @@ class CmsController &lt; MyProfileController
534 end 533 end
535 end 534 end
536 535
  536 + def escape_fields article
  537 + unless article.kind_of?(RssFeed)
  538 + @escaped_body = CGI::escapeHTML(article.body || '')
  539 + @escaped_abstract = CGI::escapeHTML(article.abstract || '')
  540 + end
  541 + end
537 end 542 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/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
@@ -109,7 +110,7 @@ class ProfileEditorController &lt; MyProfileController @@ -109,7 +110,7 @@ class ProfileEditorController &lt; MyProfileController
109 profile = environment.profiles.find(params[:id]) 110 profile = environment.profiles.find(params[:id])
110 if profile.disable 111 if profile.disable
111 profile.save 112 profile.save
112 - session[:notice] = _("The profile '#{profile.name}' was deactivated.") 113 + session[:notice] = _("The profile '%s' was deactivated.") % profile.name
113 else 114 else
114 session[:notice] = _('Could not deactivate profile.') 115 session[:notice] = _('Could not deactivate profile.')
115 end 116 end
@@ -123,7 +124,7 @@ class ProfileEditorController &lt; MyProfileController @@ -123,7 +124,7 @@ class ProfileEditorController &lt; MyProfileController
123 profile = environment.profiles.find(params[:id]) 124 profile = environment.profiles.find(params[:id])
124 125
125 if profile.enable 126 if profile.enable
126 - session[:notice] = _("The profile '#{profile.name}' was activated.") 127 + session[:notice] = _("The profile '%s' was activated.") % profile.name
127 else 128 else
128 session[:notice] = _('Could not activate the profile.') 129 session[:notice] = _('Could not activate the profile.')
129 end 130 end
@@ -162,4 +163,10 @@ class ProfileEditorController &lt; MyProfileController @@ -162,4 +163,10 @@ class ProfileEditorController &lt; MyProfileController
162 end 163 end
163 end 164 end
164 165
  166 + def forbid_destroy_profile
  167 + if environment.enabled?('forbid_destroy_profile') && !current_person.is_admin?(environment)
  168 + session[:notice] = _('You can not destroy the profile.')
  169 + redirect_to_previous_location
  170 + end
  171 + end
165 end 172 end
app/controllers/public/account_controller.rb
@@ -46,14 +46,20 @@ class AccountController &lt; ApplicationController @@ -46,14 +46,20 @@ class AccountController &lt; ApplicationController
46 46
47 self.current_user = plugins_alternative_authentication 47 self.current_user = plugins_alternative_authentication
48 48
49 - self.current_user ||= User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user]  
50 - 49 + begin
  50 + self.current_user ||= User.authenticate(params[:user][:login], params[:user][:password], environment) if params[:user]
  51 + rescue User::UserNotActivated => e
  52 + session[:notice] = e.message
  53 + return
  54 + end
51 if logged_in? 55 if logged_in?
52 check_join_in_community(self.current_user) 56 check_join_in_community(self.current_user)
  57 +
53 if params[:remember_me] == "1" 58 if params[:remember_me] == "1"
54 self.current_user.remember_me 59 self.current_user.remember_me
55 - cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at } 60 + cookies[:auth_token] = {value: self.current_user.remember_token, expires: self.current_user.remember_token_expires_at}
56 end 61 end
  62 +
57 if redirect? 63 if redirect?
58 go_to_initial_page 64 go_to_initial_page
59 session[:notice] = _("Logged in successfully") 65 session[:notice] = _("Logged in successfully")
@@ -92,6 +98,7 @@ class AccountController &lt; ApplicationController @@ -92,6 +98,7 @@ class AccountController &lt; ApplicationController
92 @invitation_code = params[:invitation_code] 98 @invitation_code = params[:invitation_code]
93 begin 99 begin
94 @user = User.build(params[:user], params[:profile_data], environment) 100 @user = User.build(params[:user], params[:profile_data], environment)
  101 + @user.session = session
95 @terms_of_use = environment.terms_of_use 102 @terms_of_use = environment.terms_of_use
96 @user.return_to = session[:return_to] 103 @user.return_to = session[:return_to]
97 @person = Person.new(params[:profile_data]) 104 @person = Person.new(params[:profile_data])
@@ -432,7 +439,7 @@ class AccountController &lt; ApplicationController @@ -432,7 +439,7 @@ class AccountController &lt; ApplicationController
432 end 439 end
433 440
434 def go_to_signup_initial_page 441 def go_to_signup_initial_page
435 - check_redirection_options(user, user.environment.redirection_after_signup, user.url) 442 + check_redirection_options user, user.environment.redirection_after_signup, user.url, signup: true
436 end 443 end
437 444
438 def redirect_if_logged_in 445 def redirect_if_logged_in
@@ -452,8 +459,11 @@ class AccountController &lt; ApplicationController @@ -452,8 +459,11 @@ class AccountController &lt; ApplicationController
452 459
453 protected 460 protected
454 461
455 - def check_redirection_options(user, condition, default)  
456 - case condition 462 + def check_redirection_options user, condition, default, options={}
  463 + if options[:signup] and target = session.delete(:after_signup_redirect_to)
  464 + redirect_to target
  465 + else
  466 + case condition
457 when 'keep_on_same_page' 467 when 'keep_on_same_page'
458 redirect_back_or_default(user.admin_url) 468 redirect_back_or_default(user.admin_url)
459 when 'site_homepage' 469 when 'site_homepage'
@@ -466,8 +476,11 @@ class AccountController &lt; ApplicationController @@ -466,8 +476,11 @@ class AccountController &lt; ApplicationController
466 redirect_to user.admin_url 476 redirect_to user.admin_url
467 when 'welcome_page' 477 when 'welcome_page'
468 redirect_to :controller => :home, :action => :welcome, :template_id => (user.template && user.template.id) 478 redirect_to :controller => :home, :action => :welcome, :template_id => (user.template && user.template.id)
469 - else  
470 - redirect_back_or_default(default) 479 + when 'custom_url'
  480 + if (url = user.custom_url_redirection).present? then redirect_to url else redirect_back_or_default default end
  481 + else
  482 + redirect_back_or_default(default)
  483 + end
471 end 484 end
472 end 485 end
473 486
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
app/controllers/public/search_controller.rb
@@ -92,10 +92,10 @@ class SearchController &lt; PublicController @@ -92,10 +92,10 @@ class SearchController &lt; PublicController
92 92
93 def events 93 def events
94 if params[:year].blank? && params[:year].blank? && params[:day].blank? 94 if params[:year].blank? && params[:year].blank? && params[:day].blank?
95 - @date = Date.today 95 + @date = DateTime.now
96 else 96 else
97 - year = (params[:year] ? params[:year].to_i : Date.today.year)  
98 - month = (params[:month] ? params[:month].to_i : Date.today.month) 97 + year = (params[:year] ? params[:year].to_i : DateTime.now.year)
  98 + month = (params[:month] ? params[:month].to_i : DateTime.now.month)
99 day = (params[:day] ? params[:day].to_i : 1) 99 day = (params[:day] ? params[:day].to_i : 1)
100 @date = build_date(year, month, day) 100 @date = build_date(year, month, day)
101 end 101 end
@@ -106,9 +106,7 @@ class SearchController &lt; PublicController @@ -106,9 +106,7 @@ class SearchController &lt; PublicController
106 @events = @category ? 106 @events = @category ?
107 environment.events.by_day(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) : 107 environment.events.by_day(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) :
108 environment.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page]) 108 environment.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page])
109 - end  
110 -  
111 - if params[:year] || params[:month] 109 + elsif params[:year] || params[:month]
112 @events = @category ? 110 @events = @category ?
113 environment.events.by_month(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) : 111 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).paginate(:per_page => per_page, :page => params[:page]) 112 environment.events.by_month(@date).paginate(:per_page => per_page, :page => params[:page])
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
@@ -903,7 +903,7 @@ module ApplicationHelper @@ -903,7 +903,7 @@ module ApplicationHelper
903 end 903 end
904 904
905 def base_url 905 def base_url
906 - environment.top_url(request.scheme) 906 + profile ? profile.top_url(request.scheme) : environment.top_url(request.scheme)
907 end 907 end
908 alias :top_url :base_url 908 alias :top_url :base_url
909 909
app/helpers/article_helper.rb
@@ -88,7 +88,7 @@ module ArticleHelper @@ -88,7 +88,7 @@ module ArticleHelper
88 content_tag( 'small', _('Who will be able to create new topics on this forum?')) + 88 content_tag( 'small', _('Who will be able to create new topics on this forum?')) +
89 content_tag('div', '', slider_options) + 89 content_tag('div', '', slider_options) +
90 hidden_field_tag('article[topic_creation]', article.topic_creation) + 90 hidden_field_tag('article[topic_creation]', article.topic_creation) +
91 - javascript_include_tag('topic-creation-config') 91 + javascript_include_tag("#{Noosfero.root}/assets/topic-creation-config.js")
92 end 92 end
93 93
94 def privacity_exceptions(article, tokenized_children) 94 def privacity_exceptions(article, tokenized_children)
app/helpers/blog_helper.rb
@@ -6,7 +6,13 @@ module BlogHelper @@ -6,7 +6,13 @@ module BlogHelper
6 @article = article 6 @article = article
7 hidden_field_tag('article[published]', 1) + 7 hidden_field_tag('article[published]', 1) +
8 hidden_field_tag('article[accept_comments]', 0) + 8 hidden_field_tag('article[accept_comments]', 0) +
9 - visibility_options(article,tokenized_children) 9 + visibility_options(article,tokenized_children) +
  10 + content_tag('h4', _('Visualization of posts')) +
  11 + content_tag(
  12 + 'div',
  13 + check_box(:article, :display_preview) +
  14 + content_tag('label', _('I want to display the preview of posts before the text'), :for => 'article_display_preview')
  15 + )
10 end 16 end
11 17
12 def cms_label_for_new_children 18 def cms_label_for_new_children
app/helpers/content_viewer_helper.rb
@@ -51,7 +51,7 @@ module ContentViewerHelper @@ -51,7 +51,7 @@ module ContentViewerHelper
51 elsif date_format == 'past_time' 51 elsif date_format == 'past_time'
52 left_time = true 52 left_time = true
53 end 53 end
54 - content_tag('span', show_date(article.published_at, use_numbers , year, left_time), :class => 'date') 54 + content_tag('span', show_time(article.published_at, use_numbers , year, left_time), :class => 'date')
55 end 55 end
56 56
57 def link_to_comments(article, args = {}) 57 def link_to_comments(article, args = {})
app/helpers/dates_helper.rb
@@ -43,9 +43,14 @@ module DatesHelper @@ -43,9 +43,14 @@ module DatesHelper
43 end 43 end
44 44
45 # formats a datetime for displaying. 45 # formats a datetime for displaying.
46 - def show_time(time)  
47 - if time  
48 - _('%{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") }
49 else 54 else
50 '' 55 ''
51 end 56 end
@@ -53,7 +58,7 @@ module DatesHelper @@ -53,7 +58,7 @@ module DatesHelper
53 58
54 def show_period(date1, date2 = nil, use_numbers = false) 59 def show_period(date1, date2 = nil, use_numbers = false)
55 if (date1 == date2) || (date2.nil?) 60 if (date1 == date2) || (date2.nil?)
56 - show_date(date1, use_numbers) 61 + show_time(date1, use_numbers)
57 else 62 else
58 if date1.year == date2.year 63 if date1.year == date2.year
59 if date1.month == date2.month 64 if date1.month == date2.month
@@ -72,8 +77,8 @@ module DatesHelper @@ -72,8 +77,8 @@ module DatesHelper
72 end 77 end
73 else 78 else
74 _('from %{date1} to %{date2}') % { 79 _('from %{date1} to %{date2}') % {
75 - :date1 => show_date(date1, use_numbers),  
76 - :date2 => show_date(date2, use_numbers) 80 + :date1 => show_time(date1, use_numbers),
  81 + :date2 => show_time(date2, use_numbers)
77 } 82 }
78 end 83 end
79 end 84 end
@@ -106,18 +111,18 @@ module DatesHelper @@ -106,18 +111,18 @@ module DatesHelper
106 111
107 def build_date(year, month, day = 1) 112 def build_date(year, month, day = 1)
108 if year.blank? and month.blank? and day.blank? 113 if year.blank? and month.blank? and day.blank?
109 - Date.today 114 + DateTime.now
110 else 115 else
111 if year.blank? 116 if year.blank?
112 - year = Date.today.year 117 + year = DateTime.now.year
113 end 118 end
114 if month.blank? 119 if month.blank?
115 - month = Date.today.month 120 + month = DateTime.now.month
116 end 121 end
117 if day.blank? 122 if day.blank?
118 day = 1 123 day = 1
119 end 124 end
120 - Date.new(year.to_i, month.to_i, day.to_i) 125 + DateTime.new(year.to_i, month.to_i, day.to_i)
121 end 126 end
122 end 127 end
123 128
app/helpers/events_helper.rb
@@ -16,7 +16,7 @@ module EventsHelper @@ -16,7 +16,7 @@ module EventsHelper
16 16
17 content_tag( 'tr', 17 content_tag( 'tr',
18 content_tag('td', 18 content_tag('td',
19 - 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' ) +
20 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') +
21 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')
22 ) 22 )
@@ -30,7 +30,7 @@ module EventsHelper @@ -30,7 +30,7 @@ module EventsHelper
30 # the day itself 30 # the day itself
31 date, 31 date,
32 # is there any events in this date? 32 # is there any events in this date?
33 - events.any? {|event| event.date_range.include?(date)}, 33 + events.any? {|event| event.date_range.cover?(date)},
34 # is this date in the current month? 34 # is this date in the current month?
35 true 35 true
36 ] 36 ]
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/layout_helper.rb
@@ -77,15 +77,8 @@ module LayoutHelper @@ -77,15 +77,8 @@ module LayoutHelper
77 77
78 78
79 def icon_theme_stylesheet_path 79 def icon_theme_stylesheet_path
80 - icon_themes = []  
81 theme_icon_themes = theme_option(:icon_theme) || [] 80 theme_icon_themes = theme_option(:icon_theme) || []
82 - for icon_theme in theme_icon_themes do  
83 - theme_path = "designs/icons/#{icon_theme}/style.css"  
84 - if File.exists?(Rails.root.join('public', theme_path))  
85 - icon_themes << theme_path  
86 - end  
87 - end  
88 - icon_themes 81 + theme_icon_themes.map{ |it| "designs/icons/#{it}/style.css" }
89 end 82 end
90 83
91 def jquery_ui_theme_stylesheet_path 84 def jquery_ui_theme_stylesheet_path
@@ -93,7 +86,7 @@ module LayoutHelper @@ -93,7 +86,7 @@ module LayoutHelper
93 end 86 end
94 87
95 def theme_stylesheet_path 88 def theme_stylesheet_path
96 - "/assets#{theme_path}/style.css" 89 + "#{theme_path}/style.css".gsub(%r{^/}, '')
97 end 90 end
98 91
99 def layout_template 92 def layout_template
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/models/add_member.rb
@@ -29,7 +29,8 @@ class AddMember &lt; Task @@ -29,7 +29,8 @@ class AddMember &lt; Task
29 end 29 end
30 30
31 def information 31 def information
32 - {: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}}
33 end 34 end
34 35
35 def accept_details 36 def accept_details
@@ -45,7 +46,7 @@ class AddMember &lt; Task @@ -45,7 +46,7 @@ class AddMember &lt; Task
45 end 46 end
46 47
47 def target_notification_description 48 def target_notification_description
48 - _('%{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}
49 end 50 end
50 51
51 def target_notification_message 52 def target_notification_message
app/models/article.rb
@@ -8,7 +8,8 @@ class Article &lt; ActiveRecord::Base @@ -8,7 +8,8 @@ class Article &lt; ActiveRecord::Base
8 :accept_comments, :feed, :published, :source, :source_name, 8 :accept_comments, :feed, :published, :source, :source_name,
9 :highlighted, :notify_comments, :display_hits, :slug, 9 :highlighted, :notify_comments, :display_hits, :slug,
10 :external_feed_builder, :display_versions, :external_link, 10 :external_feed_builder, :display_versions, :external_link,
11 - :image_builder, :show_to_followers 11 + :image_builder, :show_to_followers,
  12 + :author, :display_preview
12 13
13 acts_as_having_image 14 acts_as_having_image
14 15
@@ -641,6 +642,20 @@ class Article &lt; ActiveRecord::Base @@ -641,6 +642,20 @@ class Article &lt; ActiveRecord::Base
641 can_display_hits? && display_hits 642 can_display_hits? && display_hits
642 end 643 end
643 644
  645 + def display_media_panel?
  646 + can_display_media_panel? && environment.enabled?('media_panel')
  647 + end
  648 +
  649 + def can_display_media_panel?
  650 + false
  651 + end
  652 +
  653 + settings_items :display_preview, :type => :boolean, :default => false
  654 +
  655 + def display_preview?
  656 + false
  657 + end
  658 +
644 def image? 659 def image?
645 false 660 false
646 end 661 end
@@ -754,9 +769,10 @@ class Article &lt; ActiveRecord::Base @@ -754,9 +769,10 @@ class Article &lt; ActiveRecord::Base
754 end 769 end
755 770
756 def body_images_paths 771 def body_images_paths
757 - require 'uri'  
758 Nokogiri::HTML.fragment(self.body.to_s).css('img[src]').collect do |i| 772 Nokogiri::HTML.fragment(self.body.to_s).css('img[src]').collect do |i|
759 - (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, URI.escape(i['src'])).to_s : i['src'] 773 + src = i['src']
  774 + src = URI.escape src if self.new_record? # xss_terminate runs on save
  775 + (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, src).to_s : src
760 end 776 end
761 end 777 end
762 778
app/models/category.rb
@@ -81,7 +81,7 @@ class Category &lt; ActiveRecord::Base @@ -81,7 +81,7 @@ class Category &lt; ActiveRecord::Base
81 end 81 end
82 82
83 def upcoming_events(limit = 10) 83 def upcoming_events(limit = 10)
84 - self.events.paginate(:conditions => [ 'start_date >= ?', Date.today ], :order => 'start_date', :page => 1, :per_page => limit) 84 + self.events.paginate(:conditions => [ 'start_date >= ?', DateTime.now.beginning_of_day ], :order => 'start_date', :page => 1, :per_page => limit)
85 end 85 end
86 86
87 def display_in_menu? 87 def display_in_menu?
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/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_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
@@ -13,7 +13,7 @@ class Environment &lt; ActiveRecord::Base @@ -13,7 +13,7 @@ class Environment &lt; ActiveRecord::Base
13 :reports_lower_bound, :noreply_email, 13 :reports_lower_bound, :noreply_email,
14 :signup_welcome_screen_body, :members_whitelist_enabled, 14 :signup_welcome_screen_body, :members_whitelist_enabled,
15 :members_whitelist, :highlighted_news_amount, 15 :members_whitelist, :highlighted_news_amount,
16 - :portal_news_amount, :date_format 16 + :portal_news_amount, :date_format, :signup_intro
17 17
18 has_many :users 18 has_many :users
19 19
@@ -128,6 +128,7 @@ class Environment &lt; ActiveRecord::Base @@ -128,6 +128,7 @@ class Environment &lt; ActiveRecord::Base
128 'disable_select_city_for_contact' => _('Disable state/city select for contact form'), 128 'disable_select_city_for_contact' => _('Disable state/city select for contact form'),
129 'disable_contact_person' => _('Disable contact for people'), 129 'disable_contact_person' => _('Disable contact for people'),
130 'disable_contact_community' => _('Disable contact for groups/communities'), 130 'disable_contact_community' => _('Disable contact for groups/communities'),
  131 + 'forbid_destroy_profile' => _('Forbid users of removing profiles'),
131 132
132 'products_for_enterprises' => _('Enable products for enterprises'), 133 'products_for_enterprises' => _('Enable products for enterprises'),
133 'enterprise_registration' => _('Enterprise registration'), 134 'enterprise_registration' => _('Enterprise registration'),
@@ -167,7 +168,8 @@ class Environment &lt; ActiveRecord::Base @@ -167,7 +168,8 @@ class Environment &lt; ActiveRecord::Base
167 'site_homepage' => _('Redirects the user to the environment homepage.'), 168 'site_homepage' => _('Redirects the user to the environment homepage.'),
168 'user_profile_page' => _('Redirects the user to his profile page.'), 169 'user_profile_page' => _('Redirects the user to his profile page.'),
169 'user_homepage' => _('Redirects the user to his homepage.'), 170 'user_homepage' => _('Redirects the user to his homepage.'),
170 - 'user_control_panel' => _('Redirects the user to his control panel.') 171 + 'user_control_panel' => _('Redirects the user to his control panel.'),
  172 + 'custom_url' => _('Specify the URL to redirect to:'),
171 } 173 }
172 end 174 end
173 validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true 175 validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true
@@ -248,6 +250,9 @@ class Environment &lt; ActiveRecord::Base @@ -248,6 +250,9 @@ class Environment &lt; ActiveRecord::Base
248 # store the Environment settings as YAML-serialized Hash. 250 # store the Environment settings as YAML-serialized Hash.
249 acts_as_having_settings :field => :settings 251 acts_as_having_settings :field => :settings
250 252
  253 + # introduce and explain to users something about the signup
  254 + settings_items :signup_intro, :type => String
  255 +
251 # the environment's terms of use: every user must accept them before registering. 256 # the environment's terms of use: every user must accept them before registering.
252 settings_items :terms_of_use, :type => String 257 settings_items :terms_of_use, :type => String
253 258
@@ -282,7 +287,20 @@ class Environment &lt; ActiveRecord::Base @@ -282,7 +287,20 @@ class Environment &lt; ActiveRecord::Base
282 settings_items :activation_blocked_text, :type => String 287 settings_items :activation_blocked_text, :type => String
283 settings_items :message_for_disabled_enterprise, :type => String, 288 settings_items :message_for_disabled_enterprise, :type => String,
284 :default => _('This enterprise needs to be enabled.') 289 :default => _('This enterprise needs to be enabled.')
285 - settings_items :location, :type => String 290 +
  291 + settings_items :contact_phone, type: String
  292 + settings_items :address, type: String
  293 + settings_items :city, type: String
  294 + settings_items :state, type: String
  295 + settings_items :country_name, type: String
  296 + settings_items :lat, type: Float
  297 + settings_items :lng, type: Float
  298 + settings_items :postal_code, type: String
  299 + settings_items :location, type: String
  300 +
  301 + alias_method :zip_code=, :postal_code
  302 + alias_method :zip_code, :postal_code
  303 +
286 settings_items :layout_template, :type => String, :default => 'default' 304 settings_items :layout_template, :type => String, :default => 'default'
287 settings_items :homepage, :type => String 305 settings_items :homepage, :type => String
288 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 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>'
app/models/event.rb
@@ -23,7 +23,7 @@ class Event &lt; Article @@ -23,7 +23,7 @@ class Event &lt; Article
23 23
24 def initialize(*args) 24 def initialize(*args)
25 super(*args) 25 super(*args)
26 - self.start_date ||= Date.today 26 + self.start_date ||= DateTime.now
27 end 27 end
28 28
29 validates_presence_of :title, :start_date 29 validates_presence_of :title, :start_date
@@ -35,7 +35,7 @@ class Event &lt; Article @@ -35,7 +35,7 @@ class Event &lt; Article
35 end 35 end
36 36
37 scope :by_day, lambda { |date| 37 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}], 38 + { :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' 39 :order => 'start_date ASC'
40 } 40 }
41 } 41 }
@@ -80,7 +80,7 @@ class Event &lt; Article @@ -80,7 +80,7 @@ class Event &lt; Article
80 80
81 def self.date_range(year, month) 81 def self.date_range(year, month)
82 if year.nil? || month.nil? 82 if year.nil? || month.nil?
83 - today = Date.today 83 + today = DateTime.now
84 year = today.year 84 year = today.year
85 month = today.month 85 month = today.month
86 else 86 else
@@ -88,7 +88,7 @@ class Event &lt; Article @@ -88,7 +88,7 @@ class Event &lt; Article
88 month = month.to_i 88 month = month.to_i
89 end 89 end
90 90
91 - first_day = Date.new(year, month, 1) 91 + first_day = DateTime.new(year, month, 1)
92 last_day = first_day + 1.month - 1.day 92 last_day = first_day + 1.month - 1.day
93 93
94 first_day..last_day 94 first_day..last_day
@@ -114,7 +114,7 @@ class Event &lt; Article @@ -114,7 +114,7 @@ class Event &lt; Article
114 end 114 end
115 115
116 def duration 116 def duration
117 - ((self.end_date || self.start_date) - self.start_date).to_i 117 + (((self.end_date || self.start_date) - self.start_date).to_i/60/60/24)
118 end 118 end
119 119
120 alias_method :article_lead, :lead 120 alias_method :article_lead, :lead
@@ -134,6 +134,10 @@ class Event &lt; Article @@ -134,6 +134,10 @@ class Event &lt; Article
134 true 134 true
135 end 135 end
136 136
  137 + def can_display_media_panel?
  138 + true
  139 + end
  140 +
137 include Noosfero::TranslatableContent 141 include Noosfero::TranslatableContent
138 include MaybeAddHttp 142 include MaybeAddHttp
139 143
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/organization.rb
@@ -59,6 +59,10 @@ class Organization &lt; Profile @@ -59,6 +59,10 @@ class Organization &lt; Profile
59 59
60 validate :presence_of_required_fieds, :unless => :is_template 60 validate :presence_of_required_fieds, :unless => :is_template
61 61
  62 + def self.notify_activity tracked_action
  63 + Delayed::Job.enqueue NotifyActivityToProfilesJob.new(tracked_action.id)
  64 + end
  65 +
62 def presence_of_required_fieds 66 def presence_of_required_fieds
63 self.required_fields.each do |field| 67 self.required_fields.each do |field|
64 if self.send(field).blank? 68 if self.send(field).blank?
app/models/person.rb
@@ -94,6 +94,9 @@ roles] } @@ -94,6 +94,9 @@ roles] }
94 94
95 has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy 95 has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy
96 96
  97 + has_many :favorite_enterprise_people
  98 + has_many :favorite_enterprises, source: :enterprise, through: :favorite_enterprise_people
  99 +
97 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people' 100 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people'
98 has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions' 101 has_and_belongs_to_many :articles_with_access, :class_name => 'Article', :join_table => 'article_privacy_exceptions'
99 102
@@ -333,8 +336,6 @@ roles] } @@ -333,8 +336,6 @@ roles] }
333 ] 336 ]
334 end 337 end
335 338
336 - has_and_belongs_to_many :favorite_enterprises, :class_name => 'Enterprise', :join_table => 'favorite_enteprises_people'  
337 -  
338 def email_domain 339 def email_domain
339 user && user.email_domain || environment.default_hostname(true) 340 user && user.email_domain || environment.default_hostname(true)
340 end 341 end
@@ -514,8 +515,8 @@ roles] } @@ -514,8 +515,8 @@ roles] }
514 user.save! 515 user.save!
515 end 516 end
516 517
517 - def activities  
518 - 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.user_id = #{self.id} and action_tracker.verb != 'leave_scrap_to_self' and action_tracker.verb != 'add_member_in_community' and action_tracker.verb != 'reply_scrap_on_self' ORDER BY updated_at DESC") 518 + def exclude_verbs_on_activities
  519 + %w[leave_scrap_to_self add_member_in_community reply_scrap_on_self]
519 end 520 end
520 521
521 # by default, all fields are private 522 # by default, all fields are private
app/models/person_notifier.rb
@@ -76,7 +76,8 @@ class PersonNotifier @@ -76,7 +76,8 @@ class PersonNotifier
76 76
77 class Mailer < ActionMailer::Base 77 class Mailer < ActionMailer::Base
78 78
79 - add_template_helper(ApplicationHelper) 79 + helper ApplicationHelper
  80 + helper ActionTrackerHelper
80 81
81 def session 82 def session
82 {:theme => nil} 83 {:theme => nil}
app/models/product.rb
@@ -17,13 +17,14 @@ class Product &lt; ActiveRecord::Base @@ -17,13 +17,14 @@ class Product &lt; ActiveRecord::Base
17 'full' 17 'full'
18 end 18 end
19 19
20 - belongs_to :enterprise, :foreign_key => :profile_id, :class_name => 'Profile'  
21 belongs_to :profile 20 belongs_to :profile
  21 + # backwards compatibility
  22 + belongs_to :enterprise, :foreign_key => :profile_id, :class_name => 'Profile'
22 alias_method :enterprise=, :profile= 23 alias_method :enterprise=, :profile=
23 alias_method :enterprise, :profile 24 alias_method :enterprise, :profile
24 25
25 - has_one :region, :through => :enterprise  
26 - validates_presence_of :enterprise 26 + has_one :region, :through => :profile
  27 + validates_presence_of :profile
27 28
28 belongs_to :product_category 29 belongs_to :product_category
29 30
@@ -37,6 +38,10 @@ class Product &lt; ActiveRecord::Base @@ -37,6 +38,10 @@ class Product &lt; ActiveRecord::Base
37 38
38 acts_as_having_settings :field => :data 39 acts_as_having_settings :field => :data
39 40
  41 + track_actions :create_product, :after_create, :keep_params => [:name, :url ], :if => Proc.new { |a| a.is_trackable? }, :custom_user => :action_tracker_user
  42 + track_actions :update_product, :before_update, :keep_params => [:name, :url], :if => Proc.new { |a| a.is_trackable? }, :custom_user => :action_tracker_user
  43 + track_actions :remove_product, :before_destroy, :keep_params => [:name], :if => Proc.new { |a| a.is_trackable? }, :custom_user => :action_tracker_user
  44 +
40 validates_uniqueness_of :name, :scope => :profile_id, :allow_nil => true, :if => :validate_uniqueness_of_column_name? 45 validates_uniqueness_of :name, :scope => :profile_id, :allow_nil => true, :if => :validate_uniqueness_of_column_name?
41 46
42 validates_presence_of :product_category_id 47 validates_presence_of :product_category_id
@@ -73,10 +78,10 @@ class Product &lt; ActiveRecord::Base @@ -73,10 +78,10 @@ class Product &lt; ActiveRecord::Base
73 after_update :save_image 78 after_update :save_image
74 79
75 def lat 80 def lat
76 - self.enterprise.lat 81 + self.profile.lat
77 end 82 end
78 def lng 83 def lng
79 - self.enterprise.lng 84 + self.profile.lng
80 end 85 end
81 86
82 xss_terminate :only => [ :name ], :on => 'validation' 87 xss_terminate :only => [ :name ], :on => 'validation'
@@ -90,7 +95,7 @@ class Product &lt; ActiveRecord::Base @@ -90,7 +95,7 @@ class Product &lt; ActiveRecord::Base
90 filter_iframes :description 95 filter_iframes :description
91 96
92 def iframe_whitelist 97 def iframe_whitelist
93 - enterprise && enterprise.environment && enterprise.environment.trusted_sites_for_iframe 98 + self.profile && self.profile.environment && self.profile.environment.trusted_sites_for_iframe
94 end 99 end
95 100
96 def name 101 def name
@@ -128,16 +133,16 @@ class Product &lt; ActiveRecord::Base @@ -128,16 +133,16 @@ class Product &lt; ActiveRecord::Base
128 end 133 end
129 134
130 def url 135 def url
131 - enterprise.public_profile_url.merge(:controller => 'manage_products', :action => 'show', :id => id) 136 + self.profile.public_profile_url.merge(:controller => 'manage_products', :action => 'show', :id => id)
132 end 137 end
133 138
134 def public? 139 def public?
135 - enterprise.public? 140 + self.profile.public?
136 end 141 end
137 142
138 def formatted_value(method) 143 def formatted_value(method)
139 value = self[method] || self.send(method) 144 value = self[method] || self.send(method)
140 - ("%.2f" % value).to_s.gsub('.', enterprise.environment.currency_separator) if value 145 + ("%.2f" % value).to_s.gsub('.', self.profile.environment.currency_separator) if value
141 end 146 end
142 147
143 def price_with_discount 148 def price_with_discount
@@ -242,16 +247,16 @@ class Product &lt; ActiveRecord::Base @@ -242,16 +247,16 @@ class Product &lt; ActiveRecord::Base
242 end 247 end
243 248
244 def available_production_costs 249 def available_production_costs
245 - self.enterprise.environment.production_costs + self.enterprise.production_costs 250 + self.profile.environment.production_costs + self.profile.production_costs
246 end 251 end
247 252
248 include Rails.application.routes.url_helpers 253 include Rails.application.routes.url_helpers
249 def price_composition_bar_display_url 254 def price_composition_bar_display_url
250 - url_for({:host => enterprise.default_hostname, :controller => 'manage_products', :action => 'display_price_composition_bar', :profile => enterprise.identifier, :id => self.id }.merge(Noosfero.url_options)) 255 + url_for({:host => self.profile.default_hostname, :controller => 'manage_products', :action => 'display_price_composition_bar', :profile => self.profile.identifier, :id => self.id }.merge(Noosfero.url_options))
251 end 256 end
252 257
253 def inputs_cost_update_url 258 def inputs_cost_update_url
254 - url_for({:host => enterprise.default_hostname, :controller => 'manage_products', :action => 'display_inputs_cost', :profile => enterprise.identifier, :id => self.id }.merge(Noosfero.url_options)) 259 + url_for({:host => self.profile.default_hostname, :controller => 'manage_products', :action => 'display_inputs_cost', :profile => self.profile.identifier, :id => self.id }.merge(Noosfero.url_options))
255 end 260 end
256 261
257 def percentage_from_solidarity_economy 262 def percentage_from_solidarity_economy
@@ -268,7 +273,7 @@ class Product &lt; ActiveRecord::Base @@ -268,7 +273,7 @@ class Product &lt; ActiveRecord::Base
268 end 273 end
269 end 274 end
270 275
271 - delegate :enabled, :region, :region_id, :environment, :environment_id, :to => :enterprise 276 + delegate :enabled, :region, :region_id, :environment, :environment_id, :to => :profile, allow_nil: true
272 277
273 protected 278 protected
274 279
@@ -276,4 +281,13 @@ class Product &lt; ActiveRecord::Base @@ -276,4 +281,13 @@ class Product &lt; ActiveRecord::Base
276 true 281 true
277 end 282 end
278 283
  284 + def is_trackable?
  285 + # shopping_cart create products without profile
  286 + self.profile.present?
  287 + end
  288 +
  289 + def action_tracker_user
  290 + self.profile
  291 + end
  292 +
279 end 293 end
app/models/profile.rb
@@ -3,7 +3,9 @@ @@ -3,7 +3,9 @@
3 # which by default is the one returned by Environment:default. 3 # which by default is the one returned by Environment:default.
4 class Profile < ActiveRecord::Base 4 class Profile < ActiveRecord::Base
5 5
6 - attr_accessible :name, :identifier, :public_profile, :nickname, :custom_footer, :custom_header, :address, :zip_code, :contact_phone, :image_builder, :description, :closed, :template_id, :environment, :lat, :lng, :is_template, :fields_privacy, :preferred_domain_id, :category_ids, :country, :city, :state, :national_region_code, :email, :contact_email, :redirect_l10n, :notification_time, :redirection_after_login, :email_suggestions, :allow_members_to_invite, :invite_friends_only, :secret 6 + attr_accessible :name, :identifier, :public_profile, :nickname, :custom_footer, :custom_header, :address, :zip_code, :contact_phone, :image_builder, :description, :closed, :template_id, :environment, :lat, :lng, :is_template, :fields_privacy, :preferred_domain_id, :category_ids, :country, :city, :state, :national_region_code, :email, :contact_email, :redirect_l10n, :notification_time,
  7 + :redirection_after_login, :custom_url_redirection,
  8 + :email_suggestions, :allow_members_to_invite, :invite_friends_only, :secret
7 9
8 # use for internationalizable human type names in search facets 10 # use for internationalizable human type names in search facets
9 # reimplement on subclasses 11 # reimplement on subclasses
@@ -188,6 +190,7 @@ class Profile &lt; ActiveRecord::Base @@ -188,6 +190,7 @@ class Profile &lt; ActiveRecord::Base
188 190
189 acts_as_trackable :dependent => :destroy 191 acts_as_trackable :dependent => :destroy
190 192
  193 + has_many :profile_activities
191 has_many :action_tracker_notifications, :foreign_key => 'profile_id' 194 has_many :action_tracker_notifications, :foreign_key => 'profile_id'
192 has_many :tracked_notifications, :through => :action_tracker_notifications, :source => :action_tracker, :order => 'updated_at DESC' 195 has_many :tracked_notifications, :through => :action_tracker_notifications, :source => :action_tracker, :order => 'updated_at DESC'
193 has_many :scraps_received, :class_name => 'Scrap', :foreign_key => :receiver_id, :order => "updated_at DESC", :dependent => :destroy 196 has_many :scraps_received, :class_name => 'Scrap', :foreign_key => :receiver_id, :order => "updated_at DESC", :dependent => :destroy
@@ -613,6 +616,14 @@ class Profile &lt; ActiveRecord::Base @@ -613,6 +616,14 @@ class Profile &lt; ActiveRecord::Base
613 options.merge(Noosfero.url_options) 616 options.merge(Noosfero.url_options)
614 end 617 end
615 618
  619 + def top_url(scheme = 'http')
  620 + url = scheme + '://'
  621 + url << url_options[:host]
  622 + url << ':' << url_options[:port].to_s if url_options.key?(:port)
  623 + url << Noosfero.root('')
  624 + url
  625 + end
  626 +
616 private :generate_url, :url_options 627 private :generate_url, :url_options
617 628
618 def default_hostname 629 def default_hostname
@@ -785,7 +796,11 @@ private :generate_url, :url_options @@ -785,7 +796,11 @@ private :generate_url, :url_options
785 include ActionView::Helpers::TextHelper 796 include ActionView::Helpers::TextHelper
786 def short_name(chars = 40) 797 def short_name(chars = 40)
787 if self[:nickname].blank? 798 if self[:nickname].blank?
788 - truncate self.name, :length => chars, :omission => '...' 799 + if chars
  800 + truncate self.name, length: chars, omission: '...'
  801 + else
  802 + self.name
  803 + end
789 else 804 else
790 self[:nickname] 805 self[:nickname]
791 end 806 end
@@ -1025,9 +1040,13 @@ private :generate_url, :url_options @@ -1025,9 +1040,13 @@ private :generate_url, :url_options
1025 name 1040 name
1026 end 1041 end
1027 1042
1028 - # Override in your subclasses 1043 + def exclude_verbs_on_activities
  1044 + %w[]
  1045 + end
  1046 +
  1047 + # Customize in subclasses
1029 def activities 1048 def activities
1030 - [] 1049 + self.profile_activities.includes(:activity).order('updated_at DESC')
1031 end 1050 end
1032 1051
1033 def may_display_field_to? field, user = nil 1052 def may_display_field_to? field, user = nil
@@ -1074,6 +1093,7 @@ private :generate_url, :url_options @@ -1074,6 +1093,7 @@ private :generate_url, :url_options
1074 def preferred_login_redirection 1093 def preferred_login_redirection
1075 redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login 1094 redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login
1076 end 1095 end
  1096 + settings_items :custom_url_redirection, type: String, default: nil
1077 1097
1078 def remove_from_suggestion_list(person) 1098 def remove_from_suggestion_list(person)
1079 suggestion = person.suggested_profiles.find_by_suggestion_id self.id 1099 suggestion = person.suggested_profiles.find_by_suggestion_id self.id
app/models/profile_activity.rb 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +class ProfileActivity < ActiveRecord::Base
  2 +
  3 + self.record_timestamps = false
  4 +
  5 + attr_accessible :profile_id,
  6 + :profile, :activity
  7 +
  8 + belongs_to :profile
  9 + belongs_to :activity, polymorphic: true
  10 +
  11 + # non polymorphic versions
  12 + belongs_to :scrap, foreign_key: :activity_id, class_name: 'Scrap', conditions: {profile_activities: {activity_type: 'Scrap'}}
  13 + belongs_to :action_tracker, foreign_key: :activity_id, class_name: 'ActionTracker::Record', conditions: {profile_activities: {activity_type: 'ActionTracker::Record'}}
  14 +
  15 + before_validation :copy_timestamps
  16 +
  17 + def self.update_activity activity
  18 + profile_activity = ProfileActivity.where(activity_id: activity.id, activity_type: activity.class.base_class.name).first
  19 + profile_activity.send :copy_timestamps
  20 + profile_activity.save!
  21 + profile_activity
  22 + end
  23 +
  24 + protected
  25 +
  26 + def copy_timestamps
  27 + self.created_at = self.activity.created_at
  28 + self.updated_at = self.activity.updated_at
  29 + end
  30 +
  31 +end
app/models/profile_list_block.rb
@@ -16,19 +16,19 @@ class ProfileListBlock &lt; Block @@ -16,19 +16,19 @@ class ProfileListBlock &lt; Block
16 16
17 def profile_list 17 def profile_list
18 result = nil 18 result = nil
19 - visible_profiles = profiles.visible.includes([:image,:domains,:preferred_domain,:environment]) 19 + public_profiles = profiles.public.includes([:image,:domains,:preferred_domain,:environment])
20 if !prioritize_profiles_with_image 20 if !prioritize_profiles_with_image
21 - result = visible_profiles.all(:limit => get_limit, :order => 'profiles.updated_at DESC').sort_by{ rand } 21 +result = public_profiles.all(:limit => get_limit, :order => 'profiles.updated_at DESC').sort_by{ rand }
22 elsif profiles.visible.with_image.count >= get_limit 22 elsif profiles.visible.with_image.count >= get_limit
23 - result = visible_profiles.with_image.all(:limit => get_limit * 5, :order => 'profiles.updated_at DESC').sort_by{ rand } 23 + result = public_profiles.with_image.all(:limit => get_limit * 5, :order => 'profiles.updated_at DESC').sort_by{ rand }
24 else 24 else
25 - result = visible_profiles.with_image.sort_by{ rand } + visible_profiles.without_image.all(:limit => get_limit * 5, :order => 'profiles.updated_at DESC').sort_by{ rand } 25 + result = public_profiles.with_image.sort_by{ rand } + public_profiles.without_image.all(:limit => get_limit * 5, :order => 'profiles.updated_at DESC').sort_by{ rand }
26 end 26 end
27 result.slice(0..get_limit-1) 27 result.slice(0..get_limit-1)
28 end 28 end
29 29
30 def profile_count 30 def profile_count
31 - profiles.visible.length 31 + profiles.public.length
32 end 32 end
33 33
34 # the title of the block. Probably will be overriden in subclasses. 34 # the title of the block. Probably will be overriden in subclasses.
app/models/scrap.rb
@@ -13,20 +13,22 @@ class Scrap &lt; ActiveRecord::Base @@ -13,20 +13,22 @@ class Scrap &lt; ActiveRecord::Base
13 has_many :replies, :class_name => 'Scrap', :foreign_key => 'scrap_id', :dependent => :destroy 13 has_many :replies, :class_name => 'Scrap', :foreign_key => 'scrap_id', :dependent => :destroy
14 belongs_to :root, :class_name => 'Scrap', :foreign_key => 'scrap_id' 14 belongs_to :root, :class_name => 'Scrap', :foreign_key => 'scrap_id'
15 15
  16 + has_many :profile_activities, foreign_key: :activity_id, conditions: {profile_activities: {activity_type: 'Scrap'}}, dependent: :destroy
  17 +
  18 + after_create :create_activity
  19 + after_update :update_activity
  20 +
16 scope :all_scraps, lambda {|profile| {:conditions => ["receiver_id = ? OR sender_id = ?", profile, profile], :limit => 30}} 21 scope :all_scraps, lambda {|profile| {:conditions => ["receiver_id = ? OR sender_id = ?", profile, profile], :limit => 30}}
17 22
18 scope :not_replies, :conditions => {:scrap_id => nil} 23 scope :not_replies, :conditions => {:scrap_id => nil}
19 24
20 - track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.sender != s.receiver && s.sender != s.top_root.receiver}, :custom_target => :action_tracker_target 25 + track_actions :leave_scrap, :after_create, :keep_params => ['sender.name', 'content', 'receiver.name', 'receiver.url'], :if => Proc.new{|s| s.sender != s.receiver && s.sender != s.top_root.receiver}, :custom_target => :action_tracker_target, :custom_user => :sender
21 26
22 - track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender == s.receiver} 27 + track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender == s.receiver}, :custom_user => :sender
23 28
24 - track_actions :reply_scrap_on_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender != s.receiver && s.sender == s.top_root.receiver} 29 + track_actions :reply_scrap_on_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender != s.receiver && s.sender == s.top_root.receiver}, :custom_user => :sender
25 30
26 - after_create do |scrap|  
27 - scrap.root.update_attribute('updated_at', DateTime.now) unless scrap.root.nil?  
28 - ScrapNotifier.notification(scrap).deliver if scrap.send_notification?  
29 - end 31 + after_create :send_notification
30 32
31 before_validation :strip_all_html_tags 33 before_validation :strip_all_html_tags
32 34
@@ -57,4 +59,21 @@ class Scrap &lt; ActiveRecord::Base @@ -57,4 +59,21 @@ class Scrap &lt; ActiveRecord::Base
57 sender != receiver && (is_root? ? root.receiver.receives_scrap_notification? : receiver.receives_scrap_notification?) 59 sender != receiver && (is_root? ? root.receiver.receives_scrap_notification? : receiver.receives_scrap_notification?)
58 end 60 end
59 61
  62 + protected
  63 +
  64 + def create_activity
  65 + # do not scrap replies (when scrap_id is not nil)
  66 + return if self.scrap_id.present?
  67 + ProfileActivity.create! profile_id: self.receiver_id, activity: self
  68 + end
  69 +
  70 + def update_activity
  71 + ProfileActivity.update_activity self
  72 + end
  73 +
  74 + def send_notification
  75 + self.root.update_attribute('updated_at', DateTime.now) unless self.root.nil?
  76 + ScrapNotifier.notification(self).deliver if self.send_notification?
  77 + end
  78 +
60 end 79 end
app/models/session.rb 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +class Session < ActiveRecord::SessionStore::Session
  2 +
  3 + # removed and redefined on super class
  4 + def self.find_by_session_id session_id
  5 + super
  6 + end
  7 +
  8 + belongs_to :user
  9 +
  10 + before_save :copy_to_columns
  11 +
  12 + protected
  13 +
  14 + def copy_to_columns
  15 + self.user_id = self.data['user']
  16 + end
  17 +
  18 +end
app/models/text_article.rb
@@ -33,12 +33,16 @@ class TextArticle &lt; Article @@ -33,12 +33,16 @@ class TextArticle &lt; Article
33 end 33 end
34 34
35 def change_element_path(el, attribute) 35 def change_element_path(el, attribute)
36 - fullpath = /(https?):\/\/(#{environment.default_hostname})(:\d+)?(\/.*)/.match(el[attribute]) 36 + fullpath = /(https?):\/\/(#{profile.default_hostname})(:\d+)?(\/.*)/.match(el[attribute])
37 if fullpath 37 if fullpath
38 domain = fullpath[2] 38 domain = fullpath[2]
39 path = fullpath[4] 39 path = fullpath[4]
40 - el[attribute] = path if domain == environment.default_hostname 40 + el[attribute] = path if domain == profile.default_hostname
41 end 41 end
42 end 42 end
43 43
  44 + def display_preview?
  45 + parent && parent.kind_of?(Blog) && parent.display_preview
  46 + end
  47 +
44 end 48 end
app/models/textile_article.rb
@@ -24,6 +24,10 @@ class TextileArticle &lt; TextArticle @@ -24,6 +24,10 @@ class TextileArticle &lt; TextArticle
24 true 24 true
25 end 25 end
26 26
  27 + def can_display_media_panel?
  28 + true
  29 + end
  30 +
27 protected 31 protected
28 32
29 def convert_to_html(textile) 33 def convert_to_html(textile)
app/models/tiny_mce_article.rb
@@ -28,4 +28,8 @@ class TinyMceArticle &lt; TextArticle @@ -28,4 +28,8 @@ class TinyMceArticle &lt; TextArticle
28 true 28 true
29 end 29 end
30 30
  31 + def can_display_media_panel?
  32 + true
  33 + end
  34 +
31 end 35 end
app/models/uploaded_file.rb
@@ -163,4 +163,8 @@ class UploadedFile &lt; Article @@ -163,4 +163,8 @@ class UploadedFile &lt; Article
163 true 163 true
164 end 164 end
165 165
  166 + def notifiable?
  167 + true
  168 + end
  169 +
166 end 170 end
app/models/user.rb
@@ -16,6 +16,14 @@ class User &lt; ActiveRecord::Base @@ -16,6 +16,14 @@ class User &lt; ActiveRecord::Base
16 :email => {:label => _('Email'), :weight => 5}, 16 :email => {:label => _('Email'), :weight => 5},
17 } 17 }
18 18
  19 + # see http://stackoverflow.com/a/2513456/670229
  20 + def self.current
  21 + Thread.current[:current_user]
  22 + end
  23 + def self.current=(user)
  24 + Thread.current[:current_user] = user
  25 + end
  26 +
19 def self.[](login) 27 def self.[](login)
20 self.find_by_login(login) 28 self.find_by_login(login)
21 end 29 end
@@ -97,6 +105,10 @@ class User &lt; ActiveRecord::Base @@ -97,6 +105,10 @@ class User &lt; ActiveRecord::Base
97 has_one :person, :dependent => :destroy 105 has_one :person, :dependent => :destroy
98 belongs_to :environment 106 belongs_to :environment
99 107
  108 + has_many :sessions, dependent: :destroy
  109 + # holds the current session, see lib/authenticated_system.rb
  110 + attr_accessor :session
  111 +
100 attr_protected :activated_at 112 attr_protected :activated_at
101 113
102 # Virtual attribute for the unencrypted password 114 # Virtual attribute for the unencrypted password
@@ -118,11 +130,18 @@ class User &lt; ActiveRecord::Base @@ -118,11 +130,18 @@ class User &lt; ActiveRecord::Base
118 130
119 validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('{fn} must be checked in order to signup.').fix_i18n 131 validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('{fn} must be checked in order to signup.').fix_i18n
120 132
  133 + scope :has_login?, lambda { |login,email,environment_id|
  134 + where('login = ? OR email = ?', login, email).
  135 + where(environment_id: environment_id)
  136 + }
  137 +
121 # Authenticates a user by their login name or email and unencrypted password. Returns the user or nil. 138 # Authenticates a user by their login name or email and unencrypted password. Returns the user or nil.
122 def self.authenticate(login, password, environment = nil) 139 def self.authenticate(login, password, environment = nil)
123 environment ||= Environment.default 140 environment ||= Environment.default
124 - u = self.first :conditions => ['(login = ? OR email = ?) AND environment_id = ? AND activated_at IS NOT NULL',  
125 - login, login, environment.id] # need to get the salt 141 +
  142 + u = self.has_login?(login, login, environment.id)
  143 + u = u.first if u.is_a?(ActiveRecord::Relation)
  144 +
126 if u && u.authenticated?(password) 145 if u && u.authenticated?(password)
127 u.generate_private_token_if_not_exist 146 u.generate_private_token_if_not_exist
128 return u 147 return u
@@ -259,7 +278,23 @@ class User &lt; ActiveRecord::Base @@ -259,7 +278,23 @@ class User &lt; ActiveRecord::Base
259 password.crypt(salt) 278 password.crypt(salt)
260 end 279 end
261 280
  281 + class UserNotActivated < StandardError
  282 + attr_reader :user
  283 +
  284 + def initialize(message, user = nil)
  285 + @user = user
  286 +
  287 + super(message)
  288 + end
  289 + end
  290 +
262 def authenticated?(password) 291 def authenticated?(password)
  292 +
  293 + unless self.activated?
  294 + message = _('The user "%{login}" is not activated! Please check your email to activate your user') % {login: self.login}
  295 + raise UserNotActivated.new(message, self)
  296 + end
  297 +
263 result = (crypted_password == encrypt(password)) 298 result = (crypted_password == encrypt(password))
264 if (encryption_method != User.system_encryption_method) && result 299 if (encryption_method != User.system_encryption_method) && result
265 self.password_type = User.system_encryption_method.to_s 300 self.password_type = User.system_encryption_method.to_s
@@ -276,8 +311,9 @@ class User &lt; ActiveRecord::Base @@ -276,8 +311,9 @@ class User &lt; ActiveRecord::Base
276 311
277 # These create and unset the fields required for remembering users between browser closes 312 # These create and unset the fields required for remembering users between browser closes
278 def remember_me 313 def remember_me
279 - self.remember_token_expires_at = 2.weeks.from_now.utc  
280 - self.remember_token = encrypt("#{email}--#{remember_token_expires_at}") 314 + self.remember_token_expires_at = 1.months.from_now.utc
  315 + # if the user's email/password changes this won't be valid anymore
  316 + self.remember_token = encrypt "#{email}-#{self.crypted_password}-#{remember_token_expires_at}"
281 save(:validate => false) 317 save(:validate => false)
282 end 318 end
283 319
@@ -297,9 +333,15 @@ class User &lt; ActiveRecord::Base @@ -297,9 +333,15 @@ class User &lt; ActiveRecord::Base
297 # current password. 333 # current password.
298 # * Saves the record unless it is a new one. 334 # * Saves the record unless it is a new one.
299 def change_password!(current, new, confirmation) 335 def change_password!(current, new, confirmation)
300 - unless self.authenticated?(current)  
301 - self.errors.add(:current_password, _('does not match.'))  
302 - raise IncorrectPassword 336 +
  337 + begin
  338 + unless self.authenticated?(current)
  339 + self.errors.add(:current_password, _('does not match.'))
  340 + raise IncorrectPassword
  341 + end
  342 + rescue UserNotActivated => e
  343 + self.errors.add(:current_password, e.message)
  344 + raise UserNotActivated
303 end 345 end
304 self.force_change_password!(new, confirmation) 346 self.force_change_password!(new, confirmation)
305 end 347 end
app/models/validation_info.rb
@@ -2,9 +2,10 @@ class ValidationInfo &lt; ActiveRecord::Base @@ -2,9 +2,10 @@ class ValidationInfo &lt; ActiveRecord::Base
2 2
3 attr_accessible :validation_methodology, :restrictions, :organization 3 attr_accessible :validation_methodology, :restrictions, :organization
4 4
5 - validates_presence_of :validation_methodology  
6 -  
7 belongs_to :organization 5 belongs_to :organization
8 6
  7 + validates_presence_of :organization
  8 + validates_presence_of :validation_methodology
  9 +
9 xss_terminate :only => [ :validation_methodology, :restrictions ], :on => 'validation' 10 xss_terminate :only => [ :validation_methodology, :restrictions ], :on => 'validation'
10 end 11 end
app/views/account/login.html.erb
@@ -13,7 +13,14 @@ @@ -13,7 +13,14 @@
13 13
14 <%= f.password_field :password %> 14 <%= f.password_field :password %>
15 15
16 - <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }.join("") %> 16 + <div class='checkbox'>
  17 + <label>
  18 + <%= check_box_tag :remember_me, '1', true %>
  19 + <%= _'Keep me logged in' %>
  20 + </label>
  21 + </div>
  22 +
  23 + <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_exec(&content) }.join("") %>
17 24
18 <% button_bar do %> 25 <% button_bar do %>
19 <%= submit_button( 'login', _('Log in') )%> 26 <%= submit_button( 'login', _('Log in') )%>
app/views/account/signup.html.erb
1 <h1><%= _('Sign up for %s!') % environment.name %></h1> 1 <h1><%= _('Sign up for %s!') % environment.name %></h1>
  2 +
  3 +<div id='signup-intro'>
  4 + <%= environment.signup_intro %>
  5 +</div>
  6 +
2 <%= render :partial => 'signup_form' %> 7 <%= render :partial => 'signup_form' %>
app/views/admin_panel/_signup_intro.html.erb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<div class='description'>
  2 + <%= _('This text will be shown to the user on the top of the sign up form.') %>
  3 +</div>
  4 +
  5 +<%= labelled_form_field(_('Body'), text_area(:environment, :signup_intro, :cols => 40, :style => 'width: 100%', :class => 'mceEditor')) %>
app/views/admin_panel/site_info.html.erb
@@ -17,6 +17,8 @@ @@ -17,6 +17,8 @@
17 :content => (render :partial => 'signup_welcome_text', :locals => {:f => f})} %> 17 :content => (render :partial => 'signup_welcome_text', :locals => {:f => f})} %>
18 <% tabs << {:title => _('Signup welcome page'), :id => 'signup-welcome-message', 18 <% tabs << {:title => _('Signup welcome page'), :id => 'signup-welcome-message',
19 :content => (render :partial => 'signup_welcome_screen', :locals => {:f => f}) }%> 19 :content => (render :partial => 'signup_welcome_screen', :locals => {:f => f}) }%>
  20 + <% tabs << {:title => _('Signup introduction text'), :id => 'signup-intro',
  21 + :content => (render :partial => 'signup_intro', :locals => {:f => f})} %>
20 <%= render_tabs(tabs) %> 22 <%= render_tabs(tabs) %>
21 <% button_bar do %> 23 <% button_bar do %>
22 <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %> 24 <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %>
app/views/blocks/profile_info_actions/_enterprise.html.erb
1 <ul> 1 <ul>
2 <%if logged_in? %> 2 <%if logged_in? %>
3 <%if !user.favorite_enterprises.include?(profile) %> 3 <%if !user.favorite_enterprises.include?(profile) %>
4 - <li><%= button(:add, _('Add as favorite'), { :profile => user.identifier, :controller => 'favorite_enterprises', :action => 'add', :id => profile.id }, :title => _('Add enterprise as favorite')) %></li> 4 + <li><%= button(:love, _('Add as favorite'), { profile: user.identifier, controller: 'favorite_enterprises', action: 'add', id: profile.id }, title: _('Add enterprise as favorite')) %></li>
5 <% end %> 5 <% end %>
6 <% end %> 6 <% end %>
7 <% if profile.enable_contact? %> 7 <% if profile.enable_contact? %>
app/views/blocks/profile_info_actions/_join_leave_community.html.erb
1 <div class='join-leave-button require-login-popup'> 1 <div class='join-leave-button require-login-popup'>
2 <% if logged_in? %> 2 <% if logged_in? %>
3 - <% if profile.members.include?(user) %>  
4 - <%= button(:delete, content_tag('span', _('Leave community')), profile.leave_url,  
5 - :class => 'leave-community',  
6 - :title => _("Leave community"),  
7 - :style => 'position: relative;') %>  
8 - <%= button(:add, content_tag('span', _('Join')), profile.join_url,  
9 - :class => 'join-community',  
10 - :title => _("Join community"),  
11 - :style => 'position: relative; display: none;') %> 3 + <% if profile.already_request_membership? user %>
  4 + <%= _('Your membership is waiting for approval') %>
12 <% else %> 5 <% else %>
13 - <% unless profile.already_request_membership?(user) %>  
14 - <%= button(:delete, content_tag('span', _('Leave community')), profile.leave_url,  
15 - :class => 'leave-community',  
16 - :title => _("Leave community"),  
17 - :style => 'position: relative; display: none;') %>  
18 - <%= button(:add, content_tag('span', _('Join')), profile.join_url,  
19 - :class => 'join-community',  
20 - :title => _("Join community"),  
21 - :style => 'position: relative;') %> 6 + <% if user.in? profile.members %>
  7 + <%= button :delete, content_tag('span', _('Leave community')), profile.leave_url,
  8 + class: 'leave-community',
  9 + style: 'position: relative;' %>
  10 + <%= button :add, content_tag('span', _('Join this community')), profile.join_url,
  11 + class: 'join-community',
  12 + style: 'position: relative; display: none;' %>
  13 + <% else %>
  14 + <%= button :add, _('Join this community'), profile.join_url, class: 'join-community' %>
22 <% end %> 15 <% end %>
23 <% end %> 16 <% end %>
24 <% else %> 17 <% else %>
25 - <%= button(:add, _('Join'), profile.join_not_logged_url, :title => _('Join this community')) %> 18 + <%= button :add, _('Join this community'), profile.join_not_logged_url %>
26 <% end %> 19 <% end %>
27 </div> 20 </div>
  21 +
  22 +<%= javascript_tag do %>
  23 + noosfero.add_and_join.locales.leaveConfirmation = <%= (_("Please confirm to leave the community '%{name}'") % {name: profile.name}).to_json %>
  24 +<% end %>
  25 +
app/views/cms/_blog.html.erb
@@ -53,7 +53,7 @@ @@ -53,7 +53,7 @@
53 %> 53 %>
54 </div> 54 </div>
55 55
56 -<%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 10)) %> 56 +<%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 10, :class => 'mceEditor')) %>
57 57
58 <%= f.fields_for :image_builder, @article.image do |i| %> 58 <%= f.fields_for :image_builder, @article.image do |i| %>
59 <%= file_field_or_thumbnail(_('Cover image:'), @article.image, i)%> 59 <%= file_field_or_thumbnail(_('Cover image:'), @article.image, i)%>
app/views/cms/_event.html.erb
@@ -8,9 +8,8 @@ @@ -8,9 +8,8 @@
8 <%= render :partial => 'general_fields' %> 8 <%= render :partial => 'general_fields' %>
9 <%= render :partial => 'translatable' %> 9 <%= render :partial => 'translatable' %>
10 10
11 -<%= labelled_form_field(_('Start date'), pick_date(:article, :start_date)) %> 11 +<%= date_range_field('article[start_date]', 'article[end_date]', @article.start_date, @article.end_date, _('%Y-%m-%d %H:%M'), {:time => true}, {:id => 'article_start_date'} ) %>
12 12
13 -<%= labelled_form_field(_('End date'), pick_date(:article, :end_date)) %>  
14 13
15 <%= labelled_form_field(_('Event website:'), text_field(:article, :link)) %> 14 <%= labelled_form_field(_('Event website:'), text_field(:article, :link)) %>
16 15
app/views/cms/edit.html.erb
1 <%= error_messages_for 'article' %> 1 <%= error_messages_for 'article' %>
2 2
3 -<% show_media_panel = environment.enabled?('media_panel') && [TinyMceArticle, TextileArticle, Event, EnterpriseHomepage].any?{|klass| @article.kind_of?(klass)} %>  
4 -  
5 -<div class='<%= (show_media_panel ? 'with_media_panel' : 'no_media_panel') %>'> 3 +<div class='<%= (@article.display_media_panel? ? 'with_media_panel' : 'no_media_panel') %>'>
6 <%= labelled_form_for 'article', :html => { :multipart => true, :class => @type } do |f| %> 4 <%= labelled_form_for 'article', :html => { :multipart => true, :class => @type } do |f| %>
7 5
8 <%= hidden_field_tag("type", @type) if @type %> 6 <%= hidden_field_tag("type", @type) if @type %>
9 7
10 - <%= hidden_field_tag('parent_id', @parent_id) if @parent_id %>  
11 -  
12 <%= hidden_field_tag('back_to', @back_to) %> 8 <%= hidden_field_tag('back_to', @back_to) %>
13 9
14 <%= hidden_field_tag('success_back_to', @success_back_to) %> 10 <%= hidden_field_tag('success_back_to', @success_back_to) %>
@@ -68,7 +64,7 @@ @@ -68,7 +64,7 @@
68 <% end %> 64 <% end %>
69 </div> 65 </div>
70 66
71 -<% if show_media_panel %> 67 +<% if @article.display_media_panel? %>
72 <%= render :partial => 'text_editor_sidebar' %> 68 <%= render :partial => 'text_editor_sidebar' %>
73 <% end %> 69 <% end %>
74 70
app/views/content_viewer/_article_title.html.erb
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 <% end %> 7 <% end %>
8 </h1> 8 </h1>
9 <%= render :partial => "publishing_info" %> 9 <%= render :partial => "publishing_info" %>
10 - <% unless @page.abstract.blank? %> 10 + <% if @page.display_preview? %>
11 <div class="preview"> 11 <div class="preview">
12 <%= @page.lead %> 12 <%= @page.lead %>
13 </div> 13 </div>
app/views/content_viewer/_article_toolbar.html.erb
@@ -29,10 +29,10 @@ @@ -29,10 +29,10 @@
29 <%= expirable_button @page, :locale, content, url %> 29 <%= expirable_button @page, :locale, content, url %>
30 <% end %> 30 <% end %>
31 31
32 - <%= modal_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) unless remove_content_button(:new, @page) %> 32 + <%= modal_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : @page.parent))) unless remove_content_button(:new, @page) %>
33 33
34 <% content = content_tag('span', label_for_clone_article(@page)) %> 34 <% content = content_tag('span', label_for_clone_article(@page)) %>
35 - <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'new', :id => @page.id, :clone => true, :type => @page.class }) %> 35 + <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'new', :id => @page.id, :clone => true, :parent_id => (@page.folder? ? @page : @page.parent), :type => @page.class}) %>
36 <%= expirable_button @page, :clone, content, url %> 36 <%= expirable_button @page, :clone, content, url %>
37 <% end %> 37 <% end %>
38 38
@@ -62,7 +62,7 @@ @@ -62,7 +62,7 @@
62 <% if @page.blog? and !@page.image.nil? %> 62 <% if @page.blog? and !@page.image.nil? %>
63 <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div> 63 <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div>
64 <% end %> 64 <% end %>
65 - <%= link_to(image_tag('/images/icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> 65 + <%= button_without_text(:feed, _('RSS feed'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %>
66 <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %> 66 <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %>
67 <%= render :partial => 'article_title', :locals => {:no_link => true} %> 67 <%= render :partial => 'article_title', :locals => {:no_link => true} %>
68 <%= article_translations(@page) %> 68 <%= article_translations(@page) %>
app/views/content_viewer/_publishing_info.html.erb
1 <span class="publishing-info"> 1 <span class="publishing-info">
2 <span class="date"> 2 <span class="date">
3 - <%= show_date(@page.published_at) %> 3 + <%= show_time(@page.published_at) %>
4 </span> 4 </span>
5 <span class="author"> 5 <span class="author">
6 <%= _(", by %s") % (@page.author ? link_to(@page.author_name, @page.author_url) : @page.author_name) %> 6 <%= _(", by %s") % (@page.author ? link_to(@page.author_name, @page.author_url) : @page.author_name) %>
app/views/content_viewer/_uploaded_file.html.erb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <%= link_to '', 2 <%= link_to '',
3 uploaded_file.view_url, 3 uploaded_file.view_url,
4 :class => 'image', 4 :class => 'image',
5 - :style => 'background-image: url(%s)'% uploaded_file.public_filename(:thumb) 5 + :style => 'background-image: url(%s)'% [Noosfero.root, uploaded_file.public_filename(:thumb)].join
6 %> 6 %>
7 <span><%=h uploaded_file.title %></span> 7 <span><%=h uploaded_file.title %></span>
8 <% else %> 8 <% else %>
app/views/content_viewer/article_versions.html.erb
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <li> 12 <li>
13 <%= radio_button_tag 'v1', v.version, false, :onclick => 'versionInputClicked(this)' %> 13 <%= radio_button_tag 'v1', v.version, false, :onclick => 'versionInputClicked(this)' %>
14 <%= radio_button_tag 'v2', v.version, false, :onclick => 'versionInputClicked(this)' %> 14 <%= radio_button_tag 'v2', v.version, false, :onclick => 'versionInputClicked(this)' %>
15 - <%= link_to(_("Version #{v.version}"), @page.url.merge(:version => v.version)) %> 15 + <%= link_to(_("Version %s") % v.version, @page.url.merge(:version => v.version)) %>
16 <%= @page.version == v.version ? _('(current)') : '' %> 16 <%= @page.version == v.version ? _('(current)') : '' %>
17 <span class='updated-by'><%= _('by %{author}') % {:author => link_to(@page.author_name(v.version), @page.author_url(v.version))} %></span> 17 <span class='updated-by'><%= _('by %{author}') % {:author => link_to(@page.author_name(v.version), @page.author_url(v.version))} %></span>
18 <span class='updated-on'><%= show_time(v.updated_at) %></span> 18 <span class='updated-on'><%= show_time(v.updated_at) %></span>
app/views/content_viewer/folder.html.erb
@@ -4,8 +4,5 @@ @@ -4,8 +4,5 @@
4 </div> 4 </div>
5 <% end %> 5 <% end %>
6 6
7 -<% if folder.children.empty? %>  
8 - <em><%= _('(empty folder)') %></em>  
9 -<% else %>  
10 - <%= list_contents(:contents=>folder.children) %>  
11 -<% end %> 7 +<%= list_contents contents: folder.children %>
  8 +
app/views/content_viewer/view_page.html.erb
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 <%= render :partial => 'article_toolbar' %> 24 <%= render :partial => 'article_toolbar' %>
25 </div> 25 </div>
26 26
27 -<% if NOOSFERO_CONF['addthis_enabled'] %> 27 +<% if NOOSFERO_CONF['addthis_enabled'] and @page.public? %>
28 <%= render :partial => 'addthis' %> 28 <%= render :partial => 'addthis' %>
29 <% end %> 29 <% end %>
30 30
app/views/file_presenter/_generic.html.erb
1 -<span class="download-link">  
2 - <span>Download</span>  
3 - <strong><%= link_to generic.filename, [Noosfero.root, generic.public_filename].join %></strong>  
4 -</span>  
5 -  
6 <div class="uploaded-file-description <%= 'empty' if generic.abstract.blank? %>"> 1 <div class="uploaded-file-description <%= 'empty' if generic.abstract.blank? %>">
7 <%= generic.abstract %> 2 <%= generic.abstract %>
8 </div> 3 </div>
9 4
  5 +<%= button(:download, _('Download'), [Noosfero.root, generic.public_filename].join, class:'download-link', option:'primary', size:'lg') %>
app/views/organizations/_results.html.erb
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 </div> 30 </div>
31 </td> 31 </td>
32 32
33 - <td> <%= _("#{p.type}") %> </td> 33 + <td> <%= _(p.type) %> </td>
34 </tr> 34 </tr>
35 <% end %> 35 <% end %>
36 </table> 36 </table>
app/views/person_notifier/mailer/_default_activity.html.erb
@@ -4,7 +4,10 @@ @@ -4,7 +4,10 @@
4 </td> 4 </td>
5 <td> 5 <td>
6 <p> 6 <p>
7 - <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> 7 + <span style="font-size: 14px;">
  8 + <%= link_to activity.user.name, activity.user.url %>
  9 + <%= describe activity %>
  10 + </span>
8 <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(activity.created_at) %></span> 11 <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(activity.created_at) %></span>
9 </p> 12 </p>
10 </td> 13 </td>
app/views/profile/_create_product.html.erb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<div class='profile-activity-image'>
  2 + <%= link_to image_tag(activity.target.default_image :minor), activity.target.url, class: 'product-pic' if activity.target.present? %>
  3 +</div>
  4 +<div class='profile-activity-description'>
  5 + <p class='profile-activity-text'><%= link_to activity.user.short_name(nil), activity.user.url %> <%= describe activity %></p>
  6 + <p class='profile-activity-time'><%= time_ago_as_sentence activity.created_at %></p>
  7 +
  8 + <div class='profile-wall-actions'>
  9 + <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
  10 + </div>
  11 +</div>
  12 +
  13 +<div style="clear: both"></div>
app/views/profile/_favorite_enterprise.html.erb 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +<div class='profile-activity-image'>
  2 + <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
  3 +</div>
  4 +<div class='profile-activity-description'>
  5 + <p class='profile-activity-text'>
  6 + <%= link_to activity.user.short_name(nil), activity.user.url %> <%= describe activity %>
  7 + </p>
  8 + <p class='profile-activity-time'><%= time_ago_as_sentence activity.created_at %></p>
  9 +
  10 + <div class='profile-wall-actions'>
  11 + <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
  12 + </div>
  13 +</div>
  14 +
  15 +<div style="clear: both"></div>
app/views/profile/_profile_activities_list.html.erb
1 <% unless activities.nil? %> 1 <% unless activities.nil? %>
2 - <% activities.each do |a| %>  
3 - <% activity = a.klass.constantize.find(a.id) %> 2 + <% activities.each do |profile_activity| %>
  3 + <% activity = profile_activity.activity %>
4 <% if activity.kind_of?(ActionTracker::Record) %> 4 <% if activity.kind_of?(ActionTracker::Record) %>
5 <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'wall' } if activity.visible? %> 5 <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'wall' } if activity.visible? %>
6 <% else %> 6 <% else %>
app/views/profile/_remove_product.html.erb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +<div class='profile-activity-image'>
  2 +</div>
  3 +<div class='profile-activity-description'>
  4 + <p class='profile-activity-text'><%= link_to activity.user.short_name(nil), activity.user.url %> <%= describe activity %></p>
  5 + <p class='profile-activity-time'><%= time_ago_as_sentence activity.created_at %></p>
  6 +
  7 + <div class='profile-wall-actions'>
  8 + <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
  9 + </div>
  10 +</div>
  11 +
  12 +<div style="clear: both"></div>
app/views/profile/_update_product.html.erb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<div class='profile-activity-image'>
  2 + <%= link_to image_tag(activity.target.default_image :minor), activity.target.url, class: 'product-pic' if activity.target.present? %>
  3 +</div>
  4 +<div class='profile-activity-description'>
  5 + <p class='profile-activity-text'><%= link_to activity.user.short_name(nil), activity.user.url %> <%= describe activity %></p>
  6 + <p class='profile-activity-time'><%= time_ago_as_sentence activity.created_at %></p>
  7 +
  8 + <div class='profile-wall-actions'>
  9 + <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
  10 + </div>
  11 +</div>
  12 +
  13 +<div style="clear: both"></div>
app/views/profile_editor/_redirection_after_login.html.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<% content_for :head do %>
  2 + <%= javascript_include_tag 'redirection_after_login' %>
  3 +<% end %>
  4 +
  5 +<h2><%= _('Page to redirect after login') %></h2>
  6 +<%= f.select :redirection_after_login, Environment.login_redirection_options.map{ |key,value| [value,key] }, selected: @profile.preferred_login_redirection %>
  7 +
  8 +<%= f.text_field :custom_url_redirection %>
  9 +
app/views/profile_editor/edit.html.erb
@@ -44,8 +44,7 @@ @@ -44,8 +44,7 @@
44 <% end %> 44 <% end %>
45 45
46 <% if environment.enabled?('allow_change_of_redirection_after_login') %> 46 <% if environment.enabled?('allow_change_of_redirection_after_login') %>
47 - <h2><%= _('Page to redirect after login') %></h2>  
48 - <%= select 'profile_data', 'redirection_after_login', Environment.login_redirection_options.map{|key,value|[value,key]}, { :selected => @profile.preferred_login_redirection} %> 47 + <%= render 'redirection_after_login', f: f %>
49 <% end %> 48 <% end %>
50 49
51 <h2><%= _('Translations') %></h2> 50 <h2><%= _('Translations') %></h2>
@@ -75,14 +74,23 @@ @@ -75,14 +74,23 @@
75 74
76 <% if user && user.has_permission?('destroy_profile', profile) %> 75 <% if user && user.has_permission?('destroy_profile', profile) %>
77 <% button_bar(:id => 'delete-profile') do %> 76 <% button_bar(:id => 'delete-profile') do %>
78 - <%= button(:remove, _('Delete profile'), {:action => :destroy_profile}) %>  
79 77
80 - <% if environment.admins.include?(current_person) %> 78 + <% if !environment.enabled?('forbid_destroy_profile') || user.is_admin?(environment) %>
  79 + <%= button(:remove, _('Delete profile'), {:action => :destroy_profile}) %>
  80 + <% end %>
81 81
  82 + <% if user.is_admin?(environment) %>
82 <% if profile.visible? %> 83 <% if profile.visible? %>
83 - <%= button(:remove, _('Deactivate profile'), {:action => :deactivate_profile, :id=>profile.id}, :id=>'deactivate_profile_button', :data => {:confirm=>_("Are you sure you want to deactivate this profile?")}) %> 84 + <%= button(:remove, _('Deactivate profile'),
  85 + {:action => :deactivate_profile, :id=>profile.id},
  86 + :id=>'deactivate_profile_button',
  87 + :data => {:confirm=>_("Are you sure you want to deactivate this profile?")})
  88 + %>
84 <% else %> 89 <% else %>
85 - <%= button(:add, _('Activate profile'), {:action => :activate_profile, :id=>profile.id}, :data => {:confirm=>_("Are you sure you want to deactivate this profile?")}) %> 90 + <%= button(:add, _('Activate profile'),
  91 + {:action => :activate_profile, :id=>profile.id},
  92 + :data => {:confirm=>_("Are you sure you want to activate this profile?")})
  93 + %>
86 <% end %> 94 <% end %>
87 <% end %> 95 <% end %>
88 <% end %> 96 <% end %>
app/views/profile_roles/assign.html.erb
1 <%= javascript_include_tag('assign_role.js') %> 1 <%= javascript_include_tag('assign_role.js') %>
2 2
3 -<h1> <%= _("Assign #{@role.name}") %> </h1> 3 +<h1> <%= _("Assign %s") % @role.name %> </h1>
4 4
5 5
6 <%= labelled_form_for :role, :url => { :action => 'define', :id => @role.id } do |f| %> 6 <%= labelled_form_for :role, :url => { :action => 'define', :id => @role.id } do |f| %>
app/views/profile_roles/destroy.html.erb
1 -<h1> <%= _("Deleting #{@role.name}") %> </h1> 1 +<h1> <%= _("Deleting %s") % @role.name %> </h1>
2 2
3 <% if @members.nil? || @members.empty? %> 3 <% if @members.nil? || @members.empty? %>
4 <p><%= _('This role is not being currently used.')%></p> 4 <p><%= _('This role is not being currently used.')%></p>
app/views/profile_roles/edit.html.erb
1 -<h1> <%= _("Editing #{@role.name}") %> </h1> 1 +<h1> <%= _("Editing %s") % @role.name %> </h1>
2 2
3 <%= render :partial => 'form', :locals => { :mode => :edit, :role => @role, :permissions => [@role.kind] } %> 3 <%= render :partial => 'form', :locals => { :mode => :edit, :role => @role, :permissions => [@role.kind] } %>
app/views/role/edit.html.erb
1 -<h2> <%= _("Editing #{@role.name}") %> </h2> 1 +<h2> <%= _("Editing %s") % @role.name %> </h2>
2 2
3 <%= render :partial => 'form', :locals => { :mode => :edit, :role => @role, :permissions => role_available_permissions(@role) } %> 3 <%= render :partial => 'form', :locals => { :mode => :edit, :role => @role, :permissions => role_available_permissions(@role) } %>
app/views/shared/_content_item.html.erb
@@ -6,6 +6,6 @@ @@ -6,6 +6,6 @@
6 <span class="item-description"> 6 <span class="item-description">
7 <%= link_to(content.name, content.url) %> 7 <%= link_to(content.name, content.url) %>
8 </span> 8 </span>
9 - <span class="item-date"><%= _("Published at: #{show_date(content.updated_at)}") %></span> 9 + <span class="item-date"><%= _("Published at: %s") % show_date(content.updated_at) %></span>
10 </div> 10 </div>
11 </div> 11 </div>
app/views/shared/_list_groups.html.erb
1 <ul id="groups-list"> 1 <ul id="groups-list">
2 -<% for group in groups %>  
3 - <li>  
4 - <div class='common-profile-list-block'>  
5 - <%= profile_image_link(group, :portrait, 'div') %>  
6 - </div>  
7 - <span class='profile-details'>  
8 - <strong><%= group.name %></strong><br/>  
9 - <%= _('Role: %s') % rolename_for(profile, group) + '<br/>' if profile.role_assignments.find_by_resource_id(group.id) %>  
10 - <%= _('Type: %s') % _(group.class.identification) %> <br/>  
11 - <%= _('Description: %s') % group.description + '<br/>' if group.community? %>  
12 - <%= _('Members: %s') % group.members_count.to_s %> <br/>  
13 - <%= _('Created at: %s') % show_date(group.created_at) unless group.enterprise? %> <br/>  
14 - <% button_bar do %>  
15 - <% if user.has_permission?(:edit_profile, group) %>  
16 - <%= button 'menu-ctrl-panel', _('Control panel of this group'), group.admin_url %>  
17 - <% end %>  
18 - <%= button 'menu-logout', _('Leave community'), group.leave_url(true), :class => 'leave-community' %>  
19 - <% if (group.community? && user.has_permission?(:destroy_profile, group)) %>  
20 - <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => group.identifier } %> 2 + <% for group in groups %>
  3 + <li>
  4 + <div class='common-profile-list-block'>
  5 + <%= profile_image_link(group, :portrait, 'div') %>
  6 + </div>
  7 + <span class='profile-details'>
  8 + <strong><%= group.name %></strong><br/>
  9 + <%= _('Role: %s') % rolename_for(profile, group) + '<br/>' if profile.role_assignments.find_by_resource_id(group.id) %>
  10 + <%= _('Type: %s') % _(group.class.identification) %> <br/>
  11 + <%= _('Description: %s') % group.description + '<br/>' if group.community? %>
  12 + <%= _('Members: %s') % group.members_count.to_s %> <br/>
  13 + <%= _('Created at: %s') % show_date(group.created_at) unless group.enterprise? %> <br/>
  14 + <% button_bar do %>
  15 + <% if user.has_permission?(:edit_profile, group) %>
  16 + <%= button 'menu-ctrl-panel', _('Control panel of this group'), group.admin_url %>
  17 + <% end %>
  18 + <%= button 'menu-logout', _('Leave community'), group.leave_url(true), :class => 'leave-community' %>
  19 +
  20 + <% if (user.has_permission?(:destroy_profile, group) && !environment.enabled?('forbid_destroy_profile')) || user.is_admin?(environment) %>
  21 + <%= button 'delete', _('Remove'),
  22 + { :controller => 'profile_editor',
  23 + :action => 'destroy_profile',
  24 + :profile => group.identifier }
  25 + %>
  26 + <% end %>
21 <% end %> 27 <% end %>
22 - <% end %>  
23 - </span>  
24 - <br class="may-clear" />  
25 - </li>  
26 -<% end %> 28 + </span>
  29 + <br class="may-clear" />
  30 + </li>
  31 + <% end %>
27 </ul> 32 </ul>
28 -  
config/application.rb
@@ -126,7 +126,7 @@ module Noosfero @@ -126,7 +126,7 @@ module Noosfero
126 # Make sure the secret is at least 30 characters and all random, 126 # Make sure the secret is at least 30 characters and all random,
127 # no regular words or you'll be exposed to dictionary attacks. 127 # no regular words or you'll be exposed to dictionary attacks.
128 config.secret_token = noosfero_session_secret 128 config.secret_token = noosfero_session_secret
129 - config.session_store :cookie_store, :key => '_noosfero_session' 129 + config.session_store :active_record_store, key: '_noosfero_session'
130 130
131 config.paths['db/migrate'] += Dir.glob "#{Rails.root}/{baseplugins,config/plugins}/*/db/migrate" 131 config.paths['db/migrate'] += Dir.glob "#{Rails.root}/{baseplugins,config/plugins}/*/db/migrate"
132 config.i18n.load_path += Dir.glob "#{Rails.root}/{baseplugins,config/plugins}/*/locales/*.{rb,yml}" 132 config.i18n.load_path += Dir.glob "#{Rails.root}/{baseplugins,config/plugins}/*/locales/*.{rb,yml}"
config/initializers/action_tracker.rb
@@ -2,67 +2,51 @@ require &#39;noosfero/i18n&#39; @@ -2,67 +2,51 @@ require &#39;noosfero/i18n&#39;
2 2
3 # ActionTracker plugin stuff 3 # ActionTracker plugin stuff
4 4
5 -@reply_scrap_description = proc { _('sent a message to %{receiver}: <br /> "%{message}"') % { :receiver => "{{link_to(ta.get_receiver_name, ta.get_receiver_url)}}", :message => "{{auto_link_urls(ta.get_content)}}" } }  
6 -  
7 ActionTrackerConfig.verbs = { 5 ActionTrackerConfig.verbs = {
8 6
9 - :create_article => {  
10 - :description => proc { _('published an article: %{title}') % { :title => '{{link_to(truncate(ta.get_name), ta.get_url)}}' } } 7 + create_article: {
  8 + },
  9 +
  10 + new_friendship: {
  11 + type: :groupable
  12 + },
  13 +
  14 + join_community: {
  15 + type: :groupable
11 }, 16 },
12 17
13 - :new_friendship => {  
14 - :description => proc { n_('has made 1 new friend:<br />%{name}', 'has made %{num} new friends:<br />%{name}', get_friend_name.size) % { :num => get_friend_name.size, :name => '{{ta.collect_group_with_index(:friend_name){ |n,i| link_to(image_tag(ta.get_friend_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/person-icon.png")), ta.get_friend_url[i], :title => n)}.join}}' } },  
15 - :type => :groupable 18 + add_member_in_community: {
16 }, 19 },
17 20
18 - :join_community => {  
19 - :description => proc { n_('has joined 1 community:<br />%{name}', 'has joined %{num} communities:<br />%{name}', get_resource_name.size) % { :num => get_resource_name.size, :name => '{{ta.collect_group_with_index(:resource_name){ |n,i| link_to(image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")), ta.get_resource_url[i], :title => n)}.join}}' } },  
20 - :type => :groupable 21 + upload_image: {
  22 + type: :groupable
21 }, 23 },
22 24
23 - :add_member_in_community => {  
24 - :description => proc { _('has joined the community.') }, 25 + leave_scrap: {
25 }, 26 },
26 27
27 - :upload_image => {  
28 - :description => proc do  
29 - total = get_view_url.size  
30 - n_('uploaded 1 image', 'uploaded %d images', total) % total +  
31 - '<br />{{'+  
32 - 'ta.collect_group_with_index(:thumbnail_path) { |t,i|' +  
33 - " if ( #{total} == 1 );" +  
34 - ' link_to( image_tag(t), ta.get_view_url[i], :class => \'upimg\' );' +  
35 - ' else;' +  
36 - " pos = #{total}-i;" +  
37 - ' morethen2 = pos>2 ? \'morethen2\' : \'\';' +  
38 - ' morethen5 = pos>5 ? \'morethen5\' : \'\';' +  
39 - ' t = t.gsub(/(.*)(display)(.*)/, \'\\1thumb\\3\');' +  
40 - ' link_to( \'&nbsp;\', ta.get_view_url[i],' +  
41 - ' :style => "background-image:url(#{t})",' +  
42 - ' :class => "upimg pos#{pos} #{morethen2} #{morethen5}" );' +  
43 - ' end' +  
44 - '}.reverse.join}}' +  
45 - ( total > 5 ?  
46 - '<span class="more" onclick="this.parentNode.className+=\' show-all\'">' +  
47 - '&hellip;</span>' : '' ) +  
48 - '<br style="clear: both;" />'  
49 - end,  
50 - :type => :groupable 28 + leave_scrap_to_self: {
51 }, 29 },
52 30
53 - :leave_scrap => {  
54 - :description => @reply_scrap_description 31 + reply_scrap_on_self: {
55 }, 32 },
56 33
57 - :leave_scrap_to_self => {  
58 - :description => proc { _('wrote: <br /> "%{text}"') % { :text => "{{auto_link_urls(ta.get_content)}}" } } 34 + create_product: {
59 }, 35 },
60 36
61 - :reply_scrap_on_self => {  
62 - :description => @reply_scrap_description 37 + update_product: {
63 }, 38 },
  39 +
  40 + remove_product: {
  41 + },
  42 +
  43 + favorite_enterprise: {
  44 + },
  45 +
64 } 46 }
65 47
66 -ActionTrackerConfig.current_user_method = :current_person 48 +ActionTrackerConfig.current_user = proc do
  49 + User.current.person rescue nil
  50 +end
67 51
68 ActionTrackerConfig.timeout = 24.hours 52 ActionTrackerConfig.timeout = 24.hours
config/initializers/session.rb 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +ActionDispatch::Reloader.to_prepare do
  2 + ActiveRecord::SessionStore.session_class = Session
  3 +end
  4 +
config/routes.rb
@@ -57,37 +57,37 @@ Noosfero::Application.routes.draw do @@ -57,37 +57,37 @@ Noosfero::Application.routes.draw do
57 match 'search(/:action(/*category_path))', :controller => 'search' 57 match 'search(/:action(/*category_path))', :controller => 'search'
58 58
59 # events 59 # events
60 - match 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format_in_url}/  
61 - match 'profile/:profile/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format_in_url}/  
62 - match 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/  
63 - match 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/  
64 - match 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format_in_url}/ 60 + match 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format_in_url}/i
  61 + match 'profile/:profile/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format_in_url}/i
  62 + match 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/i
  63 + match 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/i
  64 + match 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format_in_url}/i
65 65
66 # catalog 66 # catalog
67 - match 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/, :as => :catalog 67 + match 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/i, :as => :catalog
68 68
69 # invite 69 # invite
70 - match 'profile/:profile/invite/friends', :controller => 'invite', :action => 'invite_friends', :profile => /#{Noosfero.identifier_format_in_url}/  
71 - match 'profile/:profile/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format_in_url}/ 70 + match 'profile/:profile/invite/friends', :controller => 'invite', :action => 'invite_friends', :profile => /#{Noosfero.identifier_format_in_url}/i
  71 + match 'profile/:profile/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format_in_url}/i
72 72
73 # feeds per tag 73 # feeds per tag
74 - match 'profile/:profile/tags/:id/feed', :controller => 'profile', :action =>'tag_feed', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :tag_feed 74 + match 'profile/:profile/tags/:id/feed', :controller => 'profile', :action =>'tag_feed', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/i, :as => :tag_feed
75 75
76 # profile tags 76 # profile tags
77 - match 'profile/:profile/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/  
78 - match 'profile/:profile/tags(/:id)', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format_in_url}/ 77 + match 'profile/:profile/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/i
  78 + match 'profile/:profile/tags(/:id)', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format_in_url}/i
79 79
80 # profile search 80 # profile search
81 - match 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/ 81 + match 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/i
82 82
83 # comments 83 # comments
84 - match 'profile/:profile/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format_in_url}/ 84 + match 'profile/:profile/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format_in_url}/i
85 85
86 # public profile information 86 # public profile information
87 - match 'profile/:profile(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :profile 87 + match 'profile/:profile(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format_in_url}/i, :as => :profile
88 88
89 # contact 89 # contact
90 - match 'contact/:profile/:action(/:id)', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format_in_url}/ 90 + match 'contact/:profile/:action(/:id)', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format_in_url}/i
91 91
92 # map balloon 92 # map balloon
93 match 'map_balloon/:action/:id', :controller => 'map_balloon', :id => /.*/ 93 match 'map_balloon/:action/:id', :controller => 'map_balloon', :id => /.*/
@@ -99,8 +99,8 @@ Noosfero::Application.routes.draw do @@ -99,8 +99,8 @@ Noosfero::Application.routes.draw do
99 ## Controllers that are profile-specific (for profile admins ) 99 ## Controllers that are profile-specific (for profile admins )
100 ###################################################### 100 ######################################################
101 # profile customization - "My profile" 101 # profile customization - "My profile"
102 - match 'myprofile/:profile', :controller => 'profile_editor', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/  
103 - match 'myprofile/:profile/:controller(/:action(/:id))', :controller => Noosfero.pattern_for_controllers_in_directory('my_profile'), :profile => /#{Noosfero.identifier_format_in_url}/, :as => :myprofile 102 + match 'myprofile/:profile', :controller => 'profile_editor', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/i
  103 + match 'myprofile/:profile/:controller(/:action(/:id))', :controller => Noosfero.pattern_for_controllers_in_directory('my_profile'), :profile => /#{Noosfero.identifier_format_in_url}/i, :as => :myprofile
104 104
105 105
106 ###################################################### 106 ######################################################
@@ -128,14 +128,14 @@ Noosfero::Application.routes.draw do @@ -128,14 +128,14 @@ Noosfero::Application.routes.draw do
128 # cache stuff - hack 128 # cache stuff - hack
129 match 'public/:action/:id', :controller => 'public' 129 match 'public/:action/:id', :controller => 'public'
130 130
131 - match ':profile/*page/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => /#{Noosfero.identifier_format_in_url}/, :constraints => EnvironmentDomainConstraint.new 131 + match ':profile/*page/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => /#{Noosfero.identifier_format_in_url}/i, :constraints => EnvironmentDomainConstraint.new
132 match '*page/versions', :controller => 'content_viewer', :action => 'article_versions' 132 match '*page/versions', :controller => 'content_viewer', :action => 'article_versions'
133 133
134 - match ':profile/*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff', :profile => /#{Noosfero.identifier_format_in_url}/, :constraints => EnvironmentDomainConstraint.new 134 + match ':profile/*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff', :profile => /#{Noosfero.identifier_format_in_url}/i, :constraints => EnvironmentDomainConstraint.new
135 match '*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff' 135 match '*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff'
136 136
137 # match requests for profiles that don't have a custom domain 137 # match requests for profiles that don't have a custom domain
138 - match ':profile(/*page)', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format_in_url}/, :constraints => EnvironmentDomainConstraint.new 138 + match ':profile(/*page)', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format_in_url}/i, :constraints => EnvironmentDomainConstraint.new
139 139
140 # match requests for content in domains hosted for profiles 140 # match requests for content in domains hosted for profiles
141 match '/(*page)', :controller => 'content_viewer', :action => 'view_page' 141 match '/(*page)', :controller => 'content_viewer', :action => 'view_page'
db/migrate/20150216213259_create_profile_activity.rb 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +class CreateProfileActivity < ActiveRecord::Migration
  2 + def up
  3 + ActiveRecord::Base.transaction do
  4 + create_table :profile_activities do |t|
  5 + t.integer :profile_id
  6 + t.integer :activity_id
  7 + t.string :activity_type
  8 + t.timestamps
  9 + end
  10 + add_index :profile_activities, :profile_id
  11 + add_index :profile_activities, [:activity_id, :activity_type]
  12 + add_index :profile_activities, :activity_type
  13 +
  14 + Scrap.find_each batch_size: 50 do |scrap|
  15 + scrap.send :create_activity
  16 + end
  17 + ActionTracker::Record.find_each batch_size: 50 do |action_tracker|
  18 + action_tracker.send :create_activity
  19 + end
  20 + end
  21 + end
  22 +
  23 + def down
  24 + drop_table :profile_activities
  25 + end
  26 +end
db/migrate/20150310132902_add_id_to_favorite_enterprises_people.rb 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +class AddIdToFavoriteEnterprisesPeople < ActiveRecord::Migration
  2 + def up
  3 + rename_table :favorite_enteprises_people, :favorite_enterprise_people
  4 +
  5 + change_table :favorite_enterprise_people do |t|
  6 + t.timestamps
  7 + end
  8 + add_column :favorite_enterprise_people, :id, :primary_key
  9 +
  10 + add_index :favorite_enterprise_people, [:person_id, :enterprise_id]
  11 + add_index :favorite_enterprise_people, :person_id
  12 + add_index :favorite_enterprise_people, :enterprise_id
  13 + end
  14 +
  15 + def down
  16 + rename_table :favorite_enterprise_people, :favorite_enteprises_people
  17 +
  18 + remove_column :favorite_enteprises_people, :id
  19 + remove_column :favorite_enteprises_people, :created_at
  20 + remove_column :favorite_enteprises_people, :updated_at
  21 +
  22 + remove_index :favorite_enteprises_people, [:person_id, :enterprise_id]
  23 + remove_index :favorite_enteprises_people, :person_id
  24 + remove_index :favorite_enteprises_people, :enterprise_id
  25 + end
  26 +end
db/migrate/20150625234824_add_user_id_to_session.rb 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +class AddUserIdToSession < ActiveRecord::Migration
  2 +
  3 + def change
  4 + add_column :sessions, :user_id, :integer
  5 + add_index :sessions, :user_id
  6 + end
  7 +
  8 + def up
  9 + Session.reset_column_information
  10 +
  11 + # cleanup data: {}
  12 + Session.where(data: "BAh7AA==\n").delete_all
  13 + # cleanup data with lang key only
  14 + Session.where("data ~ 'BAh7BjoJbGFuZyIH.{3,3}=\n'").delete_all
  15 +
  16 + # very slow migration, only do for the last month
  17 + Session.where('updated_at > ?', 1.month.ago).find_each batch_size: 50 do |session|
  18 + begin
  19 + # this calls Session#copy_to_columns
  20 + session.save!
  21 + rescue ArgumentError
  22 + # old ActionController::Flash::FlashHash from rails 2.3
  23 + session.destroy
  24 + end
  25 +
  26 + # limit limitless allocations
  27 + GC.start
  28 + end
  29 + end
  30 +
  31 +end
db/migrate/20150712130827_index_user_id_on_profiles.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +class IndexUserIdOnProfiles < ActiveRecord::Migration
  2 +
  3 + def change
  4 + add_index :profiles, :user_id
  5 + add_index :profiles, [:user_id, :type]
  6 + end
  7 +
  8 +end
db/migrate/20150722042714_change_article_date_to_datetime.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +class ChangeArticleDateToDatetime < ActiveRecord::Migration
  2 +
  3 + def up
  4 + change_table :articles do |t|
  5 + t.change :start_date, :datetime
  6 + t.change :end_date, :datetime
  7 + end
  8 +
  9 + change_table :article_versions do |t|
  10 + t.change :start_date, :datetime
  11 + t.change :end_date, :datetime
  12 + end
  13 + end
  14 +
  15 + def down
  16 + change_table :articles do |t|
  17 + t.change :start_date, :date
  18 + t.change :end_date, :date
  19 + end
  20 +
  21 + change_table :article_versions do |t|
  22 + t.change :start_date, :date
  23 + t.change :end_date, :date
  24 + end
  25 + end
  26 +
  27 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20150603182105) do 14 +ActiveRecord::Schema.define(:version => 20150722042714) do
15 15
16 create_table "abuse_reports", :force => true do |t| 16 create_table "abuse_reports", :force => true do |t|
17 t.integer "reporter_id" 17 t.integer "reporter_id"
@@ -75,8 +75,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do @@ -75,8 +75,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
75 t.integer "comments_count" 75 t.integer "comments_count"
76 t.boolean "advertise", :default => true 76 t.boolean "advertise", :default => true
77 t.boolean "published", :default => true 77 t.boolean "published", :default => true
78 - t.date "start_date"  
79 - t.date "end_date" 78 + t.datetime "start_date"
  79 + t.datetime "end_date"
80 t.integer "children_count", :default => 0 80 t.integer "children_count", :default => 0
81 t.boolean "accept_comments", :default => true 81 t.boolean "accept_comments", :default => true
82 t.integer "reference_article_id" 82 t.integer "reference_article_id"
@@ -127,8 +127,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do @@ -127,8 +127,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
127 t.integer "comments_count", :default => 0 127 t.integer "comments_count", :default => 0
128 t.boolean "advertise", :default => true 128 t.boolean "advertise", :default => true
129 t.boolean "published", :default => true 129 t.boolean "published", :default => true
130 - t.date "start_date"  
131 - t.date "end_date" 130 + t.datetime "start_date"
  131 + t.datetime "end_date"
132 t.integer "children_count", :default => 0 132 t.integer "children_count", :default => 0
133 t.boolean "accept_comments", :default => true 133 t.boolean "accept_comments", :default => true
134 t.integer "reference_article_id" 134 t.integer "reference_article_id"
@@ -351,11 +351,17 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do @@ -351,11 +351,17 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
351 add_index "external_feeds", ["enabled"], :name => "index_external_feeds_on_enabled" 351 add_index "external_feeds", ["enabled"], :name => "index_external_feeds_on_enabled"
352 add_index "external_feeds", ["fetched_at"], :name => "index_external_feeds_on_fetched_at" 352 add_index "external_feeds", ["fetched_at"], :name => "index_external_feeds_on_fetched_at"
353 353
354 - create_table "favorite_enteprises_people", :id => false, :force => true do |t|  
355 - t.integer "person_id"  
356 - t.integer "enterprise_id" 354 + create_table "favorite_enterprise_people", :force => true do |t|
  355 + t.integer "person_id"
  356 + t.integer "enterprise_id"
  357 + t.datetime "created_at"
  358 + t.datetime "updated_at"
357 end 359 end
358 360
  361 + add_index "favorite_enterprise_people", ["enterprise_id"], :name => "index_favorite_enterprise_people_on_enterprise_id"
  362 + add_index "favorite_enterprise_people", ["person_id", "enterprise_id"], :name => "index_favorite_enterprise_people_on_person_id_and_enterprise_id"
  363 + add_index "favorite_enterprise_people", ["person_id"], :name => "index_favorite_enterprise_people_on_person_id"
  364 +
359 create_table "friendships", :force => true do |t| 365 create_table "friendships", :force => true do |t|
360 t.integer "person_id" 366 t.integer "person_id"
361 t.integer "friend_id" 367 t.integer "friend_id"
@@ -489,6 +495,18 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do @@ -489,6 +495,18 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
489 add_index "products", ["product_category_id"], :name => "index_products_on_product_category_id" 495 add_index "products", ["product_category_id"], :name => "index_products_on_product_category_id"
490 add_index "products", ["profile_id"], :name => "index_products_on_profile_id" 496 add_index "products", ["profile_id"], :name => "index_products_on_profile_id"
491 497
  498 + create_table "profile_activities", :force => true do |t|
  499 + t.integer "profile_id"
  500 + t.integer "activity_id"
  501 + t.string "activity_type"
  502 + t.datetime "created_at", :null => false
  503 + t.datetime "updated_at", :null => false
  504 + end
  505 +
  506 + add_index "profile_activities", ["activity_id", "activity_type"], :name => "index_profile_activities_on_activity_id_and_activity_type"
  507 + add_index "profile_activities", ["activity_type"], :name => "index_profile_activities_on_activity_type"
  508 + add_index "profile_activities", ["profile_id"], :name => "index_profile_activities_on_profile_id"
  509 +
492 create_table "profile_suggestions", :force => true do |t| 510 create_table "profile_suggestions", :force => true do |t|
493 t.integer "person_id" 511 t.integer "person_id"
494 t.integer "suggestion_id" 512 t.integer "suggestion_id"
@@ -555,6 +573,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do @@ -555,6 +573,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
555 add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier" 573 add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier"
556 add_index "profiles", ["members_count"], :name => "index_profiles_on_members_count" 574 add_index "profiles", ["members_count"], :name => "index_profiles_on_members_count"
557 add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id" 575 add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id"
  576 + add_index "profiles", ["user_id", "type"], :name => "index_profiles_on_user_id_and_type"
  577 + add_index "profiles", ["user_id"], :name => "index_profiles_on_user_id"
558 578
559 create_table "qualifier_certifiers", :force => true do |t| 579 create_table "qualifier_certifiers", :force => true do |t|
560 t.integer "qualifier_id" 580 t.integer "qualifier_id"
@@ -645,10 +665,12 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do @@ -645,10 +665,12 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
645 t.text "data" 665 t.text "data"
646 t.datetime "created_at" 666 t.datetime "created_at"
647 t.datetime "updated_at" 667 t.datetime "updated_at"
  668 + t.integer "user_id"
648 end 669 end
649 670
650 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id" 671 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
651 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at" 672 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
  673 + add_index "sessions", ["user_id"], :name => "index_sessions_on_user_id"
652 674
653 create_table "suggestion_connections", :force => true do |t| 675 create_table "suggestion_connections", :force => true do |t|
654 t.integer "suggestion_id", :null => false 676 t.integer "suggestion_id", :null => false
debian/changelog
  1 +noosfero (1.2) wheezy; urgency=low
  2 +
  3 + * Noosfero 1.2
  4 +
  5 + -- Antonio Terceiro <terceiro@colivre.coop.br> Fri, 07 Aug 2015 13:39:14 -0300
  6 +
1 noosfero (1.2~rc2) wheezy; urgency=low 7 noosfero (1.2~rc2) wheezy; urgency=low
2 8
3 * Noosfero 1.2 RC2 9 * Noosfero 1.2 RC2
doc/noosfero/navigation/searching-enterprises.textile
@@ -14,7 +14,7 @@ p. Find on top of page the term &quot;Enterprises&quot; and click on it: @@ -14,7 +14,7 @@ p. Find on top of page the term &quot;Enterprises&quot; and click on it:
14 h2(#description). Description 14 h2(#description). Description
15 15
16 # Fill in the search field with what you want to look for and click on "Search" !=/images/doc/enterprises-search-field.en.png(Enterprises search field)! 16 # Fill in the search field with what you want to look for and click on "Search" !=/images/doc/enterprises-search-field.en.png(Enterprises search field)!
17 -# Then you will see the search results. To see more results, click on the pages below the search results. !=/images/doc/enterprises-search-results-with-example.en.png(Enteprises search results with example)! 17 +# Then you will see the search results. To see more results, click on the pages below the search results. !=/images/doc/enterprises-search-results-with-example.en.png(Enterprises search results with example)!
18 # Clicking on one of the search results, you will be redirected to the homepage of choosen enterprise. 18 # Clicking on one of the search results, you will be redirected to the homepage of choosen enterprise.
19 19
20 h3. More options 20 h3. More options
features/accept_member.feature
@@ -14,6 +14,16 @@ Feature: accept member @@ -14,6 +14,16 @@ Feature: accept member
14 And the community "My Community" is closed 14 And the community "My Community" is closed
15 And "Mario Souto" is admin of "My Community" 15 And "Mario Souto" is admin of "My Community"
16 16
  17 + Scenario: a user should see its merbership is pending
  18 + Given I am logged in as "mario"
  19 + And the following communities
  20 + | owner | identifier | name | closed |
  21 + | marie | private-community | Private Community | true |
  22 + And I go to private-community's homepage
  23 + When I follow "Join this community"
  24 + And I go to private-community's homepage
  25 + Then I should see "Your membership is waiting for approval"
  26 +
17 @selenium 27 @selenium
18 Scenario: approve a task to accept a member as admin in a closed community 28 Scenario: approve a task to accept a member as admin in a closed community
19 Given "Marie Curie" asked to join "My Community" 29 Given "Marie Curie" asked to join "My Community"
features/events.feature
@@ -223,7 +223,7 @@ Feature: events @@ -223,7 +223,7 @@ Feature: events
223 | owner | name | start_date | end_date | 223 | owner | name | start_date | end_date |
224 | josesilva | WikiSym 2009 | 2009-10-25 | 2009-10-27 | 224 | josesilva | WikiSym 2009 | 2009-10-25 | 2009-10-27 |
225 When I am on /profile/josesilva/events/2009/10/26 225 When I am on /profile/josesilva/events/2009/10/26
226 - Then I should see "October 25, 2009 to October 27, 2009" 226 + Then I should see "October 25, 2009 0:00 to October 27, 2009 0:00"
227 227
228 Scenario: show place of the event 228 Scenario: show place of the event
229 Given I am on /profile/josesilva/events/2009/10 229 Given I am on /profile/josesilva/events/2009/10
features/members_block.feature
@@ -9,8 +9,8 @@ Feature: @@ -9,8 +9,8 @@ Feature:
9 | joaosilva | Joao Silva | 9 | joaosilva | Joao Silva |
10 | mariasilva | Maria Silva | 10 | mariasilva | Maria Silva |
11 And the following communities 11 And the following communities
12 - | owner | identifier | name |  
13 - | joaosilva | sample-community | Sample Community | 12 + | owner | identifier | name |
  13 + | joaosilva | sample-community | Sample Community |
14 And the following blocks 14 And the following blocks
15 | owner | type | 15 | owner | type |
16 | sample-community | MembersBlock | 16 | sample-community | MembersBlock |
@@ -24,7 +24,7 @@ Feature: @@ -24,7 +24,7 @@ Feature:
24 Scenario: a user can join in a community by members block's button 24 Scenario: a user can join in a community by members block's button
25 Given I am logged in as "mariasilva" 25 Given I am logged in as "mariasilva"
26 And I go to sample-community's homepage 26 And I go to sample-community's homepage
27 - When I follow "Join" within ".members-block" 27 + When I follow "Join this community" within ".members-block"
28 And I go to mariasilva's control panel 28 And I go to mariasilva's control panel
29 And I follow "Manage my groups" 29 And I follow "Manage my groups"
30 Then I should see "Sample Community" 30 Then I should see "Sample Community"
@@ -41,7 +41,7 @@ Feature: @@ -41,7 +41,7 @@ Feature:
41 Scenario: a not logged in user can log in by members block's button 41 Scenario: a not logged in user can log in by members block's button
42 Given I am not logged in 42 Given I am not logged in
43 When I go to sample-community's homepage 43 When I go to sample-community's homepage
44 - And I follow "Join" within ".members-block" 44 + And I follow "Join this community" within ".members-block"
45 Then I should see "Username / Email" 45 Then I should see "Username / Email"
46 46
47 Scenario: the join-leave button do not appear if the checkbox show-join-leave-button is not checked 47 Scenario: the join-leave button do not appear if the checkbox show-join-leave-button is not checked
@@ -51,5 +51,5 @@ Feature: @@ -51,5 +51,5 @@ Feature:
51 And I uncheck "Show join leave button" 51 And I uncheck "Show join leave button"
52 And I press "Save" 52 And I press "Save"
53 When I go to sample-community's homepage 53 When I go to sample-community's homepage
54 - Then I should not see "Join" within ".members-block" 54 + Then I should not see "Join this community" within ".members-block"
55 And I should not see "Leave community" within ".members-block" 55 And I should not see "Leave community" within ".members-block"
lib/authenticated_system.rb
1 module AuthenticatedSystem 1 module AuthenticatedSystem
  2 +
2 protected 3 protected
  4 +
  5 + # See impl. from http://stackoverflow.com/a/2513456/670229
  6 + def self.included? base
  7 + base.around_filter do
  8 + begin
  9 + User.current = current_user
  10 + yield
  11 + ensure
  12 + # to address the thread variable leak issues in Puma/Thin webserver
  13 + User.current = nil
  14 + end
  15 + end
  16 + end
  17 +
3 # Returns true or false if the user is logged in. 18 # Returns true or false if the user is logged in.
4 # Preloads @current_user with the user model if they're logged in. 19 # Preloads @current_user with the user model if they're logged in.
5 def logged_in? 20 def logged_in?
@@ -8,7 +23,13 @@ module AuthenticatedSystem @@ -8,7 +23,13 @@ module AuthenticatedSystem
8 23
9 # Accesses the current user from the session. 24 # Accesses the current user from the session.
10 def current_user 25 def current_user
11 - @current_user ||= (session[:user] && User.find_by_id(session[:user])) || nil 26 + @current_user ||= begin
  27 + id = session[:user]
  28 + user = User.where(id: id).first if id
  29 + user.session = session if user
  30 + User.current = user
  31 + user
  32 + end
12 end 33 end
13 34
14 # Store the given user in the session. 35 # Store the given user in the session.
@@ -17,9 +38,10 @@ module AuthenticatedSystem @@ -17,9 +38,10 @@ module AuthenticatedSystem
17 session.delete(:user) 38 session.delete(:user)
18 else 39 else
19 session[:user] = new_user.id 40 session[:user] = new_user.id
  41 + new_user.session = session
20 new_user.register_login 42 new_user.register_login
21 end 43 end
22 - @current_user = new_user 44 + @current_user = User.current = new_user
23 end 45 end
24 46
25 # Check if the user is authorized. 47 # Check if the user is authorized.
@@ -121,14 +143,9 @@ module AuthenticatedSystem @@ -121,14 +143,9 @@ module AuthenticatedSystem
121 # When called with before_filter :login_from_cookie will check for an :auth_token 143 # When called with before_filter :login_from_cookie will check for an :auth_token
122 # cookie and log the user back in if apropriate 144 # cookie and log the user back in if apropriate
123 def login_from_cookie 145 def login_from_cookie
124 - return unless cookies[:auth_token] && !logged_in?  
125 - user = User.find_by_remember_token(cookies[:auth_token])  
126 - if user && user.remember_token?  
127 - user.remember_me  
128 - self.current_user = user  
129 - cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }  
130 - flash[:notice] = "Logged in successfully"  
131 - end 146 + return if cookies[:auth_token].blank? or logged_in?
  147 + user = User.where(remember_token: cookies[:auth_token]).first
  148 + self.current_user = user if user and user.remember_token?
132 end 149 end
133 150
134 private 151 private
lib/needs_profile.rb
@@ -21,7 +21,11 @@ module NeedsProfile @@ -21,7 +21,11 @@ module NeedsProfile
21 protected 21 protected
22 22
23 def load_profile 23 def load_profile
24 - @profile ||= environment.profiles.find_by_identifier(params[:profile]) 24 + if params[:profile]
  25 + params[:profile].downcase!
  26 + @profile ||= environment.profiles.where(identifier: params[:profile]).first
  27 + end
  28 +
25 if @profile 29 if @profile
26 profile_hostname = @profile.hostname 30 profile_hostname = @profile.hostname
27 if profile_hostname && profile_hostname != request.host 31 if profile_hostname && profile_hostname != request.host
lib/noosfero/action_tracker_ext.rb
1 Rails.configuration.to_prepare do 1 Rails.configuration.to_prepare do
2 - ActionTracker::Record.module_eval do 2 + ActionTracker::Record.class_eval do
3 extend CacheCounterHelper 3 extend CacheCounterHelper
4 4
5 after_create do |record| 5 after_create do |record|
@@ -9,6 +9,11 @@ Rails.configuration.to_prepare do @@ -9,6 +9,11 @@ Rails.configuration.to_prepare do
9 end 9 end
10 end 10 end
11 11
  12 + has_many :profile_activities, foreign_key: :activity_id, conditions: {profile_activities: {activity_type: 'ActionTracker::Record'}}, dependent: :destroy
  13 +
  14 + after_create :create_activity
  15 + after_update :update_activity
  16 +
12 after_destroy do |record| 17 after_destroy do |record|
13 if record.created_at >= ActionTracker::Record::RECENT_DELAY.days.ago 18 if record.created_at >= ActionTracker::Record::RECENT_DELAY.days.ago
14 ActionTracker::Record.update_cache_counter(:activities_count, record.user, -1) 19 ActionTracker::Record.update_cache_counter(:activities_count, record.user, -1)
@@ -17,5 +22,17 @@ Rails.configuration.to_prepare do @@ -17,5 +22,17 @@ Rails.configuration.to_prepare do
17 end 22 end
18 end 23 end
19 end 24 end
  25 +
  26 + protected
  27 +
  28 + def create_activity
  29 + target = if self.target.is_a? Profile then self.target else self.target.profile rescue self.user end
  30 + return if self.verb.in? target.exclude_verbs_on_activities
  31 + ProfileActivity.create! profile: target, activity: self
  32 + end
  33 + def update_activity
  34 + ProfileActivity.update_activity self
  35 + end
  36 +
20 end 37 end
21 end 38 end
lib/noosfero/plugin/routes.rb
@@ -19,15 +19,15 @@ Dir.glob(Rails.root.join(plugins_root, &#39;*&#39;, &#39;controllers&#39;)) do |controllers_dir| @@ -19,15 +19,15 @@ Dir.glob(Rails.root.join(plugins_root, &#39;*&#39;, &#39;controllers&#39;)) do |controllers_dir|
19 controllers.each do |controller| 19 controllers.each do |controller|
20 controller_name = controller.gsub("#{plugin_name}_plugin_",'') 20 controller_name = controller.gsub("#{plugin_name}_plugin_",'')
21 if %w[profile myprofile].include?(folder.to_s) 21 if %w[profile myprofile].include?(folder.to_s)
22 - match "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}(/:action(/:id))", :controller => controller, :profile => /#{Noosfero.identifier_format}/ 22 + match "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}(/:action(/:id))", controller: controller, profile: /#{Noosfero.identifier_format_in_url}/i
23 else 23 else
24 - match "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}(/:action(/:id))", :controller => controller 24 + match "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}(/:action(/:id))", controller: controller
25 end 25 end
26 end 26 end
27 end 27 end
28 28
29 - match 'plugin/' + plugin_name + '(/:action(/:id))', :controller => plugin_name + '_plugin'  
30 - match 'profile/:profile/plugin/' + plugin_name + '(/:action(/:id))', :controller => plugin_name + '_plugin_profile', :profile => /#{Noosfero.identifier_format}/  
31 - match 'myprofile/:profile/plugin/' + plugin_name + '(/:action(/:id))', :controller => plugin_name + '_plugin_myprofile', :profile => /#{Noosfero.identifier_format}/  
32 - match 'admin/plugin/' + plugin_name + '(/:action(/:id))', :controller => plugin_name + '_plugin_admin' 29 + match 'plugin/' + plugin_name + '(/:action(/:id))', controller: plugin_name + '_plugin'
  30 + match 'profile/:profile/plugin/' + plugin_name + '(/:action(/:id))', controller: plugin_name + '_plugin_profile', profile: /#{Noosfero.identifier_format_in_url}/i
  31 + match 'myprofile/:profile/plugin/' + plugin_name + '(/:action(/:id))', controller: plugin_name + '_plugin_myprofile', profile: /#{Noosfero.identifier_format_in_url}/i
  32 + match 'admin/plugin/' + plugin_name + '(/:action(/:id))', controller: plugin_name + '_plugin_admin'
33 end 33 end
lib/noosfero/version.rb
1 module Noosfero 1 module Noosfero
2 PROJECT = 'noosfero' 2 PROJECT = 'noosfero'
3 - VERSION = '1.2~rc2' 3 + VERSION = '1.2'
4 end 4 end
5 5
6 root = File.expand_path(File.dirname(__FILE__) + '/../..') 6 root = File.expand_path(File.dirname(__FILE__) + '/../..')
lib/notify_activity_to_profiles_job.rb
@@ -22,6 +22,12 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id) @@ -22,6 +22,12 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id)
22 # Notify all friends 22 # Notify all friends
23 ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select f.friend_id, #{tracked_action.id} from friendships as f where person_id=#{tracked_action.user.id} and f.friend_id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id})") 23 ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select f.friend_id, #{tracked_action.id} from friendships as f where person_id=#{tracked_action.user.id} and f.friend_id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id})")
24 24
  25 + if tracked_action.user.is_a? Organization
  26 + ActionTrackerNotification.connection.execute "insert into action_tracker_notifications(profile_id, action_tracker_id) " +
  27 + "select distinct accessor_id, #{tracked_action.id} from role_assignments where resource_id = #{tracked_action.user.id} and resource_type='Profile' " +
  28 + if tracked_action.user.is_a? Enterprise then "union select distinct person_id, #{tracked_action.id} from favorite_enterprise_people where enterprise_id = #{tracked_action.user.id}" else "" end
  29 + end
  30 +
25 if target.is_a?(Community) 31 if target.is_a?(Community)
26 ActionTrackerNotification.create(:profile_id => target.id, :action_tracker_id => tracked_action.id) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb) 32 ActionTrackerNotification.create(:profile_id => target.id, :action_tracker_id => tracked_action.id) unless NOT_NOTIFY_COMMUNITY.include?(tracked_action.verb)
27 33
lib/tasks/ci.rake
@@ -37,6 +37,11 @@ namespace :ci do @@ -37,6 +37,11 @@ namespace :ci do
37 tests << t unless tests.include?(t) 37 tests << t unless tests.include?(t)
38 end 38 end
39 end 39 end
  40 + if f =~ %r{^app/views/(\w*)/}
  41 + controller = $1
  42 + t = "test/functional/#{controller}_controller_test.rb"
  43 + tests << t if File.exists?(t) && !tests.include?(t)
  44 + end
40 end 45 end
41 46
42 if tests.empty? && features.empty? && changed_plugins.empty? 47 if tests.empty? && features.empty? && changed_plugins.empty?
lib/tasks/enable_plugins.rake
1 namespace :noosfero do 1 namespace :noosfero do
2 namespace :plugins do 2 namespace :plugins do
  3 + desc 'Enable all installed plugins on all environment'
3 task :enable_all => :environment do 4 task :enable_all => :environment do
4 Environment.all.each do |env| 5 Environment.all.each do |env|
5 puts "Plugins Activated on #{env.name}" if env.enable_all_plugins 6 puts "Plugins Activated on #{env.name}" if env.enable_all_plugins
lib/tasks/gettext.rake
@@ -60,6 +60,8 @@ task :updatepo do @@ -60,6 +60,8 @@ task :updatepo do
60 60
61 puts 'Extracting strings from source. This may take a while ...' 61 puts 'Extracting strings from source. This may take a while ...'
62 62
  63 + # XXX this list is duplicated in test/unit/i18n_test.rb; if you change it
  64 + # here, please also update it there.
63 files_to_translate = [ 65 files_to_translate = [
64 "{app,lib}/**/*.{rb,rhtml,erb}", 66 "{app,lib}/**/*.{rb,rhtml,erb}",
65 'config/initializers/*.rb', 67 'config/initializers/*.rb',
@@ -98,7 +100,7 @@ Dir.glob(&#39;plugins/*&#39;).each do |plugindir| @@ -98,7 +100,7 @@ Dir.glob(&#39;plugins/*&#39;).each do |plugindir|
98 } 100 }
99 ) 101 )
100 plugin_pot = File.join(po_root, "#{plugin}.pot") 102 plugin_pot = File.join(po_root, "#{plugin}.pot")
101 - if File.exists?(plugin_pot) && system("LANG=C msgfmt --statistics --output /dev/null #{plugin_pot} 2>&1 | grep -q '^0 translated messages.'") 103 + if File.exists?(plugin_pot) && system("LANG=C msgfmt --statistics --output /dev/null #{plugin_pot} 2>&1 | grep -q '^0 translated messages.$'")
102 rm_f plugin_pot 104 rm_f plugin_pot
103 end 105 end
104 sh 'find', po_root, '-type', 'd', '-empty', '-delete' 106 sh 'find', po_root, '-type', 'd', '-empty', '-delete'
@@ -106,8 +108,25 @@ Dir.glob(&#39;plugins/*&#39;).each do |plugindir| @@ -106,8 +108,25 @@ Dir.glob(&#39;plugins/*&#39;).each do |plugindir|
106 end 108 end
107 end 109 end
108 110
  111 +def checkpo(po_files)
  112 + max = po_files.map(&:size).max
  113 + po_files.each do |po|
  114 + printf "%#{max}s: ", po
  115 + system "msgfmt --statistics --output /dev/null " + po
  116 + end
  117 +end
  118 +
  119 +desc "checks core translation files"
109 task :checkpo do 120 task :checkpo do
110 - sh 'for po in po/*/noosfero.po; do echo -n "$po: "; msgfmt --statistics --output /dev/null $po; done' 121 + checkpo(Dir.glob('po/*/noosfero.po'))
  122 +end
  123 +
  124 +languages = Dir.glob('po/*').select { |d| File.directory?(d) }.map { |d| File.basename(d) }
  125 +languages.each do |lang|
  126 + desc "checks #{lang} translation files"
  127 + task "checkpo:#{lang}" do
  128 + checkpo(Dir.glob("po/#{lang}/*.po") + Dir.glob("plugins/*/po/#{lang}/*.po"))
  129 + end
111 end 130 end
112 131
113 # vim: ft=ruby 132 # vim: ft=ruby
lib/tasks/plugins_tests.rake
@@ -169,7 +169,7 @@ def test_sequence(plugins, tasks) @@ -169,7 +169,7 @@ def test_sequence(plugins, tasks)
169 failed[plugin] << task 169 failed[plugin] << task
170 end 170 end
171 end 171 end
172 - disable_plugins(plugin) 172 + disable_plugins
173 end 173 end
174 fail_flag = false 174 fail_flag = false
175 failed.each do |plugin, tasks| 175 failed.each do |plugin, tasks|