Commit 42b3475d1f217d929e20e076f1fffe0b7cf12cf7

Authored by Leandro Santos
2 parents fd06f939 bd70a538

Merge branch 'master' of gitlab.com:noosfero/noosfero

app/controllers/application_controller.rb
... ... @@ -184,13 +184,7 @@ class ApplicationController < ActionController::Base
184 184 end
185 185  
186 186 include SearchTermHelper
187   -
188   - def find_by_contents(asset, context, scope, query, paginate_options={:page => 1}, options={})
189   - scope = scope.with_templates(options[:template_id]) unless options[:template_id].blank?
190   - search = plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options)
191   - register_search_term(query, scope.count, search[:results].count, context, asset)
192   - search
193   - end
  187 + include FindByContents
194 188  
195 189 def find_suggestions(query, context, asset, options={})
196 190 plugins.dispatch_first(:find_suggestions, query, context, asset, options)
... ...
config/docker/dev/Dockerfile
... ... @@ -2,7 +2,7 @@
2 2 #
3 3 # VERSION 0.0.1
4 4  
5   -FROM debian:wheezy
  5 +FROM debian:jessie
6 6 MAINTAINER Noosfero Development Team <noosfero-dev@listas.softwarelivre.org>
7 7  
8 8 LABEL Description="This dockerfile builds a noosfero development environment."
... ... @@ -13,4 +13,6 @@ RUN git clone --depth 1 https://gitlab.com/noosfero/noosfero.git .
13 13  
14 14 RUN sh script/quick-start --skip-translations
15 15  
  16 +RUN service postgresql start && sleep 2 && ruby script/sample-data
  17 +
16 18 EXPOSE 3000
... ...
lib/create_thumbnails_job.rb
... ... @@ -3,5 +3,9 @@ class CreateThumbnailsJob &lt; Struct.new(:class_name, :file_id)
3 3 return unless class_name.constantize.exists?(file_id)
4 4 file = class_name.constantize.find(file_id)
5 5 file.create_thumbnails
  6 + article = Article.where(:image_id => file_id).first
  7 + if article
  8 + article.touch
  9 + end
6 10 end
7 11 end
... ...
lib/find_by_contents.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +module FindByContents
  2 +
  3 + def find_by_contents(asset, context, scope, query, paginate_options={:page => 1}, options={})
  4 + scope = scope.with_templates(options[:template_id]) unless options[:template_id].blank?
  5 + search = plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options)
  6 + register_search_term(query, scope.count, search[:results].count, context, asset)
  7 + search
  8 + end
  9 +
  10 +end
  11 +
... ...
lib/noosfero/api/api.rb
1 1 require 'grape'
2 2 #require 'rack/contrib'
3   -
4 3 Dir["#{Rails.root}/lib/noosfero/api/*.rb"].each {|file| require file unless file =~ /api\.rb/}
  4 +
5 5 module Noosfero
6 6 module API
7 7 class API < Grape::API
... ... @@ -17,7 +17,6 @@ module Noosfero
17 17 end
18 18  
19 19 @@NOOSFERO_CONF = nil
20   -
21 20 def self.NOOSFERO_CONF
22 21 if @@NOOSFERO_CONF
23 22 @@NOOSFERO_CONF
... ... @@ -27,9 +26,11 @@ module Noosfero
27 26 end
28 27 end
29 28  
  29 + before { set_locale }
30 30 before { setup_multitenancy }
31 31 before { detect_stuff_by_domain }
32 32 before { filter_disabled_plugins_endpoints }
  33 + before { init_noosfero_plugins }
33 34 after { set_session_cookie }
34 35  
35 36 version 'v1'
... ... @@ -41,11 +42,17 @@ module Noosfero
41 42  
42 43 mount V1::Articles
43 44 mount V1::Comments
  45 + mount V1::Users
44 46 mount V1::Communities
45 47 mount V1::People
46 48 mount V1::Enterprises
47 49 mount V1::Categories
48 50 mount V1::Tasks
  51 + mount V1::Tags
  52 + mount V1::Environments
  53 + mount V1::Search
  54 + mount V1::Contacts
  55 +
49 56 mount Session
50 57  
51 58 # hook point which allow plugins to add Grape::API extensions to API::API
... ...
lib/noosfero/api/entities.rb
... ... @@ -6,6 +6,35 @@ module Noosfero
6 6 date.strftime('%Y/%m/%d %H:%M:%S') if date
7 7 end
8 8  
  9 + PERMISSIONS = {
  10 + :admin => 0,
  11 + :self => 10,
  12 + :friend => 20,
  13 + :logged_user => 30,
  14 + :anonymous => 40
  15 + }
  16 +
  17 + def self.can_display? profile, options, field, permission = :friend
  18 + return true if profile.public_fields.include?(field)
  19 + current_person = options[:current_person]
  20 +
  21 + current_permission = if current_person.present?
  22 + if current_person.is_admin?
  23 + :admin
  24 + elsif current_person == profile
  25 + :self
  26 + elsif current_person.friends.include?(profile)
  27 + :friend
  28 + else
  29 + :logged_user
  30 + end
  31 + else
  32 + :anonymous
  33 + end
  34 +
  35 + PERMISSIONS[current_permission] <= PERMISSIONS[permission]
  36 + end
  37 +
9 38 class Image < Entity
10 39 root 'images', 'image'
11 40  
... ... @@ -30,66 +59,81 @@ module Noosfero
30 59 end
31 60 end
32 61  
  62 + class CategoryBase < Entity
  63 + root 'categories', 'category'
  64 + expose :name, :id, :slug
  65 + end
  66 +
  67 + class Category < CategoryBase
  68 + root 'categories', 'category'
  69 + expose :full_name do |category, options|
  70 + category.full_name
  71 + end
  72 + expose :parent, :using => CategoryBase, if: { parent: true }
  73 + expose :children, :using => CategoryBase, if: { children: true }
  74 + expose :image, :using => Image
  75 + expose :display_color
  76 + end
  77 +
  78 + class Region < Category
  79 + root 'regions', 'region'
  80 + expose :parent_id
  81 + end
  82 +
33 83 class Profile < Entity
34 84 expose :identifier, :name, :id
35 85 expose :created_at, :format_with => :timestamp
36 86 expose :updated_at, :format_with => :timestamp
37 87 expose :image, :using => Image
  88 + expose :region, :using => Region
38 89 end
39 90  
40   - class User < Entity
  91 + class UserBasic < Entity
41 92 expose :id
42 93 expose :login
43 94 end
44 95  
45 96 class Person < Profile
46 97 root 'people', 'person'
47   - expose :user, :using => User
  98 + expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' }
48 99 end
  100 +
49 101 class Enterprise < Profile
50 102 root 'enterprises', 'enterprise'
51 103 end
  104 +
52 105 class Community < Profile
53 106 root 'communities', 'community'
54 107 expose :description
55   - expose :categories
56   - expose :members, :using => Person
57   - end
58   -
59   - class CategoryBase < Entity
60   - root 'categories', 'category'
61   - expose :name, :id
62   - end
63   -
64   - class Category < CategoryBase
65   - root 'categories', 'category'
66   - expose :slug
67   - expose :full_name do |category, options|
68   - category.full_name
  108 + expose :admins do |community, options|
  109 + community.admins.map{|admin| {"name"=>admin.name, "id"=>admin.id}}
69 110 end
70   - expose :parent, :using => CategoryBase, if: { parent: true }
71   - expose :children, :using => CategoryBase, if: { children: true }
72   - expose :image, :using => Image
  111 + expose :categories, :using => Category
  112 + expose :members, :using => Person
73 113 end
74 114  
75 115 class ArticleBase < Entity
76 116 root 'articles', 'article'
77 117 expose :id
78 118 expose :body
79   - expose :abstract
  119 + expose :abstract, documentation: {type: 'String', desc: 'Teaser of the body'}
80 120 expose :created_at, :format_with => :timestamp
81 121 expose :updated_at, :format_with => :timestamp
82 122 expose :title, :documentation => {:type => "String", :desc => "Title of the article"}
83   - expose :created_by, :as => :author, :using => Profile
84   - expose :profile, :using => Profile
  123 + expose :created_by, :as => :author, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile author that create the article'}
  124 + expose :profile, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile associated with the article'}
85 125 expose :categories, :using => Category
86 126 expose :image, :using => Image
87   - #TODO Apply vote stuff in core and make this test
88 127 expose :votes_for
89 128 expose :votes_against
90 129 expose :setting
91 130 expose :position
92 131 expose :hits
  132 + expose :start_date
  133 + expose :end_date, :documentation => {type: 'DateTime', desc: 'The date of finish of the article'}
  134 + expose :tag_list
  135 + expose :children_count
  136 + expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"}
93 137 expose :path
94 138 end
95 139  
... ... @@ -106,8 +150,32 @@ module Noosfero
106 150 expose :author, :using => Profile
107 151 end
108 152  
  153 + class User < Entity
  154 + root 'users', 'user'
  155 +
  156 + attrs = [:id,:login,:email,:activated?]
  157 + aliases = {:activated? => :activated}
  158 +
  159 + attrs.each do |attribute|
  160 + name = aliases.has_key?(attribute) ? aliases[attribute] : attribute
  161 + expose attribute, :as => name, :if => lambda{|user,options| Entities.can_display?(user.person, options, attribute)}
  162 + end
  163 +
  164 + expose :person, :using => Person
  165 + expose :permissions, :if => lambda{|user,options| Entities.can_display?(user.person, options, :permissions, :self)} do |user, options|
  166 + output = {}
  167 + user.person.role_assignments.map do |role_assigment|
  168 + if role_assigment.resource.respond_to?(:identifier) && !role_assigment.role.nil?
  169 + output[role_assigment.resource.identifier] = role_assigment.role.permissions
  170 + end
  171 + end
  172 + output
  173 + end
  174 + end
  175 +
109 176 class UserLogin < User
110   - expose :private_token
  177 + root 'users', 'user'
  178 + expose :private_token, documentation: {type: 'String', desc: 'A valid authentication code for post/delete api actions'}
111 179 end
112 180  
113 181 class Task < Entity
... ... @@ -116,6 +184,16 @@ module Noosfero
116 184 expose :type
117 185 end
118 186  
  187 + class Environment < Entity
  188 + expose :name
  189 + end
  190 +
  191 + class Tag < Entity
  192 + root 'tags', 'tag'
  193 + expose :name
  194 + end
  195 +
  196 +
119 197 end
120 198 end
121 199 end
... ...
lib/noosfero/api/helpers.rb
1   -module Noosfero
2   - module API
3   - module APIHelpers
  1 +require 'grape'
  2 +require_relative '../../find_by_contents'
  3 +
  4 + module Noosfero;
  5 + module API
  6 + module APIHelpers
4 7 PRIVATE_TOKEN_PARAM = :private_token
5   - DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type]
  8 + DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id]
  9 +
  10 + include SanitizeParams
  11 + include Noosfero::Plugin::HotSpot
  12 + include ForgotPasswordHelper
  13 + include SearchTermHelper
  14 +
  15 + def set_locale
  16 + I18n.locale = (params[:lang] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
  17 + end
  18 +
  19 + def init_noosfero_plugins
  20 + plugins
  21 + end
6 22  
7 23 def current_user
8 24 private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s
... ... @@ -23,6 +39,22 @@ module Noosfero
23 39 @environment
24 40 end
25 41  
  42 + include FindByContents
  43 +
  44 + ####################################################################
  45 + #### SEARCH
  46 + ####################################################################
  47 + def multiple_search?(searches=nil)
  48 + ['index', 'category_index'].include?(params[:action]) || (searches && searches.size > 1)
  49 + end
  50 + ####################################################################
  51 +
  52 + def logger
  53 + logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log"))
  54 + logger.formatter = GrapeLogging::Formatters::Default.new
  55 + logger
  56 + end
  57 +
26 58 def limit
27 59 limit = params[:limit].to_i
28 60 limit = default_limit if limit <= 0
... ... @@ -50,7 +82,7 @@ module Noosfero
50 82  
51 83 def find_article(articles, id)
52 84 article = articles.find(id)
53   - article.display_to?(current_user.person) ? article : forbidden!
  85 + article.display_to?(current_person) ? article : forbidden!
54 86 end
55 87  
56 88 def post_article(asset, params)
... ... @@ -75,12 +107,25 @@ module Noosfero
75 107 present article, :with => Entities::Article, :fields => params[:fields]
76 108 end
77 109  
78   - def present_articles(asset)
79   - articles = select_filtered_collection_of(asset, 'articles', params)
80   - articles = articles.display_filter(current_person, nil)
  110 + def present_articles_for_asset(asset, method = 'articles')
  111 + articles = find_articles(asset, method)
  112 + present_articles(articles)
  113 + end
  114 +
  115 + def present_articles(articles)
81 116 present articles, :with => Entities::Article, :fields => params[:fields]
82 117 end
83 118  
  119 + def find_articles(asset, method = 'articles')
  120 + articles = select_filtered_collection_of(asset, method, params)
  121 + if current_person.present?
  122 + articles = articles.display_filter(current_person, nil)
  123 + else
  124 + articles = articles.published
  125 + end
  126 + articles
  127 + end
  128 +
84 129 def find_task(asset, id)
85 130 task = asset.tasks.find(id)
86 131 current_person.has_permission?(task.permission, asset) ? task : forbidden!
... ... @@ -127,8 +172,27 @@ module Noosfero
127 172 conditions
128 173 end
129 174  
130   - def make_order_with_parameters(params)
131   - params[:order] || "created_at DESC"
  175 + # changing make_order_with_parameters to avoid sql injection
  176 + def make_order_with_parameters(object, method, params)
  177 + order = "created_at DESC"
  178 + unless params[:order].blank?
  179 + if params[:order].include? '\'' or params[:order].include? '"'
  180 + order = "created_at DESC"
  181 + elsif ['RANDOM()', 'RANDOM'].include? params[:order].upcase
  182 + order = 'RANDOM()'
  183 + else
  184 + field_name, direction = params[:order].split(' ')
  185 + assoc = object.class.reflect_on_association(method.to_sym)
  186 + if !field_name.blank? and assoc
  187 + if assoc.klass.attribute_names.include? field_name
  188 + if direction.present? and ['ASC','DESC'].include? direction.upcase
  189 + order = "#{field_name} #{direction.upcase}"
  190 + end
  191 + end
  192 + end
  193 + end
  194 + end
  195 + return order
132 196 end
133 197  
134 198 def make_page_number_with_parameters(params)
... ... @@ -152,25 +216,36 @@ module Noosfero
152 216 end
153 217  
154 218 def by_reference(scope, params)
155   - if params[:reference_id]
156   - created_at = scope.find(params[:reference_id]).created_at
157   - scope.send("#{params.key?(:oldest) ? 'older_than' : 'younger_than'}", created_at)
  219 + reference_id = params[:reference_id].to_i == 0 ? nil : params[:reference_id].to_i
  220 + if reference_id.nil?
  221 + scope
158 222 else
  223 + created_at = scope.find(reference_id).created_at
  224 + scope.send("#{params.key?(:oldest) ? 'older_than' : 'younger_than'}", created_at)
  225 + end
  226 + end
  227 +
  228 + def by_categories(scope, params)
  229 + category_ids = params[:category_ids]
  230 + if category_ids.nil?
159 231 scope
  232 + else
  233 + scope.joins(:categories).where(:categories => {:id => category_ids})
160 234 end
161 235 end
162 236  
163 237 def select_filtered_collection_of(object, method, params)
164 238 conditions = make_conditions_with_parameter(params)
165   - order = make_order_with_parameters(params)
  239 + order = make_order_with_parameters(object,method,params)
166 240 page_number = make_page_number_with_parameters(params)
167 241 per_page = make_per_page_with_parameters(params)
168 242 timestamp = make_timestamp_with_parameters_and_method(params, method)
169 243  
170 244 objects = object.send(method)
171 245 objects = by_reference(objects, params)
  246 + objects = by_categories(objects, params)
172 247  
173   - objects = objects.where(conditions).where(timestamp).page(page_number).per_page(per_page).order(order)
  248 + objects = objects.where(conditions).where(timestamp).page(page_number).per_page(per_page).reorder(order)
174 249  
175 250 objects
176 251 end
... ... @@ -179,6 +254,7 @@ module Noosfero
179 254 unauthorized! unless current_user
180 255 end
181 256  
  257 +
182 258 # Checks the occurrences of uniqueness of attributes, each attribute must be present in the params hash
183 259 # or a Bad Request error is invoked.
184 260 #
... ... @@ -198,20 +274,6 @@ module Noosfero
198 274 attrs
199 275 end
200 276  
201   - def verify_recaptcha_v2(remote_ip, g_recaptcha_response, private_key, api_recaptcha_verify_uri)
202   - verify_hash = {
203   - "secret" => private_key,
204   - "remoteip" => remote_ip,
205   - "response" => g_recaptcha_response
206   - }
207   - uri = URI(api_recaptcha_verify_uri)
208   - https = Net::HTTP.new(uri.host, uri.port)
209   - https.use_ssl = true
210   - request = Net::HTTP::Post.new(uri.path)
211   - request.set_form_data(verify_hash)
212   - JSON.parse(https.request(request).body)
213   - end
214   -
215 277 ##########################################
216 278 # error helpers #
217 279 ##########################################
... ... @@ -247,13 +309,22 @@ module Noosfero
247 309 render_api_error!(_('Method Not Allowed'), 405)
248 310 end
249 311  
250   - def render_api_error!(message, status)
251   - error!({'message' => message, :code => status}, status)
  312 + # javascript_console_message is supposed to be executed as console.log()
  313 + def render_api_error!(user_message, status, log_message = nil, javascript_console_message = nil)
  314 + message_hash = {'message' => user_message, :code => status}
  315 + message_hash[:javascript_console_message] = javascript_console_message if javascript_console_message.present?
  316 + log_msg = "#{status}, User message: #{user_message}"
  317 + log_msg = "#{log_message}, #{log_msg}" if log_message.present?
  318 + log_msg = "#{log_msg}, Javascript Console Message: #{javascript_console_message}" if javascript_console_message.present?
  319 + logger.error log_msg unless Rails.env.test?
  320 + error!(message_hash, status)
252 321 end
253 322  
254 323 def render_api_errors!(messages)
  324 + messages = messages.to_a if messages.class == ActiveModel::Errors
255 325 render_api_error!(messages.join(','), 400)
256 326 end
  327 +
257 328 protected
258 329  
259 330 def set_session_cookie
... ... @@ -278,7 +349,7 @@ module Noosfero
278 349 end
279 350  
280 351 def filter_disabled_plugins_endpoints
281   - not_found! if Noosfero::API::API.endpoint_unavailable?(self, !@environment)
  352 + not_found! if Noosfero::API::API.endpoint_unavailable?(self, @environment)
282 353 end
283 354  
284 355 private
... ... @@ -305,7 +376,6 @@ module Noosfero
305 376 def period(from_date, until_date)
306 377 begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date
307 378 end_period = until_date.nil? ? DateTime.now : until_date
308   -
309 379 begin_period..end_period
310 380 end
311 381  
... ...
lib/noosfero/api/session.rb
... ... @@ -2,7 +2,6 @@ require &quot;uri&quot;
2 2  
3 3 module Noosfero
4 4 module API
5   -
6 5 class Session < Grape::API
7 6  
8 7 # Login to get token
... ... @@ -14,11 +13,15 @@ module Noosfero
14 13 # Example Request:
15 14 # POST http://localhost:3000/api/v1/login?login=adminuser&password=admin
16 15 post "/login" do
17   - user ||= User.authenticate(params[:login], params[:password], environment)
  16 + begin
  17 + user ||= User.authenticate(params[:login], params[:password], environment)
  18 + rescue NoosferoExceptions::UserNotActivated => e
  19 + render_api_error!(e.message, 401)
  20 + end
18 21  
19 22 return unauthorized! unless user
20 23 @current_user = user
21   - present user, :with => Entities::UserLogin
  24 + present user, :with => Entities::UserLogin, :current_person => current_person
22 25 end
23 26  
24 27 # Create user.
... ... @@ -28,34 +31,103 @@ module Noosfero
28 31 # password (required) - Password
29 32 # login - login
30 33 # Example Request:
31   - # POST /register?email=some@mail.com&password=pas&login=some
  34 + # POST /register?email=some@mail.com&password=pas&password_confirmation=pas&login=some
32 35 params do
33 36 requires :email, type: String, desc: _("Email")
34 37 requires :login, type: String, desc: _("Login")
35 38 requires :password, type: String, desc: _("Password")
36 39 end
  40 +
37 41 post "/register" do
38   - unique_attributes! User, [:email, :login]
39   - attrs = attributes_for_keys [:email, :login, :password]
40   - attrs[:password_confirmation] = attrs[:password]
41   -
42   - #Commented for stress tests
43   -
44   - # remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
45   - # private_key = API.NOOSFERO_CONF['api_recaptcha_private_key']
46   - # api_recaptcha_verify_uri = API.NOOSFERO_CONF['api_recaptcha_verify_uri']
47   - # captcha_result = verify_recaptcha_v2(remote_ip, params['g-recaptcha-response'], private_key, api_recaptcha_verify_uri)
48   - user = User.new(attrs)
49   -# if captcha_result["success"] and user.save
50   - if user.save
51   - user.activate
52   - user.generate_private_token!
53   - present user, :with => Entities::UserLogin
54   - else
55   - message = user.errors.to_json
  42 + attrs = attributes_for_keys [:email, :login, :password, :password_confirmation] + environment.signup_person_fields
  43 + name = params[:name].present? ? params[:name] : attrs[:email]
  44 + attrs[:password_confirmation] = attrs[:password] if !attrs.has_key?(:password_confirmation)
  45 + user = User.new(attrs.merge(:name => name))
  46 +
  47 + begin
  48 + user.signup!
  49 + user.generate_private_token! if user.activated?
  50 + present user, :with => Entities::UserLogin, :current_person => user.person
  51 + rescue ActiveRecord::RecordInvalid
  52 + message = user.errors.as_json.merge((user.person.present? ? user.person.errors : {}).as_json).to_json
56 53 render_api_error!(message, 400)
57 54 end
58 55 end
  56 +
  57 + params do
  58 + requires :activation_code, type: String, desc: _("Activation token")
  59 + end
  60 +
  61 + # Activate a user.
  62 + #
  63 + # Parameter:
  64 + # activation_code (required) - Activation token
  65 + # Example Request:
  66 + # PATCH /activate?activation_code=28259abd12cc6a64ef9399cf3286cb998b96aeaf
  67 + patch "/activate" do
  68 + user = User.find_by_activation_code(params[:activation_code])
  69 + if user
  70 + unless user.environment.enabled?('admin_must_approve_new_users')
  71 + if user.activate
  72 + user.generate_private_token!
  73 + present user, :with => Entities::UserLogin, :current_person => current_person
  74 + end
  75 + else
  76 + if user.create_moderate_task
  77 + user.activation_code = nil
  78 + user.save!
  79 +
  80 + # Waiting for admin moderate user registration
  81 + status 202
  82 + body({
  83 + :message => 'Waiting for admin moderate user registration'
  84 + })
  85 + end
  86 + end
  87 + else
  88 + # Token not found in database
  89 + render_api_error!(_('Token is invalid'), 412)
  90 + end
  91 + end
  92 +
  93 + # Request a new password.
  94 + #
  95 + # Parameters:
  96 + # value (required) - Email or login
  97 + # Example Request:
  98 + # POST /forgot_password?value=some@mail.com
  99 + post "/forgot_password" do
  100 + requestors = fetch_requestors(params[:value])
  101 + not_found! if requestors.blank?
  102 + remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
  103 + requestors.each do |requestor|
  104 + ChangePassword.create!(:requestor => requestor)
  105 + end
  106 + end
  107 +
  108 + params do
  109 + requires :code, type: String, desc: _("Forgot password code")
  110 + end
  111 + # Change password
  112 + #
  113 + # Parameters:
  114 + # code (required) - Change password code
  115 + # password (required)
  116 + # password_confirmation (required)
  117 + # Example Request:
  118 + # PATCH /new_password?code=xxxx&password=secret&password_confirmation=secret
  119 + patch "/new_password" do
  120 + change_password = ChangePassword.find_by_code(params[:code])
  121 + not_found! if change_password.nil?
  122 +
  123 + if change_password.update_attributes(:password => params[:password], :password_confirmation => params[:password_confirmation])
  124 + change_password.finish
  125 + present change_password.requestor.user, :with => Entities::UserLogin, :current_person => current_person
  126 + else
  127 + something_wrong!
  128 + end
  129 + end
  130 +
59 131 end
60 132 end
61 133 end
... ...
lib/noosfero/api/v1/articles.rb
... ... @@ -2,7 +2,6 @@ module Noosfero
2 2 module API
3 3 module V1
4 4 class Articles < Grape::API
5   - before { authenticate! }
6 5  
7 6 ARTICLE_TYPES = Article.descendants.map{|a| a.to_s}
8 7  
... ... @@ -17,39 +16,148 @@ module Noosfero
17 16 #
18 17 # Example Request:
19 18 # GET host/api/v1/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317
  19 +
  20 + desc 'Return all articles of all kinds' do
  21 + detail 'Get all articles filtered by fields in query params'
  22 + params Noosfero::API::Entities::Article.documentation
  23 + success Noosfero::API::Entities::Article
  24 + failure [[403, 'Forbidden']]
  25 + named 'ArticlesList'
  26 + headers [
  27 + 'Per-Page' => {
  28 + description: 'Total number of records',
  29 + required: false
  30 + }
  31 + ]
  32 + end
20 33 get do
21   - present_articles(environment)
  34 + present_articles_for_asset(environment)
22 35 end
23 36  
24   - desc "Return the article id"
25   - get ':id' do
  37 + desc "Return one article by id" do
  38 + detail 'Get only one article by id. If not found the "forbidden" http error is showed'
  39 + params Noosfero::API::Entities::Article.documentation
  40 + success Noosfero::API::Entities::Article
  41 + failure [[403, 'Forbidden']]
  42 + named 'ArticleById'
  43 + end
  44 + get ':id', requirements: {id: /[0-9]+/} do
26 45 present_article(environment)
27 46 end
28 47  
  48 + post ':id' do
  49 + article = environment.articles.find(params[:id])
  50 + return forbidden! unless article.allow_edit?(current_person)
  51 + article.update_attributes!(params[:article])
  52 + present article, :with => Entities::Article, :fields => params[:fields]
  53 + end
  54 +
  55 + desc 'Report a abuse and/or violent content in a article by id' do
  56 + detail 'Submit a abuse (in general, a content violation) report about a specific article'
  57 + params Noosfero::API::Entities::Article.documentation
  58 + failure [[400, 'Bad Request']]
  59 + named 'ArticleReportAbuse'
  60 + end
  61 + post ':id/report_abuse' do
  62 + article = find_article(environment.articles, params[:id])
  63 + profile = article.profile
  64 + begin
  65 + abuse_report = AbuseReport.new(:reason => params[:report_abuse])
  66 + if !params[:content_type].blank?
  67 + article = params[:content_type].constantize.find(params[:content_id])
  68 + abuse_report.content = article_reported_version(article)
  69 + end
  70 +
  71 + current_person.register_report(abuse_report, profile)
  72 +
  73 + if !params[:content_type].blank?
  74 + abuse_report = AbuseReport.find_by_reporter_id_and_abuse_complaint_id(current_person.id, profile.opened_abuse_complaint.id)
  75 + Delayed::Job.enqueue DownloadReportedImagesJob.new(abuse_report, article)
  76 + end
  77 +
  78 + {
  79 + :success => true,
  80 + :message => _('Your abuse report was registered. The administrators are reviewing your report.'),
  81 + }
  82 + rescue Exception => exception
  83 + #logger.error(exception.to_s)
  84 + render_api_error!(_('Your report couldn\'t be saved due to some problem. Please contact the administrator.'), 400)
  85 + end
  86 +
  87 + end
  88 +
  89 + desc "Returns the articles I voted" do
  90 + detail 'Get the Articles I make a vote'
  91 + failure [[403, 'Forbidden']]
  92 + named 'ArticleFollowers'
  93 + end
  94 + #FIXME refactor this method
  95 + get 'voted_by_me' do
  96 + present_articles(current_person.votes.collect(&:voteable))
  97 + end
  98 +
  99 + desc 'Perform a vote on a article by id' do
  100 + detail 'Vote on a specific article with values: 1 (if you like) or -1 (if not)'
  101 + params Noosfero::API::Entities::UserLogin.documentation
  102 + failure [[401,'Unauthorized']]
  103 + named 'ArticleVote'
  104 + end
  105 + post ':id/vote' do
  106 + authenticate!
  107 + value = (params[:value] || 1).to_i
  108 + # FIXME verify allowed values
  109 + render_api_error!('Vote value not allowed', 400) unless [-1, 1].include?(value)
  110 + article = find_article(environment.articles, params[:id])
  111 + vote = Vote.new(:voteable => article, :voter => current_person, :vote => value)
  112 + {:vote => vote.save}
  113 + end
  114 +
  115 + desc 'Return the children of a article identified by id' do
  116 + detail 'Get all children articles of a specific article'
  117 + params Noosfero::API::Entities::Article.documentation
  118 + failure [[403, 'Forbidden']]
  119 + named 'ArticleChildren'
  120 + end
  121 +
29 122 get ':id/children' do
30 123 article = find_article(environment.articles, params[:id])
31 124  
32 125 #TODO make tests for this situation
33 126 votes_order = params.delete(:order) if params[:order]=='votes_score'
34 127 articles = select_filtered_collection_of(article, 'children', params)
35   - articles = articles.display_filter(current_person, nil)
36   -
  128 + articles = articles.display_filter(current_person, article.profile)
37 129  
38 130 #TODO make tests for this situation
39 131 if votes_order
40 132 articles = articles.joins('left join votes on articles.id=votes.voteable_id').group('articles.id').reorder('sum(coalesce(votes.vote, 0)) DESC')
41 133 end
42   -
43 134 Article.hit(articles)
44   - present articles, :with => Entities::Article, :fields => params[:fields]
  135 + present_articles(articles)
45 136 end
46 137  
  138 + desc 'Return one child of a article identified by id' do
  139 + detail 'Get a child of a specific article'
  140 + params Noosfero::API::Entities::Article.documentation
  141 + success Noosfero::API::Entities::Article
  142 + failure [[403, 'Forbidden']]
  143 + named 'ArticleChild'
  144 + end
47 145 get ':id/children/:child_id' do
48 146 article = find_article(environment.articles, params[:id])
49   - present find_article(article.children, params[:child_id]), :with => Entities::Article, :fields => params[:fields]
  147 + child = find_article(article.children, params[:child_id])
  148 + child.hit
  149 + present child, :with => Entities::Article, :fields => params[:fields]
50 150 end
51 151  
  152 + desc 'Suggest a article to another profile' do
  153 + detail 'Suggest a article to another profile (person, community...)'
  154 + params Noosfero::API::Entities::Article.documentation
  155 + success Noosfero::API::Entities::Task
  156 + failure [[401,'Unauthorized']]
  157 + named 'ArticleSuggest'
  158 + end
52 159 post ':id/children/suggest' do
  160 + authenticate!
53 161 parent_article = environment.articles.find(params[:id])
54 162  
55 163 suggest_article = SuggestArticle.new
... ... @@ -66,8 +174,15 @@ module Noosfero
66 174  
67 175 # Example Request:
68 176 # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body
  177 + desc 'Add a child article to a parent identified by id' do
  178 + detail 'Create a new article and associate to a parent'
  179 + params Noosfero::API::Entities::Article.documentation
  180 + success Noosfero::API::Entities::Article
  181 + failure [[401,'Unauthorized']]
  182 + named 'ArticleAddChild'
  183 + end
69 184 post ':id/children' do
70   -
  185 + authenticate!
71 186 parent_article = environment.articles.find(params[:id])
72 187 return forbidden! unless parent_article.allow_create?(current_person)
73 188  
... ... @@ -95,11 +210,37 @@ module Noosfero
95 210 resource kind.pluralize.to_sym do
96 211 segment "/:#{kind}_id" do
97 212 resource :articles do
  213 +
  214 + desc "Return all articles associate with a profile of type #{kind}" do
  215 + detail 'Get a list of articles of a profile'
  216 + params Noosfero::API::Entities::Article.documentation
  217 + success Noosfero::API::Entities::Article
  218 + failure [[403, 'Forbidden']]
  219 + named 'ArticlesOfProfile'
  220 + end
98 221 get do
99 222 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
100   - present_articles(profile)
  223 +
  224 + if params[:path].present?
  225 + article = profile.articles.find_by_path(params[:path])
  226 + if !article || !article.display_to?(current_person)
  227 + article = forbidden!
  228 + end
  229 +
  230 + present article, :with => Entities::Article, :fields => params[:fields]
  231 + else
  232 +
  233 + present_articles_for_asset(profile)
  234 + end
101 235 end
102 236  
  237 + desc "Return a article associate with a profile of type #{kind}" do
  238 + detail 'Get only one article of a profile'
  239 + params Noosfero::API::Entities::Article.documentation
  240 + success Noosfero::API::Entities::Article
  241 + failure [[403, 'Forbidden']]
  242 + named 'ArticleOfProfile'
  243 + end
103 244 get ':id' do
104 245 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
105 246 present_article(profile)
... ... @@ -107,6 +248,13 @@ module Noosfero
107 248  
108 249 # Example Request:
109 250 # POST api/v1/{people,communities,enterprises}/:asset_id/articles?private_token=234298743290432&article[name]=title&article[body]=body
  251 + desc "Add a new article associated with a profile of type #{kind}" do
  252 + detail 'Create a new article and associate with a profile'
  253 + params Noosfero::API::Entities::Article.documentation
  254 + success Noosfero::API::Entities::Article
  255 + failure [[403, 'Forbidden']]
  256 + named 'ArticleCreateToProfile'
  257 + end
110 258 post do
111 259 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
112 260 post_article(profile, params)
... ...
lib/noosfero/api/v1/comments.rb
... ... @@ -30,8 +30,8 @@ module Noosfero
30 30 # POST api/v1/articles/12/comments?private_token=2298743290432&body=new comment&title=New
31 31 post ":id/comments" do
32 32 article = find_article(environment.articles, params[:id])
33   - options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person)
34   - present article.comments.create(options), :with => Entities::Comment
  33 + options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person, :source => article)
  34 + present Comment.create(options), :with => Entities::Comment
35 35 end
36 36 end
37 37  
... ...
lib/noosfero/api/v1/contacts.rb 0 → 100644
... ... @@ -0,0 +1,28 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Contacts < Grape::API
  5 +
  6 + resource :communities do
  7 +
  8 + resource ':id/contact' do
  9 + #contact => {:name => 'some name', :email => 'test@mail.com', :subject => 'some title', :message => 'some message'}
  10 + desc "Send a contact message"
  11 + post do
  12 + profile = environment.communities.find(params[:id])
  13 + forbidden! unless profile.present?
  14 + contact = Contact.new params[:contact].merge(dest: profile)
  15 + if contact.deliver
  16 + {:success => true}
  17 + else
  18 + {:success => false}
  19 + end
  20 + end
  21 +
  22 + end
  23 + end
  24 +
  25 + end
  26 + end
  27 + end
  28 +end
... ...
lib/noosfero/api/v1/environments.rb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Environments < Grape::API
  5 +
  6 + resource :environment do
  7 +
  8 + desc "Return the person information"
  9 + get '/signup_person_fields' do
  10 + present environment.signup_person_fields
  11 + end
  12 +
  13 + end
  14 +
  15 + end
  16 + end
  17 + end
  18 +end
... ...
lib/noosfero/api/v1/people.rb
... ... @@ -48,6 +48,13 @@ module Noosfero
48 48 present person, :with => Entities::Person
49 49 end
50 50  
  51 + desc "Update person information"
  52 + post ':id' do
  53 + return forbidden! if current_person.id.to_s != params[:id]
  54 + current_person.update_attributes!(params[:person])
  55 + present current_person, :with => Entities::Person
  56 + end
  57 +
51 58 # Example Request:
52 59 # POST api/v1/people?person[login]=some_login&person[password]=some_password&person[name]=Jack
53 60 desc "Create person"
... ...
lib/noosfero/api/v1/search.rb 0 → 100644
... ... @@ -0,0 +1,43 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Search < Grape::API
  5 +
  6 + resource :search do
  7 + resource :article do
  8 + get do
  9 + # Security checks
  10 + sanitize_params_hash(params)
  11 + # APIHelpers
  12 + asset = :articles
  13 + context = environment
  14 +
  15 + profile = environment.profiles.find(params[:profile_id]) if params[:profile_id]
  16 + scope = profile.nil? ? environment.articles.is_public : profile.articles.is_public
  17 + scope = scope.where(:type => params[:type]) if params[:type] && !(params[:type] == 'Article')
  18 + scope = scope.where(:parent_id => params[:parent_id]) if params[:parent_id].present?
  19 + scope = scope.joins(:categories).where(:categories => {:id => params[:category_ids]}) if params[:category_ids].present?
  20 + query = params[:query] || ""
  21 + order = "more_recent"
  22 +
  23 + options = {:filter => order, :template_id => params[:template_id]}
  24 +
  25 + paginate_options = params.select{|k,v| [:page, :per_page].include?(k.to_sym)}.symbolize_keys
  26 + paginate_options.each_pair{|k,v| v=v.to_i}
  27 + paginate_options[:page]=1 if !paginate_options.keys.include?(:page)
  28 +
  29 + search_result = find_by_contents(asset, context, scope, query, paginate_options, options)
  30 +
  31 + articles = search_result[:results]
  32 +
  33 + result = present_articles(articles)
  34 +
  35 + result
  36 + end
  37 + end
  38 + end
  39 +
  40 + end
  41 + end
  42 + end
  43 +end
... ...
lib/noosfero/api/v1/tags.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Tags < Grape::API
  5 + before { authenticate! }
  6 +
  7 + resource :articles do
  8 +
  9 + resource ':id/tags' do
  10 +
  11 + get do
  12 + article = find_article(environment.articles, params[:id])
  13 + present article.tag_list
  14 + end
  15 +
  16 + desc "Add a tag to an article"
  17 + post do
  18 + article = find_article(environment.articles, params[:id])
  19 + article.tag_list=params[:tags]
  20 + article.save
  21 + present article.tag_list
  22 + end
  23 +
  24 + end
  25 + end
  26 +
  27 + end
  28 + end
  29 + end
  30 +end
... ...
lib/noosfero/api/v1/users.rb 0 → 100644
... ... @@ -0,0 +1,43 @@
  1 +module Noosfero
  2 + module API
  3 + module V1
  4 + class Users < Grape::API
  5 + before { authenticate! }
  6 +
  7 + resource :users do
  8 +
  9 + get do
  10 + users = select_filtered_collection_of(environment, 'users', params)
  11 + users = users.select{|u| u.person.display_info_to? current_person}
  12 + present users, :with => Entities::User, :current_person => current_person
  13 + end
  14 +
  15 + get "/me" do
  16 + present current_user, :with => Entities::User, :current_person => current_person
  17 + end
  18 +
  19 + get ":id" do
  20 + user = environment.users.find_by_id(params[:id])
  21 + unless user.person.display_info_to? current_person
  22 + unauthorized!
  23 + end
  24 + present user, :with => Entities::User, :current_person => current_person
  25 + end
  26 +
  27 + get ":id/permissions" do
  28 + user = environment.users.find(params[:id])
  29 + output = {}
  30 + user.person.role_assignments.map do |role_assigment|
  31 + if role_assigment.resource.respond_to?(:identifier) && role_assigment.resource.identifier == params[:profile]
  32 + output[:permissions] = role_assigment.role.permissions
  33 + end
  34 + end
  35 + present output
  36 + end
  37 +
  38 + end
  39 +
  40 + end
  41 + end
  42 + end
  43 +end
... ...
lib/sanitize_params.rb 0 → 100644
... ... @@ -0,0 +1,41 @@
  1 +module SanitizeParams
  2 +
  3 + protected
  4 +
  5 + # Check each request parameter for
  6 + # improper HTML or Script tags
  7 + def sanitize_params
  8 + sanitize_params_hash(request.params)
  9 + end
  10 +
  11 + # Given a params list sanitize all
  12 + def sanitize_params_hash(params)
  13 + params.each { |k, v|
  14 + if v.is_a?(String)
  15 + params[k] = sanitize_param v
  16 + elsif v.is_a?(Array)
  17 + params[k] = sanitize_array v
  18 + elsif v.kind_of?(Hash)
  19 + params[k] = sanitize_params_hash(v)
  20 + end
  21 + }
  22 + end
  23 +
  24 + # If the parameter was an array,
  25 + # try to sanitize each element in the array
  26 + def sanitize_array(array)
  27 + array.map! { |e|
  28 + if e.is_a?(String)
  29 + sanitize_param e
  30 + end
  31 + }
  32 + return array
  33 + end
  34 +
  35 + # Santitize a single value
  36 + def sanitize_param(value)
  37 + allowed_tags = %w(a acronym b strong i em li ul ol h1 h2 h3 h4 h5 h6 blockquote br cite sub sup ins p)
  38 + ActionController::Base.helpers.sanitize(value, tags: allowed_tags, attributes: %w(href title))
  39 + end
  40 +
  41 +end
... ...
plugins/newsletter/db/migrate/20150717195546_newsletter_plugin_newsletters.rb
... ... @@ -14,7 +14,7 @@ class NewsletterPluginNewsletters &lt; ActiveRecord::Migration
14 14 t.boolean :moderated
15 15 t.text :unsubscribers
16 16 end
17   - add_index :newsletter_plugin_newsletters, :environment_id, :uniq => true
  17 + add_index :newsletter_plugin_newsletters, :environment_id, :unique => true
18 18 end
19 19  
20 20 def down
... ...
plugins/newsletter/lib/newsletter_plugin/newsletter.rb
1 1 require 'csv'
2 2  
3   -class NewsletterPlugin::Newsletter < Noosfero::Plugin::ActiveRecord
  3 +class NewsletterPlugin::Newsletter < ActiveRecord::Base
4 4  
5 5 belongs_to :environment
6 6 belongs_to :person
... ... @@ -123,11 +123,11 @@ class NewsletterPlugin::Newsletter &lt; Noosfero::Plugin::ActiveRecord
123 123 end
124 124  
125 125 def post_with_image(post)
126   - content_tag(:tr,content_tag(:td,tag(:img, :src => "#{self.environment.top_url}#{post.image.public_filename(:big)}", :id => post.id),:style => CSS['post-image'])+content_tag(:td,content_tag(:span, show_date(post.published_at), :style => CSS['post-date'])+content_tag(:h3, link_to(h(post.title), post.url, :style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(190)),:style => CSS['post-lead'])+read_more(post.url), :style => CSS['post-info']))
  126 + content_tag(:tr,content_tag(:td,tag(:img, :src => "#{self.environment.top_url}#{post.image.public_filename(:big)}", :id => post.id),:style => CSS['post-image'])+content_tag(:td,content_tag(:span, show_date(post.published_at), :style => CSS['post-date'])+content_tag(:h3, link_to(h(post.title), post.url, :style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(190), tags: %w(strong em b i)),:style => CSS['post-lead'])+read_more(post.url), :style => CSS['post-info']))
127 127 end
128 128  
129 129 def post_without_image(post)
130   - content_tag(:tr, content_tag(:td,content_tag(:span, show_date(post.published_at),:style => CSS['post-date'], :id => post.id)+content_tag(:h3, link_to(h(post.title), post.url,:style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(360)),:style => CSS['post-lead'])+read_more(post.url),:colspan => 2, :style => CSS['post-info']))
  130 + content_tag(:tr, content_tag(:td,content_tag(:span, show_date(post.published_at),:style => CSS['post-date'], :id => post.id)+content_tag(:h3, link_to(h(post.title), post.url,:style => CSS['post-title']))+content_tag(:p,sanitize(post.lead(360), tags: %w(strong em b i)),:style => CSS['post-lead'])+read_more(post.url),:colspan => 2, :style => CSS['post-info']))
131 131 end
132 132  
133 133 def body(data = {})
... ... @@ -177,10 +177,6 @@ class NewsletterPlugin::Newsletter &lt; Noosfero::Plugin::ActiveRecord
177 177 last_mailing.nil? ? nil : last_mailing.created_at
178 178 end
179 179  
180   - def sanitize(html)
181   - html.gsub(/<\/?p>/, '')
182   - end
183   -
184 180 def has_posts_in_the_period?
185 181 ! self.posts.empty?
186 182 end
... ...
plugins/newsletter/public/style.css
... ... @@ -14,7 +14,7 @@
14 14 }
15 15  
16 16 #newsletter-moderation-preview {
17   - margin-left: 25px;
  17 + margin-left: 10px;
18 18 }
19 19  
20 20 #newsletter-moderation-preview input[type=checkbox] {
... ...
plugins/newsletter/test/unit/newsletter_plugin_newsletter_test.rb
... ... @@ -351,15 +351,30 @@ EOS
351 351 post = fast_create(TextArticle, :parent_id => blog.id,
352 352 :name => 'the last news 1',
353 353 :profile_id => community.id,
354   - :body => "<p>paragraph of news</p>")
  354 + :body => '<p style="text-align: left;">paragraph of news</p>')
355 355  
356 356 newsletter = NewsletterPlugin::Newsletter.create!(
357 357 :environment => environment,
358 358 :blog_ids => [blog.id],
359 359 :person => fast_create(Person))
360 360  
361   - assert_match /<p>paragraph of news<\/p>/, post.body
362   - assert_not_match /<p>paragraph of news<\/p>/, newsletter.body
  361 + assert_match /<p style="text-align: left;">paragraph of news<\/p>/, post.body
  362 + assert_not_match /<p style="text-align: left;">paragraph of news<\/p>/, newsletter.body
  363 + end
  364 +
  365 + should 'only include text for posts in HTML generated content' do
  366 + environment = fast_create Environment
  367 + community = fast_create(Community, :environment_id => environment.id)
  368 + blog = fast_create(Blog, :profile_id => community.id)
  369 + post = fast_create(TextArticle, :profile_id => community.id, :parent_id => blog.id, :name => 'the last news', :abstract => 'A picture<img src="example.png"> is <em>worth</em> a thousand words. <hr><h1>The main goals of visualization</h1>')
  370 + newsletter = NewsletterPlugin::Newsletter.create!(
  371 + :environment => environment,
  372 + :blog_ids => [blog.id],
  373 + :person => fast_create(Person))
  374 +
  375 + assert_match /A picture<img src="example.png"> is <em>worth<\/em> a thousand words. <hr><h1>The main goals of visualization<\/h1>/, post.abstract
  376 + # Tags for text emphasis are whitelisted
  377 + assert_match /A picture is <em>worth<\/em> a thousand words. The main goals of visualization/, newsletter.body
363 378 end
364 379  
365 380 should 'filter posts when listing posts for newsletter' do
... ...
plugins/shopping_cart/db/migrate/20131226125124_move_shopping_cart_purchase_order_to_orders_plugin_order.rb
1 1 OrdersPlugin.send :remove_const, :Item if defined? OrdersPlugin::Item
2 2 OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order
3 3  
4   -class ShoppingCartPlugin::PurchaseOrder < Noosfero::Plugin::ActiveRecord
  4 +class ShoppingCartPlugin::PurchaseOrder < ActiveRecord::Base
5 5 acts_as_having_settings :field => :data
6 6  
7 7 module Status
... ... @@ -16,10 +16,10 @@ class Profile
16 16 has_many :orders, :class_name => 'OrdersPlugin::Order'
17 17 end
18 18  
19   -class OrdersPlugin::Item < Noosfero::Plugin::ActiveRecord
  19 +class OrdersPlugin::Item < ActiveRecord::Base
20 20 belongs_to :order, :class_name => 'OrdersPlugin::Order'
21 21 end
22   -class OrdersPlugin::Order < Noosfero::Plugin::ActiveRecord
  22 +class OrdersPlugin::Order < ActiveRecord::Base
23 23 has_many :items, :class_name => 'OrdersPlugin::Item', :foreign_key => :order_id
24 24  
25 25 extend CodeNumbering::ClassMethods
... ...
script/quick-start
... ... @@ -133,6 +133,9 @@ if [ ! -f .gitignore ]; then
133 133 ln -s gitignore.example .gitignore
134 134 fi
135 135  
  136 +# remove obsolete symbolic link added by old versions
  137 +rm -f vendor/rails
  138 +
136 139 # you can now start the server
137 140 say "I: Congratulations, you are ready to run Noosfero."
138 141 say "I: To execute Noosfero in development mode, run \`./script/development\` and browse to http://localhost:3000"
... ...
test/unit/api/articles_test.rb
... ... @@ -31,7 +31,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
31 31 end
32 32  
33 33 should 'not return article if user has no permission to view it' do
34   - person = fast_create(Person)
  34 + person = fast_create(Person, :environment_id => environment.id)
35 35 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
36 36 assert !article.published?
37 37  
... ... @@ -48,8 +48,17 @@ class ArticlesTest &lt; ActiveSupport::TestCase
48 48 assert_equivalent [child1.id, child2.id], json["articles"].map { |a| a["id"] }
49 49 end
50 50  
  51 + should 'list public article children for not logged in access' do
  52 + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
  53 + child1 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing")
  54 + child2 = fast_create(Article, :parent_id => article.id, :profile_id => user.person.id, :name => "Some thing")
  55 + get "/api/v1/articles/#{article.id}/children"
  56 + json = JSON.parse(last_response.body)
  57 + assert_equivalent [child1.id, child2.id], json["articles"].map { |a| a["id"] }
  58 + end
  59 +
51 60 should 'not list children of forbidden article' do
52   - person = fast_create(Person)
  61 + person = fast_create(Person, :environment_id => environment.id)
53 62 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
54 63 child1 = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing")
55 64 child2 = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing")
... ... @@ -58,7 +67,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
58 67 end
59 68  
60 69 should 'not return child of forbidden article' do
61   - person = fast_create(Person)
  70 + person = fast_create(Person, :environment_id => environment.id)
62 71 article = fast_create(Article, :profile_id => person.id, :name => "Some thing", :published => false)
63 72 child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing")
64 73 get "/api/v1/articles/#{article.id}/children/#{child.id}?#{params.to_query}"
... ... @@ -66,7 +75,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
66 75 end
67 76  
68 77 should 'not return private child' do
69   - person = fast_create(Person)
  78 + person = fast_create(Person, :environment_id => environment.id)
70 79 article = fast_create(Article, :profile_id => person.id, :name => "Some thing")
71 80 child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing", :published => false)
72 81 get "/api/v1/articles/#{article.id}/children/#{child.id}?#{params.to_query}"
... ... @@ -74,7 +83,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
74 83 end
75 84  
76 85 should 'not list private child' do
77   - person = fast_create(Person)
  86 + person = fast_create(Person, :environment_id => environment.id)
78 87 article = fast_create(Article, :profile_id => person.id, :name => "Some thing")
79 88 child = fast_create(Article, :parent_id => article.id, :profile_id => person.id, :name => "Some thing", :published => false)
80 89 get "/api/v1/articles/#{article.id}/children?#{params.to_query}"
... ... @@ -82,6 +91,74 @@ class ArticlesTest &lt; ActiveSupport::TestCase
82 91 assert_not_includes json['articles'].map {|a| a['id']}, child.id
83 92 end
84 93  
  94 + should 'perform a vote in a article identified by id' do
  95 + article = fast_create(Article, :profile_id => @person.id, :name => "Some thing")
  96 + @params[:value] = 1
  97 +
  98 + post "/api/v1/articles/#{article.id}/vote?#{params.to_query}"
  99 + json = JSON.parse(last_response.body)
  100 +
  101 + assert_not_equal 401, last_response.status
  102 + assert_equal true, json['vote']
  103 + end
  104 +
  105 + expose_attributes = %w(id body abstract created_at title author profile categories image votes_for votes_against setting position hits start_date end_date tag_list parent children children_count)
  106 +
  107 + expose_attributes.each do |attr|
  108 + should "expose article #{attr} attribute by default" do
  109 + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
  110 + get "/api/v1/articles/?#{params.to_query}"
  111 + json = JSON.parse(last_response.body)
  112 + assert json["articles"].last.has_key?(attr)
  113 + end
  114 + end
  115 +
  116 + should "update body of article created by me" do
  117 + new_value = "Another body"
  118 + params[:article] = {:body => new_value}
  119 + article = fast_create(Article, :profile_id => person.id)
  120 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  121 + json = JSON.parse(last_response.body)
  122 + assert_equal new_value, json["article"]["body"]
  123 + end
  124 +
  125 + should "update title of article created by me" do
  126 + new_value = "Another name"
  127 + params[:article] = {:name => new_value}
  128 + article = fast_create(Article, :profile_id => person.id)
  129 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  130 + json = JSON.parse(last_response.body)
  131 + assert_equal new_value, json["article"]["title"]
  132 + end
  133 +
  134 + should 'not update article of another user' do
  135 + another_person = fast_create(Person, :environment_id => environment.id)
  136 + article = fast_create(Article, :profile_id => another_person.id)
  137 + params[:article] = {:title => 'Some title'}
  138 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  139 + assert_equal 403, last_response.status
  140 + end
  141 +
  142 + should 'not update article without permission in community' do
  143 + community = fast_create(Community, :environment_id => environment.id)
  144 + article = fast_create(Article, :profile_id => community.id)
  145 + params[:article] = {:name => 'New title'}
  146 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  147 + assert_equal 403, last_response.status
  148 + end
  149 +
  150 +
  151 + should 'update article of community if user has permission' do
  152 + community = fast_create(Community, :environment_id => environment.id)
  153 + give_permission(person, 'post_content', community)
  154 + article = fast_create(Article, :profile_id => community.id)
  155 + new_value = "Another body"
  156 + params[:article] = {:body => new_value}
  157 + post "/api/v1/articles/#{article.id}?#{params.to_query}"
  158 + json = JSON.parse(last_response.body)
  159 + assert_equal new_value, json["article"]["body"]
  160 + end
  161 +
85 162 should 'list articles with pagination' do
86 163 Article.destroy_all
87 164 article_one = fast_create(Article, :profile_id => user.person.id, :name => "Another thing", :created_at => 2.days.ago)
... ... @@ -126,7 +203,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
126 203 profile_kinds = %w(community person enterprise)
127 204 profile_kinds.each do |kind|
128 205 should "return article by #{kind}" do
129   - profile = fast_create(kind.camelcase.constantize)
  206 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
130 207 article = fast_create(Article, :profile_id => profile.id, :name => "Some thing")
131 208 get "/api/v1/#{kind.pluralize}/#{profile.id}/articles/#{article.id}?#{params.to_query}"
132 209 json = JSON.parse(last_response.body)
... ... @@ -134,7 +211,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
134 211 end
135 212  
136 213 should "not return article by #{kind} if user has no permission to view it" do
137   - profile = fast_create(kind.camelcase.constantize)
  214 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
138 215 article = fast_create(Article, :profile_id => profile.id, :name => "Some thing", :published => false)
139 216 assert !article.published?
140 217  
... ... @@ -143,7 +220,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
143 220 end
144 221  
145 222 should "not list forbidden article when listing articles by #{kind}" do
146   - profile = fast_create(kind.camelcase.constantize)
  223 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
147 224 article = fast_create(Article, :profile_id => profile.id, :name => "Some thing", :published => false)
148 225 assert !article.published?
149 226  
... ... @@ -151,6 +228,29 @@ class ArticlesTest &lt; ActiveSupport::TestCase
151 228 json = JSON.parse(last_response.body)
152 229 assert_not_includes json['articles'].map {|a| a['id']}, article.id
153 230 end
  231 +
  232 + should "return article by #{kind} and path" do
  233 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  234 + parent_article = Folder.create!(:profile => profile, :name => "Parent Folder")
  235 + article = Article.create!(:profile => profile, :name => "Some thing", :parent => parent_article)
  236 +
  237 + params[:path] = parent_article.slug+'/'+article.slug
  238 + get "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
  239 + json = JSON.parse(last_response.body)
  240 + assert_equal article.id, json["article"]["id"]
  241 + end
  242 +
  243 + should "not return article by #{kind} and path if user has no permission to view it" do
  244 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  245 + parent_article = Folder.create!(:profile => profile, :name => "Parent Folder")
  246 + article = Article.create!(:profile => profile, :name => "Some thing", :parent => parent_article, :published => false)
  247 +
  248 + assert !article.published?
  249 +
  250 + params[:path] = parent_article.slug+'/'+article.slug
  251 + get "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
  252 + assert_equal 403, last_response.status
  253 + end
154 254 end
155 255  
156 256 #############################
... ... @@ -160,7 +260,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
160 260 group_kinds = %w(community enterprise)
161 261 group_kinds.each do |kind|
162 262 should "#{kind}: create article" do
163   - profile = fast_create(kind.camelcase.constantize)
  263 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
164 264 give_permission(user.person, 'post_content', profile)
165 265 params[:article] = {:name => "Title"}
166 266 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
... ... @@ -169,16 +269,16 @@ class ArticlesTest &lt; ActiveSupport::TestCase
169 269 end
170 270  
171 271 should "#{kind}: do not create article if user has no permission to post content" do
172   - profile = fast_create(kind.camelcase.constantize)
  272 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
173 273 give_permission(user.person, 'invite_members', profile)
174 274 params[:article] = {:name => "Title"}
175 275 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
176 276 assert_equal 403, last_response.status
177 277 end
178 278  
179   - should "#{kind}: create article with parent" do
180   - profile = fast_create(kind.camelcase.constantize)
181   - profile.add_member(user.person)
  279 + should "#{kind} create article with parent" do
  280 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  281 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
182 282 article = fast_create(Article)
183 283  
184 284 params[:article] = {:name => "Title", :parent_id => article.id}
... ... @@ -187,9 +287,9 @@ class ArticlesTest &lt; ActiveSupport::TestCase
187 287 assert_equal article.id, json["article"]["parent"]["id"]
188 288 end
189 289  
190   - should "#{kind}: create article with content type passed as parameter" do
191   - profile = fast_create(kind.camelcase.constantize)
192   - profile.add_member(user.person)
  290 + should "#{kind} create article with content type passed as parameter" do
  291 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  292 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
193 293  
194 294 Article.delete_all
195 295 params[:article] = {:name => "Title"}
... ... @@ -201,8 +301,8 @@ class ArticlesTest &lt; ActiveSupport::TestCase
201 301 end
202 302  
203 303 should "#{kind}: create article of TinyMceArticle type if no content type is passed as parameter" do
204   - profile = fast_create(kind.camelcase.constantize)
205   - profile.add_member(user.person)
  304 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  305 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
206 306  
207 307 params[:article] = {:name => "Title"}
208 308 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
... ... @@ -212,7 +312,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
212 312 end
213 313  
214 314 should "#{kind}: not create article with invalid article content type" do
215   - profile = fast_create(kind.camelcase.constantize)
  315 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
216 316 profile.add_member(user.person)
217 317  
218 318 params[:article] = {:name => "Title"}
... ... @@ -223,20 +323,20 @@ class ArticlesTest &lt; ActiveSupport::TestCase
223 323 assert_equal 403, last_response.status
224 324 end
225 325  
226   - should "#{kind}: create article defining the correct profile" do
227   - profile = fast_create(kind.camelcase.constantize)
228   - profile.add_member(user.person)
  326 + should "#{kind} create article defining the correct profile" do
  327 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  328 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
229 329  
230 330 params[:article] = {:name => "Title"}
231 331 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
232 332 json = JSON.parse(last_response.body)
233 333  
234   - assert_equal profile, Article.last.profile
  334 + assert_equal profile.id, json['article']['profile']['id']
235 335 end
236 336  
237 337 should "#{kind}: create article defining the created_by" do
238   - profile = fast_create(kind.camelcase.constantize)
239   - profile.add_member(user.person)
  338 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  339 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
240 340  
241 341 params[:article] = {:name => "Title"}
242 342 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
... ... @@ -246,8 +346,8 @@ class ArticlesTest &lt; ActiveSupport::TestCase
246 346 end
247 347  
248 348 should "#{kind}: create article defining the last_changed_by" do
249   - profile = fast_create(kind.camelcase.constantize)
250   - profile.add_member(user.person)
  349 + profile = fast_create(kind.camelcase.constantize, :environment_id => environment.id)
  350 + Person.any_instance.stubs(:can_post_content?).with(profile).returns(true)
251 351  
252 352 params[:article] = {:name => "Title"}
253 353 post "/api/v1/#{kind.pluralize}/#{profile.id}/articles?#{params.to_query}"
... ... @@ -269,7 +369,7 @@ class ArticlesTest &lt; ActiveSupport::TestCase
269 369 end
270 370  
271 371 should 'person do not create article if user has no permission to post content' do
272   - person = fast_create(Person)
  372 + person = fast_create(Person, :environment_id => environment.id)
273 373 params[:article] = {:name => "Title"}
274 374 post "/api/v1/people/#{person.id}/articles?#{params.to_query}"
275 375 assert_equal 403, last_response.status
... ... @@ -376,4 +476,99 @@ class ArticlesTest &lt; ActiveSupport::TestCase
376 476 assert_equal [0, 1, 1], [a1.reload.hits, a2.reload.hits, a3.reload.hits]
377 477 end
378 478  
  479 + should 'update hit attribute of article specific children' do
  480 + a1 = fast_create(Article, :profile_id => user.person.id)
  481 + a2 = fast_create(Article, :parent_id => a1.id, :profile_id => user.person.id)
  482 + get "/api/v1/articles/#{a1.id}/children/#{a2.id}?#{params.to_query}"
  483 + json = JSON.parse(last_response.body)
  484 + assert_equal 1, json['article']['hits']
  485 + end
  486 +
  487 + should 'list all events of a community in a given category' do
  488 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  489 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  490 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  491 + e1 = fast_create(Event, :profile_id => co.id)
  492 + e2 = fast_create(Event, :profile_id => co.id)
  493 + e1.categories << c1
  494 + e2.categories << c2
  495 + e1.save!
  496 + e2.save!
  497 + params['content_type']='Event'
  498 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  499 + json = JSON.parse(last_response.body)
  500 + assert_equal json['articles'].count, 2
  501 + end
  502 +
  503 + should 'list a event of a community in a given category' do
  504 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  505 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  506 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  507 + e1 = fast_create(Event, :profile_id => co.id)
  508 + e2 = fast_create(Event, :profile_id => co.id)
  509 + e1.categories << c1
  510 + e2.categories << c2
  511 + e1.save!
  512 + e2.save!
  513 + params['category_ids[]']=c1.id
  514 + params['content_type']='Event'
  515 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  516 + json = JSON.parse(last_response.body)
  517 + #should show only one article, since the other not in the same category
  518 + assert_equal 1, json['articles'].count
  519 + assert_equal e1.id, json['articles'][0]['id']
  520 + end
  521 +
  522 + should 'not list uncategorized event of a community if a category is given' do
  523 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  524 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  525 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  526 + e1 = fast_create(Event, :profile_id => co.id)
  527 + e2 = fast_create(Event, :profile_id => co.id)
  528 + e3 = fast_create(Event, :profile_id => co.id)
  529 + e1.categories << c1
  530 + e2.categories << c2
  531 + params['category_ids[]']=c1.id
  532 + params['content_type']='Event'
  533 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  534 + json = JSON.parse(last_response.body)
  535 + assert_equal 1, json['articles'].count
  536 + assert_equal e1.id, json['articles'][0]['id']
  537 + end
  538 +
  539 + should 'list events of a community in a given 2 categories' do
  540 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  541 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  542 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  543 + e1 = fast_create(Event, :profile_id => co.id)
  544 + e2 = fast_create(Event, :profile_id => co.id)
  545 + e1.categories << c1
  546 + e2.categories << c2
  547 + e1.save!
  548 + e2.save!
  549 + params['content_type']='Event'
  550 + params['categories_ids'] = [c1.id, c2.id]
  551 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  552 + json = JSON.parse(last_response.body)
  553 + assert_equal json['articles'].count, 2
  554 + end
  555 +
  556 + should 'Show 2 events since it uses an IN operator for category instead of an OR' do
  557 + co = Community.create(identifier: 'my-community', name: 'name-my-community')
  558 + c1 = Category.create(environment: Environment.default, name: 'my-category')
  559 + c2 = Category.create(environment: Environment.default, name: 'dont-show-me-this-category')
  560 + c3 = Category.create(environment: Environment.default, name: 'extra-category')
  561 + e1 = fast_create(Event, :profile_id => co.id)
  562 + e2 = fast_create(Event, :profile_id => co.id)
  563 + e1.categories << c1
  564 + e2.categories << c2
  565 + e1.save!
  566 + e2.save!
  567 + params['content_type']='Event'
  568 + params['categories_ids'] = [c1.id, c2.id, c3.id]
  569 + get "api/v1/communities/#{co.id}/articles?#{params.to_query}"
  570 + json = JSON.parse(last_response.body)
  571 + assert_equal json['articles'].count, 2
  572 + end
  573 +
379 574 end
... ...
test/unit/api/categories_test.rb
... ... @@ -7,25 +7,25 @@ class CategoriesTest &lt; ActiveSupport::TestCase
7 7 end
8 8  
9 9 should 'list categories' do
10   - category = fast_create(Category)
  10 + category = fast_create(Category, :environment_id => environment.id)
11 11 get "/api/v1/categories/?#{params.to_query}"
12 12 json = JSON.parse(last_response.body)
13 13 assert_includes json["categories"].map { |c| c["name"] }, category.name
14 14 end
15 15  
16 16 should 'get category by id' do
17   - category = fast_create(Category)
  17 + category = fast_create(Category, :environment_id => environment.id)
18 18 get "/api/v1/categories/#{category.id}/?#{params.to_query}"
19 19 json = JSON.parse(last_response.body)
20 20 assert_equal category.name, json["category"]["name"]
21 21 end
22 22  
23 23 should 'list parent and children when get category by id' do
24   - parent = fast_create(Category)
25   - child_1 = fast_create(Category)
26   - child_2 = fast_create(Category)
  24 + parent = fast_create(Category, :environment_id => environment.id)
  25 + child_1 = fast_create(Category, :environment_id => environment.id)
  26 + child_2 = fast_create(Category, :environment_id => environment.id)
27 27  
28   - category = fast_create(Category)
  28 + category = fast_create(Category, :environment_id => environment.id)
29 29 category.parent = parent
30 30 category.children << child_1
31 31 category.children << child_2
... ... @@ -33,16 +33,16 @@ class CategoriesTest &lt; ActiveSupport::TestCase
33 33  
34 34 get "/api/v1/categories/#{category.id}/?#{params.to_query}"
35 35 json = JSON.parse(last_response.body)
36   - assert_equal({'id' => parent.id, 'name' => parent.name}, json['category']['parent'])
  36 + assert_equal({'id' => parent.id, 'name' => parent.name, 'slug' => parent.slug}, json['category']['parent'])
37 37 assert_equivalent [child_1.id, child_2.id], json['category']['children'].map { |c| c['id'] }
38 38 end
39 39  
40 40 should 'include parent in categories list if params is true' do
41   - parent_1 = fast_create(Category) # parent_1 has no parent category
42   - child_1 = fast_create(Category)
43   - child_2 = fast_create(Category)
  41 + parent_1 = fast_create(Category, :environment_id => environment.id) # parent_1 has no parent category
  42 + child_1 = fast_create(Category, :environment_id => environment.id)
  43 + child_2 = fast_create(Category, :environment_id => environment.id)
44 44  
45   - parent_2 = fast_create(Category)
  45 + parent_2 = fast_create(Category, :environment_id => environment.id)
46 46 parent_2.parent = parent_1
47 47 parent_2.children << child_1
48 48 parent_2.children << child_2
... ... @@ -60,10 +60,10 @@ class CategoriesTest &lt; ActiveSupport::TestCase
60 60 end
61 61  
62 62 should 'include children in categories list if params is true' do
63   - category = fast_create(Category)
64   - child_1 = fast_create(Category)
65   - child_2 = fast_create(Category)
66   - child_3 = fast_create(Category)
  63 + category = fast_create(Category, :environment_id => environment.id)
  64 + child_1 = fast_create(Category, :environment_id => environment.id)
  65 + child_2 = fast_create(Category, :environment_id => environment.id)
  66 + child_3 = fast_create(Category, :environment_id => environment.id)
67 67  
68 68 category.children << child_1
69 69 category.children << child_2
... ... @@ -83,4 +83,15 @@ class CategoriesTest &lt; ActiveSupport::TestCase
83 83 json["categories"].map{ |c| c['children'].map{ |child| child['id'] }.sort }
84 84 end
85 85  
  86 + expose_attributes = %w(id name full_name image display_color)
  87 +
  88 + expose_attributes.each do |attr|
  89 + should "expose category #{attr} attribute by default" do
  90 + category = fast_create(Category, :environment_id => environment.id)
  91 + get "/api/v1/categories/?#{params.to_query}"
  92 + json = JSON.parse(last_response.body)
  93 + assert json["categories"].last.has_key?(attr)
  94 + end
  95 + end
  96 +
86 97 end
... ...
test/unit/api/comments_test.rb
... ... @@ -65,4 +65,17 @@ class CommentsTest &lt; ActiveSupport::TestCase
65 65 assert_equal 201, last_response.status
66 66 assert_equal body, json['comment']['body']
67 67 end
  68 +
  69 + should 'comment creation define the source' do
  70 + amount = Comment.count
  71 + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing")
  72 + body = 'My comment'
  73 + params.merge!({:body => body})
  74 +
  75 + post "/api/v1/articles/#{article.id}/comments?#{params.to_query}"
  76 + assert_equal amount + 1, Comment.count
  77 + comment = Comment.last
  78 + assert_not_nil comment.source
  79 + end
  80 +
68 81 end
... ...
test/unit/api/communities_test.rb
... ... @@ -8,8 +8,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
8 8 end
9 9  
10 10 should 'list only communities' do
11   - community = fast_create(Community)
12   - enterprise = fast_create(Enterprise) # should not list this enterprise
  11 + community = fast_create(Community, :environment_id => environment.id)
  12 + enterprise = fast_create(Enterprise, :environment_id => environment.id) # should not list this enterprise
13 13 get "/api/v1/communities?#{params.to_query}"
14 14 json = JSON.parse(last_response.body)
15 15 assert_not_includes json['communities'].map {|c| c['id']}, enterprise.id
... ... @@ -17,16 +17,16 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
17 17 end
18 18  
19 19 should 'list all communities' do
20   - community1 = fast_create(Community, :public_profile => true)
21   - community2 = fast_create(Community)
  20 + community1 = fast_create(Community, :environment_id => environment.id, :public_profile => true)
  21 + community2 = fast_create(Community, :environment_id => environment.id)
22 22 get "/api/v1/communities?#{params.to_query}"
23 23 json = JSON.parse(last_response.body)
24 24 assert_equivalent [community1.id, community2.id], json['communities'].map {|c| c['id']}
25 25 end
26 26  
27 27 should 'not list invisible communities' do
28   - community1 = fast_create(Community)
29   - fast_create(Community, :visible => false)
  28 + community1 = fast_create(Community, :environment_id => environment.id)
  29 + fast_create(Community, :environment_id => environment.id, :visible => false)
30 30  
31 31 get "/api/v1/communities?#{params.to_query}"
32 32 json = JSON.parse(last_response.body)
... ... @@ -34,8 +34,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
34 34 end
35 35  
36 36 should 'not list private communities without permission' do
37   - community1 = fast_create(Community)
38   - fast_create(Community, :public_profile => false)
  37 + community1 = fast_create(Community, :environment_id => environment.id)
  38 + fast_create(Community, :environment_id => environment.id, :public_profile => false)
39 39  
40 40 get "/api/v1/communities?#{params.to_query}"
41 41 json = JSON.parse(last_response.body)
... ... @@ -43,8 +43,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
43 43 end
44 44  
45 45 should 'list private community for members' do
46   - c1 = fast_create(Community)
47   - c2 = fast_create(Community, :public_profile => false)
  46 + c1 = fast_create(Community, :environment_id => environment.id)
  47 + c2 = fast_create(Community, :environment_id => environment.id, :public_profile => false)
48 48 c2.add_member(person)
49 49  
50 50 get "/api/v1/communities?#{params.to_query}"
... ... @@ -66,7 +66,7 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
66 66 end
67 67  
68 68 should 'get community' do
69   - community = fast_create(Community)
  69 + community = fast_create(Community, :environment_id => environment.id)
70 70  
71 71 get "/api/v1/communities/#{community.id}?#{params.to_query}"
72 72 json = JSON.parse(last_response.body)
... ... @@ -74,7 +74,7 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
74 74 end
75 75  
76 76 should 'not get invisible community' do
77   - community = fast_create(Community, :visible => false)
  77 + community = fast_create(Community, :environment_id => environment.id, :visible => false)
78 78  
79 79 get "/api/v1/communities/#{community.id}?#{params.to_query}"
80 80 json = JSON.parse(last_response.body)
... ... @@ -82,8 +82,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
82 82 end
83 83  
84 84 should 'not get private communities without permission' do
85   - community = fast_create(Community)
86   - fast_create(Community, :public_profile => false)
  85 + community = fast_create(Community, :environment_id => environment.id)
  86 + fast_create(Community, :environment_id => environment.id, :public_profile => false)
87 87  
88 88 get "/api/v1/communities/#{community.id}?#{params.to_query}"
89 89 json = JSON.parse(last_response.body)
... ... @@ -91,17 +91,18 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
91 91 end
92 92  
93 93 should 'get private community for members' do
94   - community = fast_create(Community, :public_profile => false)
  94 + community = fast_create(Community, :environment_id => environment.id, :public_profile => false, :visible => true)
95 95 community.add_member(person)
96 96  
  97 +
97 98 get "/api/v1/communities/#{community.id}?#{params.to_query}"
98 99 json = JSON.parse(last_response.body)
99 100 assert_equal community.id, json['community']['id']
100 101 end
101 102  
102 103 should 'list person communities' do
103   - community = fast_create(Community)
104   - fast_create(Community)
  104 + community = fast_create(Community, :environment_id => environment.id)
  105 + fast_create(Community, :environment_id => environment.id)
105 106 community.add_member(person)
106 107  
107 108 get "/api/v1/people/#{person.id}/communities?#{params.to_query}"
... ... @@ -110,8 +111,8 @@ class CommunitiesTest &lt; ActiveSupport::TestCase
110 111 end
111 112  
112 113 should 'not list person communities invisible' do
113   - c1 = fast_create(Community)
114   - c2 = fast_create(Community, :visible => false)
  114 + c1 = fast_create(Community, :environment_id => environment.id)
  115 + c2 = fast_create(Community, :environment_id => environment.id, :visible => false)
115 116 c1.add_member(person)
116 117 c2.add_member(person)
117 118  
... ...
test/unit/api/enterprises_test.rb
... ... @@ -8,8 +8,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
8 8 end
9 9  
10 10 should 'list only enterprises' do
11   - community = fast_create(Community) # should not list this community
12   - enterprise = fast_create(Enterprise, :public_profile => true)
  11 + community = fast_create(Community, :environment_id => environment.id) # should not list this community
  12 + enterprise = fast_create(Enterprise, :environment_id => environment.id, :public_profile => true)
13 13 get "/api/v1/enterprises?#{params.to_query}"
14 14 json = JSON.parse(last_response.body)
15 15 assert_includes json['enterprises'].map {|c| c['id']}, enterprise.id
... ... @@ -17,15 +17,15 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
17 17 end
18 18  
19 19 should 'list all enterprises' do
20   - enterprise1 = fast_create(Enterprise, :public_profile => true)
21   - enterprise2 = fast_create(Enterprise)
  20 + enterprise1 = fast_create(Enterprise, :environment_id => environment.id, :public_profile => true)
  21 + enterprise2 = fast_create(Enterprise, :environment_id => environment.id)
22 22 get "/api/v1/enterprises?#{params.to_query}"
23 23 json = JSON.parse(last_response.body)
24 24 assert_equivalent [enterprise1.id, enterprise2.id], json['enterprises'].map {|c| c['id']}
25 25 end
26 26  
27 27 should 'not list invisible enterprises' do
28   - enterprise1 = fast_create(Enterprise)
  28 + enterprise1 = fast_create(Enterprise, :environment_id => environment.id)
29 29 fast_create(Enterprise, :visible => false)
30 30  
31 31 get "/api/v1/enterprises?#{params.to_query}"
... ... @@ -34,8 +34,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
34 34 end
35 35  
36 36 should 'not list private enterprises without permission' do
37   - enterprise1 = fast_create(Enterprise)
38   - fast_create(Enterprise, :public_profile => false)
  37 + enterprise1 = fast_create(Enterprise, :environment_id => environment.id)
  38 + fast_create(Enterprise, :environment_id => environment.id, :public_profile => false)
39 39  
40 40 get "/api/v1/enterprises?#{params.to_query}"
41 41 json = JSON.parse(last_response.body)
... ... @@ -43,8 +43,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
43 43 end
44 44  
45 45 should 'list private enterprise for members' do
46   - c1 = fast_create(Enterprise)
47   - c2 = fast_create(Enterprise, :public_profile => false)
  46 + c1 = fast_create(Enterprise, :environment_id => environment.id)
  47 + c2 = fast_create(Enterprise, :environment_id => environment.id, :public_profile => false)
48 48 c2.add_member(person)
49 49  
50 50 get "/api/v1/enterprises?#{params.to_query}"
... ... @@ -53,7 +53,7 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
53 53 end
54 54  
55 55 should 'get enterprise' do
56   - enterprise = fast_create(Enterprise)
  56 + enterprise = fast_create(Enterprise, :environment_id => environment.id)
57 57  
58 58 get "/api/v1/enterprises/#{enterprise.id}?#{params.to_query}"
59 59 json = JSON.parse(last_response.body)
... ... @@ -69,8 +69,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
69 69 end
70 70  
71 71 should 'not get private enterprises without permission' do
72   - enterprise = fast_create(Enterprise)
73   - fast_create(Enterprise, :public_profile => false)
  72 + enterprise = fast_create(Enterprise, :environment_id => environment.id)
  73 + fast_create(Enterprise, :environment_id => environment.id, :public_profile => false)
74 74  
75 75 get "/api/v1/enterprises/#{enterprise.id}?#{params.to_query}"
76 76 json = JSON.parse(last_response.body)
... ... @@ -87,8 +87,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
87 87 end
88 88  
89 89 should 'list person enterprises' do
90   - enterprise = fast_create(Enterprise)
91   - fast_create(Enterprise)
  90 + enterprise = fast_create(Enterprise, :environment_id => environment.id)
  91 + fast_create(Enterprise, :environment_id => environment.id)
92 92 enterprise.add_member(person)
93 93  
94 94 get "/api/v1/people/#{person.id}/enterprises?#{params.to_query}"
... ... @@ -97,8 +97,8 @@ class EnterprisesTest &lt; ActiveSupport::TestCase
97 97 end
98 98  
99 99 should 'not list person enterprises invisible' do
100   - c1 = fast_create(Enterprise)
101   - c2 = fast_create(Enterprise, :visible => false)
  100 + c1 = fast_create(Enterprise, :environment_id => environment.id)
  101 + c2 = fast_create(Enterprise, :environment_id => environment.id, :visible => false)
102 102 c1.add_member(person)
103 103 c2.add_member(person)
104 104  
... ...
test/unit/api/helpers_test.rb
... ... @@ -25,15 +25,6 @@ class APIHelpersTest &lt; ActiveSupport::TestCase
25 25 assert_equal user, current_user
26 26 end
27 27  
28   - should 'not get the current user with expired token' do
29   - user = create_user('someuser')
30   - user.generate_private_token!
31   - user.private_token_generated_at = DateTime.now.prev_year
32   - user.save
33   - self.params = {:private_token => user.private_token}
34   - assert_nil current_user
35   - end
36   -
37 28 should 'get the person of current user' do
38 29 user = create_user('someuser')
39 30 user.generate_private_token!
... ... @@ -161,6 +152,39 @@ class APIHelpersTest &lt; ActiveSupport::TestCase
161 152 assert_nil make_conditions_with_parameter[:type]
162 153 end
163 154  
  155 + #test_should_make_order_with_parameters_return_order_if attribute_is_found_at_object_association
  156 + should 'make_order_with_parameters return order if attribute is found at object association' do
  157 + environment = Environment.new
  158 + params = {:order => "name ASC"}
  159 + assert_equal "name ASC", make_order_with_parameters(environment, "articles", params)
  160 + end
  161 +
  162 + # test added to check for eventual sql injection vunerabillity
  163 + #test_should_make_order_with_parameters_return_default_order_if_attributes_not_exists
  164 + should 'make_order_with_parameters return default order if attributes not exists' do
  165 + environment = Environment.new
  166 + params = {:order => "CRAZY_FIELD ASC"} # quote used to check sql injection vunerabillity
  167 + assert_equal "created_at DESC", make_order_with_parameters(environment, "articles", params)
  168 + end
  169 +
  170 + should 'make_order_with_parameters return default order if sql injection detected' do
  171 + environment = Environment.new
  172 + params = {:order => "name' ASC"} # quote used to check sql injection vunerabillity
  173 + assert_equal "created_at DESC", make_order_with_parameters(environment, "articles", params)
  174 + end
  175 +
  176 + should 'make_order_with_parameters return RANDOM() if random is passed' do
  177 + environment = Environment.new
  178 + params = {:order => "random"} # quote used to check sql injection vunerabillity
  179 + assert_equal "RANDOM()", make_order_with_parameters(environment, "articles", params)
  180 + end
  181 +
  182 + should 'make_order_with_parameters return RANDOM() if random function is passed' do
  183 + environment = Environment.new
  184 + params = {:order => "random()"} # quote used to check sql injection vunerabillity
  185 + assert_equal "RANDOM()", make_order_with_parameters(environment, "articles", params)
  186 + end
  187 +
164 188 should 'render not_found if endpoint is unavailable' do
165 189 Noosfero::API::API.stubs(:endpoint_unavailable?).returns(true)
166 190 self.expects(:not_found!)
... ...
test/unit/api/people_test.rb
... ... @@ -148,4 +148,21 @@ class PeopleTest &lt; ActiveSupport::TestCase
148 148 get "/api/v1/people/#{some_person.id}/permissions?#{params.to_query}"
149 149 assert_equal 403, last_response.status
150 150 end
  151 +
  152 + should 'not update another person' do
  153 + person = fast_create(Person, :environment_id => environment.id)
  154 + post "/api/v1/people/#{person.id}?#{params.to_query}"
  155 + assert_equal 403, last_response.status
  156 + end
  157 +
  158 + should 'update yourself' do
  159 + another_name = 'Another Name'
  160 + params[:person] = {}
  161 + params[:person][:name] = another_name
  162 + assert_not_equal another_name, person.name
  163 + post "/api/v1/people/#{person.id}?#{params.to_query}"
  164 + person.reload
  165 + assert_equal another_name, person.name
  166 + end
  167 +
151 168 end
... ...
test/unit/api/search_test.rb 0 → 100644
... ... @@ -0,0 +1,139 @@
  1 +require_relative 'test_helper'
  2 +
  3 +class SearchTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @person = create_user('testing').person
  7 + end
  8 + attr_reader :person
  9 +
  10 + should 'not list unpublished articles' do
  11 + Article.delete_all
  12 + article = fast_create(Article, :profile_id => person.id, :published => false)
  13 + assert !article.published?
  14 + get "/api/v1/search/article"
  15 + json = JSON.parse(last_response.body)
  16 + assert_empty json['articles']
  17 + end
  18 +
  19 + should 'list articles' do
  20 + fast_create(Article, :profile_id => person.id)
  21 + get "/api/v1/search/article"
  22 + json = JSON.parse(last_response.body)
  23 + assert_not_empty json['articles']
  24 + end
  25 +
  26 + should 'invalid search string articles' do
  27 + fast_create(Article, :profile_id => person.id, :name => 'some article')
  28 + get "/api/v1/search/article?query=test"
  29 + json = JSON.parse(last_response.body)
  30 + assert_empty json['articles']
  31 + end
  32 +
  33 + should 'do not list articles of wrong type' do
  34 + fast_create(Article, :profile_id => person.id)
  35 + get "/api/v1/search/article?type=TinyMceArticle"
  36 + json = JSON.parse(last_response.body)
  37 + assert_empty json['articles']
  38 + end
  39 +
  40 + should 'list articles of one type' do
  41 + fast_create(Article, :profile_id => person.id)
  42 + article = fast_create(TinyMceArticle, :profile_id => person.id)
  43 +
  44 + get "/api/v1/search/article?type=TinyMceArticle"
  45 + json = JSON.parse(last_response.body)
  46 + assert_equal article.id, json['articles'].first['id']
  47 + end
  48 +
  49 + should 'list articles of one type and query string' do
  50 + fast_create(Article, :profile_id => person.id, :name => 'some article')
  51 + fast_create(Article, :profile_id => person.id, :name => 'Some thing')
  52 + article = fast_create(TinyMceArticle, :profile_id => person.id, :name => 'Some thing')
  53 + get "/api/v1/search/article?type=TinyMceArticle&query=thing"
  54 + json = JSON.parse(last_response.body)
  55 + assert_equal 1, json['articles'].count
  56 + assert_equal article.id, json['articles'].first['id']
  57 + end
  58 +
  59 + should 'not return more entries than page limit' do
  60 + 1.upto(5).each do |n|
  61 + fast_create(Article, :profile_id => person.id, :name => "Article #{n}")
  62 + end
  63 +
  64 + get "/api/v1/search/article?query=Article&per_page=3"
  65 + json = JSON.parse(last_response.body)
  66 +
  67 + assert_equal 3, json['articles'].count
  68 + end
  69 +
  70 + should 'return entries second page' do
  71 + 1.upto(5).each do |n|
  72 + fast_create(Article, :profile_id => person.id, :name => "Article #{n}")
  73 + end
  74 +
  75 + get "/api/v1/search/article?query=Article&per_page=3&page=2"
  76 + json = JSON.parse(last_response.body)
  77 +
  78 + assert_equal 2, json['articles'].count
  79 + end
  80 +
  81 + should 'search articles in profile' do
  82 + person2 = fast_create(Person)
  83 + fast_create(Article, :profile_id => person.id)
  84 + fast_create(Article, :profile_id => person.id)
  85 + article = fast_create(Article, :profile_id => person2.id)
  86 +
  87 + get "/api/v1/search/article?query=Article&profile_id=#{person2.id}"
  88 + json = JSON.parse(last_response.body)
  89 + assert_equal article.id, json['articles'].first['id']
  90 + end
  91 +
  92 + should 'search and return values specified in fields parameter' do
  93 + fast_create(Article, :profile_id => person.id)
  94 + get "/api/v1/search/article?fields=title"
  95 + json = JSON.parse(last_response.body)
  96 + assert_not_empty json['articles']
  97 + assert_equal ['title'], json['articles'].first.keys
  98 + end
  99 +
  100 + should 'search with parent' do
  101 + parent = fast_create(Folder, :profile_id => person.id)
  102 + fast_create(Article, :profile_id => person.id)
  103 + article = fast_create(Article, :profile_id => person.id, :parent_id => parent.id)
  104 + get "/api/v1/search/article?parent_id=#{parent.id}"
  105 + json = JSON.parse(last_response.body)
  106 + assert_equal 1, json['articles'].count
  107 + assert_equal article.id, json['articles'].first["id"]
  108 + end
  109 +
  110 + should 'search filter by category' do
  111 + Article.delete_all
  112 + fast_create(Article, :profile_id => person.id)
  113 + article = fast_create(Article, :profile_id => person.id)
  114 + category = fast_create(Category)
  115 + article.categories<< category
  116 + get "/api/v1/search/article?category_ids=#{category.id}"
  117 + json = JSON.parse(last_response.body)
  118 + assert_equal 1, json['articles'].count
  119 + assert_equal article.id, json['articles'].first["id"]
  120 + end
  121 +
  122 + should 'search filter by more than one category' do
  123 + Article.delete_all
  124 + fast_create(Article, :profile_id => person.id)
  125 + article1 = fast_create(Article, :profile_id => person.id)
  126 + article2 = fast_create(Article, :profile_id => person.id)
  127 + category1 = fast_create(Category)
  128 + category2 = fast_create(Category)
  129 + article1.categories<< category1
  130 + article2.categories<< category2
  131 + get "/api/v1/search/article?category_ids[]=#{category1.id}&category_ids[]=#{category2.id}"
  132 + json = JSON.parse(last_response.body)
  133 + ids = [article1.id, article2.id]
  134 + assert_equal 2, json['articles'].count
  135 + assert_includes ids, json['articles'].first["id"]
  136 + assert_includes ids, json['articles'].last["id"]
  137 + end
  138 +
  139 +end
... ...
test/unit/api/session_test.rb
... ... @@ -10,7 +10,7 @@ class SessionTest &lt; ActiveSupport::TestCase
10 10 params = {:login => "testapi", :password => "testapi"}
11 11 post "/api/v1/login?#{params.to_query}"
12 12 json = JSON.parse(last_response.body)
13   - assert !json["private_token"].blank?
  13 + assert !json['user']["private_token"].blank?
14 14 end
15 15  
16 16 should 'return 401 when login fails' do
... ... @@ -21,22 +21,165 @@ class SessionTest &lt; ActiveSupport::TestCase
21 21 end
22 22  
23 23 should 'register a user' do
24   - params = {:login => "newuserapi", :password => "newuserapi", :email => "newuserapi@email.com" }
  24 + Environment.default.enable('skip_new_user_email_confirmation')
  25 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
25 26 post "/api/v1/register?#{params.to_query}"
26 27 assert_equal 201, last_response.status
  28 + json = JSON.parse(last_response.body)
  29 + assert User['newuserapi'].activated?
  30 + assert json['user']['activated']
  31 + assert json['user']['private_token'].present?
  32 + end
  33 +
  34 + should 'register a user with name' do
  35 + Environment.default.enable('skip_new_user_email_confirmation')
  36 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com", :name => "Little John" }
  37 + post "/api/v1/register?#{params.to_query}"
  38 + assert_equal 201, last_response.status
  39 + json = JSON.parse(last_response.body)
  40 + assert json['user']['activated']
  41 + assert json['user']['private_token'].present?
  42 + end
  43 +
  44 + should 'register an inactive user' do
  45 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
  46 + post "/api/v1/register?#{params.to_query}"
  47 + assert_equal 201, last_response.status
  48 + json = JSON.parse(last_response.body)
  49 + assert !json['activated']
  50 + assert json['private_token'].blank?
27 51 end
28 52  
29   - should 'do not register a user without email' do
30   - params = {:login => "newuserapi", :password => "newuserapi", :email => nil }
  53 + should 'not register a user with invalid login' do
  54 + params = {:login => "c", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
31 55 post "/api/v1/register?#{params.to_query}"
32 56 assert_equal 400, last_response.status
  57 + json = JSON.parse(last_response.body)
  58 + msg = json['message'].split(':')
  59 + key = msg[0][2, 5]
  60 + val = msg[1][2, 38]
  61 + assert_equal "login", key
  62 + assert_equal "is too short (minimum is 2 characters)", val
33 63 end
34 64  
35   - should 'do not register a duplicated user' do
36   - params = {:login => "newuserapi", :password => "newuserapi", :email => "newuserapi@email.com" }
  65 + should 'not register a user with invalid login pt' do
  66 + I18n.locale = "pt-BR"
  67 + params = {:lang => "pt-BR", :login => "c", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
37 68 post "/api/v1/register?#{params.to_query}"
  69 + assert_equal 400, last_response.status
  70 + json = JSON.parse(last_response.body)
  71 + msg = json['message'].split(':')
  72 + key = msg[0][2, 5]
  73 + val = msg[1][2, 35]
  74 + assert_equal "login", key
  75 + assert val.include? "muito curto"
  76 + end
  77 +
  78 + should 'not register a user without email' do
  79 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => nil }
38 80 post "/api/v1/register?#{params.to_query}"
39 81 assert_equal 400, last_response.status
40 82 end
41 83  
  84 + should 'not register a duplicated user' do
  85 + params = {:login => "newuserapi", :password => "newuserapi", :password_confirmation => "newuserapi", :email => "newuserapi@email.com" }
  86 + post "/api/v1/register?#{params.to_query}"
  87 + post "/api/v1/register?#{params.to_query}"
  88 + assert_equal 400, last_response.status
  89 + json = JSON.parse(last_response.body)
  90 + end
  91 +
  92 + # TODO: Add another test cases to check register situations
  93 + should 'activate a user' do
  94 + params = {
  95 + :login => "newuserapi",
  96 + :password => "newuserapi",
  97 + :password_confirmation => "newuserapi",
  98 + :email => "newuserapi@email.com"
  99 + }
  100 + user = User.new(params)
  101 + user.save!
  102 +
  103 + params = { activation_code: user.activation_code}
  104 + patch "/api/v1/activate?#{params.to_query}"
  105 + assert_equal 200, last_response.status
  106 + end
  107 +
  108 + should 'do not activate a user if admin must approve him' do
  109 + params = {
  110 + :login => "newuserapi",
  111 + :password => "newuserapi",
  112 + :password_confirmation => "newuserapi",
  113 + :email => "newuserapi@email.com",
  114 + :environment => Environment.default
  115 + }
  116 + user = User.new(params)
  117 + user.environment.enable('admin_must_approve_new_users')
  118 + user.save!
  119 +
  120 + params = { activation_code: user.activation_code}
  121 + patch "/api/v1/activate?#{params.to_query}"
  122 + assert_equal 202, last_response.status
  123 + assert_equal 'Waiting for admin moderate user registration', JSON.parse(last_response.body)["message"]
  124 + end
  125 +
  126 + should 'do not activate a user if the token is invalid' do
  127 + params = {
  128 + :login => "newuserapi",
  129 + :password => "newuserapi",
  130 + :password_confirmation => "newuserapi",
  131 + :email => "newuserapi@email.com",
  132 + :environment => Environment.default
  133 + }
  134 + user = User.new(params)
  135 + user.save!
  136 +
  137 + params = { activation_code: '70250abe20cc6a67ef9399cf3286cb998b96aeaf'}
  138 + patch "/api/v1/activate?#{params.to_query}"
  139 + assert_equal 412, last_response.status
  140 + end
  141 +
  142 + should 'create task to change password by user login' do
  143 + user = create_user
  144 + params = {:value => user.login}
  145 + assert_difference 'ChangePassword.count' do
  146 + post "/api/v1/forgot_password?#{params.to_query}"
  147 + end
  148 + end
  149 +
  150 + should 'not create task to change password when user is not found' do
  151 + params = {:value => 'wronglogin'}
  152 + assert_no_difference 'ChangePassword.count' do
  153 + post "/api/v1/forgot_password?#{params.to_query}"
  154 + end
  155 + assert_equal 404, last_response.status
  156 + end
  157 +
  158 + should 'change user password and close task' do
  159 + task = ChangePassword.create!(:requestor => @person)
  160 + params.merge!({:code => task.code, :password => 'secret', :password_confirmation => 'secret'})
  161 + patch "/api/v1/new_password?#{params.to_query}"
  162 + assert_equal Task::Status::FINISHED, task.reload.status
  163 + assert user.reload.authenticated?('secret')
  164 + json = JSON.parse(last_response.body)
  165 + assert_equal user.id, json['user']['id']
  166 + end
  167 +
  168 + should 'do not change user password when password confirmation is wrong' do
  169 + user = create_user
  170 + user.activate
  171 + task = ChangePassword.create!(:requestor => user.person)
  172 + params = {:code => task.code, :password => 'secret', :password_confirmation => 's3cret'}
  173 + patch "/api/v1/new_password?#{params.to_query}"
  174 + assert_equal Task::Status::ACTIVE, task.reload.status
  175 + assert !user.reload.authenticated?('secret')
  176 + assert_equal 400, last_response.status
  177 + end
  178 +
  179 + should 'render not found when provide a wrong code on password change' do
  180 + params = {:code => "wrongcode", :password => 'secret', :password_confirmation => 'secret'}
  181 + patch "/api/v1/new_password?#{params.to_query}"
  182 + assert_equal 404, last_response.status
  183 + end
  184 +
42 185 end
... ...
test/unit/api/test_helper.rb
1   -require 'test_helper'
  1 +require_relative '../../test_helper'
2 2  
3 3 class ActiveSupport::TestCase
4 4  
... ... @@ -9,16 +9,22 @@ class ActiveSupport::TestCase
9 9 end
10 10  
11 11 def login_api
12   - @user = User.create!(:login => 'testapi', :password => 'testapi', :password_confirmation => 'testapi', :email => 'test@test.org', :environment => Environment.default)
  12 + @environment = Environment.default
  13 + @user = User.create!(:login => 'testapi', :password => 'testapi', :password_confirmation => 'testapi', :email => 'test@test.org', :environment => @environment)
13 14 @user.activate
14 15 @person = @user.person
15 16  
16 17 post "/api/v1/login?login=testapi&password=testapi"
17 18 json = JSON.parse(last_response.body)
18 19 @private_token = json["private_token"]
  20 + unless @private_token
  21 + @user.generate_private_token!
  22 + @private_token = @user.private_token
  23 + end
  24 +
19 25 @params = {:private_token => @private_token}
20 26 end
21   - attr_accessor :private_token, :user, :person, :params
  27 + attr_accessor :private_token, :user, :person, :params, :environment
22 28  
23 29 private
24 30  
... ...
test/unit/api/users_test.rb 0 → 100644
... ... @@ -0,0 +1,105 @@
  1 +# encoding: UTF-8
  2 +require_relative 'test_helper'
  3 +
  4 +class UsersTest < ActiveSupport::TestCase
  5 +
  6 + def setup
  7 + login_api
  8 + end
  9 +
  10 + should 'list users' do
  11 + get "/api/v1/users/?#{params.to_query}"
  12 + json = JSON.parse(last_response.body)
  13 + assert_includes json["users"].map { |a| a["login"] }, user.login
  14 + end
  15 +
  16 + should 'get user' do
  17 + get "/api/v1/users/#{user.id}?#{params.to_query}"
  18 + json = JSON.parse(last_response.body)
  19 + assert_equal user.id, json['user']['id']
  20 + end
  21 +
  22 + should 'list user permissions' do
  23 + community = fast_create(Community)
  24 + community.add_admin(person)
  25 + get "/api/v1/users/#{user.id}/?#{params.to_query}"
  26 + json = JSON.parse(last_response.body)
  27 + assert_includes json["user"]["permissions"], community.identifier
  28 + end
  29 +
  30 + should 'get logged user' do
  31 + get "/api/v1/users/me?#{params.to_query}"
  32 + json = JSON.parse(last_response.body)
  33 + assert_equal user.id, json['user']['id']
  34 + end
  35 +
  36 + should 'not show permissions to logged user' do
  37 + target_person = create_user('some-user').person
  38 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  39 + json = JSON.parse(last_response.body)
  40 + refute json["user"].has_key?("permissions")
  41 + end
  42 +
  43 + should 'show permissions to self' do
  44 + get "/api/v1/users/#{user.id}/?#{params.to_query}"
  45 + json = JSON.parse(last_response.body)
  46 + assert json["user"].has_key?("permissions")
  47 + end
  48 +
  49 + should 'not show permissions to friend' do
  50 + target_person = create_user('some-user').person
  51 +
  52 + f = Friendship.new
  53 + f.friend = target_person
  54 + f.person = person
  55 + f.save!
  56 +
  57 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  58 + json = JSON.parse(last_response.body)
  59 + refute json["user"].has_key?("permissions")
  60 + end
  61 +
  62 + should 'not show private attribute to logged user' do
  63 + target_person = create_user('some-user').person
  64 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  65 + json = JSON.parse(last_response.body)
  66 + refute json["user"].has_key?("email")
  67 + end
  68 +
  69 + should 'show private attr to friend' do
  70 + target_person = create_user('some-user').person
  71 + f = Friendship.new
  72 + f.friend = target_person
  73 + f.person = person
  74 + f.save!
  75 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  76 + json = JSON.parse(last_response.body)
  77 + assert json["user"].has_key?("email")
  78 + assert_equal target_person.email, json["user"]["email"]
  79 + end
  80 +
  81 + should 'show public attribute to logged user' do
  82 + target_person = create_user('some-user').person
  83 + target_person.fields_privacy={:email=> 'public'}
  84 + target_person.save!
  85 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  86 + json = JSON.parse(last_response.body)
  87 + assert json["user"].has_key?("email")
  88 + assert_equal json["user"]["email"],target_person.email
  89 + end
  90 +
  91 + should 'show public and private field to admin' do
  92 + Environment.default.add_admin(person)
  93 +
  94 + target_person = create_user('some-user').person
  95 + target_person.fields_privacy={:email=> 'public'}
  96 + target_person.save!
  97 +
  98 + get "/api/v1/users/#{target_person.user.id}/?#{params.to_query}"
  99 + json = JSON.parse(last_response.body)
  100 + assert json["user"].has_key?("email")
  101 + assert json["user"].has_key?("permissions")
  102 + assert json["user"].has_key?("activated")
  103 + end
  104 +
  105 +end
... ...
test/unit/create_thumbnails_job_test.rb
... ... @@ -34,4 +34,16 @@ class CreateThumbnailsJobTest &lt; ActiveSupport::TestCase
34 34 end
35 35 end
36 36  
  37 + should 'expire cache of articles that use an image that just got a thumbnail' do
  38 + person = create_user('test_user').person
  39 + file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => person)
  40 + article = create(Article, :name => 'test', :image_builder => {
  41 + :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')
  42 + }, :profile_id => person.id)
  43 + old_cache_key = article.cache_key
  44 + job = CreateThumbnailsJob.new(file.class.name, file.id)
  45 + job.perform
  46 + process_delayed_job_queue
  47 + assert_not_equal old_cache_key, Article.find(article.id).reload.cache_key
  48 + end
37 49 end
... ...