Compare View
Commits (128)
-
should task endpoints be accessed only by logged users See merge request !980
-
Signed-off-by: Alessandro Caetano <alessandro.caetanob@gmail.com> Signed-off-by: Artur Bersan de Faria <arturbersan@gmail.com> Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> Signed-off-by: Matheus Miranda <matheusmirandalacerda@gmail.com> Signed-off-by: Sabryna Sousa <sabryna.sousa1323@gmail.com> Signed-off-by: Victor Matias Navarro <victor.matias.navarro@gmail.com> Signed-off-by: Vitor Barbosa <vitormga15@gmail.com>
-
Concern needs to be included before first use of setting items
-
Lists and edits followers and circles in control panel of profile that is being viewed instead of logged in person. Also unfollow person in control panel based on current viewed profile instead of current logged in user. This is necessary because sometimes an environment admin is editing someone else's profile and those actions should be performed on that profile instead of admin's profile.
-
Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com>
-
Profile followers feature Signed-off-by: Alessandro Caetano <alessandro.caetanob@gmail.com> Signed-off-by: Artur Bersan de Faria <arturbersan@gmail.com> Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> Signed-off-by: Matheus Miranda <matheusmirandalacerda@gmail.com> Signed-off-by: Sabryna Sousa <sabryna.sousa1323@gmail.com> Signed-off-by: Victor Matias Navarro <victor.matias.navarro@gmail.com> Signed-off-by: Vitor Barbosa <vitormga15@gmail.com> See merge request !976
-
We now remove profile_follewers if its circle is deleted
-
comment_paragraph: change filename of exported comments See merge request !966
-
Signed-off-by: Paulo Tada <paulohtfs@gmail.com> Signed-off-by: Tallys Martins <tallysmartins@gmail.com>
-
Adds public fields to Profile API Signed-off-by: Paulo Tada <paulohtfs@gmail.com> Signed-off-by: Tallys Martins <tallysmartins@gmail.com> See merge request !981
-
- Environments and profiles now return the layout template used. Signed-off-by: Tallys Martins <tallysmartins@gmail.com>
-
Display layout_template on api - Environments and profiles now return the layout template used. @marcosronaldo can you take a look at this? We'll use it on angular theme. See merge request !968
-
Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com>
-
Organization_ratings: Show rejected message to admins Show rejected message to admins on organization_ratings plugin. Only environment admins can see the rejected message. Signed-off-by: Gabriel Silva <gabriel93.silva@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> See merge request !969
-
… recent activities of the profile who owns it
-
Recent activities Adding a plugin "recent_activities" which adds a block that list the recent activities of the profile who owns it: ![76](/uploads/000199ff2aaf4dd40f8f905ce11d884d/76.png) See merge request !972
-
The profile activities returns action trackers and scraps, but the scraps should not be displayed on recent activities block. Only the action tracker records Related to merge request !972
-
spaminator: update mailer to rails4 new scheme See merge request !971
-
api: add and remove members from profile See merge request !977
-
API - Environment entity new fields Added the fields `:signup_intro`, `:terms_of_use` and `:top_url` (exposed using `:host` alias) to `Environment` entity: See merge request !982
-
Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com> Signed-off-by: Victor Navarro <victor.matias.navarro@gmail.com> Signed-off-by: Vitor Barbosa <vitornga15@gmail.com>
-
Add endpoint to close task with status Signed-off-by: Victor Navarro <victor.matias.navarro@gmail.com> Signed-off-by: Vitor Barbosa <vitornga15@gmail.com> See merge request !939
-
api: list all pending tasks for the current person See merge request !979
-
api: return organization roles See merge request !983
-
api: accept parameters to update a task when accept/reject See merge request !984
-
Create elasticsearch structure Index models for elasticsearch Adding category search filter Make query generic Add README.md for elasticsearch plugin Start tests with rspec for elasticsearch Applyng filtering by type on articles Adding visible filter Signed-off-by: Lucas Moura <lucas.moura128@gmail.com> Signed-off-by: Luciano Prestes Cavalcanti <lucianopcbr@gmail.com> Signed-off-by: Macartur Sousa <macartur.sc@gmail.com> Signed-off-by: Daniel Henrique <danielhmarinho@gmail.com>
-
Rakefile to download and install elasticsearch Adding rubygems.org as source for Gemfile Removing trailing whitespace Updating install instructions Elasticsearch depends on openjdk-7-jdk
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
redirect index -> search action removing models extensions that are removed from core renaming elasticsearch helper to a better name (now, working as well) model extensions working with the new helper name check :weight exists refactoring models extensions
-
Adding community.rb and fixing searchable_fields Adding regex filter Add person & gallery to allow search on those models Show all results when query is empty Signed-off-by: Daniel Henrique <danielhmarinho@gmail.com> Signed-off-by: David Carlos <ddavidcarlos1392@gmail.com>
-
Signed-off-by: Daniel Henrique <danielhmarinho@gmail.com> Signed-off-by: David Carlos <ddavidcarlos1392@gmail.com>
-
* Person * Community * TextArticle * Event * UploadedFile
-
Create initial style of elasticsearch, and refectored html Changes style of elasticsearch plugin, add variable to store search types. Adds style for communities partial. Adds person partial style Adding event to models and adding styles Refactored search controller and view - Changed search-form to use get instead of post - Uses search method directly in models - Refactored process results - Adding pagination Removed hardcode name from community view Signed-off-by: DylanGuedes <djmgguedes@gmail.com> Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Arthur Jahn <stutrzbecher@gmail.com> Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Arthur Jahn <stutrzbecher@gmail.com> Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Arthur Jahn <stutrzbecher@gmail.com> Signed-off-by: DylanGuedes <djmgguedes@gmail.com>
-
Signed-off-by: Dylan Guedes <djmgguedes@gmail.com> Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Dylan Guedes <djmgguedes@gmail.com> Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Adding tests to elasticsearch controller Adding ElasticsearchTestHelper Fixed model tests Adding tests and refactored control_fields indexed Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Fixes minor bugs in style, adds link-to to search results, and translations
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Adding Elasticsearch_helper Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com> Signed-off-by: Marcos Ronaldo <marcos.rpj2@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Adding views to uploaded_files and text_articles Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Sort documents by name Adds lexical sort for searchs without expression Sort by name.raw instead of name Indexes models by raw nested in name, remove suggests Fixes tests and alphabetical ordering Adds created at as a type of sort Fixing search using sort by Fixed Sort by to receive filter param Fixed noosfero to be support noosfero links Fixed text_articles and upload_files extensions Fixed api tests Refactored elasticsearch_plugin and elasticsearch_api Fixed to use partial query Fixed sort and query_string Signed-off-by: Arthur Jahn <stutrzbecher@gmail.com> Signed-off-by: DylanGuedes <djmgguedes@gmail.com> Signed-off-by: Macartur Sousa <macartur.sc@gmail.com> Signed-off-by: David Carlos <ddavidcarlos1392@gmail.com>
-
related to #362 - fixes for search view makes css rules more specific Signed-off-by: Arthur Jahn <stutrzbecher@gmail.com> Signed-off-by: Daniel Henrique <danielhmarinho@gmail.com>
-
* Filter by environment * Filter by visible community Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Adding nested query: * NestedEnvironment * NestedProfile Adding bool query: * should * must * must_not Moved elasticsearch_indexed_model to helpers folder Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
* Adding more_popular and more_active to Community and Person * Fixed Api to support dynamic filter Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
* Changed name from helpers to display sort_types * Adding dynamic sort to text_article * indexed category_ids to be used after Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com> Signed-off-by: Arthur Jahn <stutrzbecher@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: DylanGuedes <djmgguedes@gmail.com> Signed-off-by: Macartur de Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur de Sousa <macartur.sc@gmail.com> Signed-off-by: DylanGuedes <djmgguedes@gmail.com>
-
Signed-off-by: DylanGuedes <djmgguedes@gmail.com> Signed-off-by: Macartur de Sousa <macartur.sc@gmail.com>
-
Signed-off-by: DylanGuedes <djmgguedes@gmail.com>
-
Signed-off-by: DylanGuedes <djmgguedes@gmail.com> Signed-off-by: Macartur de Sousa <macartur.sc@gmail.com>
-
Signed-off-by: DylanGuedes <djmgguedes@gmail.com> Signed-off-by: Macartur de Sousa <macartur.sc@gmail.com>
-
Signed-off-by: DylanGuedes <djmgguedes@gmail.com>
-
Signed-off-by: DylanGuedes <djmgguedes@gmail.com> Signed-off-by: Macartur de Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
-
Signed-off-by: Macartur Sousa <macartur.sc@gmail.com>
Showing
341 changed files
Show diff stats
Too many changes.
To preserve performance only 100 of 341 files displayed.
app/api/app.rb
... | ... | @@ -54,6 +54,7 @@ module Api |
54 | 54 | mount V1::Blocks |
55 | 55 | mount V1::Profiles |
56 | 56 | mount V1::Activities |
57 | + mount V1::Roles | |
57 | 58 | |
58 | 59 | # hook point which allow plugins to add Grape::API extensions to Api::App |
59 | 60 | #finds for plugins which has api mount points classes defined (the class should extends Grape::API) | ... | ... |
app/api/entities.rb
... | ... | @@ -111,6 +111,10 @@ module Api |
111 | 111 | hash[value.custom_field.name]=value.value |
112 | 112 | end |
113 | 113 | |
114 | + profile.public_fields.each do |field| | |
115 | + hash[field] = profile.send(field.to_sym) | |
116 | + end | |
117 | + | |
114 | 118 | private_values = profile.custom_field_values - profile.public_values |
115 | 119 | private_values.each do |value| |
116 | 120 | if Entities.can_display_profile_field?(profile,options) |
... | ... | @@ -124,6 +128,7 @@ module Api |
124 | 128 | expose :type |
125 | 129 | expose :custom_header |
126 | 130 | expose :custom_footer |
131 | + expose :layout_template | |
127 | 132 | expose :permissions do |profile, options| |
128 | 133 | Entities.permissions_for_entity(profile, options[:current_person], |
129 | 134 | :allow_post_content?, :allow_edit?, :allow_destroy?) |
... | ... | @@ -258,12 +263,28 @@ module Api |
258 | 263 | root 'tasks', 'task' |
259 | 264 | expose :id |
260 | 265 | expose :type |
266 | + expose :requestor, using: Profile | |
267 | + expose :status | |
268 | + expose :created_at | |
269 | + expose :data | |
270 | + expose :accept_details | |
271 | + expose :reject_details | |
272 | + expose :accept_disabled?, as: :accept_disabled | |
273 | + expose :reject_disabled?, as: :reject_disabled | |
274 | + expose :target do |task, options| | |
275 | + type_map = {Profile => ::Profile, Environment => ::Environment}.find {|h| task.target.kind_of?(h.last)} | |
276 | + type_map.first.represent(task.target) unless type_map.nil? | |
277 | + end | |
261 | 278 | end |
262 | 279 | |
263 | 280 | class Environment < Entity |
264 | 281 | expose :name |
265 | 282 | expose :id |
266 | 283 | expose :description |
284 | + expose :layout_template | |
285 | + expose :signup_intro | |
286 | + expose :terms_of_use | |
287 | + expose :top_url, as: :host | |
267 | 288 | expose :settings, if: lambda { |instance, options| options[:is_admin] } |
268 | 289 | end |
269 | 290 | |
... | ... | @@ -281,5 +302,12 @@ module Api |
281 | 302 | type_map.first.represent(activity.target) unless type_map.nil? |
282 | 303 | end |
283 | 304 | end |
305 | + | |
306 | + class Role < Entity | |
307 | + root 'roles', 'role' | |
308 | + expose :id | |
309 | + expose :name | |
310 | + expose :key | |
311 | + end | |
284 | 312 | end |
285 | 313 | end | ... | ... |
app/api/helpers.rb
... | ... | @@ -4,7 +4,7 @@ require 'tempfile' |
4 | 4 | module Api |
5 | 5 | module Helpers |
6 | 6 | PRIVATE_TOKEN_PARAM = :private_token |
7 | - DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :identifier, :archived] | |
7 | + ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :identifier, :archived, :status] | |
8 | 8 | |
9 | 9 | include SanitizeParams |
10 | 10 | include Noosfero::Plugin::HotSpot |
... | ... | @@ -124,8 +124,8 @@ module Api |
124 | 124 | present_partial article, with: Entities::Article, params: params, current_person: current_person |
125 | 125 | end |
126 | 126 | |
127 | - def present_articles_for_asset(asset, method = 'articles') | |
128 | - articles = find_articles(asset, method) | |
127 | + def present_articles_for_asset(asset, method_or_relation = 'articles') | |
128 | + articles = find_articles(asset, method_or_relation) | |
129 | 129 | present_articles(articles) |
130 | 130 | end |
131 | 131 | |
... | ... | @@ -133,8 +133,8 @@ module Api |
133 | 133 | present_partial paginate(articles), :with => Entities::Article, :params => params, current_person: current_person |
134 | 134 | end |
135 | 135 | |
136 | - def find_articles(asset, method = 'articles') | |
137 | - articles = select_filtered_collection_of(asset, method, params) | |
136 | + def find_articles(asset, method_or_relation = 'articles') | |
137 | + articles = select_filtered_collection_of(asset, method_or_relation, params) | |
138 | 138 | if current_person.present? |
139 | 139 | articles = articles.display_filter(current_person, nil) |
140 | 140 | else |
... | ... | @@ -143,14 +143,17 @@ module Api |
143 | 143 | articles |
144 | 144 | end |
145 | 145 | |
146 | - def find_task(asset, id) | |
147 | - task = asset.tasks.find(id) | |
146 | + def find_task(asset, method_or_relation, id) | |
147 | + task = is_a_relation?(method_or_relation) ? method_or_relation : asset.send(method_or_relation) | |
148 | + task = task.find_by_id(id) | |
149 | + not_found! if task.blank? | |
148 | 150 | current_person.has_permission?(task.permission, asset) ? task : forbidden! |
149 | 151 | end |
150 | 152 | |
151 | 153 | def post_task(asset, params) |
152 | 154 | klass_type= params[:content_type].nil? ? 'Task' : params[:content_type] |
153 | 155 | return forbidden! unless klass_type.constantize <= Task |
156 | + return forbidden! if !current_person.has_permission?(:perform_task, asset) | |
154 | 157 | |
155 | 158 | task = klass_type.constantize.new(params[:task]) |
156 | 159 | task.requestor_id = current_person.id |
... | ... | @@ -163,15 +166,24 @@ module Api |
163 | 166 | present_partial task, :with => Entities::Task |
164 | 167 | end |
165 | 168 | |
166 | - def present_task(asset) | |
167 | - task = find_task(asset, params[:id]) | |
169 | + def find_tasks(asset, method_or_relation = 'tasks') | |
170 | + return forbidden! if !current_person.has_permission?(:perform_task, asset) | |
171 | + tasks = select_filtered_collection_of(asset, method_or_relation, params) | |
172 | + tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)} | |
173 | + tasks | |
174 | + end | |
175 | + | |
176 | + def present_task(asset, method_or_relation = 'tasks') | |
177 | + task = find_task(asset, method_or_relation, params[:id]) | |
168 | 178 | present_partial task, :with => Entities::Task |
169 | 179 | end |
170 | 180 | |
171 | - def present_tasks(asset) | |
172 | - tasks = select_filtered_collection_of(asset, 'tasks', params) | |
173 | - tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)} | |
174 | - return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset) | |
181 | + def present_tasks_for_asset(asset, method_or_relation = 'tasks') | |
182 | + tasks = find_tasks(asset, method_or_relation) | |
183 | + present_tasks(tasks) | |
184 | + end | |
185 | + | |
186 | + def present_tasks(tasks) | |
175 | 187 | present_partial tasks, :with => Entities::Task |
176 | 188 | end |
177 | 189 | |
... | ... | @@ -180,7 +192,6 @@ module Api |
180 | 192 | conditions = {} |
181 | 193 | from_date = DateTime.parse(parsed_params.delete(:from)) if parsed_params[:from] |
182 | 194 | until_date = DateTime.parse(parsed_params.delete(:until)) if parsed_params[:until] |
183 | - | |
184 | 195 | conditions[:type] = parse_content_type(parsed_params.delete(:content_type)) unless parsed_params[:content_type].nil? |
185 | 196 | |
186 | 197 | conditions[:created_at] = period(from_date, until_date) if from_date || until_date |
... | ... | @@ -190,7 +201,7 @@ module Api |
190 | 201 | end |
191 | 202 | |
192 | 203 | # changing make_order_with_parameters to avoid sql injection |
193 | - def make_order_with_parameters(object, method, params) | |
204 | + def make_order_with_parameters(object, method_or_relation, params) | |
194 | 205 | order = "created_at DESC" |
195 | 206 | unless params[:order].blank? |
196 | 207 | if params[:order].include? '\'' or params[:order].include? '"' |
... | ... | @@ -199,9 +210,9 @@ module Api |
199 | 210 | order = 'RANDOM()' |
200 | 211 | else |
201 | 212 | field_name, direction = params[:order].split(' ') |
202 | - assoc = object.class.reflect_on_association(method.to_sym) | |
203 | - if !field_name.blank? and assoc | |
204 | - if assoc.klass.attribute_names.include? field_name | |
213 | + assoc_class = extract_associated_classname(method_or_relation) | |
214 | + if !field_name.blank? and assoc_class | |
215 | + if assoc_class.attribute_names.include? field_name | |
205 | 216 | if direction.present? and ['ASC','DESC'].include? direction.upcase |
206 | 217 | order = "#{field_name} #{direction.upcase}" |
207 | 218 | end |
... | ... | @@ -212,12 +223,14 @@ module Api |
212 | 223 | return order |
213 | 224 | end |
214 | 225 | |
215 | - def make_timestamp_with_parameters_and_method(params, method) | |
226 | + def make_timestamp_with_parameters_and_method(params, method_or_relation) | |
216 | 227 | timestamp = nil |
217 | 228 | if params[:timestamp] |
218 | 229 | datetime = DateTime.parse(params[:timestamp]) |
219 | - table_name = method.to_s.singularize.camelize.constantize.table_name | |
220 | - timestamp = "#{table_name}.updated_at >= '#{datetime}'" | |
230 | + table_name = extract_associated_tablename(method_or_relation) | |
231 | + assoc_class = extract_associated_classname(method_or_relation) | |
232 | + date_atrr = assoc_class.attribute_names.include?('updated_at') ? 'updated_at' : 'created_at' | |
233 | + timestamp = "#{table_name}.#{date_atrr} >= '#{datetime}'" | |
221 | 234 | end |
222 | 235 | |
223 | 236 | timestamp |
... | ... | @@ -242,12 +255,12 @@ module Api |
242 | 255 | end |
243 | 256 | end |
244 | 257 | |
245 | - def select_filtered_collection_of(object, method, params) | |
258 | + def select_filtered_collection_of(object, method_or_relation, params) | |
246 | 259 | conditions = make_conditions_with_parameter(params) |
247 | - order = make_order_with_parameters(object,method,params) | |
248 | - timestamp = make_timestamp_with_parameters_and_method(params, method) | |
260 | + order = make_order_with_parameters(object,method_or_relation,params) | |
261 | + timestamp = make_timestamp_with_parameters_and_method(params, method_or_relation) | |
249 | 262 | |
250 | - objects = object.send(method) | |
263 | + objects = is_a_relation?(method_or_relation) ? method_or_relation : object.send(method_or_relation) | |
251 | 264 | objects = by_reference(objects, params) |
252 | 265 | objects = by_categories(objects, params) |
253 | 266 | |
... | ... | @@ -302,12 +315,12 @@ module Api |
302 | 315 | end |
303 | 316 | |
304 | 317 | def cant_be_saved_request!(attribute) |
305 | - message = _("(Invalid request) %s can't be saved") % attribute | |
318 | + message = _("(Invalid request) %s can't be saved").html_safe % attribute | |
306 | 319 | render_api_error!(message, 400) |
307 | 320 | end |
308 | 321 | |
309 | 322 | def bad_request!(attribute) |
310 | - message = _("(Invalid request) %s not given") % attribute | |
323 | + message = _("(Invalid request) %s not given").html_safe % attribute | |
311 | 324 | render_api_error!(message, 400) |
312 | 325 | end |
313 | 326 | |
... | ... | @@ -393,10 +406,27 @@ module Api |
393 | 406 | end |
394 | 407 | private |
395 | 408 | |
409 | + def extract_associated_tablename(method_or_relation) | |
410 | + extract_associated_classname(method_or_relation).table_name | |
411 | + end | |
412 | + | |
413 | + def extract_associated_classname(method_or_relation) | |
414 | + if is_a_relation?(method_or_relation) | |
415 | + method_or_relation.blank? ? '' : method_or_relation.first.class | |
416 | + else | |
417 | + method_or_relation.to_s.singularize.camelize.constantize | |
418 | + end | |
419 | + end | |
420 | + | |
421 | + def is_a_relation?(method_or_relation) | |
422 | + method_or_relation.kind_of?(ActiveRecord::Relation) | |
423 | + end | |
424 | + | |
425 | + | |
396 | 426 | def parser_params(params) |
397 | 427 | parsed_params = {} |
398 | 428 | params.map do |k,v| |
399 | - parsed_params[k.to_sym] = v if DEFAULT_ALLOWED_PARAMETERS.include?(k.to_sym) | |
429 | + parsed_params[k.to_sym] = v if ALLOWED_PARAMETERS.include?(k.to_sym) | |
400 | 430 | end |
401 | 431 | parsed_params |
402 | 432 | end | ... | ... |
app/api/v1/people.rb
... | ... | @@ -119,6 +119,20 @@ module Api |
119 | 119 | members = select_filtered_collection_of(profile, 'members', params) |
120 | 120 | present members, :with => Entities::Person, :current_person => current_person |
121 | 121 | end |
122 | + | |
123 | + post do | |
124 | + authenticate! | |
125 | + profile = environment.profiles.find_by id: params[:profile_id] | |
126 | + profile.add_member(current_person) rescue forbidden! | |
127 | + {pending: !current_person.is_member_of?(profile)} | |
128 | + end | |
129 | + | |
130 | + delete do | |
131 | + authenticate! | |
132 | + profile = environment.profiles.find_by id: params[:profile_id] | |
133 | + profile.remove_member(current_person) | |
134 | + present current_person, :with => Entities::Person, :current_person => current_person | |
135 | + end | |
122 | 136 | end |
123 | 137 | end |
124 | 138 | end | ... | ... |
... | ... | @@ -0,0 +1,25 @@ |
1 | +module Api | |
2 | + module V1 | |
3 | + class Roles < Grape::API | |
4 | + before { authenticate! } | |
5 | + | |
6 | + MAX_PER_PAGE = 50 | |
7 | + | |
8 | + resource :profiles do | |
9 | + segment "/:profile_id" do | |
10 | + resource :roles do | |
11 | + | |
12 | + paginate max_per_page: MAX_PER_PAGE | |
13 | + get do | |
14 | + profile = environment.profiles.find(params[:profile_id]) | |
15 | + return forbidden! unless profile.kind_of?(Organization) | |
16 | + roles = Profile::Roles.organization_roles(profile.environment.id, profile.id) | |
17 | + present_partial paginate(roles), with: Entities::Role | |
18 | + end | |
19 | + | |
20 | + end | |
21 | + end | |
22 | + end | |
23 | + end | |
24 | + end | |
25 | +end | ... | ... |
app/api/v1/tasks.rb
1 | 1 | module Api |
2 | 2 | module V1 |
3 | 3 | class Tasks < Grape::API |
4 | -# before { authenticate! } | |
4 | + before { authenticate! } | |
5 | 5 | |
6 | -# ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} | |
6 | + MAX_PER_PAGE = 50 | |
7 | 7 | |
8 | 8 | resource :tasks do |
9 | 9 | |
10 | - # Collect tasks | |
10 | + paginate max_per_page: MAX_PER_PAGE | |
11 | + # Collect all tasks that current person has permission | |
11 | 12 | # |
12 | 13 | # Parameters: |
13 | 14 | # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created |
... | ... | @@ -17,15 +18,27 @@ module Api |
17 | 18 | # Example Request: |
18 | 19 | # GET host/api/v1/tasks?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317 |
19 | 20 | get do |
20 | - tasks = select_filtered_collection_of(environment, 'tasks', params) | |
21 | - tasks = tasks.select {|t| current_person.has_permission?(t.permission, environment)} | |
22 | - present_partial tasks, :with => Entities::Task | |
21 | + tasks = Task.to(current_person) | |
22 | + present_tasks_for_asset(current_person, tasks) | |
23 | 23 | end |
24 | 24 | |
25 | 25 | desc "Return the task id" |
26 | 26 | get ':id' do |
27 | - task = find_task(environment, params[:id]) | |
28 | - present_partial task, :with => Entities::Task | |
27 | + present_task(current_person, Task.to(current_person)) | |
28 | + end | |
29 | + | |
30 | + %w[finish cancel].each do |action| | |
31 | + desc "#{action.capitalize} a task" | |
32 | + put ":id/#{action}" do | |
33 | + task = find_task(current_person, Task.to(current_person), params[:id]) | |
34 | + begin | |
35 | + task.update(params[:task]) | |
36 | + task.send(action, current_person) if (task.status == Task::Status::ACTIVE) | |
37 | + present_partial task, :with => Entities::Task | |
38 | + rescue Exception => ex | |
39 | + render_api_error!(ex.message, 500) | |
40 | + end | |
41 | + end | |
29 | 42 | end |
30 | 43 | end |
31 | 44 | |
... | ... | @@ -36,7 +49,8 @@ module Api |
36 | 49 | resource :tasks do |
37 | 50 | get do |
38 | 51 | profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) |
39 | - present_tasks(profile) | |
52 | + tasks = Task.to(profile) | |
53 | + present_tasks_for_asset(profile, tasks) | |
40 | 54 | end |
41 | 55 | |
42 | 56 | get ':id' do | ... | ... |
app/controllers/admin/categories_controller.rb
... | ... | @@ -44,7 +44,7 @@ class CategoriesController < AdminController |
44 | 44 | if request.post? |
45 | 45 | @category.update!(params[:category]) |
46 | 46 | @saved = true |
47 | - session[:notice] = _("Category %s saved." % @category.name) | |
47 | + session[:notice] = _("Category %s saved." % @category.name).html_safe | |
48 | 48 | redirect_to :action => 'index' |
49 | 49 | end |
50 | 50 | rescue Exception => e | ... | ... |
app/controllers/application_controller.rb
... | ... | @@ -14,6 +14,20 @@ class ApplicationController < ActionController::Base |
14 | 14 | before_filter :redirect_to_current_user |
15 | 15 | |
16 | 16 | before_filter :set_session_theme |
17 | + | |
18 | + # FIXME: only include necessary methods | |
19 | + include ApplicationHelper | |
20 | + | |
21 | + # concerns | |
22 | + include PermissionCheck | |
23 | + include CustomDesign | |
24 | + include NeedsProfile | |
25 | + | |
26 | + # implementations | |
27 | + include FindByContents | |
28 | + include Noosfero::Plugin::HotSpot | |
29 | + include SearchTermHelper | |
30 | + | |
17 | 31 | def set_session_theme |
18 | 32 | if params[:theme] |
19 | 33 | session[:theme] = environment.theme_ids.include?(params[:theme]) ? params[:theme] : nil |
... | ... | @@ -48,7 +62,6 @@ class ApplicationController < ActionController::Base |
48 | 62 | end |
49 | 63 | end |
50 | 64 | |
51 | - include ApplicationHelper | |
52 | 65 | layout :get_layout |
53 | 66 | def get_layout |
54 | 67 | return false if request.format == :js or request.xhr? |
... | ... | @@ -74,9 +87,6 @@ class ApplicationController < ActionController::Base |
74 | 87 | helper :document |
75 | 88 | helper :language |
76 | 89 | |
77 | - include DesignHelper | |
78 | - include PermissionCheck | |
79 | - | |
80 | 90 | before_filter :set_locale |
81 | 91 | def set_locale |
82 | 92 | FastGettext.available_locales = environment.available_locales |
... | ... | @@ -89,8 +99,6 @@ class ApplicationController < ActionController::Base |
89 | 99 | end |
90 | 100 | end |
91 | 101 | |
92 | - include NeedsProfile | |
93 | - | |
94 | 102 | attr_reader :environment |
95 | 103 | |
96 | 104 | # declares that the given <tt>actions</tt> cannot be accessed by other HTTP |
... | ... | @@ -107,6 +115,10 @@ class ApplicationController < ActionController::Base |
107 | 115 | |
108 | 116 | protected |
109 | 117 | |
118 | + def accept_only_post | |
119 | + return render_not_found if !request.post? | |
120 | + end | |
121 | + | |
110 | 122 | def verified_request? |
111 | 123 | super || form_authenticity_token == request.headers['X-XSRF-TOKEN'] |
112 | 124 | end |
... | ... | @@ -151,8 +163,6 @@ class ApplicationController < ActionController::Base |
151 | 163 | end |
152 | 164 | end |
153 | 165 | |
154 | - include Noosfero::Plugin::HotSpot | |
155 | - | |
156 | 166 | # FIXME this filter just loads @plugins to children controllers and helpers |
157 | 167 | def init_noosfero_plugins |
158 | 168 | plugins |
... | ... | @@ -184,9 +194,6 @@ class ApplicationController < ActionController::Base |
184 | 194 | end |
185 | 195 | end |
186 | 196 | |
187 | - include SearchTermHelper | |
188 | - include FindByContents | |
189 | - | |
190 | 197 | def find_suggestions(query, context, asset, options={}) |
191 | 198 | plugins.dispatch_first(:find_suggestions, query, context, asset, options) |
192 | 199 | end | ... | ... |
app/controllers/box_organizer_controller.rb
... | ... | @@ -109,7 +109,7 @@ class BoxOrganizerController < ApplicationController |
109 | 109 | def show_block_type_info |
110 | 110 | type = params[:type] |
111 | 111 | if type.blank? || !available_blocks.map(&:name).include?(type) |
112 | - raise ArgumentError.new("Type %s is not allowed. Go away." % type) | |
112 | + raise ArgumentError.new("Type %s is not allowed. Go away.".html_safe % type) | |
113 | 113 | end |
114 | 114 | @block = type.constantize.new |
115 | 115 | @block.box = Box.new(:owner => boxes_holder) |
... | ... | @@ -122,7 +122,7 @@ class BoxOrganizerController < ApplicationController |
122 | 122 | |
123 | 123 | def new_block(type, box) |
124 | 124 | if !available_blocks.map(&:name).include?(type) |
125 | - raise ArgumentError.new("Type %s is not allowed. Go away." % type) | |
125 | + raise ArgumentError.new("Type %s is not allowed. Go away.".html_safe % type) | |
126 | 126 | end |
127 | 127 | block = type.constantize.new |
128 | 128 | box.blocks << block | ... | ... |
... | ... | @@ -0,0 +1,169 @@ |
1 | +module AuthenticatedSystem | |
2 | + | |
3 | + protected | |
4 | + | |
5 | + extend ActiveSupport::Concern | |
6 | + | |
7 | + included do | |
8 | + if self < ActionController::Base | |
9 | + around_filter :user_set_current | |
10 | + before_filter :override_user | |
11 | + before_filter :login_from_cookie | |
12 | + end | |
13 | + | |
14 | + # Inclusion hook to make #current_user and #logged_in? | |
15 | + # available as ActionView helper methods. | |
16 | + helper_method :current_user, :logged_in? | |
17 | + end | |
18 | + | |
19 | + # Returns true or false if the user is logged in. | |
20 | + # Preloads @current_user with the user model if they're logged in. | |
21 | + def logged_in? | |
22 | + current_user != nil | |
23 | + end | |
24 | + | |
25 | + # Accesses the current user from the session. | |
26 | + def current_user user_id = session[:user] | |
27 | + @current_user ||= begin | |
28 | + user = User.find_by id: user_id if user_id | |
29 | + user.session = session if user | |
30 | + User.current = user | |
31 | + user | |
32 | + end | |
33 | + end | |
34 | + | |
35 | + # Store the given user in the session. | |
36 | + def current_user=(new_user) | |
37 | + if new_user.nil? | |
38 | + session.delete(:user) | |
39 | + else | |
40 | + session[:user] = new_user.id | |
41 | + new_user.session = session | |
42 | + new_user.register_login | |
43 | + end | |
44 | + @current_user = User.current = new_user | |
45 | + end | |
46 | + | |
47 | + # See impl. from http://stackoverflow.com/a/2513456/670229 | |
48 | + def user_set_current | |
49 | + User.current = current_user | |
50 | + yield | |
51 | + ensure | |
52 | + # to address the thread variable leak issues in Puma/Thin webserver | |
53 | + User.current = nil | |
54 | + end | |
55 | + | |
56 | + # Check if the user is authorized. | |
57 | + # | |
58 | + # Override this method in your controllers if you want to restrict access | |
59 | + # to only a few actions or if you want to check if the user | |
60 | + # has the correct rights. | |
61 | + # | |
62 | + # Example: | |
63 | + # | |
64 | + # # only allow nonbobs | |
65 | + # def authorize? | |
66 | + # current_user.login != "bob" | |
67 | + # end | |
68 | + def authorized? | |
69 | + true | |
70 | + end | |
71 | + | |
72 | + # Filter method to enforce a login requirement. | |
73 | + # | |
74 | + # To require logins for all actions, use this in your controllers: | |
75 | + # | |
76 | + # before_filter :login_required | |
77 | + # | |
78 | + # To require logins for specific actions, use this in your controllers: | |
79 | + # | |
80 | + # before_filter :login_required, :only => [ :edit, :update ] | |
81 | + # | |
82 | + # To skip this in a subclassed controller: | |
83 | + # | |
84 | + # skip_before_filter :login_required | |
85 | + # | |
86 | + def login_required | |
87 | + username, passwd = get_auth_data | |
88 | + if username && passwd | |
89 | + self.current_user ||= User.authenticate(username, passwd) || nil | |
90 | + end | |
91 | + if logged_in? && authorized? | |
92 | + true | |
93 | + else | |
94 | + if params[:require_login_popup] | |
95 | + render :json => { :require_login_popup => true } | |
96 | + else | |
97 | + access_denied | |
98 | + end | |
99 | + end | |
100 | + end | |
101 | + | |
102 | + # Redirect as appropriate when an access request fails. | |
103 | + # | |
104 | + # The default action is to redirect to the login screen. | |
105 | + # | |
106 | + # Override this method in your controllers if you want to have special | |
107 | + # behavior in case the user is not authorized | |
108 | + # to access the requested action. For example, a popup window might | |
109 | + # simply close itself. | |
110 | + def access_denied | |
111 | + respond_to do |accepts| | |
112 | + accepts.html do | |
113 | + if request.xhr? | |
114 | + render :text => _('Access denied'), :status => 401 | |
115 | + else | |
116 | + store_location | |
117 | + redirect_to :controller => '/account', :action => 'login' | |
118 | + end | |
119 | + end | |
120 | + accepts.xml do | |
121 | + headers["Status"] = "Unauthorized" | |
122 | + headers["WWW-Authenticate"] = %(Basic realm="Web Password") | |
123 | + render :text => "Could't authenticate you", :status => '401 Unauthorized' | |
124 | + end | |
125 | + end | |
126 | + false | |
127 | + end | |
128 | + | |
129 | + # Store the URI of the current request in the session. | |
130 | + # | |
131 | + # We can return to this location by calling #redirect_back_or_default. | |
132 | + def store_location(location = request.url) | |
133 | + session[:return_to] = location | |
134 | + end | |
135 | + | |
136 | + # Redirect to the URI stored by the most recent store_location call or | |
137 | + # to the passed default. | |
138 | + def redirect_back_or_default(default) | |
139 | + if session[:return_to] | |
140 | + redirect_to(session.delete(:return_to)) | |
141 | + else | |
142 | + redirect_to(default) | |
143 | + end | |
144 | + end | |
145 | + | |
146 | + def override_user | |
147 | + return if params[:override_user].blank? | |
148 | + return unless logged_in? and user.is_admin? environment | |
149 | + @current_user = nil | |
150 | + current_user params[:override_user] | |
151 | + end | |
152 | + | |
153 | + # When called with before_filter :login_from_cookie will check for an :auth_token | |
154 | + # cookie and log the user back in if apropriate | |
155 | + def login_from_cookie | |
156 | + return if cookies[:auth_token].blank? or logged_in? | |
157 | + user = User.where(remember_token: cookies[:auth_token]).first | |
158 | + self.current_user = user if user and user.remember_token? | |
159 | + end | |
160 | + | |
161 | + private | |
162 | + @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization) | |
163 | + # gets BASIC auth info | |
164 | + def get_auth_data | |
165 | + auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) } | |
166 | + auth_data = request.env[auth_key].to_s.split unless auth_key.blank? | |
167 | + return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil] | |
168 | + end | |
169 | +end | ... | ... |
... | ... | @@ -0,0 +1,50 @@ |
1 | +module CustomDesign | |
2 | + | |
3 | + extend ActiveSupport::Concern | |
4 | + | |
5 | + included do | |
6 | + extend ClassMethods | |
7 | + include InstanceMethods | |
8 | + before_filter :load_custom_design if self.respond_to? :before_filter | |
9 | + end | |
10 | + | |
11 | + module ClassMethods | |
12 | + | |
13 | + def no_design_blocks | |
14 | + @no_design_blocks = true | |
15 | + end | |
16 | + | |
17 | + def use_custom_design options = {} | |
18 | + @custom_design = options | |
19 | + end | |
20 | + | |
21 | + def custom_design | |
22 | + @custom_design ||= {} | |
23 | + end | |
24 | + | |
25 | + def uses_design_blocks? | |
26 | + !@no_design_blocks | |
27 | + end | |
28 | + | |
29 | + end | |
30 | + | |
31 | + module InstanceMethods | |
32 | + | |
33 | + protected | |
34 | + | |
35 | + def uses_design_blocks? | |
36 | + !@no_design_blocks && self.class.uses_design_blocks? | |
37 | + end | |
38 | + | |
39 | + def load_custom_design | |
40 | + # see also: LayoutHelper#body_classes | |
41 | + @layout_template = self.class.custom_design[:layout_template] | |
42 | + end | |
43 | + | |
44 | + def custom_design | |
45 | + @custom_design || self.class.custom_design | |
46 | + end | |
47 | + | |
48 | + end | |
49 | + | |
50 | +end | ... | ... |
... | ... | @@ -0,0 +1,40 @@ |
1 | +module NeedsProfile | |
2 | + | |
3 | + module ClassMethods | |
4 | + def needs_profile | |
5 | + before_filter :load_profile | |
6 | + end | |
7 | + end | |
8 | + | |
9 | + def self.included(including) | |
10 | + including.send(:extend, NeedsProfile::ClassMethods) | |
11 | + end | |
12 | + | |
13 | + def boxes_holder | |
14 | + profile || environment # prefers profile, but defaults to environment | |
15 | + end | |
16 | + | |
17 | + def profile | |
18 | + @profile | |
19 | + end | |
20 | + | |
21 | + protected | |
22 | + | |
23 | + def load_profile | |
24 | + if params[:profile] | |
25 | + params[:profile].downcase! | |
26 | + @profile ||= environment.profiles.where(identifier: params[:profile]).first | |
27 | + end | |
28 | + | |
29 | + if @profile | |
30 | + profile_hostname = @profile.hostname | |
31 | + if profile_hostname && profile_hostname != request.host | |
32 | + params.delete(:profile) | |
33 | + redirect_to(Noosfero.url_options.merge(params).merge(:host => profile_hostname)) | |
34 | + end | |
35 | + else | |
36 | + render_not_found | |
37 | + end | |
38 | + end | |
39 | + | |
40 | +end | ... | ... |
... | ... | @@ -0,0 +1,58 @@ |
1 | +class CirclesController < MyProfileController | |
2 | + | |
3 | + before_action :accept_only_post, :only => [:create, :update, :destroy] | |
4 | + | |
5 | + def index | |
6 | + @circles = profile.circles | |
7 | + end | |
8 | + | |
9 | + def new | |
10 | + @circle = Circle.new | |
11 | + end | |
12 | + | |
13 | + def create | |
14 | + @circle = Circle.new(params[:circle].merge({ :person => profile })) | |
15 | + if @circle.save | |
16 | + redirect_to :action => 'index' | |
17 | + else | |
18 | + render :action => 'new' | |
19 | + end | |
20 | + end | |
21 | + | |
22 | + def xhr_create | |
23 | + if request.xhr? | |
24 | + circle = Circle.new(params[:circle].merge({:person => profile })) | |
25 | + if circle.save | |
26 | + render :partial => "circle_checkbox", :locals => { :circle => circle }, | |
27 | + :status => 201 | |
28 | + else | |
29 | + render :text => _('The circle could not be saved'), :status => 400 | |
30 | + end | |
31 | + else | |
32 | + render_not_found | |
33 | + end | |
34 | + end | |
35 | + | |
36 | + def edit | |
37 | + @circle = Circle.find_by_id(params[:id]) | |
38 | + render_not_found if @circle.nil? | |
39 | + end | |
40 | + | |
41 | + def update | |
42 | + @circle = Circle.find_by_id(params[:id]) | |
43 | + return render_not_found if @circle.nil? | |
44 | + | |
45 | + if @circle.update(params[:circle]) | |
46 | + redirect_to :action => 'index' | |
47 | + else | |
48 | + render :action => 'edit' | |
49 | + end | |
50 | + end | |
51 | + | |
52 | + def destroy | |
53 | + @circle = Circle.find_by_id(params[:id]) | |
54 | + return render_not_found if @circle.nil? | |
55 | + @circle.destroy | |
56 | + redirect_to :action => 'index' | |
57 | + end | |
58 | +end | ... | ... |
... | ... | @@ -0,0 +1,43 @@ |
1 | +class FollowersController < MyProfileController | |
2 | + | |
3 | + before_action :only_for_person, :only => :index | |
4 | + before_action :accept_only_post, :only => [:update_category] | |
5 | + | |
6 | + def index | |
7 | + @followed_people = profile.followed_profiles.order(:type) | |
8 | + @profile_types = {_('All profiles') => nil}.merge(Circle.profile_types).to_a | |
9 | + | |
10 | + if params['filter'].present? | |
11 | + @followed_people = @followed_people.where(:type => params['filter']) | |
12 | + @active_filter = params['filter'] | |
13 | + end | |
14 | + | |
15 | + @followed_people = @followed_people.paginate(:per_page => 15, :page => params[:npage]) | |
16 | + end | |
17 | + | |
18 | + def set_category_modal | |
19 | + followed_profile = Profile.find(params[:followed_profile_id]) | |
20 | + circles = Circle.where(:person => profile, :profile_type => followed_profile.class.name) | |
21 | + render :partial => 'followers/edit_circles_modal', :locals => { :circles => circles, :followed_profile => followed_profile } | |
22 | + end | |
23 | + | |
24 | + def update_category | |
25 | + followed_profile = Profile.find_by(:id => params["followed_profile_id"]) | |
26 | + | |
27 | + selected_circles = params[:circles].map{ |circle_name, circle_id| Circle.find_by(:id => circle_id) }.select{ |c| c.present? } | |
28 | + | |
29 | + if followed_profile | |
30 | + profile.update_profile_circles(followed_profile, selected_circles) | |
31 | + render :text => _("Circles of %s updated successfully") % followed_profile.name, :status => 200 | |
32 | + else | |
33 | + render :text => _("Error: No profile to follow."), :status => 400 | |
34 | + end | |
35 | + end | |
36 | + | |
37 | + protected | |
38 | + | |
39 | + def only_for_person | |
40 | + render_not_found unless profile.person? | |
41 | + end | |
42 | + | |
43 | +end | ... | ... |
app/controllers/my_profile/tasks_controller.rb
... | ... | @@ -14,7 +14,7 @@ class TasksController < MyProfileController |
14 | 14 | @filter_text = params[:filter_text].presence |
15 | 15 | @filter_responsible = params[:filter_responsible] |
16 | 16 | @task_types = Task.pending_types_for(profile) |
17 | - @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | |
17 | + @tasks = Task.pending_all_by_filter(profile, @filter_type, @filter_text).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | |
18 | 18 | @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present? |
19 | 19 | @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page]) |
20 | 20 | @failed = params ? params[:failed] : {} |
... | ... | @@ -101,7 +101,7 @@ class TasksController < MyProfileController |
101 | 101 | def search_tasks |
102 | 102 | filter_type = params[:filter_type].presence |
103 | 103 | filter_text = params[:filter_text].presence |
104 | - result = Task.pending_all(profile,filter_type, filter_text) | |
104 | + result = Task.pending_all_by_filter(profile,filter_type, filter_text) | |
105 | 105 | |
106 | 106 | render :json => result.map { |task| {:label => task.data[:name], :value => task.data[:name]} } |
107 | 107 | end | ... | ... |
app/controllers/public/account_controller.rb
... | ... | @@ -205,7 +205,7 @@ class AccountController < ApplicationController |
205 | 205 | if params[:value].blank? |
206 | 206 | @change_password.errors[:base] << _('Can not recover user password with blank value.') |
207 | 207 | else |
208 | - @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] | |
208 | + @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".').html_safe % [fields_label, params[:value]] | |
209 | 209 | end |
210 | 210 | rescue ActiveRecord::RecordInvalid |
211 | 211 | @change_password.errors[:base] << _('Could not perform password recovery for the user.') | ... | ... |
app/controllers/public/content_viewer_controller.rb
... | ... | @@ -128,9 +128,9 @@ class ContentViewerController < ApplicationController |
128 | 128 | end |
129 | 129 | |
130 | 130 | unless @page.display_to?(user) |
131 | - if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank? | |
131 | + if !profile.visible? || profile.secret? || (user && profile.in_social_circle?(user)) || user.blank? | |
132 | 132 | render_access_denied |
133 | - else #!profile.public? | |
133 | + else | |
134 | 134 | private_profile_partial_parameters |
135 | 135 | render :template => 'profile/_private_profile', :status => 403, :formats => [:html] |
136 | 136 | end | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -3,7 +3,9 @@ class ProfileController < PublicController |
3 | 3 | needs_profile |
4 | 4 | before_filter :check_access_to_profile, :except => [:join, :join_not_logged, :index, :add] |
5 | 5 | before_filter :store_location, :only => [:join, :join_not_logged, :report_abuse, :send_mail] |
6 | - before_filter :login_required, :only => [:add, :join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail] | |
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, :follow, :unfollow] | |
7 | + before_filter :allow_followers?, :only => [:follow, :unfollow] | |
8 | + before_filter :accept_only_post, :only => [:follow, :unfollow] | |
7 | 9 | |
8 | 10 | helper TagsHelper |
9 | 11 | helper ActionTrackerHelper |
... | ... | @@ -42,8 +44,8 @@ class ProfileController < PublicController |
42 | 44 | feed_writer = FeedWriter.new |
43 | 45 | data = feed_writer.write( |
44 | 46 | tagged, |
45 | - :title => _("%s's contents tagged with \"%s\"") % [profile.name, @tag], | |
46 | - :description => _("%s's contents tagged with \"%s\"") % [profile.name, @tag], | |
47 | + :title => _("%s's contents tagged with \"%s\"").html_safe % [profile.name, @tag], | |
48 | + :description => _("%s's contents tagged with \"%s\"").html_safe % [profile.name, @tag], | |
47 | 49 | :link => url_for(profile.url) |
48 | 50 | ) |
49 | 51 | render :text => data, :content_type => "text/xml" |
... | ... | @@ -65,6 +67,14 @@ class ProfileController < PublicController |
65 | 67 | end |
66 | 68 | end |
67 | 69 | |
70 | + def following | |
71 | + @followed_people = profile.followed_profiles.paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.followed_profiles.count) | |
72 | + end | |
73 | + | |
74 | + def followed | |
75 | + @followed_by = profile.followers.paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.followers.count) | |
76 | + end | |
77 | + | |
68 | 78 | def members |
69 | 79 | if is_cache_expired?(profile.members_cache_key(params)) |
70 | 80 | sort = (params[:sort] == 'desc') ? params[:sort] : 'asc' |
... | ... | @@ -88,7 +98,7 @@ class ProfileController < PublicController |
88 | 98 | |
89 | 99 | def join_modal |
90 | 100 | profile.add_member(user) |
91 | - session[:notice] = _('%s administrator still needs to accept you as member.') % profile.name | |
101 | + session[:notice] = _('%s administrator still needs to accept you as member.').html_safe % profile.name | |
92 | 102 | redirect_to :action => :index |
93 | 103 | end |
94 | 104 | |
... | ... | @@ -98,12 +108,12 @@ class ProfileController < PublicController |
98 | 108 | |
99 | 109 | profile.add_member(user) |
100 | 110 | if !profile.members.include?(user) |
101 | - render :text => {:message => _('%s administrator still needs to accept you as member.') % profile.name}.to_json | |
111 | + render :text => {:message => _('%s administrator still needs to accept you as member.').html_safe % profile.name}.to_json | |
102 | 112 | else |
103 | - render :text => {:message => _('You just became a member of %s.') % profile.name}.to_json | |
113 | + render :text => {:message => _('You just became a member of %s.').html_safe % profile.name}.to_json | |
104 | 114 | end |
105 | 115 | else |
106 | - render :text => {:message => _('You are already a member of %s.') % profile.name}.to_json | |
116 | + render :text => {:message => _('You are already a member of %s.').html_safe % profile.name}.to_json | |
107 | 117 | end |
108 | 118 | end |
109 | 119 | |
... | ... | @@ -125,7 +135,7 @@ class ProfileController < PublicController |
125 | 135 | render :text => current_person.leave(profile, params[:reload]) |
126 | 136 | end |
127 | 137 | else |
128 | - render :text => {:message => _('You are not a member of %s.') % profile.name}.to_json | |
138 | + render :text => {:message => _('You are not a member of %s.').html_safe % profile.name}.to_json | |
129 | 139 | end |
130 | 140 | end |
131 | 141 | |
... | ... | @@ -145,12 +155,41 @@ class ProfileController < PublicController |
145 | 155 | # FIXME this shouldn't be in Person model? |
146 | 156 | if !user.memberships.include?(profile) |
147 | 157 | AddFriend.create!(:person => user, :friend => profile) |
148 | - render :text => _('%s still needs to accept being your friend.') % profile.name | |
158 | + render :text => _('%s still needs to accept being your friend.').html_safe % profile.name | |
149 | 159 | else |
150 | - render :text => _('You are already a friend of %s.') % profile.name | |
160 | + render :text => _('You are already a friend of %s.').html_safe % profile.name | |
161 | + end | |
162 | + end | |
163 | + | |
164 | + def follow | |
165 | + if profile.followed_by?(current_person) | |
166 | + render :text => _("You are already following %s.") % profile.name, :status => 400 | |
167 | + else | |
168 | + selected_circles = params[:circles].map{ |circle_name, circle_id| Circle.find_by(:id => circle_id) }.select{ |c| c.present? } | |
169 | + if selected_circles.present? | |
170 | + current_person.follow(profile, selected_circles) | |
171 | + render :text => _("You are now following %s") % profile.name, :status => 200 | |
172 | + else | |
173 | + render :text => _("Select at least one circle to follow %s.") % profile.name, :status => 400 | |
174 | + end | |
151 | 175 | end |
152 | 176 | end |
153 | 177 | |
178 | + def find_profile_circles | |
179 | + circles = Circle.where(:person => current_person, :profile_type => profile.class.name) | |
180 | + render :partial => 'blocks/profile_info_actions/circles', :locals => { :circles => circles, :profile_types => Circle.profile_types.to_a } | |
181 | + end | |
182 | + | |
183 | + def unfollow | |
184 | + follower = params[:follower_id].present? ? Person.find_by(id: params[:follower_id]) : current_person | |
185 | + | |
186 | + if follower && follower.follows?(profile) | |
187 | + follower.unfollow(profile) | |
188 | + end | |
189 | + redirect_url = params["redirect_to"] ? params["redirect_to"] : profile.url | |
190 | + redirect_to redirect_url | |
191 | + end | |
192 | + | |
154 | 193 | def check_friendship |
155 | 194 | unless logged_in? |
156 | 195 | render :text => '' |
... | ... | @@ -178,7 +217,7 @@ class ProfileController < PublicController |
178 | 217 | def unblock |
179 | 218 | if current_user.person.is_admin?(profile.environment) |
180 | 219 | profile.unblock |
181 | - session[:notice] = _("You have unblocked %s successfully. ") % profile.name | |
220 | + session[:notice] = _("You have unblocked %s successfully. ").html_safe % profile.name | |
182 | 221 | redirect_to :controller => 'profile', :action => 'index' |
183 | 222 | else |
184 | 223 | message = _('You are not allowed to unblock enterprises in this environment.') |
... | ... | @@ -437,4 +476,8 @@ class ProfileController < PublicController |
437 | 476 | [:image, :domains, :preferred_domain, :environment] |
438 | 477 | end |
439 | 478 | |
479 | + def allow_followers? | |
480 | + render_not_found unless profile.allow_followers? | |
481 | + end | |
482 | + | |
440 | 483 | end | ... | ... |
app/helpers/action_tracker_helper.rb
... | ... | @@ -14,13 +14,23 @@ module ActionTrackerHelper |
14 | 14 | } |
15 | 15 | end |
16 | 16 | |
17 | + def new_follower_description ta | |
18 | + n_('has 1 new follower:<br />%{name}', 'has %{num} new followers:<br />%{name}', ta.get_follower_name.size).html_safe % { | |
19 | + num: ta.get_follower_name.size, | |
20 | + name: safe_join(ta.collect_group_with_index(:follower_name) do |n,i| | |
21 | + link_to image_tag(ta.get_follower_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/person-icon.png")), | |
22 | + ta.get_follower_url[i], title: n | |
23 | + end) | |
24 | + } | |
25 | + end | |
26 | + | |
17 | 27 | def join_community_description ta |
18 | - n_('has joined 1 community:<br />%{name}'.html_safe, 'has joined %{num} communities:<br />%{name}'.html_safe, ta.get_resource_name.size) % { | |
28 | + n_('has joined 1 community:<br />%{name}', 'has joined %{num} communities:<br />%{name}', ta.get_resource_name.size).html_safe % { | |
19 | 29 | num: ta.get_resource_name.size, |
20 | - name: ta.collect_group_with_index(:resource_name) do |n,i| | |
30 | + name: safe_join(ta.collect_group_with_index(:resource_name) do |n,i| | |
21 | 31 | link = link_to image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")), |
22 | 32 | ta.get_resource_url[i], title: n |
23 | - end.join.html_safe | |
33 | + end) | |
24 | 34 | } |
25 | 35 | end |
26 | 36 | |
... | ... | @@ -68,9 +78,9 @@ module ActionTrackerHelper |
68 | 78 | end |
69 | 79 | |
70 | 80 | def favorite_enterprise_description ta |
71 | - _('favorited enterprise %{title}') % { | |
81 | + (_('favorited enterprise %{title}') % { | |
72 | 82 | title: link_to(truncate(ta.get_enterprise_name), ta.get_enterprise_url), |
73 | - } | |
83 | + }).html_safe | |
74 | 84 | end |
75 | 85 | |
76 | 86 | end | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -880,7 +880,7 @@ module ApplicationHelper |
880 | 880 | link_to_all = link_to(content_tag('strong', _('See all')), :controller => 'memberships', :profile => user.identifier) |
881 | 881 | end |
882 | 882 | link = list.map do |element| |
883 | - link_to(content_tag('strong', _('<span>Manage</span> %s') % element.short_name(25)), element.admin_url, :class => "icon-menu-"+element.class.identification.underscore, :title => _('Manage %s') % element.short_name) | |
883 | + link_to(content_tag('strong', _('<span>Manage</span> %s').html_safe % element.short_name(25)), element.admin_url, :class => "icon-menu-"+element.class.identification.underscore, :title => _('Manage %s').html_safe % element.short_name) | |
884 | 884 | end |
885 | 885 | if link_to_all |
886 | 886 | link << link_to_all |
... | ... | @@ -921,7 +921,7 @@ module ApplicationHelper |
921 | 921 | logout_link = link_to(logout_icon.html_safe, { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system")) |
922 | 922 | join_result = safe_join( |
923 | 923 | [welcome_span.html_safe, render_environment_features(:usermenu).html_safe, admin_link.html_safe, |
924 | - manage_enterprises.html_safe, manage_communities.html_safe, ctrl_panel_link.html_safe, | |
924 | + manage_enterprises, manage_communities, ctrl_panel_link.html_safe, | |
925 | 925 | pending_tasks_count.html_safe, logout_link.html_safe], "") |
926 | 926 | join_result |
927 | 927 | end | ... | ... |
app/helpers/boxes_helper.rb
... | ... | @@ -285,7 +285,7 @@ module BoxesHelper |
285 | 285 | end |
286 | 286 | |
287 | 287 | if block.respond_to?(:help) |
288 | - buttons << modal_inline_icon(:help, _('Help on this block'), {}, "#help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + modal_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}") | |
288 | + buttons << modal_inline_icon(:help, _('Help on this block'), {}, "#help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help.html_safe, :style => 'margin-bottom: 1em;') + modal_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}") | |
289 | 289 | end |
290 | 290 | |
291 | 291 | if block.embedable? | ... | ... |
app/helpers/forms_helper.rb
... | ... | @@ -128,14 +128,14 @@ module FormsHelper |
128 | 128 | counter += 1 |
129 | 129 | row << item |
130 | 130 | if counter % per_row == 0 |
131 | - rows << content_tag('tr', row.join("\n")) | |
131 | + rows << content_tag('tr', row.join("\n").html_safe) | |
132 | 132 | counter = 0 |
133 | 133 | row = [] |
134 | 134 | end |
135 | 135 | end |
136 | - rows << content_tag('tr', row.join("\n")) | |
136 | + rows << content_tag('tr', row.join("\n").html_safe) | |
137 | 137 | |
138 | - content_tag('table',rows.join("\n")) | |
138 | + content_tag('table',rows.join("\n").html_safe) | |
139 | 139 | end |
140 | 140 | |
141 | 141 | def date_field(name, value, datepicker_options = {}, html_options = {}) | ... | ... |
app/helpers/profile_helper.rb
... | ... | @@ -11,7 +11,7 @@ module ProfileHelper |
11 | 11 | PERSON_CATEGORIES[:location] = [:address, :address_reference, :zip_code, :city, :state, :district, :country, :nationality] |
12 | 12 | PERSON_CATEGORIES[:work] = [:organization, :organization_website, :professional_activity] |
13 | 13 | PERSON_CATEGORIES[:study] = [:schooling, :formation, :area_of_study] |
14 | - PERSON_CATEGORIES[:network] = [:friends, :communities, :enterprises] | |
14 | + PERSON_CATEGORIES[:network] = [:friends, :followers, :followed_profiles, :communities, :enterprises] | |
15 | 15 | PERSON_CATEGORIES.merge!(COMMON_CATEGORIES) |
16 | 16 | |
17 | 17 | ORGANIZATION_CATEGORIES = {} |
... | ... | @@ -42,7 +42,8 @@ module ProfileHelper |
42 | 42 | :created_at => _('Profile created at'), |
43 | 43 | :members_count => _('Members'), |
44 | 44 | :privacy_setting => _('Privacy setting'), |
45 | - :article_tags => _('Tags') | |
45 | + :article_tags => _('Tags'), | |
46 | + :followed_profiles => _('Following') | |
46 | 47 | } |
47 | 48 | |
48 | 49 | EXCEPTION = { |
... | ... | @@ -144,6 +145,14 @@ module ProfileHelper |
144 | 145 | link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url) |
145 | 146 | end |
146 | 147 | |
148 | + def treat_followers(followers) | |
149 | + link_to(profile.followers.count, {:action=>"followed", :controller=>"profile", :profile=>"#{profile.identifier}"}) | |
150 | + end | |
151 | + | |
152 | + def treat_followed_profiles(followed_profiles) | |
153 | + link_to(profile.followed_profiles.count, {:action=>"following", :controller=>"profile", :profile=>"#{profile.identifier}"}) | |
154 | + end | |
155 | + | |
147 | 156 | def treat_events(events) |
148 | 157 | link_to events.published.count, :controller => 'events', :action => 'events' |
149 | 158 | end | ... | ... |
app/jobs/notify_activity_to_profiles_job.rb
... | ... | @@ -19,8 +19,8 @@ class NotifyActivityToProfilesJob < Struct.new(:tracked_action_id) |
19 | 19 | # Notify the user |
20 | 20 | ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id) |
21 | 21 | |
22 | - # Notify all friends | |
23 | - ActionTrackerNotification.connection.execute("insert into action_tracker_notifications(profile_id, action_tracker_id) select f.friend_id, #{tracked_action.id} from friendships as f where person_id=#{tracked_action.user.id} and f.friend_id not in (select atn.profile_id from action_tracker_notifications as atn where atn.action_tracker_id = #{tracked_action.id})") | |
22 | + # Notify all followers | |
23 | + ActionTrackerNotification.connection.execute("INSERT INTO action_tracker_notifications(profile_id, action_tracker_id) SELECT DISTINCT c.person_id, #{tracked_action.id} FROM profiles_circles AS p JOIN circles as c ON c.id = p.circle_id WHERE p.profile_id = #{tracked_action.user.id} AND (c.person_id NOT IN (SELECT atn.profile_id FROM action_tracker_notifications AS atn WHERE atn.action_tracker_id = #{tracked_action.id}))") | |
24 | 24 | |
25 | 25 | if tracked_action.user.is_a? Organization |
26 | 26 | ActionTrackerNotification.connection.execute "insert into action_tracker_notifications(profile_id, action_tracker_id) " + | ... | ... |
app/mailers/contact.rb
... | ... | @@ -47,8 +47,8 @@ class Contact |
47 | 47 | content_type: 'text/html', |
48 | 48 | to: contact.dest.notification_emails, |
49 | 49 | reply_to: contact.email, |
50 | - subject: "[#{contact.dest.short_name(30)}] " + contact.subject, | |
51 | - from: "#{contact.name} <#{contact.dest.environment.noreply_email}>" | |
50 | + subject: "[#{contact.dest.short_name(30)}] #{contact.subject}".html_safe, | |
51 | + from: "#{contact.name} <#{contact.dest.environment.noreply_email}>".html_safe | |
52 | 52 | } |
53 | 53 | |
54 | 54 | if contact.sender | ... | ... |
app/mailers/environment_mailing.rb
app/mailers/mailing.rb
... | ... | @@ -2,7 +2,8 @@ require_dependency 'mailing_job' |
2 | 2 | |
3 | 3 | class Mailing < ApplicationRecord |
4 | 4 | |
5 | - acts_as_having_settings :field => :data | |
5 | + extend ActsAsHavingSettings::ClassMethods | |
6 | + acts_as_having_settings field: :data | |
6 | 7 | |
7 | 8 | attr_accessible :subject, :body, :data |
8 | 9 | |
... | ... | @@ -23,11 +24,11 @@ class Mailing < ApplicationRecord |
23 | 24 | end |
24 | 25 | |
25 | 26 | def generate_from |
26 | - "#{source.name} <#{if source.is_a? Environment then source.noreply_email else source.contact_email end}>" | |
27 | + "#{source.name} <#{if source.is_a? Environment then source.noreply_email else source.contact_email end}>".html_safe | |
27 | 28 | end |
28 | 29 | |
29 | 30 | def generate_subject |
30 | - '[%s] %s' % [source.name, subject] | |
31 | + '[%s] %s'.html_safe % [source.name, subject] | |
31 | 32 | end |
32 | 33 | |
33 | 34 | def signature_message | ... | ... |
app/mailers/organization_mailing.rb
app/mailers/pending_task_notifier.rb
... | ... | @@ -12,8 +12,8 @@ class PendingTaskNotifier < ApplicationMailer |
12 | 12 | |
13 | 13 | mail( |
14 | 14 | to: person.email, |
15 | - from: "#{person.environment.name} <#{person.environment.noreply_email}>", | |
16 | - subject: _("[%s] Pending tasks") % person.environment.name | |
15 | + from: "#{person.environment.name} <#{person.environment.noreply_email}>".html_safe, | |
16 | + subject: _("[%s] Pending tasks").html_safe % person.environment.name | |
17 | 17 | ) |
18 | 18 | end |
19 | 19 | ... | ... |
app/mailers/scrap_notifier.rb
... | ... | @@ -14,8 +14,8 @@ class ScrapNotifier < ApplicationMailer |
14 | 14 | @url = sender.environment.top_url |
15 | 15 | mail( |
16 | 16 | to: receiver.email, |
17 | - from: "#{sender.environment.name} <#{sender.environment.noreply_email}>", | |
18 | - subject: _("[%s] You received a scrap!") % [sender.environment.name] | |
17 | + from: "#{sender.environment.name} <#{sender.environment.noreply_email}>".html_safe, | |
18 | + subject: _("[%s] You received a scrap!").html_safe % [sender.environment.name] | |
19 | 19 | ) |
20 | 20 | end |
21 | 21 | end | ... | ... |
app/mailers/task_mailer.rb
... | ... | @@ -14,7 +14,7 @@ class TaskMailer < ApplicationMailer |
14 | 14 | mail( |
15 | 15 | to: task.target.notification_emails.compact, |
16 | 16 | from: self.class.generate_from(task), |
17 | - subject: "[%s] %s" % [task.environment.name, task.target_notification_description] | |
17 | + subject: "[%s] %s".html_safe % [task.environment.name, task.target_notification_description] | |
18 | 18 | ) |
19 | 19 | end |
20 | 20 | |
... | ... | @@ -27,7 +27,7 @@ class TaskMailer < ApplicationMailer |
27 | 27 | mail( |
28 | 28 | to: task.friend_email, |
29 | 29 | from: self.class.generate_from(task), |
30 | - subject: '[%s] %s' % [ task.requestor.environment.name, task.target_notification_description ] | |
30 | + subject: '[%s] %s'.html_safe % [ task.requestor.environment.name, task.target_notification_description ] | |
31 | 31 | ) |
32 | 32 | end |
33 | 33 | |
... | ... | @@ -43,7 +43,7 @@ class TaskMailer < ApplicationMailer |
43 | 43 | mail_with_template( |
44 | 44 | to: task.requestor.notification_emails, |
45 | 45 | from: self.class.generate_from(task), |
46 | - subject: '[%s] %s' % [task.requestor.environment.name, task.target_notification_description], | |
46 | + subject: '[%s] %s'.html_safe % [task.requestor.environment.name, task.target_notification_description], | |
47 | 47 | email_template: task.email_template, |
48 | 48 | template_params: {:environment => task.requestor.environment, :task => task, :message => @message, :url => @url, :requestor => task.requestor} |
49 | 49 | ) | ... | ... |
app/mailers/user_mailer.rb
... | ... | @@ -13,8 +13,8 @@ class UserMailer < ApplicationMailer |
13 | 13 | |
14 | 14 | mail( |
15 | 15 | to: user_email, |
16 | - from: "#{user.environment.name} <#{user.environment.contact_email}>", | |
17 | - subject: _("[%{environment}] Welcome to %{environment} mail!") % { :environment => user.environment.name } | |
16 | + from: "#{user.environment.name} <#{user.environment.contact_email}>".html_safe, | |
17 | + subject: _("[%{environment}] Welcome to %{environment} mail!").html_safe % { :environment => user.environment.name } | |
18 | 18 | ) |
19 | 19 | end |
20 | 20 | |
... | ... | @@ -30,7 +30,7 @@ class UserMailer < ApplicationMailer |
30 | 30 | mail_with_template( |
31 | 31 | from: "#{user.environment.name} <#{user.environment.contact_email}>", |
32 | 32 | to: user.email, |
33 | - subject: _("[%s] Activate your account") % [user.environment.name], | |
33 | + subject: _("[%s] Activate your account").html_safe % [user.environment.name], | |
34 | 34 | template_params: {:environment => user.environment, :activation_code => @activation_code, :redirection => @redirection, :join => @join, :person => user.person, :url => @url}, |
35 | 35 | email_template: user.environment.email_templates.find_by_template_type(:user_activation), |
36 | 36 | ) |
... | ... | @@ -44,8 +44,8 @@ class UserMailer < ApplicationMailer |
44 | 44 | mail( |
45 | 45 | content_type: 'text/html', |
46 | 46 | to: user.email, |
47 | - from: "#{user.environment.name} <#{user.environment.contact_email}>", | |
48 | - subject: email_subject.blank? ? _("Welcome to environment %s") % [user.environment.name] : email_subject, | |
47 | + from: "#{user.environment.name} <#{user.environment.contact_email}>".html_safe, | |
48 | + subject: email_subject.blank? ? _("Welcome to environment %s").html_safe % [user.environment.name] : email_subject, | |
49 | 49 | body: @body |
50 | 50 | ) |
51 | 51 | end |
... | ... | @@ -63,8 +63,8 @@ class UserMailer < ApplicationMailer |
63 | 63 | mail( |
64 | 64 | content_type: 'text/html', |
65 | 65 | to: user.email, |
66 | - from: "#{user.environment.name} <#{user.environment.contact_email}>", | |
67 | - subject: _("[%s] What about grow up your network?") % user.environment.name | |
66 | + from: "#{user.environment.name} <#{user.environment.contact_email}>".html_safe, | |
67 | + subject: _("[%s] What about grow up your network?").html_safe % user.environment.name | |
68 | 68 | ) |
69 | 69 | end |
70 | 70 | ... | ... |
app/models/abuse_complaint.rb
... | ... | @@ -25,7 +25,7 @@ class AbuseComplaint < Task |
25 | 25 | end |
26 | 26 | |
27 | 27 | def title |
28 | - abuse_reports.count > 1 ? (_('Abuse complaint (%s)') % abuse_reports.count) :_('Abuse complaint') | |
28 | + abuse_reports.count > 1 ? (_('Abuse complaint (%s)').html_safe % abuse_reports.count) :_('Abuse complaint') | |
29 | 29 | end |
30 | 30 | |
31 | 31 | def linked_subject |
... | ... | @@ -57,15 +57,15 @@ class AbuseComplaint < Task |
57 | 57 | end |
58 | 58 | |
59 | 59 | def task_activated_message |
60 | - _('Your profile was reported by the users of %s due to inappropriate behavior. The administrators of the environment are now reviewing the report. To solve this misunderstanding, please contact the administrators.') % environment.name | |
60 | + _('Your profile was reported by the users of %s due to inappropriate behavior. The administrators of the environment are now reviewing the report. To solve this misunderstanding, please contact the administrators.').html_safe % environment.name | |
61 | 61 | end |
62 | 62 | |
63 | 63 | def task_finished_message |
64 | - _('Your profile was disabled by the administrators of %s due to inappropriate behavior. To solve this misunderstanding please contact them.') % environment.name | |
64 | + _('Your profile was disabled by the administrators of %s due to inappropriate behavior. To solve this misunderstanding please contact them.').html_safe % environment.name | |
65 | 65 | end |
66 | 66 | |
67 | 67 | def target_notification_description |
68 | - _('%s was reported due to inappropriate behavior.') % reported.name | |
68 | + _('%s was reported due to inappropriate behavior.').html_safe % reported.name | |
69 | 69 | end |
70 | 70 | |
71 | 71 | def target_notification_message | ... | ... |
app/models/add_member.rb
... | ... | @@ -22,6 +22,7 @@ class AddMember < Task |
22 | 22 | self.roles = [Profile::Roles.member(organization.environment.id).id] |
23 | 23 | end |
24 | 24 | target.affiliate(requestor, self.roles.select{|r| !r.to_i.zero? }.map{|i| Role.find(i)}) |
25 | + person.follow(organization, Circle.find_or_create_by(:person => person, :name =>_('memberships'), :profile_type => 'Community')) | |
25 | 26 | end |
26 | 27 | |
27 | 28 | def title |
... | ... | @@ -56,7 +57,7 @@ class AddMember < Task |
56 | 57 | def target_notification_description |
57 | 58 | requestor_email = " (#{requestor.email})" if requestor.may_display_field_to?("email") |
58 | 59 | |
59 | - _("%{requestor}%{requestor_email} wants to be a member of '%{organization}'.") % {:requestor => requestor.name, :requestor_email => requestor_email, :organization => organization.name} | |
60 | + _("%{requestor}%{requestor_email} wants to be a member of '%{organization}'.").html_safe % {:requestor => requestor.name, :requestor_email => requestor_email, :organization => organization.name} | |
60 | 61 | end |
61 | 62 | |
62 | 63 | def target_notification_message | ... | ... |
app/models/article.rb
... | ... | @@ -13,7 +13,9 @@ class Article < ApplicationRecord |
13 | 13 | :image_builder, :show_to_followers, :archived, |
14 | 14 | :author, :display_preview, :published_at, :person_followers |
15 | 15 | |
16 | + extend ActsAsHavingImage::ClassMethods | |
16 | 17 | acts_as_having_image |
18 | + | |
17 | 19 | include Noosfero::Plugin::HotSpot |
18 | 20 | |
19 | 21 | SEARCHABLE_FIELDS = { |
... | ... | @@ -91,7 +93,8 @@ class Article < ApplicationRecord |
91 | 93 | has_many :article_categorizations_including_virtual, :class_name => 'ArticleCategorization' |
92 | 94 | has_many :categories_including_virtual, :through => :article_categorizations_including_virtual, :source => :category |
93 | 95 | |
94 | - acts_as_having_settings :field => :setting | |
96 | + extend ActsAsHavingSettings::ClassMethods | |