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.

AUTHORS.md
  1 +This list is automatically generated at release time. Please do not change it.
  2 +
1 3 If you are not listed here, but should be, please write to the noosfero mailing
2 4 list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev
3 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 8 Developers
7 9 ==========
8 10  
  11 +Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>
9 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 13 Alessandro Palmeira <alessandro.palmeira@gmail.com>
  14 +Alex Campelo <campelo.al1@gmail.com>
  15 +Álvaro Fernando <alvarofernandoms@gmail.com>
41 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 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 21 Antonio Terceiro <terceiro@colivre.coop.br>
49 22 Arthur Del Esposte <arthurmde@gmail.com>
50   -Arthur Del Esposte <arthurmde@yahoo.com.br>
51 23 Athos Ribeiro <athoscribeiro@gmail.com>
52 24 Aurelio A. Heckert <aurelio@colivre.coop.br>
53 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 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 28 Caio Salgado <caio.csalgado@gmail.com>
  29 +Caio SBA <caio@colivre.coop.br>
78 30 Caio Tiago Oliveira <caiotiago@colivre.coop.br>
79   -Caio, Pedro <caio.csalgado@gmail.com>
80 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 32 Carlos Morais <carlos88morais@gmail.com>
86 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 37 Daniel Bucher <daniel.bucher88@gmail.com>
97 38 Daniel Cunha <daniel@colivre.coop.br>
98   -Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
  39 +Daniel Tygel <dtygel@eita.org.br>
99 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 44 Eduardo Passos <eduardosteps@gmail.com>
129 45 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
130 46 Eduardo Vital <vitaldu@gmail.com>
131   -Evandro Jr <evandrojr@gmail.com>
132   -Evandro Junior <evandrojr@gmail.com>
133 47 Evandro Magalhaes Leite Junior <evandro.leite@serpro.gov.br>
134 48 Fabio Teixeira <fabio1079@gmail.com>
135 49 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com>
136   -Fabio Teixeira <fabio1079@gmail.com>
137 50 Fernanda Lopes <nanda.listas+psl@gmail.com>
138 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 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 53 Gabriela Navarro <navarro1703@gmail.com>
144 54 Gonzalo Exequiel Pedone <hipersayan.x@gmail.com>
145 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 59 Hebert Douglas <hebertdougl@gmail.com>
148 60 Hugo Melo <hugo@riseup.net>
  61 +Iolane Andrade <andrade.icaa@gmail.com>
149 62 Isaac Canan <isaac@intelletto.com.br>
150 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 68 Joenio Costa <joenio@colivre.coop.br>
158   -Jose Pedro <1jpsneto@gmail.com>
159 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 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 72 Keilla Menezes <keilla@colivre.coop.br>
193 73 Larissa Reis <larissa@colivre.coop.br>
194   -Larissa Reis <reiss.larissa@gmail.com>
195 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 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 77 LinguÁgil 2010 <linguagil.bahia@gmail.com>
  78 +Lucas Couto <loc.unb@gmail.com>
201 79 Lucas Kanashiro <kanashiro.duarte@gmail.com>
202   -Lucas Melo <lucas@colivre.coop.br>
203 80 Lucas Melo <lucaspradomelo@gmail.com>
204   -Luciano <lucianopcbr@gmail.com>
205   -Luciano Prestes Cavacanti <lucianopcbr@gmail.com>
206 81 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com>
207 82 Luis David Aguilar Carlos <ludwig9003@gmail.com>
208 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 85 Marcos Ramos <ms.ramos@outlook.com>
  86 +Marcos Ronaldo <marcos.rpj2@gmail.com>
  87 +Mariel Zasso <noosfero-br@listas.softwarelivre.org>
213 88 Martín Olivera <molivera@solar.org.ar>
  89 +Matheus Faria <matheus.sousa.faria@gmail.com>
214 90 Maurilio Atila <cabelotaina@gmail.com>
  91 +M for Momo <mo@rtnp.org>
215 92 Michal Čihař <michal@cihar.com>
216 93 Michel Felipe <mfelipeof@gmail.com>
217 94 Moises Machado <moises@colivre.coop.br>
218   -Nanda Lopes <nanda.listas+psl@gmail.com>
219 95 Naíla Alves <naila@colivre.coop.br>
  96 +Nanda Lopes <nanda.listas+psl@gmail.com>
220 97 Niemand Jedermann <predatorix@web.de>
221 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 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 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 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 105 Rafael Reggiani Manzo <rr.manzo@gmail.com>
242 106 Raphaël Rousseau <raph@r4f.org>
243   -Raquel <rcordioli@gmail.com>
244 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 112 Rodrigo Souto <rodrigo@colivre.coop.br>
253 113 Ronny Kursawe <kursawe.ronny@googlemail.com>
254 114 Samuel R. C. Vale <srcvale@holoscopio.com>
255   -TWS <tablettws@gmail.com>
256   -Tallys Martins <tallysmartins@gmail.com>
257 115 Tallys Martins <tallysmartins@yahoo.com.br>
258 116 Thiago Casotti <thiago.casotti@uol.com.br>
  117 +Thiago Kairala <thiagor.kairala@gmail.com>
259 118 Thiago Ribeiro <thiagitosouza@hotmail.com>
260 119 Thiago Zoroastro <thiago.zoroastro@bol.com.br>
261 120 Tuux <tuxa@galaxie.eu.org>
  121 +TWS <tablettws@gmail.com>
262 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 123 Victor Costa <vfcosta@gmail.com>
267 124 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>
268 125 Vinicius Cubas Brand <viniciuscb@gmail.com>
269   -Visita <visita@debian.(none)>
  126 +Wilton Rodrigues <braynwilton@gmail.com>
270 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 129 Ideas, specifications and incentive
285 130 ===================================
... ...
app/controllers/application_controller.rb
... ... @@ -7,7 +7,10 @@ class ApplicationController &lt; ActionController::Base
7 7 before_filter :detect_stuff_by_domain
8 8 before_filter :init_noosfero_plugins
9 9 before_filter :allow_cross_domain_access
  10 +
  11 + before_filter :login_from_cookie
10 12 before_filter :login_required, :if => :private_environment?
  13 +
11 14 before_filter :verify_members_whitelist, :if => [:private_environment?, :user]
12 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 111 end
112 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 115 end
119 116  
120 117 def new
... ... @@ -185,6 +182,8 @@ class CmsController &lt; MyProfileController
185 182 end
186 183 end
187 184  
  185 + escape_fields @article
  186 +
188 187 render :action => 'edit'
189 188 end
190 189  
... ... @@ -534,4 +533,10 @@ class CmsController &lt; MyProfileController
534 533 end
535 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 542 end
... ...
app/controllers/my_profile/enterprise_validation_controller.rb
1 1 class EnterpriseValidationController < MyProfileController
2 2  
3 3 protect 'validate_enterprise', :profile
4   -
  4 +
5 5 def index
6 6 @pending_validations = profile.pending_validations
7 7 end
... ... @@ -27,7 +27,7 @@ class EnterpriseValidationController &lt; MyProfileController
27 27 post_only :reject
28 28 def reject
29 29 @pending = profile.find_pending_validation(params[:id])
30   - if @pending
  30 + if @pending
31 31 @pending.reject_explanation = params[:reject_explanation]
32 32 begin
33 33 @pending.reject
... ...
app/controllers/my_profile/favorite_enterprises_controller.rb
1 1 class FavoriteEnterprisesController < MyProfileController
2   -
3   -# protect 'manage_favorite_enteprises', :profile
  2 +
  3 +# protect 'manage_favorite_enterprises', :profile
4 4  
5 5 requires_profile_class Person
6   -
  6 +
7 7 def index
8 8 @favorite_enterprises = profile.favorite_enterprises
9 9 end
... ... @@ -12,7 +12,7 @@ class FavoriteEnterprisesController &lt; MyProfileController
12 12 @favorite_enterprise = Enterprise.find(params[:id])
13 13 if request.post? && params[:confirmation]
14 14 profile.favorite_enterprises << @favorite_enterprise
15   - redirect_to :action => 'index'
  15 + redirect_to :action => 'index'
16 16 end
17 17 end
18 18  
... ...
app/controllers/my_profile/profile_editor_controller.rb
... ... @@ -5,6 +5,7 @@ class ProfileEditorController &lt; MyProfileController
5 5  
6 6 before_filter :access_welcome_page, :only => [:welcome_page]
7 7 before_filter :back_to
  8 + before_filter :forbid_destroy_profile, :only => [:destroy_profile]
8 9 helper_method :has_welcome_page
9 10  
10 11 def index
... ... @@ -109,7 +110,7 @@ class ProfileEditorController &lt; MyProfileController
109 110 profile = environment.profiles.find(params[:id])
110 111 if profile.disable
111 112 profile.save
112   - session[:notice] = _("The profile '#{profile.name}' was deactivated.")
  113 + session[:notice] = _("The profile '%s' was deactivated.") % profile.name
113 114 else
114 115 session[:notice] = _('Could not deactivate profile.')
115 116 end
... ... @@ -123,7 +124,7 @@ class ProfileEditorController &lt; MyProfileController
123 124 profile = environment.profiles.find(params[:id])
124 125  
125 126 if profile.enable
126   - session[:notice] = _("The profile '#{profile.name}' was activated.")
  127 + session[:notice] = _("The profile '%s' was activated.") % profile.name
127 128 else
128 129 session[:notice] = _('Could not activate the profile.')
129 130 end
... ... @@ -162,4 +163,10 @@ class ProfileEditorController &lt; MyProfileController
162 163 end
163 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 172 end
... ...
app/controllers/public/account_controller.rb
... ... @@ -46,14 +46,20 @@ class AccountController &lt; ApplicationController
46 46  
47 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 55 if logged_in?
52 56 check_join_in_community(self.current_user)
  57 +
53 58 if params[:remember_me] == "1"
54 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 61 end
  62 +
57 63 if redirect?
58 64 go_to_initial_page
59 65 session[:notice] = _("Logged in successfully")
... ... @@ -92,6 +98,7 @@ class AccountController &lt; ApplicationController
92 98 @invitation_code = params[:invitation_code]
93 99 begin
94 100 @user = User.build(params[:user], params[:profile_data], environment)
  101 + @user.session = session
95 102 @terms_of_use = environment.terms_of_use
96 103 @user.return_to = session[:return_to]
97 104 @person = Person.new(params[:profile_data])
... ... @@ -432,7 +439,7 @@ class AccountController &lt; ApplicationController
432 439 end
433 440  
434 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 443 end
437 444  
438 445 def redirect_if_logged_in
... ... @@ -452,8 +459,11 @@ class AccountController &lt; ApplicationController
452 459  
453 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 467 when 'keep_on_same_page'
458 468 redirect_back_or_default(user.admin_url)
459 469 when 'site_homepage'
... ... @@ -466,8 +476,11 @@ class AccountController &lt; ApplicationController
466 476 redirect_to user.admin_url
467 477 when 'welcome_page'
468 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 484 end
472 485 end
473 486  
... ...
app/controllers/public/profile_controller.rb
... ... @@ -6,6 +6,7 @@ class ProfileController &lt; PublicController
6 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 8 helper TagsHelper
  9 + helper ActionTrackerHelper
9 10  
10 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 92  
93 93 def events
94 94 if params[:year].blank? && params[:year].blank? && params[:day].blank?
95   - @date = Date.today
  95 + @date = DateTime.now
96 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 99 day = (params[:day] ? params[:day].to_i : 1)
100 100 @date = build_date(year, month, day)
101 101 end
... ... @@ -106,9 +106,7 @@ class SearchController &lt; PublicController
106 106 @events = @category ?
107 107 environment.events.by_day(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) :
108 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 110 @events = @category ?
113 111 environment.events.by_month(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) :
114 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 @@
  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 903 end
904 904  
905 905 def base_url
906   - environment.top_url(request.scheme)
  906 + profile ? profile.top_url(request.scheme) : environment.top_url(request.scheme)
907 907 end
908 908 alias :top_url :base_url
909 909  
... ...
app/helpers/article_helper.rb
... ... @@ -88,7 +88,7 @@ module ArticleHelper
88 88 content_tag( 'small', _('Who will be able to create new topics on this forum?')) +
89 89 content_tag('div', '', slider_options) +
90 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 92 end
93 93  
94 94 def privacity_exceptions(article, tokenized_children)
... ...
app/helpers/blog_helper.rb
... ... @@ -6,7 +6,13 @@ module BlogHelper
6 6 @article = article
7 7 hidden_field_tag('article[published]', 1) +
8 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 16 end
11 17  
12 18 def cms_label_for_new_children
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -51,7 +51,7 @@ module ContentViewerHelper
51 51 elsif date_format == 'past_time'
52 52 left_time = true
53 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 55 end
56 56  
57 57 def link_to_comments(article, args = {})
... ...
app/helpers/dates_helper.rb
... ... @@ -43,9 +43,14 @@ module DatesHelper
43 43 end
44 44  
45 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 54 else
50 55 ''
51 56 end
... ... @@ -53,7 +58,7 @@ module DatesHelper
53 58  
54 59 def show_period(date1, date2 = nil, use_numbers = false)
55 60 if (date1 == date2) || (date2.nil?)
56   - show_date(date1, use_numbers)
  61 + show_time(date1, use_numbers)
57 62 else
58 63 if date1.year == date2.year
59 64 if date1.month == date2.month
... ... @@ -72,8 +77,8 @@ module DatesHelper
72 77 end
73 78 else
74 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 83 end
79 84 end
... ... @@ -106,18 +111,18 @@ module DatesHelper
106 111  
107 112 def build_date(year, month, day = 1)
108 113 if year.blank? and month.blank? and day.blank?
109   - Date.today
  114 + DateTime.now
110 115 else
111 116 if year.blank?
112   - year = Date.today.year
  117 + year = DateTime.now.year
113 118 end
114 119 if month.blank?
115   - month = Date.today.month
  120 + month = DateTime.now.month
116 121 end
117 122 if day.blank?
118 123 day = 1
119 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 126 end
122 127 end
123 128  
... ...
app/helpers/events_helper.rb
... ... @@ -16,7 +16,7 @@ module EventsHelper
16 16  
17 17 content_tag( 'tr',
18 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 20 content_tag('div',link_to(article.name,article.url),:class => 'event-title') +
21 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 30 # the day itself
31 31 date,
32 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 34 # is this date in the current month?
35 35 true
36 36 ]
... ...
app/helpers/forms_helper.rb
... ... @@ -151,7 +151,7 @@ module FormsHelper
151 151 datepicker_options[:close_text] ||= _('Done')
152 152 datepicker_options[:constrain_input] ||= true
153 153 datepicker_options[:current_text] ||= _('Today')
154   - datepicker_options[:date_format] ||= 'mm/dd/yy'
  154 + datepicker_options[:date_format] ||= 'yy/mm/dd'
155 155 datepicker_options[:day_names] ||= [_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')]
156 156 datepicker_options[:day_names_min] ||= [_('Su'), _('Mo'), _('Tu'), _('We'), _('Th'), _('Fr'), _('Sa')]
157 157 datepicker_options[:day_names_short] ||= [_('Sun'), _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat')]
... ... @@ -236,7 +236,7 @@ module FormsHelper
236 236 weekHeader: #{datepicker_options[:week_header].to_json},
237 237 yearRange: #{datepicker_options[:year_range].to_json},
238 238 yearSuffix: #{datepicker_options[:year_suffix].to_json}
239   - })
  239 + }).datepicker('setDate', new Date('#{value}'))
240 240 </script>
241 241 ".html_safe
242 242 result
... ...
app/helpers/layout_helper.rb
... ... @@ -77,15 +77,8 @@ module LayoutHelper
77 77  
78 78  
79 79 def icon_theme_stylesheet_path
80   - icon_themes = []
81 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 82 end
90 83  
91 84 def jquery_ui_theme_stylesheet_path
... ... @@ -93,7 +86,7 @@ module LayoutHelper
93 86 end
94 87  
95 88 def theme_stylesheet_path
96   - "/assets#{theme_path}/style.css"
  89 + "#{theme_path}/style.css".gsub(%r{^/}, '')
97 90 end
98 91  
99 92 def layout_template
... ...
app/mailers/scrap_notifier.rb
1 1 class ScrapNotifier < ActionMailer::Base
2 2 def notification(scrap)
3 3 sender, receiver = scrap.sender, scrap.receiver
  4 + # for tests
  5 + return unless receiver.email
  6 +
4 7 @recipient = receiver.name
5 8 @sender = sender.name
6 9 @sender_link = sender.url
... ...
app/models/add_member.rb
... ... @@ -29,7 +29,8 @@ class AddMember &lt; Task
29 29 end
30 30  
31 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 34 end
34 35  
35 36 def accept_details
... ... @@ -45,7 +46,7 @@ class AddMember &lt; Task
45 46 end
46 47  
47 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 50 end
50 51  
51 52 def target_notification_message
... ...
app/models/article.rb
... ... @@ -8,7 +8,8 @@ class Article &lt; ActiveRecord::Base
8 8 :accept_comments, :feed, :published, :source, :source_name,
9 9 :highlighted, :notify_comments, :display_hits, :slug,
10 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 14 acts_as_having_image
14 15  
... ... @@ -641,6 +642,20 @@ class Article &lt; ActiveRecord::Base
641 642 can_display_hits? && display_hits
642 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 659 def image?
645 660 false
646 661 end
... ... @@ -754,9 +769,10 @@ class Article &lt; ActiveRecord::Base
754 769 end
755 770  
756 771 def body_images_paths
757   - require 'uri'
758 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 776 end
761 777 end
762 778  
... ...
app/models/category.rb
... ... @@ -81,7 +81,7 @@ class Category &lt; ActiveRecord::Base
81 81 end
82 82  
83 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 85 end
86 86  
87 87 def display_in_menu?
... ...
app/models/community.rb
... ... @@ -86,8 +86,8 @@ class Community &lt; Organization
86 86 {:title => _('Community Info and settings'), :icon => 'edit-profile-group'}
87 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 91 end
92 92  
93 93 end
... ...
app/models/enterprise.rb
... ... @@ -15,12 +15,15 @@ class Enterprise &lt; Organization
15 15  
16 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 22 has_many :inputs, :through => :products
20 23 has_many :production_costs, :as => :owner
21 24  
22 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 28 def product_categories
26 29 ProductCategory.by_enterprise(self)
... ... @@ -194,10 +197,6 @@ class Enterprise &lt; Organization
194 197 true
195 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 200 def catalog_url
202 201 { :profile => identifier, :controller => 'catalog'}
203 202 end
... ... @@ -206,4 +205,9 @@ class Enterprise &lt; Organization
206 205 ''
207 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 213 end
... ...
app/models/enterprise_homepage.rb
... ... @@ -35,4 +35,8 @@ class EnterpriseHomepage &lt; Article
35 35 false
36 36 end
37 37  
  38 + def can_display_media_panel?
  39 + true
  40 + end
  41 +
38 42 end
... ...
app/models/environment.rb
... ... @@ -13,7 +13,7 @@ class Environment &lt; ActiveRecord::Base
13 13 :reports_lower_bound, :noreply_email,
14 14 :signup_welcome_screen_body, :members_whitelist_enabled,
15 15 :members_whitelist, :highlighted_news_amount,
16   - :portal_news_amount, :date_format
  16 + :portal_news_amount, :date_format, :signup_intro
17 17  
18 18 has_many :users
19 19  
... ... @@ -128,6 +128,7 @@ class Environment &lt; ActiveRecord::Base
128 128 'disable_select_city_for_contact' => _('Disable state/city select for contact form'),
129 129 'disable_contact_person' => _('Disable contact for people'),
130 130 'disable_contact_community' => _('Disable contact for groups/communities'),
  131 + 'forbid_destroy_profile' => _('Forbid users of removing profiles'),
131 132  
132 133 'products_for_enterprises' => _('Enable products for enterprises'),
133 134 'enterprise_registration' => _('Enterprise registration'),
... ... @@ -167,7 +168,8 @@ class Environment &lt; ActiveRecord::Base
167 168 'site_homepage' => _('Redirects the user to the environment homepage.'),
168 169 'user_profile_page' => _('Redirects the user to his profile page.'),
169 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 174 end
173 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 250 # store the Environment settings as YAML-serialized Hash.
249 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 256 # the environment's terms of use: every user must accept them before registering.
252 257 settings_items :terms_of_use, :type => String
253 258  
... ... @@ -282,7 +287,20 @@ class Environment &lt; ActiveRecord::Base
282 287 settings_items :activation_blocked_text, :type => String
283 288 settings_items :message_for_disabled_enterprise, :type => String,
284 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 304 settings_items :layout_template, :type => String, :default => 'default'
287 305 settings_items :homepage, :type => String
288 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 23  
24 24 def initialize(*args)
25 25 super(*args)
26   - self.start_date ||= Date.today
  26 + self.start_date ||= DateTime.now
27 27 end
28 28  
29 29 validates_presence_of :title, :start_date
... ... @@ -35,7 +35,7 @@ class Event &lt; Article
35 35 end
36 36  
37 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 39 :order => 'start_date ASC'
40 40 }
41 41 }
... ... @@ -80,7 +80,7 @@ class Event &lt; Article
80 80  
81 81 def self.date_range(year, month)
82 82 if year.nil? || month.nil?
83   - today = Date.today
  83 + today = DateTime.now
84 84 year = today.year
85 85 month = today.month
86 86 else
... ... @@ -88,7 +88,7 @@ class Event &lt; Article
88 88 month = month.to_i
89 89 end
90 90  
91   - first_day = Date.new(year, month, 1)
  91 + first_day = DateTime.new(year, month, 1)
92 92 last_day = first_day + 1.month - 1.day
93 93  
94 94 first_day..last_day
... ... @@ -114,7 +114,7 @@ class Event &lt; Article
114 114 end
115 115  
116 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 118 end
119 119  
120 120 alias_method :article_lead, :lead
... ... @@ -134,6 +134,10 @@ class Event &lt; Article
134 134 true
135 135 end
136 136  
  137 + def can_display_media_panel?
  138 + true
  139 + end
  140 +
137 141 include Noosfero::TranslatableContent
138 142 include MaybeAddHttp
139 143  
... ...
app/models/favorite_enterprise_person.rb
1 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 7 belongs_to :enterprise
6 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 23 end
... ...
app/models/organization.rb
... ... @@ -59,6 +59,10 @@ class Organization &lt; Profile
59 59  
60 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 66 def presence_of_required_fieds
63 67 self.required_fields.each do |field|
64 68 if self.send(field).blank?
... ...
app/models/person.rb
... ... @@ -94,6 +94,9 @@ roles] }
94 94  
95 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 100 has_and_belongs_to_many :acepted_forums, :class_name => 'Forum', :join_table => 'terms_forum_people'
98 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 336 ]
334 337 end
335 338  
336   - has_and_belongs_to_many :favorite_enterprises, :class_name => 'Enterprise', :join_table => 'favorite_enteprises_people'
337   -
338 339 def email_domain
339 340 user && user.email_domain || environment.default_hostname(true)
340 341 end
... ... @@ -514,8 +515,8 @@ roles] }
514 515 user.save!
515 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 520 end
520 521  
521 522 # by default, all fields are private
... ...
app/models/person_notifier.rb
... ... @@ -76,7 +76,8 @@ class PersonNotifier
76 76  
77 77 class Mailer < ActionMailer::Base
78 78  
79   - add_template_helper(ApplicationHelper)
  79 + helper ApplicationHelper
  80 + helper ActionTrackerHelper
80 81  
81 82 def session
82 83 {:theme => nil}
... ...
app/models/product.rb
... ... @@ -17,13 +17,14 @@ class Product &lt; ActiveRecord::Base
17 17 'full'
18 18 end
19 19  
20   - belongs_to :enterprise, :foreign_key => :profile_id, :class_name => 'Profile'
21 20 belongs_to :profile
  21 + # backwards compatibility
  22 + belongs_to :enterprise, :foreign_key => :profile_id, :class_name => 'Profile'
22 23 alias_method :enterprise=, :profile=
23 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 29 belongs_to :product_category
29 30  
... ... @@ -37,6 +38,10 @@ class Product &lt; ActiveRecord::Base
37 38  
38 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 45 validates_uniqueness_of :name, :scope => :profile_id, :allow_nil => true, :if => :validate_uniqueness_of_column_name?
41 46  
42 47 validates_presence_of :product_category_id
... ... @@ -73,10 +78,10 @@ class Product &lt; ActiveRecord::Base
73 78 after_update :save_image
74 79  
75 80 def lat
76   - self.enterprise.lat
  81 + self.profile.lat
77 82 end
78 83 def lng
79   - self.enterprise.lng
  84 + self.profile.lng
80 85 end
81 86  
82 87 xss_terminate :only => [ :name ], :on => 'validation'
... ... @@ -90,7 +95,7 @@ class Product &lt; ActiveRecord::Base
90 95 filter_iframes :description
91 96  
92 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 99 end
95 100  
96 101 def name
... ... @@ -128,16 +133,16 @@ class Product &lt; ActiveRecord::Base
128 133 end
129 134  
130 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 137 end
133 138  
134 139 def public?
135   - enterprise.public?
  140 + self.profile.public?
136 141 end
137 142  
138 143 def formatted_value(method)
139 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 146 end
142 147  
143 148 def price_with_discount
... ... @@ -242,16 +247,16 @@ class Product &lt; ActiveRecord::Base
242 247 end
243 248  
244 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 251 end
247 252  
248 253 include Rails.application.routes.url_helpers
249 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 256 end
252 257  
253 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 260 end
256 261  
257 262 def percentage_from_solidarity_economy
... ... @@ -268,7 +273,7 @@ class Product &lt; ActiveRecord::Base
268 273 end
269 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 278 protected
274 279  
... ... @@ -276,4 +281,13 @@ class Product &lt; ActiveRecord::Base
276 281 true
277 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 293 end
... ...
app/models/profile.rb
... ... @@ -3,7 +3,9 @@
3 3 # which by default is the one returned by Environment:default.
4 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 10 # use for internationalizable human type names in search facets
9 11 # reimplement on subclasses
... ... @@ -188,6 +190,7 @@ class Profile &lt; ActiveRecord::Base
188 190  
189 191 acts_as_trackable :dependent => :destroy
190 192  
  193 + has_many :profile_activities
191 194 has_many :action_tracker_notifications, :foreign_key => 'profile_id'
192 195 has_many :tracked_notifications, :through => :action_tracker_notifications, :source => :action_tracker, :order => 'updated_at DESC'
193 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 616 options.merge(Noosfero.url_options)
614 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 627 private :generate_url, :url_options
617 628  
618 629 def default_hostname
... ... @@ -785,7 +796,11 @@ private :generate_url, :url_options
785 796 include ActionView::Helpers::TextHelper
786 797 def short_name(chars = 40)
787 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 804 else
790 805 self[:nickname]
791 806 end
... ... @@ -1025,9 +1040,13 @@ private :generate_url, :url_options
1025 1040 name
1026 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 1048 def activities
1030   - []
  1049 + self.profile_activities.includes(:activity).order('updated_at DESC')
1031 1050 end
1032 1051  
1033 1052 def may_display_field_to? field, user = nil
... ... @@ -1074,6 +1093,7 @@ private :generate_url, :url_options
1074 1093 def preferred_login_redirection
1075 1094 redirection_after_login.blank? ? environment.redirection_after_login : redirection_after_login
1076 1095 end
  1096 + settings_items :custom_url_redirection, type: String, default: nil
1077 1097  
1078 1098 def remove_from_suggestion_list(person)
1079 1099 suggestion = person.suggested_profiles.find_by_suggestion_id self.id
... ...
app/models/profile_activity.rb 0 → 100644
... ... @@ -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 16  
17 17 def profile_list
18 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 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 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 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 26 end
27 27 result.slice(0..get_limit-1)
28 28 end
29 29  
30 30 def profile_count
31   - profiles.visible.length
  31 + profiles.public.length
32 32 end
33 33  
34 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 13 has_many :replies, :class_name => 'Scrap', :foreign_key => 'scrap_id', :dependent => :destroy
14 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 21 scope :all_scraps, lambda {|profile| {:conditions => ["receiver_id = ? OR sender_id = ?", profile, profile], :limit => 30}}
17 22  
18 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 33 before_validation :strip_all_html_tags
32 34  
... ... @@ -57,4 +59,21 @@ class Scrap &lt; ActiveRecord::Base
57 59 sender != receiver && (is_root? ? root.receiver.receives_scrap_notification? : receiver.receives_scrap_notification?)
58 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 79 end
... ...
app/models/session.rb 0 → 100644
... ... @@ -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 33 end
34 34  
35 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 37 if fullpath
38 38 domain = fullpath[2]
39 39 path = fullpath[4]
40   - el[attribute] = path if domain == environment.default_hostname
  40 + el[attribute] = path if domain == profile.default_hostname
41 41 end
42 42 end
43 43  
  44 + def display_preview?
  45 + parent && parent.kind_of?(Blog) && parent.display_preview
  46 + end
  47 +
44 48 end
... ...
app/models/textile_article.rb
... ... @@ -24,6 +24,10 @@ class TextileArticle &lt; TextArticle
24 24 true
25 25 end
26 26  
  27 + def can_display_media_panel?
  28 + true
  29 + end
  30 +
27 31 protected
28 32  
29 33 def convert_to_html(textile)
... ...
app/models/tiny_mce_article.rb
... ... @@ -28,4 +28,8 @@ class TinyMceArticle &lt; TextArticle
28 28 true
29 29 end
30 30  
  31 + def can_display_media_panel?
  32 + true
  33 + end
  34 +
31 35 end
... ...
app/models/uploaded_file.rb
... ... @@ -163,4 +163,8 @@ class UploadedFile &lt; Article
163 163 true
164 164 end
165 165  
  166 + def notifiable?
  167 + true
  168 + end
  169 +
166 170 end
... ...
app/models/user.rb
... ... @@ -16,6 +16,14 @@ class User &lt; ActiveRecord::Base
16 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 27 def self.[](login)
20 28 self.find_by_login(login)
21 29 end
... ... @@ -97,6 +105,10 @@ class User &lt; ActiveRecord::Base
97 105 has_one :person, :dependent => :destroy
98 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 112 attr_protected :activated_at
101 113  
102 114 # Virtual attribute for the unencrypted password
... ... @@ -118,11 +130,18 @@ class User &lt; ActiveRecord::Base
118 130  
119 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 138 # Authenticates a user by their login name or email and unencrypted password. Returns the user or nil.
122 139 def self.authenticate(login, password, environment = nil)
123 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 145 if u && u.authenticated?(password)
127 146 u.generate_private_token_if_not_exist
128 147 return u
... ... @@ -259,7 +278,23 @@ class User &lt; ActiveRecord::Base
259 278 password.crypt(salt)
260 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 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 298 result = (crypted_password == encrypt(password))
264 299 if (encryption_method != User.system_encryption_method) && result
265 300 self.password_type = User.system_encryption_method.to_s
... ... @@ -276,8 +311,9 @@ class User &lt; ActiveRecord::Base
276 311  
277 312 # These create and unset the fields required for remembering users between browser closes
278 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 317 save(:validate => false)
282 318 end
283 319  
... ... @@ -297,9 +333,15 @@ class User &lt; ActiveRecord::Base
297 333 # current password.
298 334 # * Saves the record unless it is a new one.
299 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 345 end
304 346 self.force_change_password!(new, confirmation)
305 347 end
... ...
app/models/validation_info.rb
... ... @@ -2,9 +2,10 @@ class ValidationInfo &lt; ActiveRecord::Base
2 2  
3 3 attr_accessible :validation_methodology, :restrictions, :organization
4 4  
5   - validates_presence_of :validation_methodology
6   -
7 5 belongs_to :organization
8 6  
  7 + validates_presence_of :organization
  8 + validates_presence_of :validation_methodology
  9 +
9 10 xss_terminate :only => [ :validation_methodology, :restrictions ], :on => 'validation'
10 11 end
... ...
app/views/account/login.html.erb
... ... @@ -13,7 +13,14 @@
13 13  
14 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 25 <% button_bar do %>
19 26 <%= submit_button( 'login', _('Log in') )%>
... ...
app/views/account/signup.html.erb
1 1 <h1><%= _('Sign up for %s!') % environment.name %></h1>
  2 +
  3 +<div id='signup-intro'>
  4 + <%= environment.signup_intro %>
  5 +</div>
  6 +
2 7 <%= render :partial => 'signup_form' %>
... ...
app/views/admin_panel/_signup_intro.html.erb 0 → 100644
... ... @@ -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 17 :content => (render :partial => 'signup_welcome_text', :locals => {:f => f})} %>
18 18 <% tabs << {:title => _('Signup welcome page'), :id => 'signup-welcome-message',
19 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 22 <%= render_tabs(tabs) %>
21 23 <% button_bar do %>
22 24 <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %>
... ...
app/views/blocks/profile_info_actions/_enterprise.html.erb
1 1 <ul>
2 2 <%if logged_in? %>
3 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 5 <% end %>
6 6 <% end %>
7 7 <% if profile.enable_contact? %>
... ...
app/views/blocks/profile_info_actions/_join_leave_community.html.erb
1 1 <div class='join-leave-button require-login-popup'>
2 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 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 15 <% end %>
23 16 <% end %>
24 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 19 <% end %>
27 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 53 %>
54 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 58 <%= f.fields_for :image_builder, @article.image do |i| %>
59 59 <%= file_field_or_thumbnail(_('Cover image:'), @article.image, i)%>
... ...
app/views/cms/_event.html.erb
... ... @@ -8,9 +8,8 @@
8 8 <%= render :partial => 'general_fields' %>
9 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 14 <%= labelled_form_field(_('Event website:'), text_field(:article, :link)) %>
16 15  
... ...
app/views/cms/edit.html.erb
1 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 4 <%= labelled_form_for 'article', :html => { :multipart => true, :class => @type } do |f| %>
7 5  
8 6 <%= hidden_field_tag("type", @type) if @type %>
9 7  
10   - <%= hidden_field_tag('parent_id', @parent_id) if @parent_id %>
11   -
12 8 <%= hidden_field_tag('back_to', @back_to) %>
13 9  
14 10 <%= hidden_field_tag('success_back_to', @success_back_to) %>
... ... @@ -68,7 +64,7 @@
68 64 <% end %>
69 65 </div>
70 66  
71   -<% if show_media_panel %>
  67 +<% if @article.display_media_panel? %>
72 68 <%= render :partial => 'text_editor_sidebar' %>
73 69 <% end %>
74 70  
... ...
app/views/content_viewer/_article_title.html.erb
... ... @@ -7,7 +7,7 @@
7 7 <% end %>
8 8 </h1>
9 9 <%= render :partial => "publishing_info" %>
10   - <% unless @page.abstract.blank? %>
  10 + <% if @page.display_preview? %>
11 11 <div class="preview">
12 12 <%= @page.lead %>
13 13 </div>
... ...
app/views/content_viewer/_article_toolbar.html.erb
... ... @@ -29,10 +29,10 @@
29 29 <%= expirable_button @page, :locale, content, url %>
30 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 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 36 <%= expirable_button @page, :clone, content, url %>
37 37 <% end %>
38 38  
... ... @@ -62,7 +62,7 @@
62 62 <% if @page.blog? and !@page.image.nil? %>
63 63 <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div>
64 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 66 <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %>
67 67 <%= render :partial => 'article_title', :locals => {:no_link => true} %>
68 68 <%= article_translations(@page) %>
... ...
app/views/content_viewer/_publishing_info.html.erb
1 1 <span class="publishing-info">
2 2 <span class="date">
3   - <%= show_date(@page.published_at) %>
  3 + <%= show_time(@page.published_at) %>
4 4 </span>
5 5 <span class="author">
6 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 2 <%= link_to '',
3 3 uploaded_file.view_url,
4 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 7 <span><%=h uploaded_file.title %></span>
8 8 <% else %>
... ...
app/views/content_viewer/article_versions.html.erb
... ... @@ -12,7 +12,7 @@
12 12 <li>
13 13 <%= radio_button_tag 'v1', v.version, false, :onclick => 'versionInputClicked(this)' %>
14 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 16 <%= @page.version == v.version ? _('(current)') : '' %>
17 17 <span class='updated-by'><%= _('by %{author}') % {:author => link_to(@page.author_name(v.version), @page.author_url(v.version))} %></span>
18 18 <span class='updated-on'><%= show_time(v.updated_at) %></span>
... ...
app/views/content_viewer/folder.html.erb
... ... @@ -4,8 +4,5 @@
4 4 </div>
5 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 24 <%= render :partial => 'article_toolbar' %>
25 25 </div>
26 26  
27   -<% if NOOSFERO_CONF['addthis_enabled'] %>
  27 +<% if NOOSFERO_CONF['addthis_enabled'] and @page.public? %>
28 28 <%= render :partial => 'addthis' %>
29 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 1 <div class="uploaded-file-description <%= 'empty' if generic.abstract.blank? %>">
7 2 <%= generic.abstract %>
8 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 30 </div>
31 31 </td>
32 32  
33   - <td> <%= _("#{p.type}") %> </td>
  33 + <td> <%= _(p.type) %> </td>
34 34 </tr>
35 35 <% end %>
36 36 </table>
... ...
app/views/person_notifier/mailer/_default_activity.html.erb
... ... @@ -4,7 +4,10 @@
4 4 </td>
5 5 <td>
6 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 11 <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(activity.created_at) %></span>
9 12 </p>
10 13 </td>
... ...
app/views/profile/_create_product.html.erb 0 → 100644
... ... @@ -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 @@
  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 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 4 <% if activity.kind_of?(ActionTracker::Record) %>
5 5 <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'wall' } if activity.visible? %>
6 6 <% else %>
... ...
app/views/profile/_remove_product.html.erb 0 → 100644
... ... @@ -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 @@
  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 @@
  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 44 <% end %>
45 45  
46 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 48 <% end %>
50 49  
51 50 <h2><%= _('Translations') %></h2>
... ... @@ -75,14 +74,23 @@
75 74  
76 75 <% if user && user.has_permission?('destroy_profile', profile) %>
77 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 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 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 94 <% end %>
87 95 <% end %>
88 96 <% end %>
... ...
app/views/profile_roles/assign.html.erb
1 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 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 3 <% if @members.nil? || @members.empty? %>
4 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 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 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 <span class="item-description">
7 7 <%= link_to(content.name, content.url) %>
8 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 10 </div>
11 11 </div>
... ...
app/views/shared/_list_groups.html.erb
1 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 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 32 </ul>
28   -
... ...
config/application.rb
... ... @@ -126,7 +126,7 @@ module Noosfero
126 126 # Make sure the secret is at least 30 characters and all random,
127 127 # no regular words or you'll be exposed to dictionary attacks.
128 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 131 config.paths['db/migrate'] += Dir.glob "#{Rails.root}/{baseplugins,config/plugins}/*/db/migrate"
132 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 2  
3 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 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 52 ActionTrackerConfig.timeout = 24.hours
... ...
config/initializers/session.rb 0 → 100644
... ... @@ -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 57 match 'search(/:action(/*category_path))', :controller => 'search'
58 58  
59 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 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 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 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 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 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 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 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 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 92 # map balloon
93 93 match 'map_balloon/:action/:id', :controller => 'map_balloon', :id => /.*/
... ... @@ -99,8 +99,8 @@ Noosfero::Application.routes.draw do
99 99 ## Controllers that are profile-specific (for profile admins )
100 100 ######################################################
101 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 128 # cache stuff - hack
129 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 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 135 match '*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff'
136 136  
137 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 140 # match requests for content in domains hosted for profiles
141 141 match '/(*page)', :controller => 'content_viewer', :action => 'view_page'
... ...
db/migrate/20150216213259_create_profile_activity.rb 0 → 100644
... ... @@ -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 @@
  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 @@
  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 @@
  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 @@
  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
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 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 16 create_table "abuse_reports", :force => true do |t|
17 17 t.integer "reporter_id"
... ... @@ -75,8 +75,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
75 75 t.integer "comments_count"
76 76 t.boolean "advertise", :default => true
77 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 80 t.integer "children_count", :default => 0
81 81 t.boolean "accept_comments", :default => true
82 82 t.integer "reference_article_id"
... ... @@ -127,8 +127,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
127 127 t.integer "comments_count", :default => 0
128 128 t.boolean "advertise", :default => true
129 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 132 t.integer "children_count", :default => 0
133 133 t.boolean "accept_comments", :default => true
134 134 t.integer "reference_article_id"
... ... @@ -351,11 +351,17 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
351 351 add_index "external_feeds", ["enabled"], :name => "index_external_feeds_on_enabled"
352 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 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 365 create_table "friendships", :force => true do |t|
360 366 t.integer "person_id"
361 367 t.integer "friend_id"
... ... @@ -489,6 +495,18 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
489 495 add_index "products", ["product_category_id"], :name => "index_products_on_product_category_id"
490 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 510 create_table "profile_suggestions", :force => true do |t|
493 511 t.integer "person_id"
494 512 t.integer "suggestion_id"
... ... @@ -555,6 +573,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
555 573 add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier"
556 574 add_index "profiles", ["members_count"], :name => "index_profiles_on_members_count"
557 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 579 create_table "qualifier_certifiers", :force => true do |t|
560 580 t.integer "qualifier_id"
... ... @@ -645,10 +665,12 @@ ActiveRecord::Schema.define(:version =&gt; 20150603182105) do
645 665 t.text "data"
646 666 t.datetime "created_at"
647 667 t.datetime "updated_at"
  668 + t.integer "user_id"
648 669 end
649 670  
650 671 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
651 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 675 create_table "suggestion_connections", :force => true do |t|
654 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 7 noosfero (1.2~rc2) wheezy; urgency=low
2 8  
3 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 14 h2(#description). Description
15 15  
16 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 18 # Clicking on one of the search results, you will be redirected to the homepage of choosen enterprise.
19 19  
20 20 h3. More options
... ...
features/accept_member.feature
... ... @@ -14,6 +14,16 @@ Feature: accept member
14 14 And the community "My Community" is closed
15 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 27 @selenium
18 28 Scenario: approve a task to accept a member as admin in a closed community
19 29 Given "Marie Curie" asked to join "My Community"
... ...
features/events.feature
... ... @@ -223,7 +223,7 @@ Feature: events
223 223 | owner | name | start_date | end_date |
224 224 | josesilva | WikiSym 2009 | 2009-10-25 | 2009-10-27 |
225 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 228 Scenario: show place of the event
229 229 Given I am on /profile/josesilva/events/2009/10
... ...
features/members_block.feature
... ... @@ -9,8 +9,8 @@ Feature:
9 9 | joaosilva | Joao Silva |
10 10 | mariasilva | Maria Silva |
11 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 14 And the following blocks
15 15 | owner | type |
16 16 | sample-community | MembersBlock |
... ... @@ -24,7 +24,7 @@ Feature:
24 24 Scenario: a user can join in a community by members block's button
25 25 Given I am logged in as "mariasilva"
26 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 28 And I go to mariasilva's control panel
29 29 And I follow "Manage my groups"
30 30 Then I should see "Sample Community"
... ... @@ -41,7 +41,7 @@ Feature:
41 41 Scenario: a not logged in user can log in by members block's button
42 42 Given I am not logged in
43 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 45 Then I should see "Username / Email"
46 46  
47 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 51 And I uncheck "Show join leave button"
52 52 And I press "Save"
53 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 55 And I should not see "Leave community" within ".members-block"
... ...
lib/authenticated_system.rb
1 1 module AuthenticatedSystem
  2 +
2 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 18 # Returns true or false if the user is logged in.
4 19 # Preloads @current_user with the user model if they're logged in.
5 20 def logged_in?
... ... @@ -8,7 +23,13 @@ module AuthenticatedSystem
8 23  
9 24 # Accesses the current user from the session.
10 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 33 end
13 34  
14 35 # Store the given user in the session.
... ... @@ -17,9 +38,10 @@ module AuthenticatedSystem
17 38 session.delete(:user)
18 39 else
19 40 session[:user] = new_user.id
  41 + new_user.session = session
20 42 new_user.register_login
21 43 end
22   - @current_user = new_user
  44 + @current_user = User.current = new_user
23 45 end
24 46  
25 47 # Check if the user is authorized.
... ... @@ -121,14 +143,9 @@ module AuthenticatedSystem
121 143 # When called with before_filter :login_from_cookie will check for an :auth_token
122 144 # cookie and log the user back in if apropriate
123 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 149 end
133 150  
134 151 private
... ...
lib/needs_profile.rb
... ... @@ -21,7 +21,11 @@ module NeedsProfile
21 21 protected
22 22  
23 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 29 if @profile
26 30 profile_hostname = @profile.hostname
27 31 if profile_hostname && profile_hostname != request.host
... ...
lib/noosfero/action_tracker_ext.rb
1 1 Rails.configuration.to_prepare do
2   - ActionTracker::Record.module_eval do
  2 + ActionTracker::Record.class_eval do
3 3 extend CacheCounterHelper
4 4  
5 5 after_create do |record|
... ... @@ -9,6 +9,11 @@ Rails.configuration.to_prepare do
9 9 end
10 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 17 after_destroy do |record|
13 18 if record.created_at >= ActionTracker::Record::RECENT_DELAY.days.ago
14 19 ActionTracker::Record.update_cache_counter(:activities_count, record.user, -1)
... ... @@ -17,5 +22,17 @@ Rails.configuration.to_prepare do
17 22 end
18 23 end
19 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 37 end
21 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 19 controllers.each do |controller|
20 20 controller_name = controller.gsub("#{plugin_name}_plugin_",'')
21 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 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 25 end
26 26 end
27 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 33 end
... ...
lib/noosfero/version.rb
1 1 module Noosfero
2 2 PROJECT = 'noosfero'
3   - VERSION = '1.2~rc2'
  3 + VERSION = '1.2'
4 4 end
5 5  
6 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 22 # Notify all friends
23 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 31 if target.is_a?(Community)
26 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 37 tests << t unless tests.include?(t)
38 38 end
39 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 45 end
41 46  
42 47 if tests.empty? && features.empty? && changed_plugins.empty?
... ...
lib/tasks/enable_plugins.rake
1 1 namespace :noosfero do
2 2 namespace :plugins do
  3 + desc 'Enable all installed plugins on all environment'
3 4 task :enable_all => :environment do
4 5 Environment.all.each do |env|
5 6 puts "Plugins Activated on #{env.name}" if env.enable_all_plugins
... ...
lib/tasks/gettext.rake
... ... @@ -60,6 +60,8 @@ task :updatepo do
60 60  
61 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 65 files_to_translate = [
64 66 "{app,lib}/**/*.{rb,rhtml,erb}",
65 67 'config/initializers/*.rb',
... ... @@ -98,7 +100,7 @@ Dir.glob(&#39;plugins/*&#39;).each do |plugindir|
98 100 }
99 101 )
100 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 104 rm_f plugin_pot
103 105 end
104 106 sh 'find', po_root, '-type', 'd', '-empty', '-delete'
... ... @@ -106,8 +108,25 @@ Dir.glob(&#39;plugins/*&#39;).each do |plugindir|
106 108 end
107 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 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 130 end
112 131  
113 132 # vim: ft=ruby
... ...
lib/tasks/plugins_tests.rake
... ... @@ -169,7 +169,7 @@ def test_sequence(plugins, tasks)
169 169 failed[plugin] << task
170 170 end
171 171 end
172   - disable_plugins(plugin)
  172 + disable_plugins
173 173 end
174 174 fail_flag = false
175 175 failed.each do |plugin, tasks|
... ...