Commit 87ccdfde777a2f6d1ef511c6a052ae68e298fee9

Authored by Victor Costa
2 parents 40c630fd 24b3013c
Exists in staging

Merge branch 'master' into staging

Showing 2490 changed files with 297841 additions and 297897 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 2490 files displayed.

.gitlab-ci.yml
... ... @@ -59,18 +59,18 @@ selenium-6:
59 59 # NOOSFERO_BUNDLE_OPTS=install makes migrations fails
60 60 # probably because of rubygems-integration
61 61 plugins-1:
62   - script: SLICE=1/5 bundle exec rake test:noosfero_plugins
  62 + script: SLICE=1/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
63 63 stage: all-tests
64 64 plugins-2:
65   - script: SLICE=2/5 bundle exec rake test:noosfero_plugins
  65 + script: SLICE=2/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
66 66 stage: all-tests
67 67 plugins-3:
68   - script: SLICE=3/5 bundle exec rake test:noosfero_plugins
  68 + script: SLICE=3/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
69 69 stage: all-tests
70 70 plugins-4:
71   - script: SLICE=4/5 bundle exec rake test:noosfero_plugins
  71 + script: SLICE=4/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
72 72 stage: all-tests
73 73 plugins-5:
74   - script: SLICE=5/5 bundle exec rake test:noosfero_plugins
  74 + script: SLICE=5/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
75 75 stage: all-tests
76 76  
... ...
.travis.yml
... ... @@ -19,6 +19,10 @@ language: ruby
19 19 rvm:
20 20 - 2.3.1
21 21  
  22 +services:
  23 + - postgresql
  24 + - elasticsearch
  25 +
22 26 addons:
23 27 apt:
24 28 packages:
... ...
AUTHORS.md
... ... @@ -8,38 +8,42 @@ noosfero, that's not a problem).
8 8 Developers
9 9 ==========
10 10  
11   -Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>
12 11 Alan Freihof Tygel <alantygel@gmail.com>
  12 +Alessandro Caetano <alesasndro.caetanob@gmail.com>
  13 +Alessandro Caetano <alessandro.caetanob@gmail.com>
13 14 Alessandro Palmeira <alessandro.palmeira@gmail.com>
  15 +Alex Campelo <campelo.al1@gmail.com>
14 16 Alexandre Barbosa <alexandreab@live.com>
15 17 Alexandre Torres <alexandrekry@gmail.com>
16   -Alex Campelo <campelo.al1@gmail.com>
17   -Álvaro Fernando <alvarofernandoms@gmail.com>
  18 +Alipio muñiz <alipio@ecoalternative.net>
18 19 Ana Losnak <analosnak@gmail.com>
19 20 Ana Paula Vargas <anapaulavnoronha@gmail.com>
20 21 Andre Bedran <bedran.fleck@gmail.com>
21   -André Guedes <andrebsguedes@gmail.com>
22 22 Andrey Aleksanyants <aaleksanyants@yahoo.com>
  23 +André Guedes <andrebsguedes@gmail.com>
23 24 Antonio Terceiro <terceiro@colivre.coop.br>
24 25 Arthur Del Esposte <arthurmde@gmail.com>
  26 +Arthur Jahn <stutrzbecher@gmail.com>
  27 +Artur Bersan de Faria <arturbersan@gmail.com>
25 28 Athos Ribeiro <athoscribeiro@gmail.com>
26   -Aurelio A. Heckert <aurelio@colivre.coop.br>
  29 +Aurelio A. Heckert <aurium@colivre.coop.br>
  30 +Becca Cook <b.cook28@gmail.com>
27 31 Braulio Bhavamitra <braulio@eita.org.br>
28 32 Brenddon Gontijo <brenddongontijo@msn.com>
29 33 Caio Formiga <caio.formiga@gmail.com>
30   -Caio Salgado <caio.csalgado@gmail.com>
31 34 Caio SBA <caio@colivre.coop.br>
  35 +Caio Salgado <caio.csalgado@gmail.com>
32 36 Caio Tiago Oliveira <caiotiago@colivre.coop.br>
33 37 Carlos Andre de Souza <carlos.andre.souza@msn.com>
34 38 Carlos Morais <carlos88morais@gmail.com>
35 39 Carlos Purificacao <carloseugenio@gmail.com>
36 40 Christophe DANIEL <papaeng@gmail.com>
37   -Daniela Feitosa <alessandro.palmeira@gmail.com>
38 41 Daniel Alves <danpaulalves@gmail.com>
39   -Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
40 42 Daniel Bucher <daniel.bucher88@gmail.com>
41 43 Daniel Cunha <daniel@colivre.coop.br>
  44 +Daniel Henrique <danielhmarinho@gmail.com>
42 45 Daniel Tygel <dtygel@eita.org.br>
  46 +Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
43 47 David Carlos <ddavidcarlos1392@gmail.com>
44 48 Diego Araujo <diegoamc90@gmail.com>
45 49 Dylan Guedes <djmgguedes@gmail.com>
... ... @@ -48,76 +52,91 @@ Eduardo Passos &lt;eduardosteps@gmail.com&gt;
48 52 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
49 53 Eduardo Vital <vitaldu@gmail.com>
50 54 Evandro Magalhaes Leite Junior <evandro.leite@serpro.gov.br>
51   -Fabio Teixeira <fabio1079@gmail.com>
52 55 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com>
  56 +Fabio Teixeira <fabio1079@gmail.com>
  57 +Fagner Rodrigues <fagner128@gmail.com>
53 58 Fernanda Lopes <nanda.listas+psl@gmail.com>
54 59 Filipe Ribeiro <firibeiro77@live.com>
55 60 Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br>
56   -Gabriela Navarro <navarro1703@gmail.com>
57 61 Gabriel Silva <gabriel93.silva@gmail.com>
  62 +Gabriel Silva <grabriel93.silva@gmail.com>
  63 +Gabriela Navarro <navarro1703@gmail.com>
58 64 Gonzalo Exequiel Pedone <hipersayan.x@gmail.com>
59 65 Grazieno Pellegrino <grazieno@gmail.com>
60 66 Guilherme C. Muniz <guilherme.cmuniz@gmail.com>
61 67 Guilherme Rojas <guilhermehrojas@gmail.com>
  68 +Gustavo Cavalcante <gustavo.cavalcante.oliveira@live.com>
62 69 Gustavo Coelho <gust.rod.coelho@gmail.com>
  70 +Gustavo Jaruga <darkshades@gmail.com>
63 71 Gustavo Jaruga <darksshades@gmail.com>
64 72 Hebert Douglas <hebertdougl@gmail.com>
65 73 Hugo Melo <hugo@riseup.net>
  74 +Iago Rodrigues <iago006@hotmailcom>
66 75 Iolane Andrade <andrade.icaa@gmail.com>
  76 +Iryna Pruitt <jdpruitt2807@prodigy.net>
67 77 Isaac Canan <isaac@intelletto.com.br>
68 78 Italo Valcy <italo@dcc.ufba.br>
  79 +Izharul Haq <atoz.chevara.2013@gmail.com>
69 80 Jefferson Fernandes <jeffs.fernandes@gmail.com>
70   -Jérôme Jutteau <j.jutteau@gmail.com>
71   -Jéssica Cristina <jessica.cris1127@gmail.com>
72   -João Machini
73   -João M. M. da Silva <jaodsilv@linux.ime.usp.br>
74 81 Joenio Costa <joenio@colivre.coop.br>
75   -Josef Spillner <josef.spillner@tu-dresden.de>
  82 +Joenio Costa <joenio@joenio.me>
76 83 Jose Pedro <1jpsneto@gmail.com>
  84 +Josef Spillner <josef.spillner@tu-dresden.de>
  85 +João M. M. da Silva <jaodsilv@linux.ime.usp.br>
  86 +João Machini
77 87 Junior Silva <juniorsilva1001@gmail.com>
  88 +Jérôme Jutteau <j.jutteau@gmail.com>
  89 +Jéssica Cristina <jessica.cris1127@gmail.com>
  90 +Karine Valença <valenca.karine@gmail.com>
78 91 Keilla Menezes <keilla@colivre.coop.br>
79 92 Larissa Reis <larissa@colivre.coop.br>
80 93 Leandro Alves <leandrosustenido@gmail.com>
81 94 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br>
82 95 Leandro Veloso <leandrovelosorodrigues@gmail.com>
83 96 LinguÁgil 2010 <linguagil.bahia@gmail.com>
  97 +Luan Guimarães <guimaraesluan@me.com>
84 98 Lucas Couto <loc.unb@gmail.com>
85 99 Lucas Kanashiro <kanashiro.duarte@gmail.com>
86 100 Lucas Melo <lucaspradomelo@gmail.com>
  101 +Lucas Moura <lucas.moura128@gmail.com>
  102 +Lucas Severo <lucassalves65@gmail.com>
87 103 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com>
88 104 Luis David Aguilar Carlos <ludwig9003@gmail.com>
89 105 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com>
90 106 Luiz Matos <luizff.matos@gmail.com>
  107 +M for Momo <mo@rtnp.org>
91 108 Macartur de Sousa <macartur.sc@gmail.com>
92 109 Marcelo Júnior <maljunior@gmail.com>
93 110 Marcos Ramos <ms.ramos@outlook.com>
94 111 Marcos Ronaldo <marcos.rpj2@gmail.com>
95   -María Vecino <mariavecino@ecoalternative.net>
96 112 Mariel Zasso <noosfero-br@listas.softwarelivre.org>
97 113 Martín Olivera <molivera@solar.org.ar>
  114 +María Vecino <mariavecino@ecoalternative.net>
98 115 Matheus Faria <matheus.sousa.faria@gmail.com>
  116 +Matheus Miranda <matheusmirandalacerda@gmail.com>
99 117 Maurilio Atila <cabelotaina@gmail.com>
100 118 Melissa Wen <melissa.srw@gmail.com>
101   -M for Momo <mo@rtnp.org>
102 119 Michal Čihař <michal@cihar.com>
103 120 Michel Felipe de Oliveira Ferreira <michel.ferreira@serpro.gov.br>
104 121 Moises Machado <moises@colivre.coop.br>
105   -Naíla Alves <naila@colivre.coop.br>
  122 +Murilo Duarte <muriloduartegoncalves@hotmail.com>
106 123 Nanda Lopes <nanda.listas+psl@gmail.com>
  124 +Naíla Alves <naila@colivre.coop.br>
107 125 Niemand Jedermann <predatorix@web.de>
108 126 Omar Junior <omarroinuj@gmail.com>
109 127 Parley Martins <parleypachecomartins@gmail.com>
110 128 Paulo Meirelles <paulo@softwarelivre.org>
111   -Pedro de Lyra <pedrodelyra@gmail.com>
  129 +Paulo Tada <paulohtfs@gmail.com>
112 130 Pedro Leal
  131 +Pedro de Lyra <pedrodelyra@gmail.com>
113 132 Phillip Rohmberger <rohmberger@hotmail.de>
114   -Rafael de Souza Queiroz <querafael@live.com>
115 133 Rafael Gomes <rafaelgomes@techfree.com.br>
116 134 Rafael Martins <rmmartins@gmail.com>
117 135 Rafael Reggiani Manzo <rr.manzo@gmail.com>
  136 +Rafael de Souza Queiroz <querafael@live.com>
118 137 Raphaël Rousseau <raph@r4f.org>
119   -Raquel Lira <raquel.lira@gmail.com>
120 138 Raquel <rcordioli@gmail.com>
  139 +Raquel Lira <raquel.lira@gmail.com>
121 140 Renan Costa <renan2727@hotmail.com>
122 141 Renan Teruo <renanteruoc@gmail.com>
123 142 Rodrigo Medeiros <rodrigo.mss01@gmail.com>
... ... @@ -125,16 +144,18 @@ Rodrigo Siqueira &lt;siqueira@kuniri.org&gt;
125 144 Rodrigo Souto <rodrigo@colivre.coop.br>
126 145 Ronnie Simon <ronniesimonf@gmail.com>
127 146 Ronny Kursawe <kursawe.ronny@googlemail.com>
  147 +Sabryna Sousa <sabryna.sousa1323@gmail.com>
128 148 Samuel R. C. Vale <srcvale@holoscopio.com>
129 149 Simião Carvalho <simiaosimis@gmail.com>
  150 +TWS <tablettws@gmail.com>
130 151 Tallys Martins <tallysmartins@yahoo.com.br>
131 152 Thiago Casotti <thiago.casotti@uol.com.br>
132 153 Thiago Kairala <thiagor.kairala@gmail.com>
133 154 Thiago Ribeiro <thiagitosouza@hotmail.com>
134 155 Thiago Zoroastro <thiago.zoroastro@bol.com.br>
135 156 Tuux <tuxa@galaxie.eu.org>
136   -TWS <tablettws@gmail.com>
137 157 Valessio Brito <contato@valessiobrito.com.br>
  158 +Valet 322 <petymakar@gmail.com>
138 159 Victor Costa <vfcosta@gmail.com>
139 160 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>
140 161 Victor Navarro <victor.matias.navarro@gmail.com>
... ... @@ -142,6 +163,9 @@ Vinicius Brand &lt;viniciuscb@gmail.com&gt;
142 163 Vitor Barbosa <vitornga15@gmail.com>
143 164 Wilton Rodrigues <braynwilton@gmail.com>
144 165 Yann Lugrin <yann.lugrin@liquid-concept.ch>
  166 +Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>
  167 +Álvaro Fernando <alvarofernandoms@gmail.com>
  168 +Вадим Кардашьян <iosphone77@gmail.com>
145 169  
146 170 Ideas, specifications and incentive
147 171 ===================================
... ...
Gemfile
... ... @@ -27,7 +27,7 @@ gem &#39;rest-client&#39;, &#39;~&gt; 1.6&#39;
27 27 gem 'exception_notification', '~> 4.0.1'
28 28 gem 'gettext', '~> 3.1', :require => false
29 29 gem 'locale', '~> 2.1'
30   -gem 'whenever', :require => false
  30 +gem 'whenever', '~> 0.9.4', :require => false
31 31 gem 'eita-jrails', '~> 0.10.0', require: 'jrails'
32 32 gem 'diffy', '~> 3.0'
33 33 gem 'slim'
... ... @@ -35,17 +35,16 @@ gem &#39;activerecord-session_store&#39;, (&#39;1.0.0.pre&#39; if RUBY_VERSION &gt;= &#39;2.3.0&#39;)
35 35  
36 36 # API dependencies
37 37 gem 'grape', '~> 0.12'
38   -gem 'grape-entity', '0.4.8'
  38 +gem 'grape-entity', '~>0.4.8'
39 39 gem 'grape_logging'
40 40 gem 'grape-swagger'
41 41 gem 'swagger-ui_rails'
42 42 gem 'kramdown'
43 43 gem 'rack-cors'
44 44 gem 'rack-contrib'
45   -gem 'liquid', '~> 3.0.3'
46 45  
47 46 gem 'api-pagination', '>= 4.1.1'
48   -gem 'liquid', '~> 3.0.3'
  47 +gem 'liquid', '>= 3.0.3'
49 48  
50 49 # asset pipeline
51 50 gem 'uglifier', '>= 1.0.3'
... ... @@ -81,10 +80,10 @@ end
81 80 group :cucumber do
82 81 gem 'capybara', '~> 2.2'
83 82 gem 'launchy'
84   - gem 'cucumber'
  83 + gem 'cucumber', '~> 1.3'
85 84 gem 'cucumber-rails', '~> 1.4.2', :require => false
86 85 gem 'database_cleaner', '~> 1.3'
87   - gem 'selenium-webdriver', '>= 2.50'
  86 + gem 'selenium-webdriver', '>= 2.53'
88 87 gem 'chromedriver-helper' if ENV['SELENIUM_DRIVER'] == 'chrome'
89 88 end
90 89  
... ...
HACKING.md
... ... @@ -31,7 +31,7 @@ If you want to use a different port than 3000, pass `-p &lt;PORT&gt;` to `./script/dev
31 31 Instructions for other systems
32 32 ------------------------------
33 33  
34   -On other OS, you have 2 options:
  34 +On other OS, you have many options:
35 35  
36 36 ### 1) using a chroot or a VM with Debian stable (easier)
37 37  
... ... @@ -45,6 +45,14 @@ You can check `./script/install-dependencies/debian-squeeze.sh` to have an idea
45 45  
46 46 If you write such script for your own OS, *please* share it with us at the development mailing list so that we can include it in the official repository. This way other people using the same OS will have to put less effort to develop Noosfero.
47 47  
  48 +### 3) Installing dependencies via Rubygems and RVM
  49 +
  50 +To setup the development environment through Rubygems you just need to install some basic deps and then install the gems defined on the Gemfile. Further instructions can be found on: http://noosfero.org/bin/view/Development/DepsWithRVMAndGems
  51 +
  52 +### 4) Using a docker image
  53 +
  54 +Use a docker image to run an out-of-the-box development environment. Further information can be found on: https://hub.docker.com/r/noosfero/dev-rails4/
  55 +
48 56 Submitting your changes back
49 57 ----------------------------
50 58  
... ...
app/api/entities.rb
... ... @@ -38,9 +38,17 @@ module Api
38 38 PERMISSIONS[current_permission] <= PERMISSIONS[permission]
39 39 end
40 40  
  41 + def self.expose_optional_field?(field, options = {})
  42 + return false if options[:params].nil?
  43 + optional_fields = options[:params][:optional_fields] || []
  44 + optional_fields.include?(field.to_s)
  45 + end
  46 +
  47 +
41 48 class Image < Entity
42 49 root 'images', 'image'
43 50  
  51 + expose :filename
44 52 expose :url do |image, options|
45 53 image.public_filename
46 54 end
... ... @@ -153,6 +161,9 @@ module Api
153 161 expose :articles_count do |person, options|
154 162 person.articles.count
155 163 end
  164 + expose :friends_count do |person, options|
  165 + person.friends.size
  166 + end
156 167 end
157 168  
158 169 class Enterprise < Profile
... ... @@ -166,7 +177,8 @@ module Api
166 177 community.admins.map{|admin| {"name"=>admin.name, "id"=>admin.id, "username" => admin.identifier}}
167 178 end
168 179 expose :categories, :using => Category
169   - expose :members, :using => Person , :if => lambda{ |community, options| community.display_info_to? options[:current_person] }
  180 + expose :members_count
  181 + expose :members, :if => lambda {|community, options| Entities.expose_optional_field?(:members, options)}
170 182 end
171 183  
172 184 class CommentBase < Entity
... ... @@ -174,6 +186,10 @@ module Api
174 186 expose :created_at, :format_with => :timestamp
175 187 expose :author, :using => Profile
176 188 expose :reply_of, :using => CommentBase
  189 + expose :permissions do |comment, options|
  190 + Entities.permissions_for_entity(comment, options[:current_person],
  191 + :allow_destroy?)
  192 + end
177 193 end
178 194  
179 195 class Comment < CommentBase
... ... @@ -209,7 +225,7 @@ module Api
209 225 expose :comments_count
210 226 expose :archived, :documentation => {:type => "Boolean", :desc => "Defines if a article is readonly"}
211 227 expose :type
212   - expose :comments, using: CommentBase, :if => lambda{|obj,opt| opt[:params] && ['1','true',true].include?(opt[:params][:show_comments])}
  228 + expose :comments, using: CommentBase, :if => lambda{|comment,options| Entities.expose_optional_field?(:comments, options)}
213 229 expose :published
214 230 expose :accept_comments?, as: :accept_comments
215 231 end
... ... @@ -304,7 +320,7 @@ module Api
304 320 end
305 321 expose :params, :if => lambda { |activity, options| activity.kind_of?(ActionTracker::Record)}
306 322 expose :content, :if => lambda { |activity, options| activity.kind_of?(Scrap)}
307   - expose :verb do |activity, options|
  323 + expose :verb do |activity, options|
308 324 activity.kind_of?(Scrap) ? 'leave_scrap' : activity.verb
309 325 end
310 326  
... ...
app/api/helpers.rb
... ... @@ -57,9 +57,11 @@ module Api
57 57 def present_partial(model, options)
58 58 if(params[:fields].present?)
59 59 begin
60   - fields = JSON.parse(params[:fields])
  60 + fields = JSON.parse((params.to_hash[:fields] || params.to_hash['fields']).to_json)
61 61 if fields.present?
62   - options.merge!(fields.symbolize_keys.slice(:only, :except))
  62 + fields = fields.symbolize_keys
  63 + options.merge!(:only => fields[:only]) if fields[:only].present?
  64 + options.merge!(:except => fields[:except]) if fields[:except].present?
63 65 end
64 66 rescue
65 67 fields = params[:fields]
... ... @@ -116,7 +118,7 @@ module Api
116 118 def post_article(asset, params)
117 119 return forbidden! unless current_person.can_post_content?(asset)
118 120  
119   - klass_type = params[:content_type] || params[:article].delete(:type) || TinyMceArticle.name
  121 + klass_type = params[:content_type] || params[:article].delete(:type) || TextArticle.name
120 122 return forbidden! unless klass_type.constantize <= Article
121 123  
122 124 article = klass_type.constantize.new(params[:article])
... ... @@ -447,12 +449,12 @@ module Api
447 449 end
448 450  
449 451 def asset_with_image params
450   - if params.has_key? :image_builder
  452 + if !params.nil? && params.has_key?(:image_builder)
451 453 asset_api_params = params
452 454 asset_api_params[:image_builder] = base64_to_uploadedfile(asset_api_params[:image_builder])
453 455 return asset_api_params
454 456 end
455   - params
  457 + params
456 458 end
457 459  
458 460 def base64_to_uploadedfile(base64_image)
... ... @@ -503,11 +505,9 @@ module Api
503 505  
504 506 def parse_content_type(content_type)
505 507 return nil if content_type.blank?
506   - content_types = content_type.split(',').map do |content_type|
507   - content_type = content_type.camelcase
508   - content_type == 'TextArticle' ? Article.text_article_types : content_type
  508 + content_type.split(',').map do |content_type|
  509 + content_type.camelcase
509 510 end
510   - content_types.flatten.uniq
511 511 end
512 512  
513 513 def period(from_date, until_date)
... ...
app/api/v1/articles.rb
... ... @@ -284,7 +284,7 @@ module Api
284 284  
285 285 if params[:path].present?
286 286 article = profile.articles.find_by path: params[:path]
287   - if !article || !article.display_to?(current_person)
  287 + if article && !article.display_to?(current_person)
288 288 article = forbidden!
289 289 end
290 290  
... ...
app/api/v1/blocks.rb
... ... @@ -6,6 +6,7 @@ module Api
6 6 get ':id' do
7 7 block = Block.find(params["id"])
8 8 return forbidden! unless block.visible_to_user?(current_person) || block.allow_edit?(current_person)
  9 + block.api_content_params = params.except("id")
9 10 present block, :with => Entities::Block, display_api_content: true, current_person: current_person
10 11 end
11 12  
... ...
app/api/v1/communities.rb
... ... @@ -18,7 +18,7 @@ module Api
18 18 communities = select_filtered_collection_of(environment, 'communities', params)
19 19 communities = profiles_for_person(communities, current_person)
20 20 communities = communities.by_location(params) # Must be the last. May return Exception obj
21   - present communities, :with => Entities::Community, :current_person => current_person
  21 + present communities, :with => Entities::Community, :current_person => current_person, :params => params
22 22 end
23 23  
24 24  
... ... @@ -49,7 +49,7 @@ module Api
49 49  
50 50 get ':id' do
51 51 community = profiles_for_person(environment.communities, current_person).find_by_id(params[:id])
52   - present community, :with => Entities::Community, :current_person => current_person
  52 + present community, :with => Entities::Community, :current_person => current_person, :params => params
53 53 end
54 54  
55 55 end
... ...
app/api/v1/profiles.rb
... ... @@ -28,7 +28,7 @@ module Api
28 28 authenticate!
29 29 profile = environment.profiles.find_by(id: params[:id])
30 30 return forbidden! unless profile.allow_edit?(current_person)
31   - profile.update_attributes!(params[:profile])
  31 + profile.update_attributes!(asset_with_image(params[:profile]))
32 32 present profile, :with => Entities::Profile, :current_person => current_person
33 33 end
34 34  
... ...
app/api/v1/session.rb
... ... @@ -174,14 +174,13 @@ module Api
174 174 # Example Request:
175 175 # PATCH /new_password?code=xxxx&password=secret&password_confirmation=secret
176 176 patch "/new_password" do
177   - change_password = ChangePassword.find_by code: params[:code]
178   - not_found! if change_password.nil?
179   -
180   - if change_password.update_attributes(:password => params[:password], :password_confirmation => params[:password_confirmation])
  177 + begin
  178 + change_password = ChangePassword.find_by! code: params[:code]
  179 + change_password.update_attributes!(:password => params[:password], :password_confirmation => params[:password_confirmation])
181 180 change_password.finish
182 181 present change_password.requestor.user, :with => Entities::UserLogin, :current_person => current_person
183   - else
184   - something_wrong!
  182 + rescue Exception => ex
  183 + render_api_error!(ex.message, 400)
185 184 end
186 185 end
187 186  
... ...
app/controllers/my_profile/cms_controller.rb
... ... @@ -146,11 +146,14 @@ class CmsController &lt; MyProfileController
146 146 parent = check_parent(params[:parent_id])
147 147 if parent
148 148 @article.parent = parent
  149 + @article.published = parent.published
  150 + @article.show_to_followers = parent.show_to_followers
149 151 @parent_id = parent.id
150 152 end
151 153  
152 154 @article.profile = profile
153 155 @article.author = user
  156 + @article.editor = current_person.editor
154 157 @article.last_changed_by = user
155 158 @article.created_by = user
156 159  
... ... @@ -399,8 +402,7 @@ class CmsController &lt; MyProfileController
399 402  
400 403 def available_article_types
401 404 articles = [
402   - TinyMceArticle,
403   - TextileArticle,
  405 + TextArticle,
404 406 Event
405 407 ]
406 408 articles += special_article_types if params && params[:cms]
... ... @@ -408,9 +410,6 @@ class CmsController &lt; MyProfileController
408 410 if @parent && @parent.blog?
409 411 articles -= Article.folder_types.map(&:constantize)
410 412 end
411   - if user.is_admin?(profile.environment)
412   - articles << RawHTMLArticle
413   - end
414 413 articles
415 414 end
416 415  
... ...
app/controllers/my_profile/profile_editor_controller.rb
... ... @@ -12,7 +12,7 @@ class ProfileEditorController &lt; MyProfileController
12 12 include CategoriesHelper
13 13  
14 14 def index
15   - @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)}
  15 + @pending_tasks = Task.to(profile).pending.without_spam
16 16 @show_appearance_option = user.is_admin?(environment) || environment.enabled?('enable_appearance')
17 17 @show_header_footer_option = user.is_admin?(environment) || (!profile.enterprise? && !environment.enabled?('disable_header_and_footer'))
18 18 end
... ... @@ -95,7 +95,7 @@ class ProfileEditorController &lt; MyProfileController
95 95 end
96 96  
97 97 def welcome_page
98   - @welcome_page = profile.welcome_page || TinyMceArticle.new(:name => 'Welcome Page', :profile => profile, :published => false)
  98 + @welcome_page = profile.welcome_page || TextArticle.new(:name => 'Welcome Page', :profile => profile, :published => false)
99 99 if request.post?
100 100 begin
101 101 @welcome_page.update!(params[:welcome_page])
... ...
app/controllers/public/account_controller.rb
... ... @@ -164,6 +164,7 @@ class AccountController &lt; ApplicationController
164 164 def logout
165 165 if logged_in?
166 166 self.current_user.forget_me
  167 + current_user.update({:chat_status_at => DateTime.now}.merge({:last_chat_status => current_user.chat_status, :chat_status => 'offline'}))
167 168 end
168 169 reset_session
169 170 session[:notice] = _("You have been logged out.")
... ...
app/controllers/public/chat_controller.rb
... ... @@ -113,8 +113,20 @@ class ChatController &lt; PublicController
113 113 end
114 114  
115 115 #TODO Ideally this is done through roster table on ejabberd.
116   - def roster_groups
117   - render :text => user.memberships.map {|m| {:jid => m.jid, :name => m.name}}.to_json
  116 + def rosters
  117 + rooms = user.memberships.map {|m| {:jid => m.jid, :name => m.name}}
  118 + friends = user.friends.map {|f| {:jid => f.jid, :name => f.name}}
  119 + rosters = {:rooms => rooms, :friends => friends}
  120 + render :text => rosters.to_json
  121 + end
  122 +
  123 + def availabilities
  124 + availabilities = user.friends.map do |friend|
  125 + status = friend.user.chat_status
  126 + status = 'offline' if status.blank?
  127 + {:jid => friend.jid, :status => status}
  128 + end
  129 + render :text => availabilities.to_json
118 130 end
119 131  
120 132 protected
... ...
app/controllers/public/invite_controller.rb
... ... @@ -98,6 +98,8 @@ class InviteController &lt; PublicController
98 98 scope = profile.invite_friends_only ? user.friends : environment.people
99 99 scope = scope.not_members_of(profile) if profile.organization?
100 100 scope = scope.not_friends_of(profile) if profile.person?
  101 + scope = scope.distinct(false).group("profiles.id")
  102 +
101 103 results = find_by_contents(:people, environment, scope, params['q'], {:page => 1}, {:joins => :user})[:results]
102 104 render :text => prepare_to_token_input(results).to_json
103 105 end
... ...
app/controllers/public/profile_controller.rb
... ... @@ -13,12 +13,13 @@ class ProfileController &lt; PublicController
13 13  
14 14 protect 'send_mail_to_members', :profile, :only => [:send_mail]
15 15  
  16 + ACTIVITIES_PER_PAGE = 15
  17 +
16 18 def index
17   - @network_activities = !@profile.is_a?(Person) ? @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) : []
18   - if logged_in? && current_person.follows?(@profile)
19   - @network_activities = @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) if @network_activities.empty?
20   - @activities = @profile.activities.paginate(:per_page => 15, :page => params[:page])
21   - end
  19 + @offsets = {:wall => 0, :network => 0}
  20 + page = (params[:page] || 1).to_i
  21 + @network_activities = loop_fetch_activities(@profile.tracked_notifications, :network, page) if !@profile.is_a?(Person) || follow_profile?
  22 + @activities = loop_fetch_activities(@profile.activities, :wall, page) if follow_profile?
22 23 @tags = profile.article_tags
23 24 allow_access_to_page
24 25 end
... ... @@ -231,6 +232,7 @@ class ProfileController &lt; PublicController
231 232 @scrap = Scrap.new(params[:scrap])
232 233 @scrap.sender= sender
233 234 @scrap.receiver= receiver