Commit 9cc1bb44ab99854b7fbe529b521e427b652e9a83

Authored by Caio Almeida
2 parents 5e0ff199 d8b7fec7

Fixing conflict

Showing 219 changed files with 2596 additions and 6319 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 219 files displayed.

app/api/app.rb 0 → 100644
@@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
  1 +require_dependency 'api/helpers'
  2 +
  3 +module Api
  4 + class App < Grape::API
  5 + use Rack::JSONP
  6 +
  7 + logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log"))
  8 + logger.formatter = GrapeLogging::Formatters::Default.new
  9 + #use GrapeLogging::Middleware::RequestLogger, { logger: logger }
  10 +
  11 + rescue_from :all do |e|
  12 + logger.error e
  13 + error! e.message, 500
  14 + end unless Rails.env.test?
  15 +
  16 + @@NOOSFERO_CONF = nil
  17 + def self.NOOSFERO_CONF
  18 + if @@NOOSFERO_CONF
  19 + @@NOOSFERO_CONF
  20 + else
  21 + file = Rails.root.join('config', 'noosfero.yml')
  22 + @@NOOSFERO_CONF = File.exists?(file) ? YAML.load_file(file)[Rails.env] || {} : {}
  23 + end
  24 + end
  25 +
  26 + before { set_locale }
  27 + before { setup_multitenancy }
  28 + before { detect_stuff_by_domain }
  29 + before { filter_disabled_plugins_endpoints }
  30 + before { init_noosfero_plugins }
  31 + after { set_session_cookie }
  32 +
  33 + version 'v1'
  34 + prefix [ENV['RAILS_RELATIVE_URL_ROOT'], "api"].compact.join('/')
  35 + format :json
  36 + content_type :txt, "text/plain"
  37 +
  38 + helpers Helpers
  39 +
  40 + mount V1::Session
  41 + mount V1::Articles
  42 + mount V1::Comments
  43 + mount V1::Users
  44 + mount V1::Communities
  45 + mount V1::People
  46 + mount V1::Enterprises
  47 + mount V1::Categories
  48 + mount V1::Tasks
  49 + mount V1::Tags
  50 + mount V1::Environments
  51 + mount V1::Search
  52 + mount V1::Contacts
  53 + mount V1::Boxes
  54 + mount V1::Blocks
  55 + mount V1::Profiles
  56 + mount V1::Activities
  57 +
  58 + # hook point which allow plugins to add Grape::API extensions to Api::App
  59 + #finds for plugins which has api mount points classes defined (the class should extends Grape::API)
  60 + @plugins = Noosfero::Plugin.all.map { |p| p.constantize }
  61 + @plugins.each do |klass|
  62 + if klass.public_methods.include? :api_mount_points
  63 + klass.api_mount_points.each do |mount_class|
  64 + mount mount_class if mount_class && ( mount_class < Grape::API )
  65 + end
  66 + end
  67 + end
  68 +
  69 + def self.endpoint_unavailable?(endpoint, environment)
  70 + api_class = endpoint.options[:app] || endpoint.options[:for]
  71 + if api_class.present?
  72 + klass = api_class.name.deconstantize.constantize
  73 + return klass < Noosfero::Plugin && !environment.plugin_enabled?(klass)
  74 + end
  75 + end
  76 +
  77 + class << self
  78 + def endpoints_with_plugins(environment = nil)
  79 + if environment.present?
  80 + cloned_endpoints = endpoints_without_plugins.dup
  81 + cloned_endpoints.delete_if { |endpoint| endpoint_unavailable?(endpoint, environment) }
  82 + else
  83 + endpoints_without_plugins
  84 + end
  85 + end
  86 + alias_method_chain :endpoints, :plugins
  87 + end
  88 + end
  89 +end
app/api/entities.rb 0 → 100644
@@ -0,0 +1,267 @@ @@ -0,0 +1,267 @@
  1 +module Api
  2 + module Entities
  3 +
  4 + Entity.format_with :timestamp do |date|
  5 + date.strftime('%Y/%m/%d %H:%M:%S') if date
  6 + end
  7 +
  8 + PERMISSIONS = {
  9 + :admin => 0,
  10 + :self => 10,
  11 + :private_content => 20,
  12 + :logged_user => 30,
  13 + :anonymous => 40
  14 + }
  15 +
  16 + def self.can_display_profile_field? profile, options, permission_options={}
  17 + permissions={:field => "", :permission => :private_content}
  18 + permissions.merge!(permission_options)
  19 + field = permissions[:field]
  20 + permission = permissions[:permission]
  21 + return true if profile.public? && profile.public_fields.map{|f| f.to_sym}.include?(field.to_sym)
  22 +
  23 + current_person = options[:current_person]
  24 +
  25 + current_permission = if current_person.present?
  26 + if current_person.is_admin?
  27 + :admin
  28 + elsif current_person == profile
  29 + :self
  30 + elsif profile.display_private_info_to?(current_person)
  31 + :private_content
  32 + else
  33 + :logged_user
  34 + end
  35 + else
  36 + :anonymous
  37 + end
  38 + PERMISSIONS[current_permission] <= PERMISSIONS[permission]
  39 + end
  40 +
  41 + class Image < Entity
  42 + root 'images', 'image'
  43 +
  44 + expose :url do |image, options|
  45 + image.public_filename
  46 + end
  47 +
  48 + expose :icon_url do |image, options|
  49 + image.public_filename(:icon)
  50 + end
  51 +
  52 + expose :minor_url do |image, options|
  53 + image.public_filename(:minor)
  54 + end
  55 +
  56 + expose :portrait_url do |image, options|
  57 + image.public_filename(:portrait)
  58 + end
  59 +
  60 + expose :thumb_url do |image, options|
  61 + image.public_filename(:thumb)
  62 + end
  63 + end
  64 +
  65 + class CategoryBase < Entity
  66 + root 'categories', 'category'
  67 + expose :name, :id, :slug
  68 + end
  69 +
  70 + class Category < CategoryBase
  71 + root 'categories', 'category'
  72 + expose :full_name do |category, options|
  73 + category.full_name
  74 + end
  75 + expose :parent, :using => CategoryBase, if: { parent: true }
  76 + expose :children, :using => CategoryBase, if: { children: true }
  77 + expose :image, :using => Image
  78 + expose :display_color
  79 + end
  80 +
  81 + class Region < Category
  82 + root 'regions', 'region'
  83 + expose :parent_id
  84 + end
  85 +
  86 + class Block < Entity
  87 + root 'blocks', 'block'
  88 + expose :id, :type, :settings, :position, :enabled
  89 + expose :mirror, :mirror_block_id, :title
  90 + expose :api_content, if: lambda { |object, options| options[:display_api_content] || object.display_api_content_by_default? }
  91 + end
  92 +
  93 + class Box < Entity
  94 + root 'boxes', 'box'
  95 + expose :id, :position
  96 + expose :blocks, :using => Block
  97 + end
  98 +
  99 + class Profile < Entity
  100 + expose :identifier, :name, :id
  101 + expose :created_at, :format_with => :timestamp
  102 + expose :updated_at, :format_with => :timestamp
  103 + expose :additional_data do |profile, options|
  104 + hash ={}
  105 + profile.public_values.each do |value|
  106 + hash[value.custom_field.name]=value.value
  107 + end
  108 +
  109 + private_values = profile.custom_field_values - profile.public_values
  110 + private_values.each do |value|
  111 + if Entities.can_display_profile_field?(profile,options)
  112 + hash[value.custom_field.name]=value.value
  113 + end
  114 + end
  115 + hash
  116 + end
  117 + expose :image, :using => Image
  118 + expose :region, :using => Region
  119 + expose :type
  120 + expose :custom_header
  121 + expose :custom_footer
  122 + end
  123 +
  124 + class UserBasic < Entity
  125 + expose :id
  126 + expose :login
  127 + end
  128 +
  129 + class Person < Profile
  130 + root 'people', 'person'
  131 + expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' }
  132 + expose :vote_count
  133 + expose :comments_count do |person, options|
  134 + person.comments.count
  135 + end
  136 + expose :following_articles_count do |person, options|
  137 + person.following_articles.count
  138 + end
  139 + expose :articles_count do |person, options|
  140 + person.articles.count
  141 + end
  142 + end
  143 +
  144 + class Enterprise < Profile
  145 + root 'enterprises', 'enterprise'
  146 + end
  147 +
  148 + class Community < Profile
  149 + root 'communities', 'community'
  150 + expose :description
  151 + expose :admins, :if => lambda { |community, options| community.display_info_to? options[:current_person]} do |community, options|
  152 + community.admins.map{|admin| {"name"=>admin.name, "id"=>admin.id, "username" => admin.identifier}}
  153 + end
  154 + expose :categories, :using => Category
  155 + expose :members, :using => Person , :if => lambda{ |community, options| community.display_info_to? options[:current_person] }
  156 + end
  157 +
  158 + class CommentBase < Entity
  159 + expose :body, :title, :id
  160 + expose :created_at, :format_with => :timestamp
  161 + expose :author, :using => Profile
  162 + expose :reply_of, :using => CommentBase
  163 + end
  164 +
  165 + class Comment < CommentBase
  166 + root 'comments', 'comment'
  167 + expose :children, as: :replies, :using => Comment
  168 + end
  169 +
  170 + class ArticleBase < Entity
  171 + root 'articles', 'article'
  172 + expose :id
  173 + expose :body
  174 + expose :abstract, documentation: {type: 'String', desc: 'Teaser of the body'}
  175 + expose :created_at, :format_with => :timestamp
  176 + expose :updated_at, :format_with => :timestamp
  177 + expose :title, :documentation => {:type => "String", :desc => "Title of the article"}
  178 + expose :created_by, :as => :author, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile author that create the article'}
  179 + expose :profile, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile associated with the article'}
  180 + expose :categories, :using => Category
  181 + expose :image, :using => Image
  182 + expose :votes_for
  183 + expose :votes_against
  184 + expose :setting
  185 + expose :position
  186 + expose :hits
  187 + expose :start_date
  188 + expose :end_date, :documentation => {type: 'DateTime', desc: 'The date of finish of the article'}
  189 + expose :tag_list
  190 + expose :children_count
  191 + expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"}
  192 + expose :path
  193 + expose :followers_count
  194 + expose :votes_count
  195 + expose :comments_count
  196 + expose :archived, :documentation => {:type => "Boolean", :desc => "Defines if a article is readonly"}
  197 + expose :type
  198 + expose :comments, using: CommentBase, :if => lambda{|obj,opt| opt[:params] && ['1','true',true].include?(opt[:params][:show_comments])}
  199 + expose :published
  200 + expose :accept_comments?, as: :accept_comments
  201 + end
  202 +
  203 + class Article < ArticleBase
  204 + root 'articles', 'article'
  205 + expose :parent, :using => ArticleBase
  206 + expose :children, :using => ArticleBase do |article, options|
  207 + article.children.published.limit(V1::Articles::MAX_PER_PAGE)
  208 + end
  209 + end
  210 +
  211 + class User < Entity
  212 + root 'users', 'user'
  213 +
  214 + attrs = [:id,:login,:email,:activated?]
  215 + aliases = {:activated? => :activated}
  216 +
  217 + attrs.each do |attribute|
  218 + name = aliases.has_key?(attribute) ? aliases[attribute] : attribute
  219 + expose attribute, :as => name, :if => lambda{|user,options| Entities.can_display_profile_field?(user.person, options, {:field => attribute})}
  220 + end
  221 +
  222 + expose :person, :using => Person, :if => lambda{|user,options| user.person.display_info_to? options[:current_person]}
  223 + expose :permissions, :if => lambda{|user,options| Entities.can_display_profile_field?(user.person, options, {:field => :permissions, :permission => :self})} do |user, options|
  224 + output = {}
  225 + user.person.role_assignments.map do |role_assigment|
  226 + if role_assigment.resource.respond_to?(:identifier) && !role_assigment.role.nil?
  227 + output[role_assigment.resource.identifier] = role_assigment.role.permissions
  228 + end
  229 + end
  230 + output
  231 + end
  232 + end
  233 +
  234 + class UserLogin < User
  235 + root 'users', 'user'
  236 + expose :private_token, documentation: {type: 'String', desc: 'A valid authentication code for post/delete api actions'}, if: lambda {|object, options| object.activated? }
  237 + end
  238 +
  239 + class Task < Entity
  240 + root 'tasks', 'task'
  241 + expose :id
  242 + expose :type
  243 + end
  244 +
  245 + class Environment < Entity
  246 + expose :name
  247 + expose :id
  248 + expose :description
  249 + expose :settings, if: lambda { |instance, options| options[:is_admin] }
  250 + end
  251 +
  252 + class Tag < Entity
  253 + root 'tags', 'tag'
  254 + expose :name
  255 + end
  256 +
  257 + class Activity < Entity
  258 + root 'activities', 'activity'
  259 + expose :id, :params, :verb, :created_at, :updated_at, :comments_count, :visible
  260 + expose :user, :using => Profile
  261 + expose :target do |activity, opts|
  262 + type_map = {Profile => ::Profile, ArticleBase => ::Article}.find {|h| activity.target.kind_of?(h.last)}
  263 + type_map.first.represent(activity.target) unless type_map.nil?
  264 + end
  265 + end
  266 + end
  267 +end
app/api/entity.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +module Api
  2 + class Entity < Grape::Entity
  3 +
  4 + def initialize(object, options = {})
  5 + object = nil if object.is_a? Exception
  6 + super object, options
  7 + end
  8 +
  9 + def self.represent(objects, options = {})
  10 + if options[:has_exception]
  11 + data = super objects, options.merge(is_inner_data: true)
  12 + if objects.is_a? Exception
  13 + data.merge ok: false, error: {
  14 + type: objects.class.name,
  15 + message: objects.message
  16 + }
  17 + else
  18 + data = data.serializable_hash if data.is_a? Entity
  19 + data.merge ok: true, error: { type: 'Success', message: '' }
  20 + end
  21 + else
  22 + super objects, options
  23 + end
  24 + end
  25 +
  26 + end
  27 +end
app/api/helpers.rb 0 → 100644
@@ -0,0 +1,421 @@ @@ -0,0 +1,421 @@
  1 +require 'base64'
  2 +require 'tempfile'
  3 +
  4 +module Api
  5 + module Helpers
  6 + PRIVATE_TOKEN_PARAM = :private_token
  7 + DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :identifier, :archived]
  8 +
  9 + include SanitizeParams
  10 + include Noosfero::Plugin::HotSpot
  11 + include ForgotPasswordHelper
  12 + include SearchTermHelper
  13 +
  14 + def set_locale
  15 + I18n.locale = (params[:lang] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
  16 + end
  17 +
  18 + def init_noosfero_plugins
  19 + plugins
  20 + end
  21 +
  22 + def current_user
  23 + private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s
  24 + @current_user ||= User.find_by private_token: private_token
  25 + @current_user ||= plugins.dispatch("api_custom_login", request).first
  26 + @current_user
  27 + end
  28 +
  29 + def current_person
  30 + current_user.person unless current_user.nil?
  31 + end
  32 +
  33 + def is_admin?(environment)
  34 + return false unless current_user
  35 + return current_person.is_admin?(environment)
  36 + end
  37 +
  38 + def logout
  39 + @current_user = nil
  40 + end
  41 +
  42 + def environment
  43 + @environment
  44 + end
  45 +
  46 + def present_partial(model, options)
  47 + if(params[:fields].present?)
  48 + begin
  49 + fields = JSON.parse(params[:fields])
  50 + if fields.present?
  51 + options.merge!(fields.symbolize_keys.slice(:only, :except))
  52 + end
  53 + rescue
  54 + fields = params[:fields]
  55 + fields = fields.split(',') if fields.kind_of?(String)
  56 + options[:only] = Array.wrap(fields)
  57 + end
  58 + end
  59 + present model, options
  60 + end
  61 +
  62 + include FindByContents
  63 +
  64 + ####################################################################
  65 + #### SEARCH
  66 + ####################################################################
  67 + def multiple_search?(searches=nil)
  68 + ['index', 'category_index'].include?(params[:action]) || (searches && searches.size > 1)
  69 + end
  70 + ####################################################################
  71 +
  72 + def logger
  73 + logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log"))
  74 + logger.formatter = GrapeLogging::Formatters::Default.new
  75 + logger
  76 + end
  77 +
  78 + def limit
  79 + limit = params[:limit].to_i
  80 + limit = default_limit if limit <= 0
  81 + limit
  82 + end
  83 +
  84 + def period(from_date, until_date)
  85 + return nil if from_date.nil? && until_date.nil?
  86 +
  87 + begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date
  88 + end_period = until_date.nil? ? DateTime.now : until_date
  89 +
  90 + begin_period..end_period
  91 + end
  92 +
  93 + def parse_content_type(content_type)
  94 + return nil if content_type.blank?
  95 + content_type.split(',').map do |content_type|
  96 + content_type.camelcase
  97 + end
  98 + end
  99 +
  100 + def find_article(articles, id)
  101 + article = articles.find(id)
  102 + article.display_to?(current_person) ? article : forbidden!
  103 + end
  104 +
  105 + def post_article(asset, params)
  106 + return forbidden! unless current_person.can_post_content?(asset)
  107 +
  108 + klass_type = params[:content_type] || params[:article].delete(:type) || TinyMceArticle.name
  109 + return forbidden! unless klass_type.constantize <= Article
  110 +
  111 + article = klass_type.constantize.new(params[:article])
  112 + article.last_changed_by = current_person
  113 + article.created_by= current_person
  114 + article.profile = asset
  115 +
  116 + if !article.save
  117 + render_api_errors!(article.errors.full_messages)
  118 + end
  119 + present_partial article, :with => Entities::Article
  120 + end
  121 +
  122 + def present_article(asset)
  123 + article = find_article(asset.articles, params[:id])
  124 + present_partial article, :with => Entities::Article, :params => params
  125 + end
  126 +
  127 + def present_articles_for_asset(asset, method = 'articles')
  128 + articles = find_articles(asset, method)
  129 + present_articles(articles)
  130 + end
  131 +
  132 + def present_articles(articles)
  133 + present_partial paginate(articles), :with => Entities::Article, :params => params
  134 + end
  135 +
  136 + def find_articles(asset, method = 'articles')
  137 + articles = select_filtered_collection_of(asset, method, params)
  138 + if current_person.present?
  139 + articles = articles.display_filter(current_person, nil)
  140 + else
  141 + articles = articles.published
  142 + end
  143 + articles
  144 + end
  145 +
  146 + def find_task(asset, id)
  147 + task = asset.tasks.find(id)
  148 + current_person.has_permission?(task.permission, asset) ? task : forbidden!
  149 + end
  150 +
  151 + def post_task(asset, params)
  152 + klass_type= params[:content_type].nil? ? 'Task' : params[:content_type]
  153 + return forbidden! unless klass_type.constantize <= Task
  154 +
  155 + task = klass_type.constantize.new(params[:task])
  156 + task.requestor_id = current_person.id
  157 + task.target_id = asset.id
  158 + task.target_type = 'Profile'
  159 +
  160 + if !task.save
  161 + render_api_errors!(task.errors.full_messages)
  162 + end
  163 + present_partial task, :with => Entities::Task
  164 + end
  165 +
  166 + def present_task(asset)
  167 + task = find_task(asset, params[:id])
  168 + present_partial task, :with => Entities::Task
  169 + end
  170 +
  171 + def present_tasks(asset)
  172 + tasks = select_filtered_collection_of(asset, 'tasks', params)
  173 + tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)}
  174 + return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset)
  175 + present_partial tasks, :with => Entities::Task
  176 + end
  177 +
  178 + def make_conditions_with_parameter(params = {})
  179 + parsed_params = parser_params(params)
  180 + conditions = {}
  181 + from_date = DateTime.parse(parsed_params.delete(:from)) if parsed_params[:from]
  182 + until_date = DateTime.parse(parsed_params.delete(:until)) if parsed_params[:until]
  183 +
  184 + conditions[:type] = parse_content_type(parsed_params.delete(:content_type)) unless parsed_params[:content_type].nil?
  185 +
  186 + conditions[:created_at] = period(from_date, until_date) if from_date || until_date
  187 + conditions.merge!(parsed_params)
  188 +
  189 + conditions
  190 + end
  191 +
  192 + # changing make_order_with_parameters to avoid sql injection
  193 + def make_order_with_parameters(object, method, params)
  194 + order = "created_at DESC"
  195 + unless params[:order].blank?
  196 + if params[:order].include? '\'' or params[:order].include? '"'
  197 + order = "created_at DESC"
  198 + elsif ['RANDOM()', 'RANDOM'].include? params[:order].upcase
  199 + order = 'RANDOM()'
  200 + else
  201 + field_name, direction = params[:order].split(' ')
  202 + assoc = object.class.reflect_on_association(method.to_sym)
  203 + if !field_name.blank? and assoc
  204 + if assoc.klass.attribute_names.include? field_name
  205 + if direction.present? and ['ASC','DESC'].include? direction.upcase
  206 + order = "#{field_name} #{direction.upcase}"
  207 + end
  208 + end
  209 + end
  210 + end
  211 + end
  212 + return order
  213 + end
  214 +
  215 + def make_timestamp_with_parameters_and_method(params, method)
  216 + timestamp = nil
  217 + if params[:timestamp]
  218 + datetime = DateTime.parse(params[:timestamp])
  219 + table_name = method.to_s.singularize.camelize.constantize.table_name
  220 + timestamp = "#{table_name}.updated_at >= '#{datetime}'"
  221 + end
  222 +
  223 + timestamp
  224 + end
  225 +
  226 + def by_reference(scope, params)
  227 + reference_id = params[:reference_id].to_i == 0 ? nil : params[:reference_id].to_i
  228 + if reference_id.nil?
  229 + scope
  230 + else
  231 + created_at = scope.find(reference_id).created_at
  232 + scope.send("#{params.key?(:oldest) ? 'older_than' : 'younger_than'}", created_at)
  233 + end
  234 + end
  235 +
  236 + def by_categories(scope, params)
  237 + category_ids = params[:category_ids]
  238 + if category_ids.nil?
  239 + scope
  240 + else
  241 + scope.joins(:categories).where(:categories => {:id => category_ids})
  242 + end
  243 + end
  244 +
  245 + def select_filtered_collection_of(object, method, params)
  246 + conditions = make_conditions_with_parameter(params)
  247 + order = make_order_with_parameters(object,method,params)
  248 + timestamp = make_timestamp_with_parameters_and_method(params, method)
  249 +
  250 + objects = object.send(method)
  251 + objects = by_reference(objects, params)
  252 + objects = by_categories(objects, params)
  253 +
  254 + objects = objects.where(conditions).where(timestamp).reorder(order)
  255 +
  256 + params[:page] ||= 1
  257 + params[:per_page] ||= limit
  258 + paginate(objects)
  259 + end
  260 +
  261 + def authenticate!
  262 + unauthorized! unless current_user
  263 + end
  264 +
  265 + def profiles_for_person(profiles, person)
  266 + if person
  267 + profiles.listed_for_person(person)
  268 + else
  269 + profiles.visible
  270 + end
  271 + end
  272 +
  273 + # Checks the occurrences of uniqueness of attributes, each attribute must be present in the params hash
  274 + # or a Bad Request error is invoked.
  275 + #
  276 + # Parameters:
  277 + # keys (unique) - A hash consisting of keys that must be unique
  278 + def unique_attributes!(obj, keys)
  279 + keys.each do |key|
  280 + cant_be_saved_request!(key) if obj.find_by(key.to_s => params[key])
  281 + end
  282 + end
  283 +
  284 + def attributes_for_keys(keys)
  285 + attrs = {}
  286 + keys.each do |key|
  287 + attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false)
  288 + end
  289 + attrs
  290 + end
  291 +
  292 + ##########################################
  293 + # error helpers #
  294 + ##########################################
  295 +
  296 + def not_found!
  297 + render_api_error!('404 Not found', 404)
  298 + end
  299 +
  300 + def forbidden!
  301 + render_api_error!('403 Forbidden', 403)
  302 + end
  303 +
  304 + def cant_be_saved_request!(attribute)
  305 + message = _("(Invalid request) %s can't be saved") % attribute
  306 + render_api_error!(message, 400)
  307 + end
  308 +
  309 + def bad_request!(attribute)
  310 + message = _("(Invalid request) %s not given") % attribute
  311 + render_api_error!(message, 400)
  312 + end
  313 +
  314 + def something_wrong!
  315 + message = _("Something wrong happened")
  316 + render_api_error!(message, 400)
  317 + end
  318 +
  319 + def unauthorized!
  320 + render_api_error!(_('Unauthorized'), 401)
  321 + end
  322 +
  323 + def not_allowed!
  324 + render_api_error!(_('Method Not Allowed'), 405)
  325 + end
  326 +
  327 + # javascript_console_message is supposed to be executed as console.log()
  328 + def render_api_error!(user_message, status, log_message = nil, javascript_console_message = nil)
  329 + message_hash = {'message' => user_message, :code => status}
  330 + message_hash[:javascript_console_message] = javascript_console_message if javascript_console_message.present?
  331 + log_msg = "#{status}, User message: #{user_message}"
  332 + log_msg = "#{log_message}, #{log_msg}" if log_message.present?
  333 + log_msg = "#{log_msg}, Javascript Console Message: #{javascript_console_message}" if javascript_console_message.present?
  334 + logger.error log_msg unless Rails.env.test?
  335 + error!(message_hash, status)
  336 + end
  337 +
  338 + def render_api_errors!(messages)
  339 + messages = messages.to_a if messages.class == ActiveModel::Errors
  340 + render_api_error!(messages.join(','), 400)
  341 + end
  342 +
  343 + protected
  344 +
  345 + def set_session_cookie
  346 + cookies['_noosfero_api_session'] = { value: @current_user.private_token, httponly: true } if @current_user.present?
  347 + end
  348 +
  349 + def setup_multitenancy
  350 + Noosfero::MultiTenancy.setup!(request.host)
  351 + end
  352 +
  353 + def detect_stuff_by_domain
  354 + @domain = Domain.by_name(request.host)
  355 + if @domain.nil?
  356 + @environment = Environment.default
  357 + if @environment.nil? && Rails.env.development?
  358 + # This should only happen in development ...
  359 + @environment = Environment.create!(:name => "Noosfero", :is_default => true)
  360 + end
  361 + else
  362 + @environment = @domain.environment
  363 + end
  364 + end
  365 +
  366 + def filter_disabled_plugins_endpoints
  367 + not_found! if Api::App.endpoint_unavailable?(self, @environment)
  368 + end
  369 +
  370 + def asset_with_image params
  371 + if params.has_key? :image_builder
  372 + asset_api_params = params
  373 + asset_api_params[:image_builder] = base64_to_uploadedfile(asset_api_params[:image_builder])
  374 + return asset_api_params
  375 + end
  376 + params
  377 + end
  378 +
  379 + def base64_to_uploadedfile(base64_image)
  380 + tempfile = base64_to_tempfile base64_image
  381 + converted_image = base64_image
  382 + converted_image[:tempfile] = tempfile
  383 + return {uploaded_data: ActionDispatch::Http::UploadedFile.new(converted_image)}
  384 + end
  385 +
  386 + def base64_to_tempfile base64_image
  387 + base64_img_str = base64_image[:tempfile]
  388 + decoded_base64_str = Base64.decode64(base64_img_str)
  389 + tempfile = Tempfile.new(base64_image[:filename])
  390 + tempfile.write(decoded_base64_str.encode("ascii-8bit").force_encoding("utf-8"))
  391 + tempfile.rewind
  392 + tempfile
  393 + end
  394 + private
  395 +
  396 + def parser_params(params)
  397 + parsed_params = {}
  398 + params.map do |k,v|
  399 + parsed_params[k.to_sym] = v if DEFAULT_ALLOWED_PARAMETERS.include?(k.to_sym)
  400 + end
  401 + parsed_params
  402 + end
  403 +
  404 + def default_limit
  405 + 20
  406 + end
  407 +
  408 + def parse_content_type(content_type)
  409 + return nil if content_type.blank?
  410 + content_type.split(',').map do |content_type|
  411 + content_type.camelcase
  412 + end
  413 + end
  414 +
  415 + def period(from_date, until_date)
  416 + begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date
  417 + end_period = until_date.nil? ? DateTime.now : until_date
  418 + begin_period..end_period
  419 + end
  420 + end
  421 +end
app/api/v1/activities.rb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +module Api
  2 + module V1
  3 + class Activities < Grape::API
  4 + before { authenticate! }
  5 +
  6 + resource :profiles do
  7 +
  8 + get ':id/activities' do
  9 + profile = Profile.find_by id: params[:id]
  10 +
  11 + not_found! if profile.blank? || profile.secret || !profile.visible
  12 + forbidden! if !profile.secret && profile.visible && !profile.display_private_info_to?(current_person)
  13 +
  14 + activities = profile.activities.map(&:activity)
  15 + present activities, :with => Entities::Activity, :current_person => current_person
  16 + end
  17 + end
  18 + end
  19 + end
  20 +end
app/api/v1/articles.rb 0 → 100644
@@ -0,0 +1,303 @@ @@ -0,0 +1,303 @@
  1 +module Api
  2 + module V1
  3 + class Articles < Grape::API
  4 +
  5 + ARTICLE_TYPES = Article.descendants.map{|a| a.to_s}
  6 +
  7 + MAX_PER_PAGE = 50
  8 +
  9 + resource :articles do
  10 +
  11 + paginate max_per_page: MAX_PER_PAGE
  12 + # Collect articles
  13 + #
  14 + # Parameters:
  15 + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created
  16 + # oldest - Collect the oldest articles. If nothing is passed the newest articles are collected
  17 + # limit - amount of articles returned. The default value is 20
  18 + #
  19 + # Example Request:
  20 + # GET host/api/v1/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317
  21 +
  22 + desc 'Return all articles of all kinds' do
  23 + detail 'Get all articles filtered by fields in query params'
  24 + params Entities::Article.documentation
  25 + success Entities::Article
  26 + failure [[403, 'Forbidden']]
  27 + named 'ArticlesList'
  28 + headers [
  29 + 'Per-Page' => {
  30 + description: 'Total number of records',
  31 + required: false
  32 + }
  33 + ]
  34 + end
  35 + get do
  36 + present_articles_for_asset(environment)
  37 + end
  38 +
  39 + desc "Return one article by id" do
  40 + detail 'Get only one article by id. If not found the "forbidden" http error is showed'
  41 + params Entities::Article.documentation
  42 + success Entities::Article
  43 + failure [[403, 'Forbidden']]
  44 + named 'ArticleById'
  45 + end
  46 + get ':id', requirements: {id: /[0-9]+/} do
  47 + present_article(environment)
  48 + end
  49 +
  50 + post ':id' do
  51 + article = environment.articles.find(params[:id])
  52 + return forbidden! unless article.allow_edit?(current_person)
  53 + article.update_attributes!(asset_with_image(params[:article]))
  54 + present_partial article, :with => Entities::Article
  55 + end
  56 +
  57 + desc 'Report a abuse and/or violent content in a article by id' do
  58 + detail 'Submit a abuse (in general, a content violation) report about a specific article'
  59 + params Entities::Article.documentation
  60 + failure [[400, 'Bad Request']]
  61 + named 'ArticleReportAbuse'
  62 + end
  63 + post ':id/report_abuse' do
  64 + article = find_article(environment.articles, params[:id])
  65 + profile = article.profile
  66 + begin
  67 + abuse_report = AbuseReport.new(:reason => params[:report_abuse])
  68 + if !params[:content_type].blank?
  69 + article = params[:content_type].constantize.find(params[:content_id])
  70 + abuse_report.content = article_reported_version(article)
  71 + end
  72 +
  73 + current_person.register_report(abuse_report, profile)
  74 +
  75 + if !params[:content_type].blank?
  76 + abuse_report = AbuseReport.find_by reporter_id: current_person.id, abuse_complaint_id: profile.opened_abuse_complaint.id
  77 + Delayed::Job.enqueue DownloadReportedImagesJob.new(abuse_report, article)
  78 + end
  79 +
  80 + {
  81 + :success => true,
  82 + :message => _('Your abuse report was registered. The administrators are reviewing your report.'),
  83 + }
  84 + rescue Exception => exception
  85 + #logger.error(exception.to_s)
  86 + render_api_error!(_('Your report couldn\'t be saved due to some problem. Please contact the administrator.'), 400)
  87 + end
  88 +
  89 + end
  90 +
  91 + desc "Returns the articles I voted" do
  92 + detail 'Get the Articles I make a vote'
  93 + failure [[403, 'Forbidden']]
  94 + named 'ArticleFollowers'
  95 + end
  96 + #FIXME refactor this method
  97 + get 'voted_by_me' do
  98 + present_articles(current_person.votes.where(:voteable_type => 'Article').collect(&:voteable))
  99 + end
  100 +
  101 + desc 'Perform a vote on a article by id' do
  102 + detail 'Vote on a specific article with values: 1 (if you like) or -1 (if not)'
  103 + params Entities::UserLogin.documentation
  104 + failure [[401,'Unauthorized']]
  105 + named 'ArticleVote'
  106 + end
  107 + post ':id/vote' do
  108 + authenticate!
  109 + value = (params[:value] || 1).to_i
  110 + # FIXME verify allowed values
  111 + render_api_error!('Vote value not allowed', 400) unless [-1, 1].include?(value)
  112 + article = find_article(environment.articles, params[:id])
  113 + begin
  114 + vote = Vote.new(:voteable => article, :voter => current_person, :vote => value)
  115 + {:vote => vote.save!}
  116 + rescue ActiveRecord::RecordInvalid => e
  117 + render_api_error!(e.message, 400)
  118 + end
  119 + end
  120 +
  121 + desc "Returns the total followers for the article" do
  122 + detail 'Get the followers of a specific article by id'
  123 + failure [[403, 'Forbidden']]
  124 + named 'ArticleFollowers'
  125 + end
  126 + get ':id/followers' do
  127 + article = find_article(environment.articles, params[:id])
  128 + total = article.person_followers.count
  129 + {:total_followers => total}
  130 + end
  131 +
  132 + desc "Return the articles followed by me"
  133 + get 'followed_by_me' do
  134 + present_articles_for_asset(current_person, 'following_articles')
  135 + end
  136 +
  137 + desc "Add a follower for the article" do
  138 + detail 'Add the current user identified by private token, like a follower of a article'
  139 + params Entities::UserLogin.documentation
  140 + failure [[401, 'Unauthorized']]
  141 + named 'ArticleFollow'
  142 + end
  143 + post ':id/follow' do
  144 + authenticate!
  145 + article = find_article(environment.articles, params[:id])
  146 + if article.article_followers.exists?(:person_id => current_person.id)
  147 + {:success => false, :already_follow => true}
  148 + else
  149 + article_follower = ArticleFollower.new
  150 + article_follower.article = article
  151 + article_follower.person = current_person
  152 + article_follower.save!
  153 + {:success => true}
  154 + end
  155 + end
  156 +
  157 + desc 'Return the children of a article identified by id' do
  158 + detail 'Get all children articles of a specific article'
  159 + params Entities::Article.documentation
  160 + failure [[403, 'Forbidden']]
  161 + named 'ArticleChildren'
  162 + end
  163 +
  164 + paginate per_page: MAX_PER_PAGE, max_per_page: MAX_PER_PAGE
  165 + get ':id/children' do
  166 + article = find_article(environment.articles, params[:id])
  167 +
  168 + #TODO make tests for this situation
  169 + votes_order = params.delete(:order) if params[:order]=='votes_score'
  170 + articles = select_filtered_collection_of(article, 'children', params)
  171 + articles = articles.display_filter(current_person, article.profile)
  172 +
  173 + #TODO make tests for this situation
  174 + if votes_order
  175 + articles = articles.joins('left join votes on articles.id=votes.voteable_id').group('articles.id').reorder('sum(coalesce(votes.vote, 0)) DESC')
  176 + end
  177 + Article.hit(articles)
  178 + present_articles(articles)
  179 + end
  180 +
  181 + desc 'Return one child of a article identified by id' do
  182 + detail 'Get a child of a specific article'
  183 + params Entities::Article.documentation
  184 + success Entities::Article
  185 + failure [[403, 'Forbidden']]
  186 + named 'ArticleChild'
  187 + end
  188 + get ':id/children/:child_id' do
  189 + article = find_article(environment.articles, params[:id])
  190 + child = find_article(article.children, params[:child_id])
  191 + child.hit
  192 + present_partial child, :with => Entities::Article
  193 + end
  194 +
  195 + desc 'Suggest a article to another profile' do
  196 + detail 'Suggest a article to another profile (person, community...)'
  197 + params Entities::Article.documentation
  198 + success Entities::Task
  199 + failure [[401,'Unauthorized']]
  200 + named 'ArticleSuggest'
  201 + end
  202 + post ':id/children/suggest' do
  203 + authenticate!
  204 + parent_article = environment.articles.find(params[:id])
  205 +
  206 + suggest_article = SuggestArticle.new
  207 + suggest_article.article = params[:article]
  208 + suggest_article.article[:parent_id] = parent_article.id
  209 + suggest_article.target = parent_article.profile
  210 + suggest_article.requestor = current_person
  211 +
  212 + unless suggest_article.save
  213 + render_api_errors!(suggest_article.article_object.errors.full_messages)
  214 + end
  215 + present_partial suggest_article, :with => Entities::Task
  216 + end
  217 +
  218 + # Example Request:
  219 + # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body
  220 + desc 'Add a child article to a parent identified by id' do
  221 + detail 'Create a new article and associate to a parent'
  222 + params Entities::Article.documentation
  223 + success Entities::Article
  224 + failure [[401,'Unauthorized']]
  225 + named 'ArticleAddChild'
  226 + end
  227 + post ':id/children' do
  228 + parent_article = environment.articles.find(params[:id])
  229 + params[:article][:parent_id] = parent_article.id
  230 + post_article(parent_article.profile, params)
  231 + end
  232 + end
  233 +
  234 + resource :profiles do
  235 + get ':id/home_page' do
  236 + profiles = environment.profiles
  237 + profiles = profiles.visible_for_person(current_person)
  238 + profile = profiles.find_by id: params[:id]
  239 + present_partial profile.home_page, :with => Entities::Article
  240 + end
  241 + end
  242 +
  243 + kinds = %w[profile community person enterprise]
  244 + kinds.each do |kind|
  245 + resource kind.pluralize.to_sym do
  246 + segment "/:#{kind}_id" do
  247 + resource :articles do
  248 +
  249 + desc "Return all articles associate with a profile of type #{kind}" do
  250 + detail 'Get a list of articles of a profile'
  251 + params Entities::Article.documentation
  252 + success Entities::Article
  253 + failure [[403, 'Forbidden']]
  254 + named 'ArticlesOfProfile'
  255 + end
  256 + get do
  257 + profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
  258 +
  259 + if params[:path].present?
  260 + article = profile.articles.find_by path: params[:path]
  261 + if !article || !article.display_to?(current_person)
  262 + article = forbidden!
  263 + end
  264 +
  265 + present_partial article, :with => Entities::Article
  266 + else
  267 +
  268 + present_articles_for_asset(profile)
  269 + end
  270 + end
  271 +
  272 + desc "Return a article associate with a profile of type #{kind}" do
  273 + detail 'Get only one article of a profile'
  274 + params Entities::Article.documentation
  275 + success Entities::Article
  276 + failure [[403, 'Forbidden']]
  277 + named 'ArticleOfProfile'
  278 + end
  279 + get ':id' do
  280 + profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
  281 + present_article(profile)
  282 + end
  283 +
  284 + # Example Request:
  285 + # POST api/v1/{people,communities,enterprises}/:asset_id/articles?private_token=234298743290432&article[name]=title&article[body]=body
  286 + desc "Add a new article associated with a profile of type #{kind}" do
  287 + detail 'Create a new article and associate with a profile'
  288 + params Entities::Article.documentation
  289 + success Entities::Article
  290 + failure [[403, 'Forbidden']]
  291 + named 'ArticleCreateToProfile'
  292 + end
  293 + post do
  294 + profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
  295 + post_article(profile, params)
  296 + end
  297 + end
  298 + end
  299 + end
  300 + end
  301 + end
  302 + end
  303 +end
app/api/v1/blocks.rb 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +module Api
  2 + module V1
  3 +
  4 + class Blocks < Grape::API
  5 + resource :blocks do
  6 + get ':id' do
  7 + block = Block.find(params["id"])
  8 + return forbidden! unless block.visible_to_user?(current_person)
  9 + present block, :with => Entities::Block, display_api_content: true
  10 + end
  11 + end
  12 + end
  13 +
  14 + end
  15 +end
app/api/v1/boxes.rb 0 → 100644
@@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
  1 +module Api
  2 + module V1
  3 +
  4 + class Boxes < Grape::API
  5 +
  6 + kinds = %w[profile community person enterprise]
  7 + kinds.each do |kind|
  8 +
  9 + resource kind.pluralize.to_sym do
  10 +
  11 + segment "/:#{kind}_id" do
  12 + resource :boxes do
  13 + get do
  14 + profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
  15 + present profile.boxes, :with => Entities::Box
  16 + end
  17 + end
  18 + end
  19 + end
  20 +
  21 + end
  22 +
  23 + resource :environments do
  24 + [ '/default', '/context', ':environment_id' ].each do |route|
  25 + segment route do
  26 + resource :boxes do
  27 + get do
  28 + if (route.match(/default/))
  29 + env = Environment.default
  30 + elsif (route.match(/context/))
  31 + env = environment
  32 + else
  33 + env = Environment.find(params[:environment_id])
  34 + end
  35 + present env.boxes, :with => Entities::Box
  36 + end
  37 + end
  38 + end
  39 + end
  40 + end
  41 + end
  42 +
  43 + end
  44 +end
app/api/v1/categories.rb 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +module Api
  2 + module V1
  3 + class Categories < Grape::API
  4 +
  5 + resource :categories do
  6 +
  7 + get do
  8 + type = params[:category_type]
  9 + include_parent = params[:include_parent] == 'true'
  10 + include_children = params[:include_children] == 'true'
  11 +
  12 + categories = type.nil? ? environment.categories : environment.categories.where(:type => type)
  13 + present categories, :with => Entities::Category, parent: include_parent, children: include_children
  14 + end
  15 +
  16 + desc "Return the category by id"
  17 + get ':id' do
  18 + present environment.categories.find(params[:id]), :with => Entities::Category, parent: true, children: true
  19 + end
  20 +
  21 + end
  22 +
  23 + end
  24 + end
  25 +end
app/api/v1/comments.rb 0 → 100644
@@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
  1 +module Api
  2 + module V1
  3 + class Comments < Grape::API
  4 + MAX_PER_PAGE = 20
  5 +
  6 +
  7 + resource :articles do
  8 + paginate max_per_page: MAX_PER_PAGE
  9 + # Collect comments from articles
  10 + #
  11 + # Parameters:
  12 + # reference_id - comment id used as reference to collect comment
  13 + # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected
  14 + # limit - amount of comments returned. The default value is 20
  15 + #
  16 + # Example Request:
  17 + # GET /articles/12/comments?oldest&limit=10&reference_id=23
  18 + get ":id/comments" do
  19 + article = find_article(environment.articles, params[:id])
  20 + comments = select_filtered_collection_of(article, :comments, params)
  21 + comments = comments.without_spam
  22 + comments = comments.without_reply if(params[:without_reply].present?)
  23 + comments = plugins.filter(:unavailable_comments, comments)
  24 + present paginate(comments), :with => Entities::Comment, :current_person => current_person
  25 + end
  26 +
  27 + get ":id/comments/:comment_id" do
  28 + article = find_article(environment.articles, params[:id])
  29 + present article.comments.find(params[:comment_id]), :with => Entities::Comment, :current_person => current_person
  30 + end
  31 +
  32 + # Example Request:
  33 + # POST api/v1/articles/12/comments?private_token=2298743290432&body=new comment&title=New
  34 + post ":id/comments" do
  35 + authenticate!
  36 + article = find_article(environment.articles, params[:id])
  37 + options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person, :source => article)
  38 + begin
  39 + comment = Comment.create!(options)
  40 + rescue ActiveRecord::RecordInvalid => e
  41 + render_api_error!(e.message, 400)
  42 + end
  43 + present comment, :with => Entities::Comment, :current_person => current_person
  44 + end
  45 + end
  46 +
  47 + end
  48 + end
  49 +end
app/api/v1/communities.rb 0 → 100644
@@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
  1 +module Api
  2 + module V1
  3 + class Communities < Grape::API
  4 +
  5 + resource :communities do
  6 +
  7 + # Collect comments from articles
  8 + #
  9 + # Parameters:
  10 + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created
  11 + # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected
  12 + # limit - amount of comments returned. The default value is 20
  13 + #
  14 + # Example Request:
  15 + # GET /communities?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10
  16 + # GET /communities?reference_id=10&limit=10&oldest
  17 + get do
  18 + communities = select_filtered_collection_of(environment, 'communities', params)
  19 + communities = profiles_for_person(communities, current_person)
  20 + communities = communities.by_location(params) # Must be the last. May return Exception obj
  21 + present communities, :with => Entities::Community, :current_person => current_person
  22 + end
  23 +
  24 +
  25 + # Example Request:
  26 + # POST api/v1/communties?private_token=234298743290432&community[name]=some_name
  27 + # for each custom field for community, add &community[field_name]=field_value to the request
  28 + post do
  29 + authenticate!
  30 + params[:community] ||= {}
  31 +
  32 + params[:community][:custom_values]={}
  33 + params[:community].keys.each do |key|
  34 + params[:community][:custom_values][key]=params[:community].delete(key) if Community.custom_fields(environment).any?{|cf| cf.name==key}
  35 + end
  36 +
  37 + begin
  38 + community = Community.create_after_moderation(current_person, params[:community].merge({:environment => environment}))
  39 + rescue
  40 + community = Community.new(params[:community])
  41 + end
  42 +
  43 + if !community.save
  44 + render_api_errors!(community.errors.full_messages)
  45 + end
  46 +
  47 + present community, :with => Entities::Community, :current_person => current_person
  48 + end
  49 +
  50 + get ':id' do
  51 + community = profiles_for_person(environment.communities, current_person).find_by_id(params[:id])
  52 + present community, :with => Entities::Community, :current_person => current_person
  53 + end
  54 +
  55 + end
  56 +
  57 + resource :people do
  58 +
  59 + segment '/:person_id' do
  60 +
  61 + resource :communities do
  62 +
  63 + get do
  64 + person = environment.people.find(params[:person_id])
  65 +
  66 + not_found! if person.blank?
  67 + forbidden! if !person.display_info_to?(current_person)
  68 +
  69 + communities = select_filtered_collection_of(person, 'communities', params)
  70 + communities = communities.visible
  71 + present communities, :with => Entities::Community, :current_person => current_person
  72 + end
  73 +
  74 + end
  75 +
  76 + end
  77 +
  78 + end
  79 +
  80 + end
  81 + end
  82 +end
app/api/v1/contacts.rb 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +module Api
  2 + module V1
  3 + class Contacts < Grape::API
  4 +
  5 + resource :communities do
  6 +
  7 + resource ':id/contact' do
  8 + #contact => {:name => 'some name', :email => 'test@mail.com', :subject => 'some title', :message => 'some message'}
  9 + desc "Send a contact message"
  10 + post do
  11 + profile = environment.communities.find(params[:id])
  12 + forbidden! unless profile.present?
  13 + contact = Contact.new params[:contact].merge(dest: profile)
  14 + if contact.deliver
  15 + {:success => true}
  16 + else
  17 + {:success => false}
  18 + end
  19 + end
  20 +
  21 + end
  22 + end
  23 +
  24 + end
  25 + end
  26 +end
app/api/v1/enterprises.rb 0 → 100644
@@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
  1 +module Api
  2 + module V1
  3 + class Enterprises < Grape::API
  4 +
  5 + resource :enterprises do
  6 +
  7 + # Collect enterprises from environment
  8 + #
  9 + # Parameters:
  10 + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created
  11 + # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected
  12 + # limit - amount of comments returned. The default value is 20
  13 + # georef params - read `Profile.by_location` for more information.
  14 + #
  15 + # Example Request:
  16 + # GET /enterprises?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10
  17 + # GET /enterprises?reference_id=10&limit=10&oldest
  18 + get do
  19 + enterprises = select_filtered_collection_of(environment, 'enterprises', params)
  20 + enterprises = enterprises.visible
  21 + enterprises = enterprises.by_location(params) # Must be the last. May return Exception obj.
  22 + present enterprises, :with => Entities::Enterprise, :current_person => current_person
  23 + end
  24 +
  25 + desc "Return one enterprise by id"
  26 + get ':id' do
  27 + enterprise = environment.enterprises.visible.find_by(id: params[:id])
  28 + present enterprise, :with => Entities::Enterprise, :current_person => current_person
  29 + end
  30 +
  31 + end
  32 +
  33 + resource :people do
  34 +
  35 + segment '/:person_id' do
  36 +
  37 + resource :enterprises do
  38 +
  39 + get do
  40 + person = environment.people.find(params[:person_id])
  41 + enterprises = select_filtered_collection_of(person, 'enterprises', params)
  42 + enterprises = enterprises.visible.by_location(params)
  43 + present enterprises, :with => Entities::Enterprise, :current_person => current_person
  44 + end
  45 +
  46 + end
  47 +
  48 + end
  49 +
  50 + end
  51 +
  52 +
  53 + end
  54 + end
  55 +end
app/api/v1/environments.rb 0 → 100644
@@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
  1 +module Api
  2 + module V1
  3 + class Environments < Grape::API
  4 +
  5 + resource :environment do
  6 +
  7 + desc "Return the person information"
  8 + get '/signup_person_fields' do
  9 + present environment.signup_person_fields
  10 + end
  11 +
  12 + get ':id' do
  13 + local_environment = nil
  14 + if (params[:id] == "default")
  15 + local_environment = Environment.default
  16 + elsif (params[:id] == "context")
  17 + local_environment = environment
  18 + else
  19 + local_environment = Environment.find(params[:id])
  20 + end
  21 + present_partial local_environment, :with => Entities::Environment, :is_admin => is_admin?(local_environment)
  22 + end
  23 +
  24 + end
  25 +
  26 + end
  27 + end
  28 +end
app/api/v1/people.rb 0 → 100644
@@ -0,0 +1,127 @@ @@ -0,0 +1,127 @@
  1 +module Api
  2 + module V1
  3 + class People < Grape::API
  4 +
  5 + MAX_PER_PAGE = 50
  6 +
  7 + desc 'API Root'
  8 +
  9 + resource :people do
  10 + paginate max_per_page: MAX_PER_PAGE
  11 +
  12 + # -- A note about privacy --
  13 + # We wold find people by location, but we must test if the related
  14 + # fields are public. We can't do it now, with SQL, while the location
  15 + # data and the fields_privacy are a serialized settings.
  16 + # We must build a new table for profile data, where we can set meta-data
  17 + # like:
  18 + # | id | profile_id | key | value | privacy_level | source |
  19 + # | 1 | 99 | city | Salvador | friends | user |
  20 + # | 2 | 99 | lng | -38.521 | me only | automatic |
  21 +
  22 + # Collect people from environment
  23 + #
  24 + # Parameters:
  25 + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created
  26 + # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected
  27 + # limit - amount of comments returned. The default value is 20
  28 + #
  29 + # Example Request:
  30 + # GET /people?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10
  31 + # GET /people?reference_id=10&limit=10&oldest
  32 +
  33 + desc "Find environment's people"
  34 + get do
  35 + people = select_filtered_collection_of(environment, 'people', params)
  36 + people = people.visible
  37 + present_partial people, :with => Entities::Person, :current_person => current_person
  38 + end
  39 +
  40 + desc "Return the logged user information"
  41 + get "/me" do
  42 + authenticate!
  43 + present_partial current_person, :with => Entities::Person, :current_person => current_person
  44 + end
  45 +
  46 + desc "Return the person information"
  47 + get ':id' do
  48 + person = environment.people.visible.find_by(id: params[:id])
  49 + return not_found! if person.blank?
  50 + present person, :with => Entities::Person, :current_person => current_person
  51 + end
  52 +
  53 + desc "Update person information"
  54 + post ':id' do
  55 + authenticate!
  56 + return forbidden! if current_person.id.to_s != params[:id]
  57 + current_person.update_attributes!(asset_with_image(params[:person]))
  58 + present current_person, :with => Entities::Person, :current_person => current_person
  59 + end
  60 +
  61 + # POST api/v1/people?person[login]=some_login&person[password]=some_password&person[name]=Jack
  62 + # for each custom field for person, add &person[field_name]=field_value to the request
  63 + desc "Create person"
  64 + post do
  65 + authenticate!
  66 + user_data = {}
  67 + user_data[:login] = params[:person].delete(:login) || params[:person][:identifier]
  68 + user_data[:email] = params[:person].delete(:email)
  69 + user_data[:password] = params[:person].delete(:password)
  70 + user_data[:password_confirmation] = params[:person].delete(:password_confirmation)
  71 +
  72 + params[:person][:custom_values]={}
  73 + params[:person].keys.each do |key|
  74 + params[:person][:custom_values][key]=params[:person].delete(key) if Person.custom_fields(environment).any?{|cf| cf.name==key}
  75 + end
  76 +
  77 + user = User.build(user_data, asset_with_image(params[:person]), environment)
  78 +
  79 + begin
  80 + user.signup!
  81 + rescue ActiveRecord::RecordInvalid
  82 + render_api_errors!(user.errors.full_messages)
  83 + end
  84 +
  85 + present user.person, :with => Entities::Person, :current_person => user.person
  86 + end
  87 +
  88 + desc "Return the person friends"
  89 + get ':id/friends' do
  90 + person = environment.people.visible.find_by(id: params[:id])
  91 + return not_found! if person.blank?
  92 + friends = person.friends.visible
  93 + present friends, :with => Entities::Person, :current_person => current_person
  94 + end
  95 +
  96 + desc "Return the person permissions on other profiles"
  97 + get ":id/permissions" do
  98 + authenticate!
  99 + person = environment.people.find(params[:id])
  100 + return not_found! if person.blank?
  101 + return forbidden! unless current_person == person || environment.admins.include?(current_person)
  102 +
  103 + output = {}
  104 + person.role_assignments.map do |role_assigment|
  105 + if role_assigment.resource.respond_to?(:identifier)
  106 + output[role_assigment.resource.identifier] = role_assigment.role.permissions
  107 + end
  108 + end
  109 + present output
  110 + end
  111 + end
  112 +
  113 + resource :profiles do
  114 + segment '/:profile_id' do
  115 + resource :members do
  116 + paginate max_per_page: MAX_PER_PAGE
  117 + get do
  118 + profile = environment.profiles.find_by id: params[:profile_id]
  119 + members = select_filtered_collection_of(profile, 'members', params)
  120 + present members, :with => Entities::Person, :current_person => current_person
  121 + end
  122 + end
  123 + end
  124 + end
  125 + end
  126 + end
  127 +end
app/api/v1/profiles.rb 0 → 100644
@@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
  1 +module Api
  2 + module V1
  3 + class Profiles < Grape::API
  4 +
  5 + resource :profiles do
  6 +
  7 + get do
  8 + profiles = select_filtered_collection_of(environment, 'profiles', params)
  9 + profiles = profiles.visible
  10 + profiles = profiles.by_location(params) # Must be the last. May return Exception obj.
  11 + present profiles, :with => Entities::Profile, :current_person => current_person
  12 + end
  13 +
  14 + get ':id' do
  15 + profiles = environment.profiles
  16 + profiles = profiles.visible
  17 + profile = profiles.find_by id: params[:id]
  18 +
  19 + if profile
  20 + present profile, :with => Entities::Profile, :current_person => current_person
  21 + else
  22 + not_found!
  23 + end
  24 + end
  25 +
  26 + delete ':id' do
  27 + authenticate!
  28 + profiles = environment.profiles
  29 + profile = profiles.find_by id: params[:id]
  30 +
  31 + not_found! if profile.blank?
  32 +
  33 + if current_person.has_permission?(:destroy_profile, profile)
  34 + profile.destroy
  35 + else
  36 + forbidden!
  37 + end
  38 + end
  39 + end
  40 + end
  41 + end
  42 +end
app/api/v1/search.rb 0 → 100644
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +module Api
  2 + module V1
  3 + class Search < Grape::API
  4 +
  5 + resource :search do
  6 + resource :article do
  7 + paginate max_per_page: 200
  8 + get do
  9 + # Security checks
  10 + sanitize_params_hash(params)
  11 + # Api::Helpers
  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(make_conditions_with_parameter(params))
  19 + scope = scope.joins(:categories).where(:categories => {:id => params[:category_ids]}) if params[:category_ids].present?
  20 + scope = scope.where('articles.children_count > 0') if params[:has_children].present?
  21 + query = params[:query] || ""
  22 + order = "more_recent"
  23 +
  24 + options = {:filter => order, :template_id => params[:template_id]}
  25 +
  26 + search_result = find_by_contents(asset, context, scope, query, {:page => 1}, options)
  27 +
  28 + articles = search_result[:results]
  29 +
  30 + present_articles(articles)
  31 + end
  32 + end
  33 + end
  34 +
  35 + end
  36 + end
  37 +end
app/api/v1/session.rb 0 → 100644
@@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
  1 +require "uri"
  2 +
  3 +module Api
  4 + module V1
  5 + class Session < Grape::API
  6 +
  7 + # Login to get token
  8 + #
  9 + # Parameters:
  10 + # login (*required) - user login or email
  11 + # password (required) - user password
  12 + #
  13 + # Example Request:
  14 + # POST http://localhost:3000/api/v1/login?login=adminuser&password=admin
  15 + post "/login" do
  16 + begin
  17 + user ||= User.authenticate(params[:login], params[:password], environment)
  18 + rescue User::UserNotActivated => e
  19 + render_api_error!(e.message, 401)
  20 + end
  21 +
  22 + return unauthorized! unless user
  23 + @current_user = user
  24 + present user, :with => Entities::UserLogin, :current_person => current_person
  25 + end
  26 +
  27 + post "/login_from_cookie" do
  28 + return unauthorized! if cookies[:auth_token].blank?
  29 + user = User.where(remember_token: cookies[:auth_token]).first
  30 + return unauthorized! unless user && user.activated?
  31 + @current_user = user
  32 + present user, :with => Entities::UserLogin, :current_person => current_person
  33 + end
  34 +
  35 + # Create user.
  36 + #
  37 + # Parameters:
  38 + # email (required) - Email
  39 + # password (required) - Password
  40 + # login - login
  41 + # Example Request:
  42 + # POST /register?email=some@mail.com&password=pas&password_confirmation=pas&login=some
  43 + params do
  44 + requires :email, type: String, desc: _("Email")
  45 + requires :login, type: String, desc: _("Login")
  46 + requires :password, type: String, desc: _("Password")
  47 + end
  48 +
  49 + post "/register" do
  50 + attrs = attributes_for_keys [:email, :login, :password, :password_confirmation] + environment.signup_person_fields
  51 + name = params[:name].present? ? params[:name] : attrs[:email]
  52 + attrs[:password_confirmation] = attrs[:password] if !attrs.has_key?(:password_confirmation)
  53 + user = User.new(attrs.merge(:name => name))
  54 +
  55 + begin
  56 + user.signup!
  57 + user.generate_private_token! if user.activated?
  58 + present user, :with => Entities::UserLogin, :current_person => user.person
  59 + rescue ActiveRecord::RecordInvalid
  60 + message = user.errors.as_json.merge((user.person.present? ? user.person.errors : {}).as_json).to_json
  61 + render_api_error!(message, 400)
  62 + end
  63 + end
  64 +
  65 + params do
  66 + requires :activation_code, type: String, desc: _("Activation token")
  67 + end
  68 +
  69 + # Activate a user.
  70 + #
  71 + # Parameter:
  72 + # activation_code (required) - Activation token
  73 + # Example Request:
  74 + # PATCH /activate?activation_code=28259abd12cc6a64ef9399cf3286cb998b96aeaf
  75 + patch "/activate" do
  76 + user = User.find_by activation_code: params[:activation_code]
  77 + if user
  78 + unless user.environment.enabled?('admin_must_approve_new_users')
  79 + if user.activate
  80 + user.generate_private_token!
  81 + present user, :with => Entities::UserLogin, :current_person => current_person
  82 + end
  83 + else
  84 + if user.create_moderate_task
  85 + user.activation_code = nil
  86 + user.save!
  87 +
  88 + # Waiting for admin moderate user registration
  89 + status 202
  90 + body({
  91 + :message => 'Waiting for admin moderate user registration'
  92 + })
  93 + end
  94 + end
  95 + else
  96 + # Token not found in database
  97 + render_api_error!(_('Token is invalid'), 412)
  98 + end
  99 + end
  100 +
  101 + # Request a new password.
  102 + #
  103 + # Parameters:
  104 + # value (required) - Email or login
  105 + # Example Request:
  106 + # POST /forgot_password?value=some@mail.com
  107 + post "/forgot_password" do
  108 + requestors = fetch_requestors(params[:value])
  109 + not_found! if requestors.blank?
  110 + remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
  111 + requestors.each do |requestor|
  112 + ChangePassword.create!(:requestor => requestor)
  113 + end
  114 + end
  115 +
  116 + # Resend activation code.
  117 + #
  118 + # Parameters:
  119 + # value (required) - Email or login
  120 + # Example Request:
  121 + # POST /resend_activation_code?value=some@mail.com
  122 + post "/resend_activation_code" do
  123 + requestors = fetch_requestors(params[:value])
  124 + not_found! if requestors.blank?
  125 + remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])
  126 + requestors.each do |requestor|
  127 + requestor.user.resend_activation_code
  128 + end
  129 + present requestors.map(&:user), :with => Entities::UserLogin
  130 + end
  131 +
  132 + params do
  133 + requires :code, type: String, desc: _("Forgot password code")
  134 + end
  135 + # Change password
  136 + #
  137 + # Parameters:
  138 + # code (required) - Change password code
  139 + # password (required)
  140 + # password_confirmation (required)
  141 + # Example Request:
  142 + # PATCH /new_password?code=xxxx&password=secret&password_confirmation=secret
  143 + patch "/new_password" do
  144 + change_password = ChangePassword.find_by code: params[:code]
  145 + not_found! if change_password.nil?
  146 +
  147 + if change_password.update_attributes(:password => params[:password], :password_confirmation => params[:password_confirmation])
  148 + change_password.finish
  149 + present change_password.requestor.user, :with => Entities::UserLogin, :current_person => current_person
  150 + else
  151 + something_wrong!
  152 + end
  153 + end
  154 +
  155 + end
  156 + end
  157 +end
app/api/v1/tags.rb 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +module Api
  2 + module V1
  3 + class Tags < Grape::API
  4 + before { authenticate! }
  5 +
  6 + resource :articles do
  7 +
  8 + resource ':id/tags' do
  9 +
  10 + get do
  11 + article = find_article(environment.articles, params[:id])
  12 + present article.tag_list
  13 + end
  14 +
  15 + desc "Add a tag to an article"
  16 + post do
  17 + article = find_article(environment.articles, params[:id])
  18 + article.tag_list=params[:tags]
  19 + article.save
  20 + present article.tag_list
  21 + end
  22 + end
  23 + end
  24 + end
  25 + end
  26 +end
app/api/v1/tasks.rb 0 → 100644
@@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
  1 +module Api
  2 + module V1
  3 + class Tasks < Grape::API
  4 +# before { authenticate! }
  5 +
  6 +# ARTICLE_TYPES = Article.descendants.map{|a| a.to_s}
  7 +
  8 + resource :tasks do
  9 +
  10 + # Collect tasks
  11 + #
  12 + # Parameters:
  13 + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created
  14 + # oldest - Collect the oldest articles. If nothing is passed the newest articles are collected
  15 + # limit - amount of articles returned. The default value is 20
  16 + #
  17 + # Example Request:
  18 + # GET host/api/v1/tasks?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317
  19 + get do
  20 + tasks = select_filtered_collection_of(environment, 'tasks', params)
  21 + tasks = tasks.select {|t| current_person.has_permission?(t.permission, environment)}
  22 + present_partial tasks, :with => Entities::Task
  23 + end
  24 +
  25 + desc "Return the task id"
  26 + get ':id' do
  27 + task = find_task(environment, params[:id])
  28 + present_partial task, :with => Entities::Task
  29 + end
  30 + end
  31 +
  32 + kinds = %w[community person enterprise]
  33 + kinds.each do |kind|
  34 + resource kind.pluralize.to_sym do
  35 + segment "/:#{kind}_id" do
  36 + resource :tasks do
  37 + get do
  38 + profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
  39 + present_tasks(profile)
  40 + end
  41 +
  42 + get ':id' do
  43 + profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
  44 + present_task(profile)
  45 + end
  46 +
  47 + post do
  48 + profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
  49 + post_task(profile, params)
  50 + end
  51 + end
  52 + end
  53 + end
  54 + end
  55 + end
  56 + end
  57 +end
app/api/v1/users.rb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +module Api
  2 + module V1
  3 + class Users < Grape::API
  4 +
  5 + resource :users do
  6 +
  7 + get do
  8 + users = select_filtered_collection_of(environment, 'users', params)
  9 + users = users.select{|u| u.person.display_info_to? current_person}
  10 + present users, :with => Entities::User, :current_person => current_person
  11 + end
  12 +
  13 + get "/me" do
  14 + authenticate!
  15 + present current_user, :with => Entities::User, :current_person => current_person
  16 + end
  17 +
  18 + get ":id" do
  19 + user = environment.users.find_by id: params[:id]
  20 + if user
  21 + present user, :with => Entities::User, :current_person => current_person
  22 + else
  23 + not_found!
  24 + end
  25 + end
  26 +
  27 + get ":id/permissions" do
  28 + authenticate!
  29 + user = environment.users.find(params[:id])
  30 + output = {}
  31 + user.person.role_assignments.map do |role_assigment|
  32 + if role_assigment.resource.respond_to?(:identifier) && role_assigment.resource.identifier == params[:profile]
  33 + output[:permissions] = role_assigment.role.permissions
  34 + end
  35 + end
  36 + present output
  37 + end
  38 +
  39 + end
  40 +
  41 + end
  42 + end
  43 +end
app/controllers/public/api_controller.rb
@@ -13,7 +13,7 @@ class ApiController &lt; PublicController @@ -13,7 +13,7 @@ class ApiController &lt; PublicController
13 private 13 private
14 14
15 def endpoints 15 def endpoints
16 - Noosfero::API::API.endpoints(environment) 16 + Api::App.endpoints(environment)
17 end 17 end
18 18
19 end 19 end
app/jobs/activities_counter_cache_job.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class ActivitiesCounterCacheJob
  2 +
  3 + def perform
  4 + person_activities_counts = ApplicationRecord.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id WHERE (action_tracker.created_at >= #{ApplicationRecord.connection.quote(ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db))}) AND ( (profiles.type = 'Person' ) ) GROUP BY profiles.id;")
  5 + organization_activities_counts = ApplicationRecord.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id WHERE (action_tracker.created_at >= #{ApplicationRecord.connection.quote(ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db))}) AND ( (profiles.type = 'Community' OR profiles.type = 'Enterprise' OR profiles.type = 'Organization' ) ) GROUP BY profiles.id;")
  6 + activities_counts = person_activities_counts.entries + organization_activities_counts.entries
  7 + activities_counts.each do |count|
  8 + update_sql = ApplicationRecord.__send__(:sanitize_sql, ["UPDATE profiles SET activities_count=? WHERE profiles.id=?;", count['count'].to_i, count['id'] ], '')
  9 + ApplicationRecord.connection.execute(update_sql)
  10 + end
  11 + Delayed::Job.enqueue(ActivitiesCounterCacheJob.new, {:priority => -3, :run_at => 1.day.from_now})
  12 + end
  13 +
  14 +end
app/jobs/create_thumbnails_job.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class CreateThumbnailsJob < Struct.new(:class_name, :file_id)
  2 + def perform
  3 + return unless class_name.constantize.exists?(file_id)
  4 + file = class_name.constantize.find(file_id)
  5 + file.create_thumbnails
  6 + article = Article.where(:image_id => file_id).first
  7 + if article
  8 + article.touch
  9 + end
  10 + end
  11 +end
app/models/application_record.rb
1 class ApplicationRecord < ActiveRecord::Base 1 class ApplicationRecord < ActiveRecord::Base
2 2
3 - self.abstract_class = true  
4 -  
5 - def self.postgresql?  
6 - self.connection.adapter_name == 'PostgreSQL'  
7 - end 3 + self.abstract_class = true
  4 + self.store_full_sti_class = true
8 5
9 # an ActionView instance for rendering views on models 6 # an ActionView instance for rendering views on models
10 def self.action_view 7 def self.action_view
@@ -25,7 +22,7 @@ class ApplicationRecord &lt; ActiveRecord::Base @@ -25,7 +22,7 @@ class ApplicationRecord &lt; ActiveRecord::Base
25 alias :meta_cache_key :cache_key 22 alias :meta_cache_key :cache_key
26 def cache_key 23 def cache_key
27 key = [Noosfero::VERSION, meta_cache_key] 24 key = [Noosfero::VERSION, meta_cache_key]
28 - key.unshift(ApplicationRecord.connection.schema_search_path) if ApplicationRecord.postgresql? 25 + key.unshift ApplicationRecord.connection.schema_search_path
29 key.join('/') 26 key.join('/')
30 end 27 end
31 28
app/models/profile.rb
@@ -1093,6 +1093,11 @@ private :generate_url, :url_options @@ -1093,6 +1093,11 @@ private :generate_url, :url_options
1093 self.data[:fields_privacy] 1093 self.data[:fields_privacy]
1094 end 1094 end
1095 1095
  1096 + # abstract
  1097 + def active_fields
  1098 + []
  1099 + end
  1100 +
1096 def public_fields 1101 def public_fields
1097 self.active_fields 1102 self.active_fields
1098 end 1103 end
app/models/recent_documents_block.rb
@@ -31,7 +31,7 @@ class RecentDocumentsBlock &lt; Block @@ -31,7 +31,7 @@ class RecentDocumentsBlock &lt; Block
31 end 31 end
32 32
33 def api_content 33 def api_content
34 - Noosfero::API::Entities::ArticleBase.represent(docs).as_json 34 + Api::Entities::ArticleBase.represent(docs).as_json
35 end 35 end
36 36
37 def display_api_content_by_default? 37 def display_api_content_by_default?
app/views/admin_panel/set_portal_community.html.erb
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <% end %> 9 <% end %>
10 <% end %> 10 <% end %>
11 <% else %> 11 <% else %>
12 - <%= _('Portal identifier: %s') % link_to(@portal_community.identifier, @portal_community.url) %> 12 + <%= _('Portal identifier: %s').html_safe % link_to(@portal_community.identifier, @portal_community.url) %>
13 13
14 <% button_bar do %> 14 <% button_bar do %>
15 <%if @portal_community.environment.enabled?('use_portal_community') %> 15 <%if @portal_community.environment.enabled?('use_portal_community') %>
app/views/api/playground.html.erb
1 <h1>API Playground</h1> 1 <h1>API Playground</h1>
2 2
3 <script> 3 <script>
4 -<% prefix = Noosfero::API::API.prefix %> 4 +<% prefix = Api::App.prefix %>
5 var prefix = <%= prefix.to_json %>; 5 var prefix = <%= prefix.to_json %>;
6 var endpoints = <%= 6 var endpoints = <%=
7 endpoints.map do |endpoint| 7 endpoints.map do |endpoint|
@@ -20,6 +20,6 @@ rails_app = Rack::Builder.new do @@ -20,6 +20,6 @@ rails_app = Rack::Builder.new do
20 end 20 end
21 21
22 run Rack::Cascade.new([ 22 run Rack::Cascade.new([
23 - Noosfero::API::API, 23 + Api::App,
24 rails_app 24 rails_app
25 ]) 25 ])
config/application.rb
1 -require File.expand_path('../boot', __FILE__) 1 +require_relative 'boot'
2 2
3 require 'rails/all' 3 require 'rails/all'
4 require 'active_support/dependencies' 4 require 'active_support/dependencies'
5 5
6 -# FIXME this silences the warnings about Rails 2.3-style plugins under  
7 -# vendor/plugins, which are deprecated. Hiding those warnings makes it easier  
8 -# to work for now, but we should really look at putting those plugins away. 6 +# Silence Rails 5 deprecation warnings
9 ActiveSupport::Deprecation.silenced = true 7 ActiveSupport::Deprecation.silenced = true
10 8
11 Bundler.require(:default, :assets, Rails.env) 9 Bundler.require(:default, :assets, Rails.env)
  10 +$: << File.expand_path('../lib', File.dirname(__FILE__))
  11 +
  12 +require_dependency 'noosfero'
  13 +require_dependency 'noosfero/plugin'
  14 +require_dependency 'noosfero/multi_tenancy'
12 15
13 module Noosfero 16 module Noosfero
14 class Application < Rails::Application 17 class Application < Rails::Application
15 18
16 - require 'noosfero/plugin'  
17 -  
18 # The plugin xss_terminator(located in vendor/plugins/xss_terminator) and the helper 19 # The plugin xss_terminator(located in vendor/plugins/xss_terminator) and the helper
19 # SanitizeHelper(located in app/helpers/sanitize_helper.rb) use 20 # SanitizeHelper(located in app/helpers/sanitize_helper.rb) use
20 # ALLOWED_TAGS and ALLOWED_ATTRIBUTES to make a sanitize with html. 21 # ALLOWED_TAGS and ALLOWED_ATTRIBUTES to make a sanitize with html.
@@ -30,9 +31,6 @@ module Noosfero @@ -30,9 +31,6 @@ module Noosfero
30 config.action_view.sanitized_allowed_tags = ALLOWED_TAGS 31 config.action_view.sanitized_allowed_tags = ALLOWED_TAGS
31 config.action_view.sanitized_allowed_attributes = ALLOWED_ATTRIBUTES 32 config.action_view.sanitized_allowed_attributes = ALLOWED_ATTRIBUTES
32 33
33 - require 'noosfero/multi_tenancy'  
34 - config.middleware.use Noosfero::MultiTenancy::Middleware  
35 -  
36 config.action_controller.include_all_helpers = false 34 config.action_controller.include_all_helpers = false
37 35
38 # Settings in config/environments/* take precedence over those specified here. 36 # Settings in config/environments/* take precedence over those specified here.
@@ -40,10 +38,12 @@ module Noosfero @@ -40,10 +38,12 @@ module Noosfero
40 # -- all .rb files in that directory are automatically loaded. 38 # -- all .rb files in that directory are automatically loaded.
41 39
42 # Custom directories with classes and modules you want to be autoloadable. 40 # Custom directories with classes and modules you want to be autoloadable.
43 - config.autoload_paths += %W( #{config.root.join('app', 'sweepers')} )  
44 - config.autoload_paths += Dir["#{config.root}/lib"]  
45 - config.autoload_paths += Dir["#{config.root}/app/controllers/**/"]  
46 - config.autoload_paths += %W( #{config.root.join('test', 'mocks', Rails.env)} ) 41 + config.autoload_paths << config.root.join('lib')
  42 + config.autoload_paths << config.root.join('app')
  43 + config.autoload_paths << config.root.join('app/jobs')
  44 + config.autoload_paths << config.root.join('app/sweepers')
  45 + config.autoload_paths.concat Dir["#{config.root}/app/controllers/**/"]
  46 + config.autoload_paths << config.root.join('test', 'mocks', Rails.env)
47 47
48 # Only load the plugins named here, in the order given (default is alphabetical). 48 # Only load the plugins named here, in the order given (default is alphabetical).
49 # :all can be used as a placeholder for all plugins not explicitly named. 49 # :all can be used as a placeholder for all plugins not explicitly named.
@@ -119,7 +119,8 @@ module Noosfero @@ -119,7 +119,8 @@ module Noosfero
119 119
120 config.eager_load = true 120 config.eager_load = true
121 121
122 - Noosfero::Plugin.setup(config) 122 + config.middleware.use Noosfero::MultiTenancy::Middleware
123 123
  124 + Noosfero::Plugin.setup(config)
124 end 125 end
125 end 126 end
config/environment.rb
1 -# Load the rails application  
2 -require File.expand_path('../application', __FILE__) 1 +require_relative 'application'
3 2
4 -#FIXME Necessary hack to avoid the need of downgrading rubygems on rails 2.3.5  
5 -# http://stackoverflow.com/questions/5564251/uninitialized-constant-activesupportdependenciesmutex  
6 -require 'thread'  
7 -  
8 -# Uncomment below to force Rails into production mode when  
9 -# you don't control web/app server and can't set it the proper way  
10 -#ENV['RAILS_ENV'] ||= 'production'  
11 -  
12 -# extra directories for controllers organization  
13 -extra_controller_dirs = %w[  
14 -].map {|item| Rails.root.join(item) }  
15 -  
16 -# Add new inflection rules using the following format  
17 -# (all these examples are active by default):  
18 -# Inflector.inflections do |inflect|  
19 -# inflect.plural /^(ox)$/i, '\1en'  
20 -# inflect.singular /^(ox)en/i, '\1'  
21 -# inflect.irregular 'person', 'people'  
22 -# inflect.uncountable %w( fish sheep )  
23 -# end  
24 -  
25 -# Include your application configuration below  
26 -  
27 -ActiveRecord::Base.store_full_sti_class = true  
28 -  
29 -#FIXME: Probably act_as_taggable_on is not being loaded or this should be on another place  
30 -#Tag.hierarchical = true  
31 -  
32 -# several local libraries  
33 -require_dependency 'noosfero'  
34 -#FIXME: error when call lib/sqlite_extention  
35 -#require 'sqlite_extension' 3 +Noosfero::Application.initialize!
36 4
37 # load a local configuration if present, but not under test environment. 5 # load a local configuration if present, but not under test environment.
38 -if !['test', 'cucumber'].include?(ENV['RAILS_ENV']) 6 +if ENV['RAILS_ENV'].in? %w[test cucumber]
39 localconfigfile = Rails.root.join('config', 'local.rb') 7 localconfigfile = Rails.root.join('config', 'local.rb')
40 - if File.exists?(localconfigfile)  
41 - require localconfigfile  
42 - end 8 + require localconfigfile if File.exists? localconfigfile
43 end 9 end
44 10
45 -Noosfero::Application.initialize!  
config/initializers/00_dependencies.rb 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +require 'pp'
  2 +
  3 +# third-party libraries
  4 +require 'will_paginate'
  5 +require 'will_paginate/array'
  6 +require 'nokogiri'
  7 +
  8 +# dependencies at vendor, firstly loaded on Gemfile
  9 +vendor = Dir.glob('vendor/{,plugins/}*') - ['vendor/plugins']
  10 +vendor.each do |dir|
  11 + init_rb = "#{Rails.root}/#{dir}/init.rb"
  12 + require init_rb if File.file? init_rb
  13 +end
  14 +
  15 +# extensions
  16 +require 'extensions'
  17 +
  18 +# locally-developed modules
  19 +require 'acts_as_filesystem'
  20 +require 'acts_as_having_settings'
  21 +require 'acts_as_having_boxes'
  22 +require 'acts_as_having_image'
  23 +require 'acts_as_having_posts'
  24 +require 'acts_as_customizable'
  25 +require 'route_if'
  26 +require 'maybe_add_http'
  27 +require 'set_profile_region_from_city_state'
  28 +require 'authenticated_system'
  29 +require 'needs_profile'
  30 +require 'white_list_filter'
  31 +
config/initializers/dependencies.rb
@@ -1,28 +0,0 @@ @@ -1,28 +0,0 @@
1 -require 'pp'  
2 -  
3 -# third-party libraries  
4 -require 'will_paginate'  
5 -require 'will_paginate/array'  
6 -require 'nokogiri'  
7 -  
8 -# dependencies at vendor, firstly loaded on Gemfile  
9 -vendor = Dir.glob('vendor/{,plugins/}*') - ['vendor/plugins']  
10 -vendor.each do |dir|  
11 - init_rb = "#{Rails.root}/#{dir}/init.rb"  
12 - require init_rb if File.file? init_rb  
13 -end  
14 -  
15 -# locally-developed modules  
16 -require 'acts_as_filesystem'  
17 -require 'acts_as_having_settings'  
18 -require 'acts_as_having_boxes'  
19 -require 'acts_as_having_image'  
20 -require 'acts_as_having_posts'  
21 -require 'acts_as_customizable'  
22 -require 'route_if'  
23 -require 'maybe_add_http'  
24 -require 'set_profile_region_from_city_state'  
25 -require 'authenticated_system'  
26 -require 'needs_profile'  
27 -require 'white_list_filter'  
28 -  
config/initializers/plugins.rb
@@ -5,3 +5,4 @@ require &#39;noosfero/plugin/mailer_base&#39; @@ -5,3 +5,4 @@ require &#39;noosfero/plugin/mailer_base&#39;
5 require 'noosfero/plugin/settings' 5 require 'noosfero/plugin/settings'
6 require 'noosfero/plugin/spammable' 6 require 'noosfero/plugin/spammable'
7 Noosfero::Plugin.initialize! 7 Noosfero::Plugin.initialize!
  8 +
lib/activities_counter_cache_job.rb
@@ -1,14 +0,0 @@ @@ -1,14 +0,0 @@
1 -class ActivitiesCounterCacheJob  
2 -  
3 - def perform  
4 - person_activities_counts = ApplicationRecord.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.user_id WHERE (action_tracker.created_at >= #{ApplicationRecord.connection.quote(ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db))}) AND ( (profiles.type = 'Person' ) ) GROUP BY profiles.id;")  
5 - organization_activities_counts = ApplicationRecord.connection.execute("SELECT profiles.id, count(action_tracker.id) as count FROM profiles LEFT OUTER JOIN action_tracker ON profiles.id = action_tracker.target_id WHERE (action_tracker.created_at >= #{ApplicationRecord.connection.quote(ActionTracker::Record::RECENT_DELAY.days.ago.to_s(:db))}) AND ( (profiles.type = 'Community' OR profiles.type = 'Enterprise' OR profiles.type = 'Organization' ) ) GROUP BY profiles.id;")  
6 - activities_counts = person_activities_counts.entries + organization_activities_counts.entries  
7 - activities_counts.each do |count|  
8 - update_sql = ApplicationRecord.__send__(:sanitize_sql, ["UPDATE profiles SET activities_count=? WHERE profiles.id=?;", count['count'].to_i, count['id'] ], '')  
9 - ApplicationRecord.connection.execute(update_sql)  
10 - end  
11 - Delayed::Job.enqueue(ActivitiesCounterCacheJob.new, {:priority => -3, :run_at => 1.day.from_now})  
12 - end  
13 -  
14 -end  
lib/acts_as_customizable.rb
@@ -122,4 +122,4 @@ module Customizable @@ -122,4 +122,4 @@ module Customizable
122 end 122 end
123 end 123 end
124 124
125 -ApplicationRecord.send :include, Customizable 125 +ActiveRecord::Base.include Customizable
lib/acts_as_filesystem.rb
@@ -33,7 +33,7 @@ module ActsAsFileSystem @@ -33,7 +33,7 @@ module ActsAsFileSystem
33 module ClassMethods 33 module ClassMethods
34 34
35 def build_ancestry(parent_id = nil, ancestry = '') 35 def build_ancestry(parent_id = nil, ancestry = '')
36 - ApplicationRecord.transaction do 36 + ActiveRecord::Base.transaction do
37 self.base_class.where(parent_id: parent_id).each do |node| 37 self.base_class.where(parent_id: parent_id).each do |node|
38 node.update_column :ancestry, ancestry 38 node.update_column :ancestry, ancestry
39 39
@@ -263,5 +263,5 @@ module ActsAsFileSystem @@ -263,5 +263,5 @@ module ActsAsFileSystem
263 end 263 end
264 end 264 end
265 265
266 -ApplicationRecord.extend ActsAsFileSystem::ActsMethods 266 +ActiveRecord::Base.extend ActsAsFileSystem::ActsMethods
267 267
lib/acts_as_having_boxes.rb
@@ -35,4 +35,4 @@ module ActsAsHavingBoxes @@ -35,4 +35,4 @@ module ActsAsHavingBoxes
35 35
36 end 36 end
37 37
38 -ApplicationRecord.extend ActsAsHavingBoxes::ClassMethods 38 +ActiveRecord::Base.extend ActsAsHavingBoxes::ClassMethods
lib/acts_as_having_image.rb
@@ -23,5 +23,5 @@ module ActsAsHavingImage @@ -23,5 +23,5 @@ module ActsAsHavingImage
23 23
24 end 24 end
25 25
26 -ApplicationRecord.extend ActsAsHavingImage::ClassMethods 26 +ActiveRecord::Base.extend ActsAsHavingImage::ClassMethods
27 27
lib/acts_as_having_posts.rb
@@ -47,5 +47,5 @@ module ActsAsHavingPosts @@ -47,5 +47,5 @@ module ActsAsHavingPosts
47 47
48 end 48 end
49 49
50 -ApplicationRecord.extend ActsAsHavingPosts::ClassMethods 50 +ActiveRecord::Base.extend ActsAsHavingPosts::ClassMethods
51 51
lib/acts_as_having_settings.rb
@@ -87,5 +87,5 @@ module ActsAsHavingSettings @@ -87,5 +87,5 @@ module ActsAsHavingSettings
87 87
88 end 88 end
89 89
90 -ApplicationRecord.extend ActsAsHavingSettings::ClassMethods 90 +ActiveRecord::Base.extend ActsAsHavingSettings::ClassMethods
91 91
lib/code_numbering.rb
@@ -55,4 +55,4 @@ module CodeNumbering @@ -55,4 +55,4 @@ module CodeNumbering
55 end 55 end
56 end 56 end
57 57
58 -ApplicationRecord.extend CodeNumbering::ClassMethods 58 +ActiveRecord::Base.extend CodeNumbering::ClassMethods
lib/create_thumbnails_job.rb
@@ -1,11 +0,0 @@ @@ -1,11 +0,0 @@
1 -class CreateThumbnailsJob < Struct.new(:class_name, :file_id)  
2 - def perform  
3 - return unless class_name.constantize.exists?(file_id)  
4 - file = class_name.constantize.find(file_id)  
5 - file.create_thumbnails  
6 - article = Article.where(:image_id => file_id).first  
7 - if article  
8 - article.touch  
9 - end  
10 - end  
11 -end  
lib/delayed_attachment_fu.rb
@@ -52,5 +52,5 @@ module DelayedAttachmentFu @@ -52,5 +52,5 @@ module DelayedAttachmentFu
52 end 52 end
53 end 53 end
54 54
55 -ApplicationRecord.extend DelayedAttachmentFu::ClassMethods 55 +ActiveRecord::Base.extend DelayedAttachmentFu::ClassMethods
56 56
lib/extensions.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +require_relative 'extensions/string'
  2 +require_relative 'extensions/integer'
  3 +require_relative 'extensions/active_record/calculations'
  4 +require_relative 'extensions/active_record/reflection'
  5 +
lib/extensions/active_record/calculations.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +ActiveRecord::Calculations.class_eval do
  2 + def count_with_distinct column_name=self.primary_key
  3 + if column_name
  4 + distinct.count_without_distinct column_name
  5 + else
  6 + count_without_distinct
  7 + end
  8 + end
  9 + alias_method_chain :count, :distinct
  10 +end
lib/extensions/active_record/reflection.rb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +
  2 +# on STI classes tike Article and Profile, plugins' extensions
  3 +# on associations should be reflected on descendants
  4 +module ActiveRecord
  5 + module Reflection
  6 +
  7 + class << self
  8 +
  9 + def add_reflection_with_descendants(ar, name, reflection)
  10 + self.add_reflection_without_descendants ar, name, reflection
  11 + ar.descendants.each do |k|
  12 + k._reflections.merge!(name.to_s => reflection)
  13 + end if ar.base_class == ar
  14 + end
  15 +
  16 + alias_method_chain :add_reflection, :descendants
  17 +
  18 + end
  19 + end
  20 +end
lib/extensions/integer.rb 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +class Integer
  2 + def to_humanreadable
  3 + value = self
  4 + if value < 1023
  5 + return "%i bytes" % value
  6 + end
  7 + value /= 1024
  8 +
  9 + if value < 1023
  10 + return "%1.1f KB" % value
  11 + end
  12 + value /= 1024
  13 +
  14 + if value < 1023
  15 + return "%1.1f MB" % value
  16 + end
  17 + value /= 1024
  18 +
  19 + if value < 1023
  20 + return "%1.1f GB" % value
  21 + end
  22 + value /= 1024
  23 +
  24 + if value < 1023
  25 + return "%1.1f TB" % value
  26 + end
  27 + value /= 1024
  28 +
  29 + if value < 1023
  30 + return "%1.1f PB" % value
  31 + end
  32 + value /= 1024
  33 +
  34 + if value < 1023
  35 + return "%1.1f EB" % value
  36 + end
  37 + value /= 1024
  38 + end
  39 +end
lib/extensions/string.rb 0 → 100644
@@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
  1 +# encoding: utf-8
  2 +
  3 +class String
  4 +
  5 + TRANSLITERATIONS = {
  6 + [ 'Á', 'À', 'À', 'Â', 'Ã', 'Ä', 'Å' ] => 'A',
  7 + [ 'á', 'à', 'à', 'â', 'ã', 'ä', 'å' ,'ª' ] => 'a',
  8 + [ 'É', 'È', 'Ê', 'Ë' ] => 'E',
  9 + [ 'é', 'è', 'ê', 'ë' ] => 'e',
  10 + [ 'Í', 'Ì', 'Î', 'Ï' ] => 'I',
  11 + [ 'í', 'ì', 'î', 'ï' ] => 'i',
  12 + [ 'Ó', 'Ò', 'Ô', 'Ö', 'Õ', 'º' ] => 'O',
  13 + [ 'ó', 'ò', 'ô', 'ö', 'õ', 'º' ] => 'o',
  14 + [ 'Ú', 'Ù', 'Û', 'Ü' ] => 'U',
  15 + [ 'ú', 'ù', 'û', 'ü' ] => 'u',
  16 + [ 'ß' ] => 'ss',
  17 + [ 'Ç' ] => 'C',
  18 + [ 'ç' ] => 'c',
  19 + [ 'Ñ' ] => 'N',
  20 + [ 'ñ' ] => 'n',
  21 + [ 'Ÿ' ] => 'Y',
  22 + [ 'ÿ' ] => 'y',
  23 +# Cyrillic alphabet transliteration
  24 + [ 'а', 'А' ] => 'a',
  25 + [ 'б', 'Б' ] => 'b',
  26 + [ 'в', 'В' ] => 'v',
  27 + [ 'г', 'Г' ] => 'g',
  28 + [ 'д', 'Д' ] => 'd',
  29 + [ 'е', 'Е' ] => 'e',
  30 + [ 'ё', 'Ё' ] => 'yo',
  31 + [ 'ж', 'Ж' ] => 'zh',
  32 + [ 'з', 'З' ] => 'z',
  33 + [ 'и', 'И' ] => 'i',
  34 + [ 'й', 'Й' ] => 'y',
  35 + [ 'к', 'К' ] => 'k',
  36 + [ 'л', 'Л' ] => 'l',
  37 + [ 'м', 'М' ] => 'm',
  38 + [ 'н', 'Н' ] => 'n',
  39 + [ 'о', 'О' ] => 'o',
  40 + [ 'п', 'П' ] => 'p',
  41 + [ 'р', 'Р' ] => 'r',
  42 + [ 'с', 'С' ] => 's',
  43 + [ 'т', 'Т' ] => 't',
  44 + [ 'у', 'У' ] => 'u',
  45 + [ 'ф', 'Ф' ] => 'f',
  46 + [ 'х', 'Х' ] => 'h',
  47 + [ 'ц', 'Ц' ] => 'ts',
  48 + [ 'ч', 'Ч' ] => 'ch',
  49 + [ 'ш', 'Ш' ] => 'sh',
  50 + [ 'щ', 'Щ' ] => 'sch',
  51 + [ 'э', 'Э' ] => 'e',
  52 + [ 'ю', 'Ю' ] => 'yu',
  53 + [ 'я', 'Я' ] => 'ya',
  54 + [ 'ы', 'Ы' ] => 'i',
  55 + [ 'ь', 'Ь' ] => '',
  56 + [ 'ъ', 'Ъ' ] => '',
  57 +# Ukrainian lovely letters
  58 + [ 'і', 'І' ] => 'i',
  59 + [ 'ї', 'Ї' ] => 'yi',
  60 + [ 'є', 'Є' ] => 'ye',
  61 + [ 'ґ', 'Ґ' ] => 'g',
  62 + }
  63 +
  64 + # transliterate a string (assumed to contain UTF-8 data)
  65 + # into ASCII by replacing non-ascii characters to their
  66 + # ASCII.
  67 + #
  68 + # The transliteration is, of course, lossy, and its performance is poor.
  69 + # Don't abuse this method.
  70 + def transliterate
  71 +
  72 + new = self.dup
  73 + TRANSLITERATIONS.each { |from,to|
  74 + from.each { |seq|
  75 + new.gsub!(seq, to)
  76 + }
  77 + }
  78 + new
  79 + end
  80 +
  81 + def to_slug
  82 + transliterate.downcase.gsub(/[^[[:word:]]~\s:;+=_."'`-]/, '').gsub(/[\s:;+=_"'`-]+/, '-').gsub(/-$/, '').gsub(/^-/, '').to_s
  83 + end
  84 +
  85 + def to_css_class
  86 + underscore.dasherize.gsub('/','_')
  87 + end
  88 +
  89 + def fix_i18n
  90 + self.sub('{fn} ', '')
  91 + end
  92 +
  93 +end
lib/noosfero.rb
1 -# encoding: utf-8 1 +require_relative 'noosfero/version'
  2 +require_relative 'noosfero/constants'
2 3
3 module Noosfero 4 module Noosfero
4 5
@@ -106,6 +107,3 @@ module Noosfero @@ -106,6 +107,3 @@ module Noosfero
106 107
107 end 108 end
108 109
109 -require 'noosfero/version'  
110 -require 'noosfero/constants'  
111 -require 'noosfero/core_ext'  
lib/noosfero/api/api.rb
@@ -1,94 +0,0 @@ @@ -1,94 +0,0 @@
1 -require 'grape'  
2 -#require 'rack/contrib'  
3 -Dir["#{Rails.root}/lib/noosfero/api/*.rb"].each {|file| require file unless file =~ /api\.rb/}  
4 -  
5 -module Noosfero  
6 - module API  
7 - class API < Grape::API  
8 - use Rack::JSONP  
9 -  
10 - logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log"))  
11 - logger.formatter = GrapeLogging::Formatters::Default.new  
12 - #use GrapeLogging::Middleware::RequestLogger, { logger: logger }  
13 -  
14 - rescue_from :all do |e|  
15 - logger.error e  
16 - error! e.message, 500  
17 - end  
18 -  
19 - @@NOOSFERO_CONF = nil  
20 - def self.NOOSFERO_CONF  
21 - if @@NOOSFERO_CONF  
22 - @@NOOSFERO_CONF  
23 - else  
24 - file = Rails.root.join('config', 'noosfero.yml')  
25 - @@NOOSFERO_CONF = File.exists?(file) ? YAML.load_file(file)[Rails.env] || {} : {}  
26 - end  
27 - end  
28 -  
29 - before { set_locale }  
30 - before { setup_multitenancy }  
31 - before { detect_stuff_by_domain }  
32 - before { filter_disabled_plugins_endpoints }  
33 - before { init_noosfero_plugins }  
34 - after { set_session_cookie }  
35 -  
36 - version 'v1'  
37 - prefix [ENV['RAILS_RELATIVE_URL_ROOT'], "api"].compact.join('/')  
38 - format :json  
39 - content_type :txt, "text/plain"  
40 -  
41 - helpers APIHelpers  
42 -  
43 - mount V1::Articles  
44 - mount V1::Comments  
45 - mount V1::Users  
46 - mount V1::Communities  
47 - mount V1::People  
48 - mount V1::Enterprises  
49 - mount V1::Categories  
50 - mount V1::Tasks  
51 - mount V1::Tags  
52 - mount V1::Environments  
53 - mount V1::Search  
54 - mount V1::Contacts  
55 - mount V1::Boxes  
56 - mount V1::Blocks  
57 - mount V1::Profiles  
58 - mount V1::Activities  
59 -  
60 - mount Session  
61 -  
62 - # hook point which allow plugins to add Grape::API extensions to API::API  
63 - #finds for plugins which has api mount points classes defined (the class should extends Grape::API)  
64 - @plugins = Noosfero::Plugin.all.map { |p| p.constantize }  
65 - @plugins.each do |klass|  
66 - if klass.public_methods.include? :api_mount_points  
67 - klass.api_mount_points.each do |mount_class|  
68 - mount mount_class if mount_class && ( mount_class < Grape::API )  
69 - end  
70 - end  
71 - end  
72 -  
73 - def self.endpoint_unavailable?(endpoint, environment)  
74 - api_class = endpoint.options[:app] || endpoint.options[:for]  
75 - if api_class.present?  
76 - klass = api_class.name.deconstantize.constantize  
77 - return klass < Noosfero::Plugin && !environment.plugin_enabled?(klass)  
78 - end  
79 - end  
80 -  
81 - class << self  
82 - def endpoints_with_plugins(environment = nil)  
83 - if environment.present?  
84 - cloned_endpoints = endpoints_without_plugins.dup  
85 - cloned_endpoints.delete_if { |endpoint| endpoint_unavailable?(endpoint, environment) }  
86 - else  
87 - endpoints_without_plugins  
88 - end  
89 - end  
90 - alias_method_chain :endpoints, :plugins  
91 - end  
92 - end  
93 - end  
94 -end  
lib/noosfero/api/entities.rb
@@ -1,269 +0,0 @@ @@ -1,269 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module Entities  
4 -  
5 - Entity.format_with :timestamp do |date|  
6 - date.strftime('%Y/%m/%d %H:%M:%S') if date  
7 - end  
8 -  
9 - PERMISSIONS = {  
10 - :admin => 0,  
11 - :self => 10,  
12 - :private_content => 20,  
13 - :logged_user => 30,  
14 - :anonymous => 40  
15 - }  
16 -  
17 - def self.can_display_profile_field? profile, options, permission_options={}  
18 - permissions={:field => "", :permission => :private_content}  
19 - permissions.merge!(permission_options)  
20 - field = permissions[:field]  
21 - permission = permissions[:permission]  
22 - return true if profile.public? && profile.public_fields.map{|f| f.to_sym}.include?(field.to_sym)  
23 -  
24 - current_person = options[:current_person]  
25 -  
26 - current_permission = if current_person.present?  
27 - if current_person.is_admin?  
28 - :admin  
29 - elsif current_person == profile  
30 - :self  
31 - elsif profile.display_private_info_to?(current_person)  
32 - :private_content  
33 - else  
34 - :logged_user  
35 - end  
36 - else  
37 - :anonymous  
38 - end  
39 - PERMISSIONS[current_permission] <= PERMISSIONS[permission]  
40 - end  
41 -  
42 - class Image < Entity  
43 - root 'images', 'image'  
44 -  
45 - expose :url do |image, options|  
46 - image.public_filename  
47 - end  
48 -  
49 - expose :icon_url do |image, options|  
50 - image.public_filename(:icon)  
51 - end  
52 -  
53 - expose :minor_url do |image, options|  
54 - image.public_filename(:minor)  
55 - end  
56 -  
57 - expose :portrait_url do |image, options|  
58 - image.public_filename(:portrait)  
59 - end  
60 -  
61 - expose :thumb_url do |image, options|  
62 - image.public_filename(:thumb)  
63 - end  
64 - end  
65 -  
66 - class CategoryBase < Entity  
67 - root 'categories', 'category'  
68 - expose :name, :id, :slug  
69 - end  
70 -  
71 - class Category < CategoryBase  
72 - root 'categories', 'category'  
73 - expose :full_name do |category, options|  
74 - category.full_name  
75 - end  
76 - expose :parent, :using => CategoryBase, if: { parent: true }  
77 - expose :children, :using => CategoryBase, if: { children: true }  
78 - expose :image, :using => Image  
79 - expose :display_color  
80 - end  
81 -  
82 - class Region < Category  
83 - root 'regions', 'region'  
84 - expose :parent_id  
85 - end  
86 -  
87 - class Block < Entity  
88 - root 'blocks', 'block'  
89 - expose :id, :type, :settings, :position, :enabled  
90 - expose :mirror, :mirror_block_id, :title  
91 - expose :api_content, if: lambda { |object, options| options[:display_api_content] || object.display_api_content_by_default? }  
92 - end  
93 -  
94 - class Box < Entity  
95 - root 'boxes', 'box'  
96 - expose :id, :position  
97 - expose :blocks, :using => Block  
98 - end  
99 -  
100 - class Profile < Entity  
101 - expose :identifier, :name, :id  
102 - expose :created_at, :format_with => :timestamp  
103 - expose :updated_at, :format_with => :timestamp  
104 - expose :additional_data do |profile, options|  
105 - hash ={}  
106 - profile.public_values.each do |value|  
107 - hash[value.custom_field.name]=value.value  
108 - end  
109 -  
110 - private_values = profile.custom_field_values - profile.public_values  
111 - private_values.each do |value|  
112 - if Entities.can_display_profile_field?(profile,options)  
113 - hash[value.custom_field.name]=value.value  
114 - end  
115 - end  
116 - hash  
117 - end  
118 - expose :image, :using => Image  
119 - expose :region, :using => Region  
120 - expose :type  
121 - expose :custom_header  
122 - expose :custom_footer  
123 - end  
124 -  
125 - class UserBasic < Entity  
126 - expose :id  
127 - expose :login  
128 - end  
129 -  
130 - class Person < Profile  
131 - root 'people', 'person'  
132 - expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' }  
133 - expose :vote_count  
134 - expose :comments_count do |person, options|  
135 - person.comments.count  
136 - end  
137 - expose :following_articles_count do |person, options|  
138 - person.following_articles.count  
139 - end  
140 - expose :articles_count do |person, options|  
141 - person.articles.count  
142 - end  
143 - end  
144 -  
145 - class Enterprise < Profile  
146 - root 'enterprises', 'enterprise'  
147 - end  
148 -  
149 - class Community < Profile  
150 - root 'communities', 'community'  
151 - expose :description  
152 - expose :admins, :if => lambda { |community, options| community.display_info_to? options[:current_person]} do |community, options|  
153 - community.admins.map{|admin| {"name"=>admin.name, "id"=>admin.id, "username" => admin.identifier}}  
154 - end  
155 - expose :categories, :using => Category  
156 - expose :members, :using => Person , :if => lambda{ |community, options| community.display_info_to? options[:current_person] }  
157 - end  
158 -  
159 - class CommentBase < Entity  
160 - expose :body, :title, :id  
161 - expose :created_at, :format_with => :timestamp  
162 - expose :author, :using => Profile  
163 - expose :reply_of, :using => CommentBase  
164 - end  
165 -  
166 - class Comment < CommentBase  
167 - root 'comments', 'comment'  
168 - expose :children, as: :replies, :using => Comment  
169 - end  
170 -  
171 - class ArticleBase < Entity  
172 - root 'articles', 'article'  
173 - expose :id  
174 - expose :body  
175 - expose :abstract, documentation: {type: 'String', desc: 'Teaser of the body'}  
176 - expose :created_at, :format_with => :timestamp  
177 - expose :updated_at, :format_with => :timestamp  
178 - expose :title, :documentation => {:type => "String", :desc => "Title of the article"}  
179 - expose :created_by, :as => :author, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile author that create the article'}  
180 - expose :profile, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile associated with the article'}  
181 - expose :categories, :using => Category  
182 - expose :image, :using => Image  
183 - expose :votes_for  
184 - expose :votes_against  
185 - expose :setting  
186 - expose :position  
187 - expose :hits  
188 - expose :start_date  
189 - expose :end_date, :documentation => {type: 'DateTime', desc: 'The date of finish of the article'}  
190 - expose :tag_list  
191 - expose :children_count  
192 - expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"}  
193 - expose :path  
194 - expose :followers_count  
195 - expose :votes_count  
196 - expose :comments_count  
197 - expose :archived, :documentation => {:type => "Boolean", :desc => "Defines if a article is readonly"}  
198 - expose :type  
199 - expose :comments, using: CommentBase, :if => lambda{|obj,opt| opt[:params] && ['1','true',true].include?(opt[:params][:show_comments])}  
200 - expose :published  
201 - expose :accept_comments?, as: :accept_comments  
202 - end  
203 -  
204 - class Article < ArticleBase  
205 - root 'articles', 'article'  
206 - expose :parent, :using => ArticleBase  
207 - expose :children, :using => ArticleBase do |article, options|  
208 - article.children.published.limit(Noosfero::API::V1::Articles::MAX_PER_PAGE)  
209 - end  
210 - end  
211 -  
212 - class User < Entity  
213 - root 'users', 'user'  
214 -  
215 - attrs = [:id,:login,:email,:activated?]  
216 - aliases = {:activated? => :activated}  
217 -  
218 - attrs.each do |attribute|  
219 - name = aliases.has_key?(attribute) ? aliases[attribute] : attribute  
220 - expose attribute, :as => name, :if => lambda{|user,options| Entities.can_display_profile_field?(user.person, options, {:field => attribute})}  
221 - end  
222 -  
223 - expose :person, :using => Person, :if => lambda{|user,options| user.person.display_info_to? options[:current_person]}  
224 - expose :permissions, :if => lambda{|user,options| Entities.can_display_profile_field?(user.person, options, {:field => :permissions, :permission => :self})} do |user, options|  
225 - output = {}  
226 - user.person.role_assignments.map do |role_assigment|  
227 - if role_assigment.resource.respond_to?(:identifier) && !role_assigment.role.nil?  
228 - output[role_assigment.resource.identifier] = role_assigment.role.permissions  
229 - end  
230 - end  
231 - output  
232 - end  
233 - end  
234 -  
235 - class UserLogin < User  
236 - root 'users', 'user'  
237 - expose :private_token, documentation: {type: 'String', desc: 'A valid authentication code for post/delete api actions'}, if: lambda {|object, options| object.activated? }  
238 - end  
239 -  
240 - class Task < Entity  
241 - root 'tasks', 'task'  
242 - expose :id  
243 - expose :type  
244 - end  
245 -  
246 - class Environment < Entity  
247 - expose :name  
248 - expose :id  
249 - expose :description  
250 - expose :settings, if: lambda { |instance, options| options[:is_admin] }  
251 - end  
252 -  
253 - class Tag < Entity  
254 - root 'tags', 'tag'  
255 - expose :name  
256 - end  
257 -  
258 - class Activity < Entity  
259 - root 'activities', 'activity'  
260 - expose :id, :params, :verb, :created_at, :updated_at, :comments_count, :visible  
261 - expose :user, :using => Profile  
262 - expose :target do |activity, opts|  
263 - type_map = {Profile => ::Profile, ArticleBase => ::Article}.find {|h| activity.target.kind_of?(h.last)}  
264 - type_map.first.represent(activity.target) unless type_map.nil?  
265 - end  
266 - end  
267 - end  
268 - end  
269 -end  
lib/noosfero/api/entity.rb
@@ -1,25 +0,0 @@ @@ -1,25 +0,0 @@
1 -class Noosfero::API::Entity < Grape::Entity  
2 -  
3 - def initialize(object, options = {})  
4 - object = nil if object.is_a? Exception  
5 - super object, options  
6 - end  
7 -  
8 - def self.represent(objects, options = {})  
9 - if options[:has_exception]  
10 - data = super objects, options.merge(is_inner_data: true)  
11 - if objects.is_a? Exception  
12 - data.merge ok: false, error: {  
13 - type: objects.class.name,  
14 - message: objects.message  
15 - }  
16 - else  
17 - data = data.serializable_hash if data.is_a? Noosfero::API::Entity  
18 - data.merge ok: true, error: { type: 'Success', message: '' }  
19 - end  
20 - else  
21 - super objects, options  
22 - end  
23 - end  
24 -  
25 -end  
lib/noosfero/api/helpers.rb
@@ -1,425 +0,0 @@ @@ -1,425 +0,0 @@
1 -require 'grape'  
2 -require 'base64'  
3 -require 'tempfile'  
4 -require_relative '../../find_by_contents'  
5 -  
6 -module Noosfero;  
7 - module API  
8 - module APIHelpers  
9 - PRIVATE_TOKEN_PARAM = :private_token  
10 - DEFAULT_ALLOWED_PARAMETERS = [:parent_id, :from, :until, :content_type, :author_id, :identifier, :archived]  
11 -  
12 - include SanitizeParams  
13 - include Noosfero::Plugin::HotSpot  
14 - include ForgotPasswordHelper  
15 - include SearchTermHelper  
16 -  
17 - def set_locale  
18 - I18n.locale = (params[:lang] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')  
19 - end  
20 -  
21 - def init_noosfero_plugins  
22 - plugins  
23 - end  
24 -  
25 - def current_user  
26 - private_token = (params[PRIVATE_TOKEN_PARAM] || headers['Private-Token']).to_s  
27 - @current_user ||= User.find_by private_token: private_token  
28 - @current_user ||= plugins.dispatch("api_custom_login", request).first  
29 - @current_user  
30 - end  
31 -  
32 - def current_person  
33 - current_user.person unless current_user.nil?  
34 - end  
35 -  
36 - def is_admin?(environment)  
37 - return false unless current_user  
38 - return current_person.is_admin?(environment)  
39 - end  
40 -  
41 - def logout  
42 - @current_user = nil  
43 - end  
44 -  
45 - def environment  
46 - @environment  
47 - end  
48 -  
49 - def present_partial(model, options)  
50 - if(params[:fields].present?)  
51 - begin  
52 - fields = JSON.parse(params[:fields])  
53 - if fields.present?  
54 - options.merge!(fields.symbolize_keys.slice(:only, :except))  
55 - end  
56 - rescue  
57 - fields = params[:fields]  
58 - fields = fields.split(',') if fields.kind_of?(String)  
59 - options[:only] = Array.wrap(fields)  
60 - end  
61 - end  
62 - present model, options  
63 - end  
64 -  
65 - include FindByContents  
66 -  
67 - ####################################################################  
68 - #### SEARCH  
69 - ####################################################################  
70 - def multiple_search?(searches=nil)  
71 - ['index', 'category_index'].include?(params[:action]) || (searches && searches.size > 1)  
72 - end  
73 - ####################################################################  
74 -  
75 - def logger  
76 - logger = Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV'] || 'production'}_api.log"))  
77 - logger.formatter = GrapeLogging::Formatters::Default.new  
78 - logger  
79 - end  
80 -  
81 - def limit  
82 - limit = params[:limit].to_i  
83 - limit = default_limit if limit <= 0  
84 - limit  
85 - end  
86 -  
87 - def period(from_date, until_date)  
88 - return nil if from_date.nil? && until_date.nil?  
89 -  
90 - begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date  
91 - end_period = until_date.nil? ? DateTime.now : until_date  
92 -  
93 - begin_period..end_period  
94 - end  
95 -  
96 - def parse_content_type(content_type)  
97 - return nil if content_type.blank?  
98 - content_type.split(',').map do |content_type|  
99 - content_type.camelcase  
100 - end  
101 - end  
102 -  
103 - def find_article(articles, id)  
104 - article = articles.find(id)  
105 - article.display_to?(current_person) ? article : forbidden!  
106 - end  
107 -  
108 - def post_article(asset, params)  
109 - return forbidden! unless current_person.can_post_content?(asset)  
110 -  
111 - klass_type = params[:content_type] || params[:article].delete(:type) || TinyMceArticle.name  
112 - return forbidden! unless klass_type.constantize <= Article  
113 -  
114 - article = klass_type.constantize.new(params[:article])  
115 - article.last_changed_by = current_person  
116 - article.created_by= current_person  
117 - article.profile = asset  
118 -  
119 - if !article.save  
120 - render_api_errors!(article.errors.full_messages)  
121 - end  
122 - present_partial article, :with => Entities::Article  
123 - end  
124 -  
125 - def present_article(asset)  
126 - article = find_article(asset.articles, params[:id])  
127 - present_partial article, :with => Entities::Article, :params => params  
128 - end  
129 -  
130 - def present_articles_for_asset(asset, method = 'articles')  
131 - articles = find_articles(asset, method)  
132 - present_articles(articles)  
133 - end  
134 -  
135 - def present_articles(articles)  
136 - present_partial paginate(articles), :with => Entities::Article, :params => params  
137 - end  
138 -  
139 - def find_articles(asset, method = 'articles')  
140 - articles = select_filtered_collection_of(asset, method, params)  
141 - if current_person.present?  
142 - articles = articles.display_filter(current_person, nil)  
143 - else  
144 - articles = articles.published  
145 - end  
146 - articles  
147 - end  
148 -  
149 - def find_task(asset, id)  
150 - task = asset.tasks.find(id)  
151 - current_person.has_permission?(task.permission, asset) ? task : forbidden!  
152 - end  
153 -  
154 - def post_task(asset, params)  
155 - klass_type= params[:content_type].nil? ? 'Task' : params[:content_type]  
156 - return forbidden! unless klass_type.constantize <= Task  
157 -  
158 - task = klass_type.constantize.new(params[:task])  
159 - task.requestor_id = current_person.id  
160 - task.target_id = asset.id  
161 - task.target_type = 'Profile'  
162 -  
163 - if !task.save  
164 - render_api_errors!(task.errors.full_messages)  
165 - end  
166 - present_partial task, :with => Entities::Task  
167 - end  
168 -  
169 - def present_task(asset)  
170 - task = find_task(asset, params[:id])  
171 - present_partial task, :with => Entities::Task  
172 - end  
173 -  
174 - def present_tasks(asset)  
175 - tasks = select_filtered_collection_of(asset, 'tasks', params)  
176 - tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)}  
177 - return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset)  
178 - present_partial tasks, :with => Entities::Task  
179 - end  
180 -  
181 - def make_conditions_with_parameter(params = {})  
182 - parsed_params = parser_params(params)  
183 - conditions = {}  
184 - from_date = DateTime.parse(parsed_params.delete(:from)) if parsed_params[:from]  
185 - until_date = DateTime.parse(parsed_params.delete(:until)) if parsed_params[:until]  
186 -  
187 - conditions[:type] = parse_content_type(parsed_params.delete(:content_type)) unless parsed_params[:content_type].nil?  
188 -  
189 - conditions[:created_at] = period(from_date, until_date) if from_date || until_date  
190 - conditions.merge!(parsed_params)  
191 -  
192 - conditions  
193 - end  
194 -  
195 - # changing make_order_with_parameters to avoid sql injection  
196 - def make_order_with_parameters(object, method, params)  
197 - order = "created_at DESC"  
198 - unless params[:order].blank?  
199 - if params[:order].include? '\'' or params[:order].include? '"'  
200 - order = "created_at DESC"  
201 - elsif ['RANDOM()', 'RANDOM'].include? params[:order].upcase  
202 - order = 'RANDOM()'  
203 - else  
204 - field_name, direction = params[:order].split(' ')  
205 - assoc = object.class.reflect_on_association(method.to_sym)  
206 - if !field_name.blank? and assoc  
207 - if assoc.klass.attribute_names.include? field_name  
208 - if direction.present? and ['ASC','DESC'].include? direction.upcase  
209 - order = "#{field_name} #{direction.upcase}"  
210 - end  
211 - end  
212 - end  
213 - end  
214 - end  
215 - return order  
216 - end  
217 -  
218 - def make_timestamp_with_parameters_and_method(params, method)  
219 - timestamp = nil  
220 - if params[:timestamp]  
221 - datetime = DateTime.parse(params[:timestamp])  
222 - table_name = method.to_s.singularize.camelize.constantize.table_name  
223 - timestamp = "#{table_name}.updated_at >= '#{datetime}'"  
224 - end  
225 -  
226 - timestamp  
227 - end  
228 -  
229 - def by_reference(scope, params)  
230 - reference_id = params[:reference_id].to_i == 0 ? nil : params[:reference_id].to_i  
231 - if reference_id.nil?  
232 - scope  
233 - else  
234 - created_at = scope.find(reference_id).created_at  
235 - scope.send("#{params.key?(:oldest) ? 'older_than' : 'younger_than'}", created_at)  
236 - end  
237 - end  
238 -  
239 - def by_categories(scope, params)  
240 - category_ids = params[:category_ids]  
241 - if category_ids.nil?  
242 - scope  
243 - else  
244 - scope.joins(:categories).where(:categories => {:id => category_ids})  
245 - end  
246 - end  
247 -  
248 - def select_filtered_collection_of(object, method, params)  
249 - conditions = make_conditions_with_parameter(params)  
250 - order = make_order_with_parameters(object,method,params)  
251 - timestamp = make_timestamp_with_parameters_and_method(params, method)  
252 -  
253 - objects = object.send(method)  
254 - objects = by_reference(objects, params)  
255 - objects = by_categories(objects, params)  
256 -  
257 - objects = objects.where(conditions).where(timestamp).reorder(order)  
258 -  
259 - params[:page] ||= 1  
260 - params[:per_page] ||= limit  
261 - paginate(objects)  
262 - end  
263 -  
264 - def authenticate!  
265 - unauthorized! unless current_user  
266 - end  
267 -  
268 - def profiles_for_person(profiles, person)  
269 - if person  
270 - profiles.listed_for_person(person)  
271 - else  
272 - profiles.visible  
273 - end  
274 - end  
275 -  
276 - # Checks the occurrences of uniqueness of attributes, each attribute must be present in the params hash  
277 - # or a Bad Request error is invoked.  
278 - #  
279 - # Parameters:  
280 - # keys (unique) - A hash consisting of keys that must be unique  
281 - def unique_attributes!(obj, keys)  
282 - keys.each do |key|  
283 - cant_be_saved_request!(key) if obj.find_by(key.to_s => params[key])  
284 - end  
285 - end  
286 -  
287 - def attributes_for_keys(keys)  
288 - attrs = {}  
289 - keys.each do |key|  
290 - attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false)  
291 - end  
292 - attrs  
293 - end  
294 -  
295 - ##########################################  
296 - # error helpers #  
297 - ##########################################  
298 -  
299 - def not_found!  
300 - render_api_error!('404 Not found', 404)  
301 - end  
302 -  
303 - def forbidden!  
304 - render_api_error!('403 Forbidden', 403)  
305 - end  
306 -  
307 - def cant_be_saved_request!(attribute)  
308 - message = _("(Invalid request) %s can't be saved") % attribute  
309 - render_api_error!(message, 400)  
310 - end  
311 -  
312 - def bad_request!(attribute)  
313 - message = _("(Invalid request) %s not given") % attribute  
314 - render_api_error!(message, 400)  
315 - end  
316 -  
317 - def something_wrong!  
318 - message = _("Something wrong happened")  
319 - render_api_error!(message, 400)  
320 - end  
321 -  
322 - def unauthorized!  
323 - render_api_error!(_('Unauthorized'), 401)  
324 - end  
325 -  
326 - def not_allowed!  
327 - render_api_error!(_('Method Not Allowed'), 405)  
328 - end  
329 -  
330 - # javascript_console_message is supposed to be executed as console.log()  
331 - def render_api_error!(user_message, status, log_message = nil, javascript_console_message = nil)  
332 - message_hash = {'message' => user_message, :code => status}  
333 - message_hash[:javascript_console_message] = javascript_console_message if javascript_console_message.present?  
334 - log_msg = "#{status}, User message: #{user_message}"  
335 - log_msg = "#{log_message}, #{log_msg}" if log_message.present?  
336 - log_msg = "#{log_msg}, Javascript Console Message: #{javascript_console_message}" if javascript_console_message.present?  
337 - logger.error log_msg unless Rails.env.test?  
338 - error!(message_hash, status)  
339 - end  
340 -  
341 - def render_api_errors!(messages)  
342 - messages = messages.to_a if messages.class == ActiveModel::Errors  
343 - render_api_error!(messages.join(','), 400)  
344 - end  
345 -  
346 - protected  
347 -  
348 - def set_session_cookie  
349 - cookies['_noosfero_api_session'] = { value: @current_user.private_token, httponly: true } if @current_user.present?  
350 - end  
351 -  
352 - def setup_multitenancy  
353 - Noosfero::MultiTenancy.setup!(request.host)  
354 - end  
355 -  
356 - def detect_stuff_by_domain  
357 - @domain = Domain.by_name(request.host)  
358 - if @domain.nil?  
359 - @environment = Environment.default  
360 - if @environment.nil? && Rails.env.development?  
361 - # This should only happen in development ...  
362 - @environment = Environment.create!(:name => "Noosfero", :is_default => true)  
363 - end  
364 - else  
365 - @environment = @domain.environment  
366 - end  
367 - end  
368 -  
369 - def filter_disabled_plugins_endpoints  
370 - not_found! if Noosfero::API::API.endpoint_unavailable?(self, @environment)  
371 - end  
372 -  
373 - def asset_with_image params  
374 - if params.has_key? :image_builder  
375 - asset_api_params = params  
376 - asset_api_params[:image_builder] = base64_to_uploadedfile(asset_api_params[:image_builder])  
377 - return asset_api_params  
378 - end  
379 - params  
380 - end  
381 -  
382 - def base64_to_uploadedfile(base64_image)  
383 - tempfile = base64_to_tempfile base64_image  
384 - converted_image = base64_image  
385 - converted_image[:tempfile] = tempfile  
386 - return {uploaded_data: ActionDispatch::Http::UploadedFile.new(converted_image)}  
387 - end  
388 -  
389 - def base64_to_tempfile base64_image  
390 - base64_img_str = base64_image[:tempfile]  
391 - decoded_base64_str = Base64.decode64(base64_img_str)  
392 - tempfile = Tempfile.new(base64_image[:filename])  
393 - tempfile.write(decoded_base64_str.encode("ascii-8bit").force_encoding("utf-8"))  
394 - tempfile.rewind  
395 - tempfile  
396 - end  
397 - private  
398 -  
399 - def parser_params(params)  
400 - parsed_params = {}  
401 - params.map do |k,v|  
402 - parsed_params[k.to_sym] = v if DEFAULT_ALLOWED_PARAMETERS.include?(k.to_sym)  
403 - end  
404 - parsed_params  
405 - end  
406 -  
407 - def default_limit  
408 - 20  
409 - end  
410 -  
411 - def parse_content_type(content_type)  
412 - return nil if content_type.blank?  
413 - content_type.split(',').map do |content_type|  
414 - content_type.camelcase  
415 - end  
416 - end  
417 -  
418 - def period(from_date, until_date)  
419 - begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date  
420 - end_period = until_date.nil? ? DateTime.now : until_date  
421 - begin_period..end_period  
422 - end  
423 - end  
424 - end  
425 -end  
lib/noosfero/api/session.rb
@@ -1,157 +0,0 @@ @@ -1,157 +0,0 @@
1 -require "uri"  
2 -  
3 -module Noosfero  
4 - module API  
5 - class Session < Grape::API  
6 -  
7 - # Login to get token  
8 - #  
9 - # Parameters:  
10 - # login (*required) - user login or email  
11 - # password (required) - user password  
12 - #  
13 - # Example Request:  
14 - # POST http://localhost:3000/api/v1/login?login=adminuser&password=admin  
15 - post "/login" do  
16 - begin  
17 - user ||= User.authenticate(params[:login], params[:password], environment)  
18 - rescue User::UserNotActivated => e  
19 - render_api_error!(e.message, 401)  
20 - end  
21 -  
22 - return unauthorized! unless user  
23 - @current_user = user  
24 - present user, :with => Entities::UserLogin, :current_person => current_person  
25 - end  
26 -  
27 - post "/login_from_cookie" do  
28 - return unauthorized! if cookies[:auth_token].blank?  
29 - user = User.where(remember_token: cookies[:auth_token]).first  
30 - return unauthorized! unless user && user.activated?  
31 - @current_user = user  
32 - present user, :with => Entities::UserLogin, :current_person => current_person  
33 - end  
34 -  
35 - # Create user.  
36 - #  
37 - # Parameters:  
38 - # email (required) - Email  
39 - # password (required) - Password  
40 - # login - login  
41 - # Example Request:  
42 - # POST /register?email=some@mail.com&password=pas&password_confirmation=pas&login=some  
43 - params do  
44 - requires :email, type: String, desc: _("Email")  
45 - requires :login, type: String, desc: _("Login")  
46 - requires :password, type: String, desc: _("Password")  
47 - end  
48 -  
49 - post "/register" do  
50 - attrs = attributes_for_keys [:email, :login, :password, :password_confirmation] + environment.signup_person_fields  
51 - name = params[:name].present? ? params[:name] : attrs[:email]  
52 - attrs[:password_confirmation] = attrs[:password] if !attrs.has_key?(:password_confirmation)  
53 - user = User.new(attrs.merge(:name => name))  
54 -  
55 - begin  
56 - user.signup!  
57 - user.generate_private_token! if user.activated?  
58 - present user, :with => Entities::UserLogin, :current_person => user.person  
59 - rescue ActiveRecord::RecordInvalid  
60 - message = user.errors.as_json.merge((user.person.present? ? user.person.errors : {}).as_json).to_json  
61 - render_api_error!(message, 400)  
62 - end  
63 - end  
64 -  
65 - params do  
66 - requires :activation_code, type: String, desc: _("Activation token")  
67 - end  
68 -  
69 - # Activate a user.  
70 - #  
71 - # Parameter:  
72 - # activation_code (required) - Activation token  
73 - # Example Request:  
74 - # PATCH /activate?activation_code=28259abd12cc6a64ef9399cf3286cb998b96aeaf  
75 - patch "/activate" do  
76 - user = User.find_by activation_code: params[:activation_code]  
77 - if user  
78 - unless user.environment.enabled?('admin_must_approve_new_users')  
79 - if user.activate  
80 - user.generate_private_token!  
81 - present user, :with => Entities::UserLogin, :current_person => current_person  
82 - end  
83 - else  
84 - if user.create_moderate_task  
85 - user.activation_code = nil  
86 - user.save!  
87 -  
88 - # Waiting for admin moderate user registration  
89 - status 202  
90 - body({  
91 - :message => 'Waiting for admin moderate user registration'  
92 - })  
93 - end  
94 - end  
95 - else  
96 - # Token not found in database  
97 - render_api_error!(_('Token is invalid'), 412)  
98 - end  
99 - end  
100 -  
101 - # Request a new password.  
102 - #  
103 - # Parameters:  
104 - # value (required) - Email or login  
105 - # Example Request:  
106 - # POST /forgot_password?value=some@mail.com  
107 - post "/forgot_password" do  
108 - requestors = fetch_requestors(params[:value])  
109 - not_found! if requestors.blank?  
110 - remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])  
111 - requestors.each do |requestor|  
112 - ChangePassword.create!(:requestor => requestor)  
113 - end  
114 - end  
115 -  
116 - # Resend activation code.  
117 - #  
118 - # Parameters:  
119 - # value (required) - Email or login  
120 - # Example Request:  
121 - # POST /resend_activation_code?value=some@mail.com  
122 - post "/resend_activation_code" do  
123 - requestors = fetch_requestors(params[:value])  
124 - not_found! if requestors.blank?  
125 - remote_ip = (request.respond_to?(:remote_ip) && request.remote_ip) || (env && env['REMOTE_ADDR'])  
126 - requestors.each do |requestor|  
127 - requestor.user.resend_activation_code  
128 - end  
129 - present requestors.map(&:user), :with => Entities::UserLogin  
130 - end  
131 -  
132 - params do  
133 - requires :code, type: String, desc: _("Forgot password code")  
134 - end  
135 - # Change password  
136 - #  
137 - # Parameters:  
138 - # code (required) - Change password code  
139 - # password (required)  
140 - # password_confirmation (required)  
141 - # Example Request:  
142 - # PATCH /new_password?code=xxxx&password=secret&password_confirmation=secret  
143 - patch "/new_password" do  
144 - change_password = ChangePassword.find_by code: params[:code]  
145 - not_found! if change_password.nil?  
146 -  
147 - if change_password.update_attributes(:password => params[:password], :password_confirmation => params[:password_confirmation])  
148 - change_password.finish  
149 - present change_password.requestor.user, :with => Entities::UserLogin, :current_person => current_person  
150 - else  
151 - something_wrong!  
152 - end  
153 - end  
154 -  
155 - end  
156 - end  
157 -end  
lib/noosfero/api/v1/activities.rb
@@ -1,22 +0,0 @@ @@ -1,22 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Activities < Grape::API  
5 - before { authenticate! }  
6 -  
7 - resource :profiles do  
8 -  
9 - get ':id/activities' do  
10 - profile = Profile.find_by id: params[:id]  
11 -  
12 - not_found! if profile.blank? || profile.secret || !profile.visible  
13 - forbidden! if !profile.secret && profile.visible && !profile.display_private_info_to?(current_person)  
14 -  
15 - activities = profile.activities.map(&:activity)  
16 - present activities, :with => Entities::Activity, :current_person => current_person  
17 - end  
18 - end  
19 - end  
20 - end  
21 - end  
22 -end  
lib/noosfero/api/v1/articles.rb
@@ -1,305 +0,0 @@ @@ -1,305 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Articles < Grape::API  
5 -  
6 - ARTICLE_TYPES = Article.descendants.map{|a| a.to_s}  
7 -  
8 - MAX_PER_PAGE = 50  
9 -  
10 - resource :articles do  
11 -  
12 - paginate max_per_page: MAX_PER_PAGE  
13 - # Collect articles  
14 - #  
15 - # Parameters:  
16 - # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created  
17 - # oldest - Collect the oldest articles. If nothing is passed the newest articles are collected  
18 - # limit - amount of articles returned. The default value is 20  
19 - #  
20 - # Example Request:  
21 - # GET host/api/v1/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317  
22 -  
23 - desc 'Return all articles of all kinds' do  
24 - detail 'Get all articles filtered by fields in query params'  
25 - params Noosfero::API::Entities::Article.documentation  
26 - success Noosfero::API::Entities::Article  
27 - failure [[403, 'Forbidden']]  
28 - named 'ArticlesList'  
29 - headers [  
30 - 'Per-Page' => {  
31 - description: 'Total number of records',  
32 - required: false  
33 - }  
34 - ]  
35 - end  
36 - get do  
37 - present_articles_for_asset(environment)  
38 - end  
39 -  
40 - desc "Return one article by id" do  
41 - detail 'Get only one article by id. If not found the "forbidden" http error is showed'  
42 - params Noosfero::API::Entities::Article.documentation  
43 - success Noosfero::API::Entities::Article  
44 - failure [[403, 'Forbidden']]  
45 - named 'ArticleById'  
46 - end  
47 - get ':id', requirements: {id: /[0-9]+/} do  
48 - present_article(environment)  
49 - end  
50 -  
51 - post ':id' do  
52 - article = environment.articles.find(params[:id])  
53 - return forbidden! unless article.allow_edit?(current_person)  
54 - article.update_attributes!(asset_with_image(params[:article]))  
55 - present_partial article, :with => Entities::Article  
56 - end  
57 -  
58 - desc 'Report a abuse and/or violent content in a article by id' do  
59 - detail 'Submit a abuse (in general, a content violation) report about a specific article'  
60 - params Noosfero::API::Entities::Article.documentation  
61 - failure [[400, 'Bad Request']]  
62 - named 'ArticleReportAbuse'  
63 - end  
64 - post ':id/report_abuse' do  
65 - article = find_article(environment.articles, params[:id])  
66 - profile = article.profile  
67 - begin  
68 - abuse_report = AbuseReport.new(:reason => params[:report_abuse])  
69 - if !params[:content_type].blank?  
70 - article = params[:content_type].constantize.find(params[:content_id])  
71 - abuse_report.content = article_reported_version(article)  
72 - end  
73 -  
74 - current_person.register_report(abuse_report, profile)  
75 -  
76 - if !params[:content_type].blank?  
77 - abuse_report = AbuseReport.find_by reporter_id: current_person.id, abuse_complaint_id: profile.opened_abuse_complaint.id  
78 - Delayed::Job.enqueue DownloadReportedImagesJob.new(abuse_report, article)  
79 - end  
80 -  
81 - {  
82 - :success => true,  
83 - :message => _('Your abuse report was registered. The administrators are reviewing your report.'),  
84 - }  
85 - rescue Exception => exception  
86 - #logger.error(exception.to_s)  
87 - render_api_error!(_('Your report couldn\'t be saved due to some problem. Please contact the administrator.'), 400)  
88 - end  
89 -  
90 - end  
91 -  
92 - desc "Returns the articles I voted" do  
93 - detail 'Get the Articles I make a vote'  
94 - failure [[403, 'Forbidden']]  
95 - named 'ArticleFollowers'  
96 - end  
97 - #FIXME refactor this method  
98 - get 'voted_by_me' do  
99 - present_articles(current_person.votes.where(:voteable_type => 'Article').collect(&:voteable))  
100 - end  
101 -  
102 - desc 'Perform a vote on a article by id' do  
103 - detail 'Vote on a specific article with values: 1 (if you like) or -1 (if not)'  
104 - params Noosfero::API::Entities::UserLogin.documentation  
105 - failure [[401,'Unauthorized']]  
106 - named 'ArticleVote'  
107 - end  
108 - post ':id/vote' do  
109 - authenticate!  
110 - value = (params[:value] || 1).to_i  
111 - # FIXME verify allowed values  
112 - render_api_error!('Vote value not allowed', 400) unless [-1, 1].include?(value)  
113 - article = find_article(environment.articles, params[:id])  
114 - begin  
115 - vote = Vote.new(:voteable => article, :voter => current_person, :vote => value)  
116 - {:vote => vote.save!}  
117 - rescue ActiveRecord::RecordInvalid => e  
118 - render_api_error!(e.message, 400)  
119 - end  
120 - end  
121 -  
122 - desc "Returns the total followers for the article" do  
123 - detail 'Get the followers of a specific article by id'  
124 - failure [[403, 'Forbidden']]  
125 - named 'ArticleFollowers'  
126 - end  
127 - get ':id/followers' do  
128 - article = find_article(environment.articles, params[:id])  
129 - total = article.person_followers.count  
130 - {:total_followers => total}  
131 - end  
132 -  
133 - desc "Return the articles followed by me"  
134 - get 'followed_by_me' do  
135 - present_articles_for_asset(current_person, 'following_articles')  
136 - end  
137 -  
138 - desc "Add a follower for the article" do  
139 - detail 'Add the current user identified by private token, like a follower of a article'  
140 - params Noosfero::API::Entities::UserLogin.documentation  
141 - failure [[401, 'Unauthorized']]  
142 - named 'ArticleFollow'  
143 - end  
144 - post ':id/follow' do  
145 - authenticate!  
146 - article = find_article(environment.articles, params[:id])  
147 - if article.article_followers.exists?(:person_id => current_person.id)  
148 - {:success => false, :already_follow => true}  
149 - else  
150 - article_follower = ArticleFollower.new  
151 - article_follower.article = article  
152 - article_follower.person = current_person  
153 - article_follower.save!  
154 - {:success => true}  
155 - end  
156 - end  
157 -  
158 - desc 'Return the children of a article identified by id' do  
159 - detail 'Get all children articles of a specific article'  
160 - params Noosfero::API::Entities::Article.documentation  
161 - failure [[403, 'Forbidden']]  
162 - named 'ArticleChildren'  
163 - end  
164 -  
165 - paginate per_page: MAX_PER_PAGE, max_per_page: MAX_PER_PAGE  
166 - get ':id/children' do  
167 - article = find_article(environment.articles, params[:id])  
168 -  
169 - #TODO make tests for this situation  
170 - votes_order = params.delete(:order) if params[:order]=='votes_score'  
171 - articles = select_filtered_collection_of(article, 'children', params)  
172 - articles = articles.display_filter(current_person, article.profile)  
173 -  
174 - #TODO make tests for this situation  
175 - if votes_order  
176 - articles = articles.joins('left join votes on articles.id=votes.voteable_id').group('articles.id').reorder('sum(coalesce(votes.vote, 0)) DESC')  
177 - end  
178 - Article.hit(articles)  
179 - present_articles(articles)  
180 - end  
181 -  
182 - desc 'Return one child of a article identified by id' do  
183 - detail 'Get a child of a specific article'  
184 - params Noosfero::API::Entities::Article.documentation  
185 - success Noosfero::API::Entities::Article  
186 - failure [[403, 'Forbidden']]  
187 - named 'ArticleChild'  
188 - end  
189 - get ':id/children/:child_id' do  
190 - article = find_article(environment.articles, params[:id])  
191 - child = find_article(article.children, params[:child_id])  
192 - child.hit  
193 - present_partial child, :with => Entities::Article  
194 - end  
195 -  
196 - desc 'Suggest a article to another profile' do  
197 - detail 'Suggest a article to another profile (person, community...)'  
198 - params Noosfero::API::Entities::Article.documentation  
199 - success Noosfero::API::Entities::Task  
200 - failure [[401,'Unauthorized']]  
201 - named 'ArticleSuggest'  
202 - end  
203 - post ':id/children/suggest' do  
204 - authenticate!  
205 - parent_article = environment.articles.find(params[:id])  
206 -  
207 - suggest_article = SuggestArticle.new  
208 - suggest_article.article = params[:article]  
209 - suggest_article.article[:parent_id] = parent_article.id  
210 - suggest_article.target = parent_article.profile  
211 - suggest_article.requestor = current_person  
212 -  
213 - unless suggest_article.save  
214 - render_api_errors!(suggest_article.article_object.errors.full_messages)  
215 - end  
216 - present_partial suggest_article, :with => Entities::Task  
217 - end  
218 -  
219 - # Example Request:  
220 - # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body  
221 - desc 'Add a child article to a parent identified by id' do  
222 - detail 'Create a new article and associate to a parent'  
223 - params Noosfero::API::Entities::Article.documentation  
224 - success Noosfero::API::Entities::Article  
225 - failure [[401,'Unauthorized']]  
226 - named 'ArticleAddChild'  
227 - end  
228 - post ':id/children' do  
229 - parent_article = environment.articles.find(params[:id])  
230 - params[:article][:parent_id] = parent_article.id  
231 - post_article(parent_article.profile, params)  
232 - end  
233 - end  
234 -  
235 - resource :profiles do  
236 - get ':id/home_page' do  
237 - profiles = environment.profiles  
238 - profiles = profiles.visible_for_person(current_person)  
239 - profile = profiles.find_by id: params[:id]  
240 - present_partial profile.home_page, :with => Entities::Article  
241 - end  
242 - end  
243 -  
244 - kinds = %w[profile community person enterprise]  
245 - kinds.each do |kind|  
246 - resource kind.pluralize.to_sym do  
247 - segment "/:#{kind}_id" do  
248 - resource :articles do  
249 -  
250 - desc "Return all articles associate with a profile of type #{kind}" do  
251 - detail 'Get a list of articles of a profile'  
252 - params Noosfero::API::Entities::Article.documentation  
253 - success Noosfero::API::Entities::Article  
254 - failure [[403, 'Forbidden']]  
255 - named 'ArticlesOfProfile'  
256 - end  
257 - get do  
258 - profile = environment.send(kind.pluralize).find(params["#{kind}_id"])  
259 -  
260 - if params[:path].present?  
261 - article = profile.articles.find_by path: params[:path]  
262 - if !article || !article.display_to?(current_person)  
263 - article = forbidden!  
264 - end  
265 -  
266 - present_partial article, :with => Entities::Article  
267 - else  
268 -  
269 - present_articles_for_asset(profile)  
270 - end  
271 - end  
272 -  
273 - desc "Return a article associate with a profile of type #{kind}" do  
274 - detail 'Get only one article of a profile'  
275 - params Noosfero::API::Entities::Article.documentation  
276 - success Noosfero::API::Entities::Article  
277 - failure [[403, 'Forbidden']]  
278 - named 'ArticleOfProfile'  
279 - end  
280 - get ':id' do  
281 - profile = environment.send(kind.pluralize).find(params["#{kind}_id"])  
282 - present_article(profile)  
283 - end  
284 -  
285 - # Example Request:  
286 - # POST api/v1/{people,communities,enterprises}/:asset_id/articles?private_token=234298743290432&article[name]=title&article[body]=body  
287 - desc "Add a new article associated with a profile of type #{kind}" do  
288 - detail 'Create a new article and associate with a profile'  
289 - params Noosfero::API::Entities::Article.documentation  
290 - success Noosfero::API::Entities::Article  
291 - failure [[403, 'Forbidden']]  
292 - named 'ArticleCreateToProfile'  
293 - end  
294 - post do  
295 - profile = environment.send(kind.pluralize).find(params["#{kind}_id"])  
296 - post_article(profile, params)  
297 - end  
298 - end  
299 - end  
300 - end  
301 - end  
302 - end  
303 - end  
304 - end  
305 -end  
lib/noosfero/api/v1/blocks.rb
@@ -1,17 +0,0 @@ @@ -1,17 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 -  
5 - class Blocks < Grape::API  
6 - resource :blocks do  
7 - get ':id' do  
8 - block = Block.find(params["id"])  
9 - return forbidden! unless block.visible_to_user?(current_person)  
10 - present block, :with => Entities::Block, display_api_content: true  
11 - end  
12 - end  
13 - end  
14 -  
15 - end  
16 - end  
17 -end  
lib/noosfero/api/v1/boxes.rb
@@ -1,46 +0,0 @@ @@ -1,46 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 -  
5 - class Boxes < Grape::API  
6 -  
7 - kinds = %w[profile community person enterprise]  
8 - kinds.each do |kind|  
9 -  
10 - resource kind.pluralize.to_sym do  
11 -  
12 - segment "/:#{kind}_id" do  
13 - resource :boxes do  
14 - get do  
15 - profile = environment.send(kind.pluralize).find(params["#{kind}_id"])  
16 - present profile.boxes, :with => Entities::Box  
17 - end  
18 - end  
19 - end  
20 - end  
21 -  
22 - end  
23 -  
24 - resource :environments do  
25 - [ '/default', '/context', ':environment_id' ].each do |route|  
26 - segment route do  
27 - resource :boxes do  
28 - get do  
29 - if (route.match(/default/))  
30 - env = Environment.default  
31 - elsif (route.match(/context/))  
32 - env = environment  
33 - else  
34 - env = Environment.find(params[:environment_id])  
35 - end  
36 - present env.boxes, :with => Entities::Box  
37 - end  
38 - end  
39 - end  
40 - end  
41 - end  
42 - end  
43 -  
44 - end  
45 - end  
46 -end  
lib/noosfero/api/v1/categories.rb
@@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Categories < Grape::API  
5 -  
6 - resource :categories do  
7 -  
8 - get do  
9 - type = params[:category_type]  
10 - include_parent = params[:include_parent] == 'true'  
11 - include_children = params[:include_children] == 'true'  
12 -  
13 - categories = type.nil? ? environment.categories : environment.categories.where(:type => type)  
14 - present categories, :with => Entities::Category, parent: include_parent, children: include_children  
15 - end  
16 -  
17 - desc "Return the category by id"  
18 - get ':id' do  
19 - present environment.categories.find(params[:id]), :with => Entities::Category, parent: true, children: true  
20 - end  
21 -  
22 - end  
23 -  
24 - end  
25 - end  
26 - end  
27 -end  
lib/noosfero/api/v1/comments.rb
@@ -1,51 +0,0 @@ @@ -1,51 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Comments < Grape::API  
5 - MAX_PER_PAGE = 20  
6 -  
7 -  
8 - resource :articles do  
9 - paginate max_per_page: MAX_PER_PAGE  
10 - # Collect comments from articles  
11 - #  
12 - # Parameters:  
13 - # reference_id - comment id used as reference to collect comment  
14 - # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected  
15 - # limit - amount of comments returned. The default value is 20  
16 - #  
17 - # Example Request:  
18 - # GET /articles/12/comments?oldest&limit=10&reference_id=23  
19 - get ":id/comments" do  
20 - article = find_article(environment.articles, params[:id])  
21 - comments = select_filtered_collection_of(article, :comments, params)  
22 - comments = comments.without_spam  
23 - comments = comments.without_reply if(params[:without_reply].present?)  
24 - comments = plugins.filter(:unavailable_comments, comments)  
25 - present paginate(comments), :with => Entities::Comment, :current_person => current_person  
26 - end  
27 -  
28 - get ":id/comments/:comment_id" do  
29 - article = find_article(environment.articles, params[:id])  
30 - present article.comments.find(params[:comment_id]), :with => Entities::Comment, :current_person => current_person  
31 - end  
32 -  
33 - # Example Request:  
34 - # POST api/v1/articles/12/comments?private_token=2298743290432&body=new comment&title=New  
35 - post ":id/comments" do  
36 - authenticate!  
37 - article = find_article(environment.articles, params[:id])  
38 - options = params.select { |key,v| !['id','private_token'].include?(key) }.merge(:author => current_person, :source => article)  
39 - begin  
40 - comment = Comment.create!(options)  
41 - rescue ActiveRecord::RecordInvalid => e  
42 - render_api_error!(e.message, 400)  
43 - end  
44 - present comment, :with => Entities::Comment, :current_person => current_person  
45 - end  
46 - end  
47 -  
48 - end  
49 - end  
50 - end  
51 -end  
lib/noosfero/api/v1/communities.rb
@@ -1,84 +0,0 @@ @@ -1,84 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Communities < Grape::API  
5 -  
6 - resource :communities do  
7 -  
8 - # Collect comments from articles  
9 - #  
10 - # Parameters:  
11 - # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created  
12 - # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected  
13 - # limit - amount of comments returned. The default value is 20  
14 - #  
15 - # Example Request:  
16 - # GET /communities?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10  
17 - # GET /communities?reference_id=10&limit=10&oldest  
18 - get do  
19 - communities = select_filtered_collection_of(environment, 'communities', params)  
20 - communities = profiles_for_person(communities, current_person)  
21 - communities = communities.by_location(params) # Must be the last. May return Exception obj  
22 - present communities, :with => Entities::Community, :current_person => current_person  
23 - end  
24 -  
25 -  
26 - # Example Request:  
27 - # POST api/v1/communties?private_token=234298743290432&community[name]=some_name  
28 - # for each custom field for community, add &community[field_name]=field_value to the request  
29 - post do  
30 - authenticate!  
31 - params[:community] ||= {}  
32 -  
33 - params[:community][:custom_values]={}  
34 - params[:community].keys.each do |key|  
35 - params[:community][:custom_values][key]=params[:community].delete(key) if Community.custom_fields(environment).any?{|cf| cf.name==key}  
36 - end  
37 -  
38 - begin  
39 - community = Community.create_after_moderation(current_person, params[:community].merge({:environment => environment}))  
40 - rescue  
41 - community = Community.new(params[:community])  
42 - end  
43 -  
44 - if !community.save  
45 - render_api_errors!(community.errors.full_messages)  
46 - end  
47 -  
48 - present community, :with => Entities::Community, :current_person => current_person  
49 - end  
50 -  
51 - get ':id' do  
52 - community = profiles_for_person(environment.communities, current_person).find_by_id(params[:id])  
53 - present community, :with => Entities::Community, :current_person => current_person  
54 - end  
55 -  
56 - end  
57 -  
58 - resource :people do  
59 -  
60 - segment '/:person_id' do  
61 -  
62 - resource :communities do  
63 -  
64 - get do  
65 - person = environment.people.find(params[:person_id])  
66 -  
67 - not_found! if person.blank?  
68 - forbidden! if !person.display_info_to?(current_person)  
69 -  
70 - communities = select_filtered_collection_of(person, 'communities', params)  
71 - communities = communities.visible  
72 - present communities, :with => Entities::Community, :current_person => current_person  
73 - end  
74 -  
75 - end  
76 -  
77 - end  
78 -  
79 - end  
80 -  
81 - end  
82 - end  
83 - end  
84 -end  
lib/noosfero/api/v1/contacts.rb
@@ -1,28 +0,0 @@ @@ -1,28 +0,0 @@
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/enterprises.rb
@@ -1,57 +0,0 @@ @@ -1,57 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Enterprises < Grape::API  
5 -  
6 - resource :enterprises do  
7 -  
8 - # Collect enterprises from environment  
9 - #  
10 - # Parameters:  
11 - # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created  
12 - # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected  
13 - # limit - amount of comments returned. The default value is 20  
14 - # georef params - read `Profile.by_location` for more information.  
15 - #  
16 - # Example Request:  
17 - # GET /enterprises?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10  
18 - # GET /enterprises?reference_id=10&limit=10&oldest  
19 - get do  
20 - enterprises = select_filtered_collection_of(environment, 'enterprises', params)  
21 - enterprises = enterprises.visible  
22 - enterprises = enterprises.by_location(params) # Must be the last. May return Exception obj.  
23 - present enterprises, :with => Entities::Enterprise, :current_person => current_person  
24 - end  
25 -  
26 - desc "Return one enterprise by id"  
27 - get ':id' do  
28 - enterprise = environment.enterprises.visible.find_by(id: params[:id])  
29 - present enterprise, :with => Entities::Enterprise, :current_person => current_person  
30 - end  
31 -  
32 - end  
33 -  
34 - resource :people do  
35 -  
36 - segment '/:person_id' do  
37 -  
38 - resource :enterprises do  
39 -  
40 - get do  
41 - person = environment.people.find(params[:person_id])  
42 - enterprises = select_filtered_collection_of(person, 'enterprises', params)  
43 - enterprises = enterprises.visible.by_location(params)  
44 - present enterprises, :with => Entities::Enterprise, :current_person => current_person  
45 - end  
46 -  
47 - end  
48 -  
49 - end  
50 -  
51 - end  
52 -  
53 -  
54 - end  
55 - end  
56 - end  
57 -end  
lib/noosfero/api/v1/environments.rb
@@ -1,30 +0,0 @@ @@ -1,30 +0,0 @@
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 - get ':id' do  
14 - local_environment = nil  
15 - if (params[:id] == "default")  
16 - local_environment = Environment.default  
17 - elsif (params[:id] == "context")  
18 - local_environment = environment  
19 - else  
20 - local_environment = Environment.find(params[:id])  
21 - end  
22 - present_partial local_environment, :with => Entities::Environment, :is_admin => is_admin?(local_environment)  
23 - end  
24 -  
25 - end  
26 -  
27 - end  
28 - end  
29 - end  
30 -end  
lib/noosfero/api/v1/people.rb
@@ -1,129 +0,0 @@ @@ -1,129 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class People < Grape::API  
5 -  
6 - MAX_PER_PAGE = 50  
7 -  
8 - desc 'API Root'  
9 -  
10 - resource :people do  
11 - paginate max_per_page: MAX_PER_PAGE  
12 -  
13 - # -- A note about privacy --  
14 - # We wold find people by location, but we must test if the related  
15 - # fields are public. We can't do it now, with SQL, while the location  
16 - # data and the fields_privacy are a serialized settings.  
17 - # We must build a new table for profile data, where we can set meta-data  
18 - # like:  
19 - # | id | profile_id | key | value | privacy_level | source |  
20 - # | 1 | 99 | city | Salvador | friends | user |  
21 - # | 2 | 99 | lng | -38.521 | me only | automatic |  
22 -  
23 - # Collect people from environment  
24 - #  
25 - # Parameters:  
26 - # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created  
27 - # oldest - Collect the oldest comments from reference_id comment. If nothing is passed the newest comments are collected  
28 - # limit - amount of comments returned. The default value is 20  
29 - #  
30 - # Example Request:  
31 - # GET /people?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10  
32 - # GET /people?reference_id=10&limit=10&oldest  
33 -  
34 - desc "Find environment's people"  
35 - get do  
36 - people = select_filtered_collection_of(environment, 'people', params)  
37 - people = people.visible  
38 - present_partial people, :with => Entities::Person, :current_person => current_person  
39 - end  
40 -  
41 - desc "Return the logged user information"  
42 - get "/me" do  
43 - authenticate!  
44 - present_partial current_person, :with => Entities::Person, :current_person => current_person  
45 - end  
46 -  
47 - desc "Return the person information"  
48 - get ':id' do  
49 - person = environment.people.visible.find_by(id: params[:id])  
50 - return not_found! if person.blank?  
51 - present person, :with => Entities::Person, :current_person => current_person  
52 - end  
53 -  
54 - desc "Update person information"  
55 - post ':id' do  
56 - authenticate!  
57 - return forbidden! if current_person.id.to_s != params[:id]  
58 - current_person.update_attributes!(asset_with_image(params[:person]))  
59 - present current_person, :with => Entities::Person, :current_person => current_person  
60 - end  
61 -  
62 - # POST api/v1/people?person[login]=some_login&person[password]=some_password&person[name]=Jack  
63 - # for each custom field for person, add &person[field_name]=field_value to the request  
64 - desc "Create person"  
65 - post do  
66 - authenticate!  
67 - user_data = {}  
68 - user_data[:login] = params[:person].delete(:login) || params[:person][:identifier]  
69 - user_data[:email] = params[:person].delete(:email)  
70 - user_data[:password] = params[:person].delete(:password)  
71 - user_data[:password_confirmation] = params[:person].delete(:password_confirmation)  
72 -  
73 - params[:person][:custom_values]={}  
74 - params[:person].keys.each do |key|  
75 - params[:person][:custom_values][key]=params[:person].delete(key) if Person.custom_fields(environment).any?{|cf| cf.name==key}  
76 - end  
77 -  
78 - user = User.build(user_data, asset_with_image(params[:person]), environment)  
79 -  
80 - begin  
81 - user.signup!  
82 - rescue ActiveRecord::RecordInvalid  
83 - render_api_errors!(user.errors.full_messages)  
84 - end  
85 -  
86 - present user.person, :with => Entities::Person, :current_person => user.person  
87 - end  
88 -  
89 - desc "Return the person friends"  
90 - get ':id/friends' do  
91 - person = environment.people.visible.find_by(id: params[:id])  
92 - return not_found! if person.blank?  
93 - friends = person.friends.visible  
94 - present friends, :with => Entities::Person, :current_person => current_person  
95 - end  
96 -  
97 - desc "Return the person permissions on other profiles"  
98 - get ":id/permissions" do  
99 - authenticate!  
100 - person = environment.people.find(params[:id])  
101 - return not_found! if person.blank?  
102 - return forbidden! unless current_person == person || environment.admins.include?(current_person)  
103 -  
104 - output = {}  
105 - person.role_assignments.map do |role_assigment|  
106 - if role_assigment.resource.respond_to?(:identifier)  
107 - output[role_assigment.resource.identifier] = role_assigment.role.permissions  
108 - end  
109 - end  
110 - present output  
111 - end  
112 - end  
113 -  
114 - resource :profiles do  
115 - segment '/:profile_id' do  
116 - resource :members do  
117 - paginate max_per_page: MAX_PER_PAGE  
118 - get do  
119 - profile = environment.profiles.find_by id: params[:profile_id]  
120 - members = select_filtered_collection_of(profile, 'members', params)  
121 - present members, :with => Entities::Person, :current_person => current_person  
122 - end  
123 - end  
124 - end  
125 - end  
126 - end  
127 - end  
128 - end  
129 -end  
lib/noosfero/api/v1/profiles.rb
@@ -1,44 +0,0 @@ @@ -1,44 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Profiles < Grape::API  
5 -  
6 - resource :profiles do  
7 -  
8 - get do  
9 - profiles = select_filtered_collection_of(environment, 'profiles', params)  
10 - profiles = profiles.visible  
11 - profiles = profiles.by_location(params) # Must be the last. May return Exception obj.  
12 - present profiles, :with => Entities::Profile, :current_person => current_person  
13 - end  
14 -  
15 - get ':id' do  
16 - profiles = environment.profiles  
17 - profiles = profiles.visible  
18 - profile = profiles.find_by id: params[:id]  
19 -  
20 - if profile  
21 - present profile, :with => Entities::Profile, :current_person => current_person  
22 - else  
23 - not_found!  
24 - end  
25 - end  
26 -  
27 - delete ':id' do  
28 - authenticate!  
29 - profiles = environment.profiles  
30 - profile = profiles.find_by id: params[:id]  
31 -  
32 - not_found! if profile.blank?  
33 -  
34 - if current_person.has_permission?(:destroy_profile, profile)  
35 - profile.destroy  
36 - else  
37 - forbidden!  
38 - end  
39 - end  
40 - end  
41 - end  
42 - end  
43 - end  
44 -end  
lib/noosfero/api/v1/search.rb
@@ -1,39 +0,0 @@ @@ -1,39 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Search < Grape::API  
5 -  
6 - resource :search do  
7 - resource :article do  
8 - paginate max_per_page: 200  
9 - get do  
10 - # Security checks  
11 - sanitize_params_hash(params)  
12 - # APIHelpers  
13 - asset = :articles  
14 - context = environment  
15 -  
16 - profile = environment.profiles.find(params[:profile_id]) if params[:profile_id]  
17 - scope = profile.nil? ? environment.articles.is_public : profile.articles.is_public  
18 - scope = scope.where(:type => params[:type]) if params[:type] && !(params[:type] == 'Article')  
19 - scope = scope.where(make_conditions_with_parameter(params))  
20 - scope = scope.joins(:categories).where(:categories => {:id => params[:category_ids]}) if params[:category_ids].present?  
21 - scope = scope.where('articles.children_count > 0') if params[:has_children].present?  
22 - query = params[:query] || ""  
23 - order = "more_recent"  
24 -  
25 - options = {:filter => order, :template_id => params[:template_id]}  
26 -  
27 - search_result = find_by_contents(asset, context, scope, query, {:page => 1}, options)  
28 -  
29 - articles = search_result[:results]  
30 -  
31 - present_articles(articles)  
32 - end  
33 - end  
34 - end  
35 -  
36 - end  
37 - end  
38 - end  
39 -end  
lib/noosfero/api/v1/tags.rb
@@ -1,32 +0,0 @@ @@ -1,32 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Tags < Grape::API  
5 - resource :articles do  
6 - resource ':id/tags' do  
7 - get do  
8 - article = find_article(environment.articles, params[:id])  
9 - present article.tag_list  
10 - end  
11 -  
12 - desc "Add a tag to an article"  
13 - post do  
14 - authenticate!  
15 - article = find_article(environment.articles, params[:id])  
16 - article.tag_list=params[:tags]  
17 - article.save  
18 - present article.tag_list  
19 - end  
20 - end  
21 - end  
22 -  
23 - resource :environment do  
24 - desc 'Return the tag counts for this environment'  
25 - get '/tags' do  
26 - present environment.tag_counts  
27 - end  
28 - end  
29 - end  
30 - end  
31 - end  
32 -end  
lib/noosfero/api/v1/tasks.rb
@@ -1,59 +0,0 @@ @@ -1,59 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Tasks < Grape::API  
5 -# before { authenticate! }  
6 -  
7 -# ARTICLE_TYPES = Article.descendants.map{|a| a.to_s}  
8 -  
9 - resource :tasks do  
10 -  
11 - # Collect tasks  
12 - #  
13 - # Parameters:  
14 - # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created  
15 - # oldest - Collect the oldest articles. If nothing is passed the newest articles are collected  
16 - # limit - amount of articles returned. The default value is 20  
17 - #  
18 - # Example Request:  
19 - # GET host/api/v1/tasks?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317  
20 - get do  
21 - tasks = select_filtered_collection_of(environment, 'tasks', params)  
22 - tasks = tasks.select {|t| current_person.has_permission?(t.permission, environment)}  
23 - present_partial tasks, :with => Entities::Task  
24 - end  
25 -  
26 - desc "Return the task id"  
27 - get ':id' do  
28 - task = find_task(environment, params[:id])  
29 - present_partial task, :with => Entities::Task  
30 - end  
31 - end  
32 -  
33 - kinds = %w[community person enterprise]  
34 - kinds.each do |kind|  
35 - resource kind.pluralize.to_sym do  
36 - segment "/:#{kind}_id" do  
37 - resource :tasks do  
38 - get do  
39 - profile = environment.send(kind.pluralize).find(params["#{kind}_id"])  
40 - present_tasks(profile)  
41 - end  
42 -  
43 - get ':id' do  
44 - profile = environment.send(kind.pluralize).find(params["#{kind}_id"])  
45 - present_task(profile)  
46 - end  
47 -  
48 - post do  
49 - profile = environment.send(kind.pluralize).find(params["#{kind}_id"])  
50 - post_task(profile, params)  
51 - end  
52 - end  
53 - end  
54 - end  
55 - end  
56 - end  
57 - end  
58 - end  
59 -end  
lib/noosfero/api/v1/users.rb
@@ -1,45 +0,0 @@ @@ -1,45 +0,0 @@
1 -module Noosfero  
2 - module API  
3 - module V1  
4 - class Users < Grape::API  
5 -  
6 - resource :users do  
7 -  
8 - get do  
9 - users = select_filtered_collection_of(environment, 'users', params)  
10 - users = users.select{|u| u.person.display_info_to? current_person}  
11 - present users, :with => Entities::User, :current_person => current_person  
12 - end  
13 -  
14 - get "/me" do  
15 - authenticate!  
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 - if user  
22 - present user, :with => Entities::User, :current_person => current_person  
23 - else  
24 - not_found!  
25 - end  
26 - end  
27 -  
28 - get ":id/permissions" do  
29 - authenticate!  
30 - user = environment.users.find(params[:id])  
31 - output = {}  
32 - user.person.role_assignments.map do |role_assigment|  
33 - if role_assigment.resource.respond_to?(:identifier) && role_assigment.resource.identifier == params[:profile]  
34 - output[:permissions] = role_assigment.role.permissions  
35 - end  
36 - end  
37 - present output  
38 - end  
39 -  
40 - end  
41 -  
42 - end  
43 - end  
44 - end  
45 -end  
lib/noosfero/core_ext.rb
@@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
1 -require 'noosfero/core_ext/string'  
2 -require 'noosfero/core_ext/integer'  
3 -require 'noosfero/core_ext/active_record/calculations'  
4 -require 'noosfero/core_ext/active_record/reflection'  
5 -  
lib/noosfero/core_ext/active_record/calculations.rb
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -ActiveRecord::Calculations.class_eval do  
2 - def count_with_distinct column_name=self.primary_key  
3 - if column_name  
4 - distinct.count_without_distinct column_name  
5 - else  
6 - count_without_distinct  
7 - end  
8 - end  
9 - alias_method_chain :count, :distinct  
10 -end  
lib/noosfero/core_ext/active_record/reflection.rb
@@ -1,20 +0,0 @@ @@ -1,20 +0,0 @@
1 -  
2 -# on STI classes tike Article and Profile, plugins' extensions  
3 -# on associations should be reflected on descendants  
4 -module ActiveRecord  
5 - module Reflection  
6 -  
7 - class << self  
8 -  
9 - def add_reflection_with_descendants(ar, name, reflection)  
10 - self.add_reflection_without_descendants ar, name, reflection  
11 - ar.descendants.each do |k|  
12 - k._reflections.merge!(name.to_s => reflection)  
13 - end if ar.base_class == ar  
14 - end  
15 -  
16 - alias_method_chain :add_reflection, :descendants  
17 -  
18 - end  
19 - end  
20 -end  
lib/noosfero/core_ext/integer.rb
@@ -1,39 +0,0 @@ @@ -1,39 +0,0 @@
1 -class Integer  
2 - def to_humanreadable  
3 - value = self  
4 - if value < 1023  
5 - return "%i bytes" % value  
6 - end  
7 - value /= 1024  
8 -  
9 - if value < 1023  
10 - return "%1.1f KB" % value  
11 - end  
12 - value /= 1024  
13 -  
14 - if value < 1023  
15 - return "%1.1f MB" % value  
16 - end  
17 - value /= 1024  
18 -  
19 - if value < 1023  
20 - return "%1.1f GB" % value  
21 - end  
22 - value /= 1024  
23 -  
24 - if value < 1023  
25 - return "%1.1f TB" % value  
26 - end  
27 - value /= 1024  
28 -  
29 - if value < 1023  
30 - return "%1.1f PB" % value  
31 - end  
32 - value /= 1024  
33 -  
34 - if value < 1023  
35 - return "%1.1f EB" % value  
36 - end  
37 - value /= 1024  
38 - end  
39 -end  
lib/noosfero/core_ext/string.rb
@@ -1,93 +0,0 @@ @@ -1,93 +0,0 @@
1 -# encoding: utf-8  
2 -  
3 -class String  
4 -  
5 - TRANSLITERATIONS = {  
6 - [ 'Á', 'À', 'À', 'Â', 'Ã', 'Ä', 'Å' ] => 'A',  
7 - [ 'á', 'à', 'à', 'â', 'ã', 'ä', 'å' ,'ª' ] => 'a',  
8 - [ 'É', 'È', 'Ê', 'Ë' ] => 'E',  
9 - [ 'é', 'è', 'ê', 'ë' ] => 'e',  
10 - [ 'Í', 'Ì', 'Î', 'Ï' ] => 'I',  
11 - [ 'í', 'ì', 'î', 'ï' ] => 'i',  
12 - [ 'Ó', 'Ò', 'Ô', 'Ö', 'Õ', 'º' ] => 'O',  
13 - [ 'ó', 'ò', 'ô', 'ö', 'õ', 'º' ] => 'o',  
14 - [ 'Ú', 'Ù', 'Û', 'Ü' ] => 'U',  
15 - [ 'ú', 'ù', 'û', 'ü' ] => 'u',  
16 - [ 'ß' ] => 'ss',  
17 - [ 'Ç' ] => 'C',  
18 - [ 'ç' ] => 'c',  
19 - [ 'Ñ' ] => 'N',  
20 - [ 'ñ' ] => 'n',  
21 - [ 'Ÿ' ] => 'Y',  
22 - [ 'ÿ' ] => 'y',  
23 -# Cyrillic alphabet transliteration  
24 - [ 'а', 'А' ] => 'a',  
25 - [ 'б', 'Б' ] => 'b',  
26 - [ 'в', 'В' ] => 'v',  
27 - [ 'г', 'Г' ] => 'g',  
28 - [ 'д', 'Д' ] => 'd',  
29 - [ 'е', 'Е' ] => 'e',  
30 - [ 'ё', 'Ё' ] => 'yo',  
31 - [ 'ж', 'Ж' ] => 'zh',  
32 - [ 'з', 'З' ] => 'z',  
33 - [ 'и', 'И' ] => 'i',  
34 - [ 'й', 'Й' ] => 'y',  
35 - [ 'к', 'К' ] => 'k',  
36 - [ 'л', 'Л' ] => 'l',  
37 - [ 'м', 'М' ] => 'm',  
38 - [ 'н', 'Н' ] => 'n',  
39 - [ 'о', 'О' ] => 'o',  
40 - [ 'п', 'П' ] => 'p',  
41 - [ 'р', 'Р' ] => 'r',  
42 - [ 'с', 'С' ] => 's',  
43 - [ 'т', 'Т' ] => 't',  
44 - [ 'у', 'У' ] => 'u',  
45 - [ 'ф', 'Ф' ] => 'f',  
46 - [ 'х', 'Х' ] => 'h',  
47 - [ 'ц', 'Ц' ] => 'ts',  
48 - [ 'ч', 'Ч' ] => 'ch',  
49 - [ 'ш', 'Ш' ] => 'sh',  
50 - [ 'щ', 'Щ' ] => 'sch',  
51 - [ 'э', 'Э' ] => 'e',  
52 - [ 'ю', 'Ю' ] => 'yu',  
53 - [ 'я', 'Я' ] => 'ya',  
54 - [ 'ы', 'Ы' ] => 'i',  
55 - [ 'ь', 'Ь' ] => '',  
56 - [ 'ъ', 'Ъ' ] => '',  
57 -# Ukrainian lovely letters  
58 - [ 'і', 'І' ] => 'i',  
59 - [ 'ї', 'Ї' ] => 'yi',  
60 - [ 'є', 'Є' ] => 'ye',  
61 - [ 'ґ', 'Ґ' ] => 'g',  
62 - }  
63 -  
64 - # transliterate a string (assumed to contain UTF-8 data)  
65 - # into ASCII by replacing non-ascii characters to their  
66 - # ASCII.  
67 - #  
68 - # The transliteration is, of course, lossy, and its performance is poor.  
69 - # Don't abuse this method.  
70 - def transliterate  
71 -  
72 - new = self.dup  
73 - TRANSLITERATIONS.each { |from,to|  
74 - from.each { |seq|  
75 - new.gsub!(seq, to)  
76 - }  
77 - }  
78 - new  
79 - end  
80 -  
81 - def to_slug  
82 - transliterate.downcase.gsub(/[^[[:word:]]~\s:;+=_."'`-]/, '').gsub(/[\s:;+=_"'`-]+/, '-').gsub(/-$/, '').gsub(/^-/, '').to_s  
83 - end  
84 -  
85 - def to_css_class  
86 - underscore.dasherize.gsub('/','_')  
87 - end  
88 -  
89 - def fix_i18n  
90 - self.sub('{fn} ', '')  
91 - end  
92 -  
93 -end  
lib/noosfero/multi_tenancy.rb
@@ -12,14 +12,13 @@ module Noosfero @@ -12,14 +12,13 @@ module Noosfero
12 def self.db_by_host=(host) 12 def self.db_by_host=(host)
13 if host != @db_by_host 13 if host != @db_by_host
14 @db_by_host = host 14 @db_by_host = host
15 - ApplicationRecord.connection.schema_search_path = self.mapping[host] 15 + ActiveRecord::Base.connection.schema_search_path = self.mapping[host]
16 end 16 end
17 end 17 end
18 18
19 def self.setup!(host) 19 def self.setup!(host)
20 - if Noosfero::MultiTenancy.on? and ApplicationRecord.postgresql?  
21 - Noosfero::MultiTenancy.db_by_host = host  
22 - end 20 + return unless Noosfero::MultiTenancy.on?
  21 + Noosfero::MultiTenancy.db_by_host = host
23 end 22 end
24 23
25 class Middleware 24 class Middleware
lib/noosfero/unicorn.rb
@@ -7,11 +7,11 @@ GC.respond_to?(:copy_on_write_friendly=) and @@ -7,11 +7,11 @@ GC.respond_to?(:copy_on_write_friendly=) and
7 GC.copy_on_write_friendly = true 7 GC.copy_on_write_friendly = true
8 8
9 before_fork do |server, worker| 9 before_fork do |server, worker|
10 - ApplicationRecord.connection.disconnect! if defined?(ApplicationRecord) 10 + ActiveRecord::Base.connection.disconnect! if defined? ActiveRecord::Base
11 end 11 end
12 12
13 after_fork do |server, worker| 13 after_fork do |server, worker|
14 - ApplicationRecord.establish_connection if defined?(ApplicationRecord) 14 + ActiveRecord::Base.establish_connection if defined? ActiveRecord::Base
15 end 15 end
16 16
17 # load local configuration file, if it exists 17 # load local configuration file, if it exists
lib/postgresql_attachment_fu.rb
@@ -9,12 +9,12 @@ module PostgresqlAttachmentFu @@ -9,12 +9,12 @@ module PostgresqlAttachmentFu
9 module InstanceMethods 9 module InstanceMethods
10 def full_filename(thumbnail = nil) 10 def full_filename(thumbnail = nil)
11 file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s 11 file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s
12 - file_system_path = File.join(file_system_path, ApplicationRecord.connection.schema_search_path) if ApplicationRecord.postgresql? and Noosfero::MultiTenancy.on? 12 + file_system_path = File.join(file_system_path, ActiveRecord::Base.connection.schema_search_path) if Noosfero::MultiTenancy.on?
13 Rails.root.join(file_system_path, *partitioned_path(thumbnail_name_for(thumbnail))).to_s 13 Rails.root.join(file_system_path, *partitioned_path(thumbnail_name_for(thumbnail))).to_s
14 end 14 end
15 end 15 end
16 16
17 end 17 end
18 18
19 -ApplicationRecord.extend PostgresqlAttachmentFu::ClassMethods 19 +ActiveRecord::Base.extend PostgresqlAttachmentFu::ClassMethods
20 20
lib/split_datetime.rb
@@ -69,5 +69,5 @@ module SplitDatetime @@ -69,5 +69,5 @@ module SplitDatetime
69 end 69 end
70 70
71 Class.extend SplitDatetime::SplitMethods 71 Class.extend SplitDatetime::SplitMethods
72 -ApplicationRecord.extend SplitDatetime::SplitMethods 72 +ActiveRecord::Base.extend SplitDatetime::SplitMethods
73 73
lib/sqlite_extension.rb
@@ -1,28 +0,0 @@ @@ -1,28 +0,0 @@
1 -if ApplicationRecord.connection.adapter_name.downcase == 'sqlite'  
2 -  
3 - database = ApplicationRecord.connection.raw_connection  
4 -  
5 - database.create_function('pow', 2, 1) do |func, base, exponent|  
6 - func.set_result(base.to_f ** exponent.to_f)  
7 - end  
8 -  
9 - database.create_function('sqrt', 1, 1) do |func, value|  
10 - func.set_result(Math.sqrt(value))  
11 - end  
12 -  
13 - database.create_function('radians', 1, 1) do |func, value|  
14 - func.set_result(value.to_f * Math::PI / 180.0)  
15 - end  
16 -  
17 - database.create_function('spheric_distance', 5, 1) do |func, lat1, long1, lat2, long2, radius|  
18 - func.set_result(  
19 - radius.to_f * Math.acos(  
20 - [1,  
21 - Math.cos(lat1.to_f) * Math.cos(long1.to_f) * Math.cos(lat2.to_f) * Math.cos(long2.to_f) +  
22 - Math.cos(lat1.to_f) * Math.sin(long1.to_f) * Math.cos(lat2.to_f) * Math.sin(long2.to_f) +  
23 - Math.sin(lat1.to_f) * Math.sin(lat2.to_f)  
24 - ].min  
25 - )  
26 - )  
27 - end  
28 -end  
lib/tasks/backup.rake
@@ -115,7 +115,7 @@ end @@ -115,7 +115,7 @@ end
115 115
116 desc 'Removes emails from database' 116 desc 'Removes emails from database'
117 task 'restore:remove_emails' => :environment do 117 task 'restore:remove_emails' => :environment do
118 - connection = ApplicationRecord.connection 118 + connection = ActiveRecord::Base.connection
119 [ 119 [
120 "UPDATE users SET email = concat('user', id, '@localhost.localdomain')", 120 "UPDATE users SET email = concat('user', id, '@localhost.localdomain')",
121 "UPDATE environments SET contact_email = concat('environment', id, '@localhost.localdomain')", 121 "UPDATE environments SET contact_email = concat('environment', id, '@localhost.localdomain')",
lib/tasks/grape_routes.rb
1 desc "Print out grape routes" 1 desc "Print out grape routes"
2 task :grape_routes => :environment do 2 task :grape_routes => :environment do
3 #require 'api/api.rb' 3 #require 'api/api.rb'
4 - Noosfero::API::API.routes.each do |route| 4 + Api::App.routes.each do |route|
5 puts route 5 puts route
6 method = route.route_method 6 method = route.route_method
7 path = route.route_path 7 path = route.route_path
lib/tasks/multitenancy.rake
1 namespace :multitenancy do 1 namespace :multitenancy do
2 2
3 task :create => :environment do 3 task :create => :environment do
4 - db_envs = ApplicationRecord.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) } 4 + db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) }
5 cd Rails.root.join('config', 'environments'), :verbose => true 5 cd Rails.root.join('config', 'environments'), :verbose => true
6 file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}" 6 file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}"
7 (db_envs.map{ |e| e + '.rb' } - file_envs).each { |env| ln_s env.split('_').last, env } 7 (db_envs.map{ |e| e + '.rb' } - file_envs).each { |env| ln_s env.split('_').last, env }
8 end 8 end
9 9
10 task :remove => :environment do 10 task :remove => :environment do
11 - db_envs = ApplicationRecord.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) } 11 + db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) }
12 cd Rails.root.join('config', 'environments'), :verbose => true 12 cd Rails.root.join('config', 'environments'), :verbose => true
13 file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}" 13 file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}"
14 (file_envs - db_envs.map{ |e| e + '.rb' }).each { |env| safe_unlink env } 14 (file_envs - db_envs.map{ |e| e + '.rb' }).each { |env| safe_unlink env }
@@ -19,7 +19,7 @@ end @@ -19,7 +19,7 @@ end
19 namespace :db do 19 namespace :db do
20 20
21 task :migrate_other_environments => :environment do 21 task :migrate_other_environments => :environment do
22 - envs = ApplicationRecord.configurations.keys.select{ |k| k.match(/_#{Rails.env}$/) } 22 + envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_#{Rails.env}$/) }
23 envs.each do |e| 23 envs.each do |e|
24 puts "*** Migrating #{e}" if Rake.application.options.trace 24 puts "*** Migrating #{e}" if Rake.application.options.trace
25 system "rake db:migrate RAILS_ENV=#{e} SCHEMA=/dev/null" 25 system "rake db:migrate RAILS_ENV=#{e} SCHEMA=/dev/null"
lib/upload_sanitizer.rb
@@ -10,4 +10,4 @@ module UploadSanitizer @@ -10,4 +10,4 @@ module UploadSanitizer
10 end 10 end
11 end 11 end
12 12
13 -ApplicationRecord.send :include, UploadSanitizer 13 +ActiveRecord::Base.send :include, UploadSanitizer
plugins/admin_notifications/lib/admin_notifications_plugin/notifications_user.rb
1 -class AdminNotificationsPlugin::NotificationsUser < ActiveRecord::Base 1 +class AdminNotificationsPlugin::NotificationsUser < ApplicationRecord
2 self.table_name = "admin_notifications_plugin_notifications_users" 2 self.table_name = "admin_notifications_plugin_notifications_users"
3 3
4 belongs_to :user 4 belongs_to :user
plugins/admin_notifications/models/admin_notifications_plugin/notification.rb
1 -class AdminNotificationsPlugin::Notification < ActiveRecord::Base 1 +class AdminNotificationsPlugin::Notification < ApplicationRecord
2 2
3 self.table_name = "admin_notifications_plugin_notifications" 3 self.table_name = "admin_notifications_plugin_notifications"
4 4
plugins/admin_notifications/views/admin_notifications_plugin_public/notifications_with_popup.html.erb
@@ -9,12 +9,12 @@ @@ -9,12 +9,12 @@
9 </div> 9 </div>
10 </div> 10 </div>
11 <div class="notification-message notification-with-title-message"> 11 <div class="notification-message notification-with-title-message">
12 - <%= AdminNotificationsPlugin::NotificationHelper.substitute_variables(notification.message, current_user) %> 12 + <%= AdminNotificationsPlugin::NotificationHelper.substitute_variables(notification.message, current_user).html_safe %>
13 </div> 13 </div>
14 <% else %> 14 <% else %>
15 <div class="<%= notification.type.gsub("AdminNotificationsPlugin::", "").downcase %> notification notification-without-title" data-notification="<%=notification.id%>"> 15 <div class="<%= notification.type.gsub("AdminNotificationsPlugin::", "").downcase %> notification notification-without-title" data-notification="<%=notification.id%>">
16 <div class="notification-message"> 16 <div class="notification-message">
17 - <%= AdminNotificationsPlugin::NotificationHelper.substitute_variables(notification.message, current_user) %> 17 + <%= AdminNotificationsPlugin::NotificationHelper.substitute_variables(notification.message, current_user).html_safe %>
18 </div> 18 </div>
19 </div> 19 </div>
20 <% end %> 20 <% end %>
plugins/admin_notifications/views/shared/_notifications_list.html.erb
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 <% @notifications.each do |notification| %> 23 <% @notifications.each do |notification| %>
24 <div class="notification-line"> 24 <div class="notification-line">
25 <div class="notification-message"> 25 <div class="notification-message">
26 - <%= truncate(notification.message, length: 50) %> 26 + <%= truncate(notification.message.html_safe, length: 50) %>
27 </div> 27 </div>
28 <div class="notification-action"> 28 <div class="notification-action">
29 <% if notification.active? %> 29 <% if notification.active? %>
plugins/admin_notifications/views/shared/show_notification.html.erb
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 <% @notifications.each do |notification| %> 22 <% @notifications.each do |notification| %>
23 <div class="<%= notification.type.gsub("AdminNotificationsPlugin::", "").downcase %> notification" data-notification="<%=notification.id%>" notification-display-popup="<%=notification.display_popup?%>"> 23 <div class="<%= notification.type.gsub("AdminNotificationsPlugin::", "").downcase %> notification" data-notification="<%=notification.id%>" notification-display-popup="<%=notification.display_popup?%>">
24 <div class="notification-message"> 24 <div class="notification-message">
25 - <%= AdminNotificationsPlugin::NotificationHelper.substitute_variables(notification.message, current_user) %> 25 + <%= AdminNotificationsPlugin::NotificationHelper.substitute_variables(notification.message, current_user).html_safe %>
26 </div> 26 </div>
27 <% if logged_in? %> 27 <% if logged_in? %>
28 <div class="notification-close" title="<%= _('Do not show anymore') %>"></div> 28 <div class="notification-close" title="<%= _('Do not show anymore') %>"></div>
plugins/breadcrumbs/lib/breadcrumbs_plugin/content_breadcrumbs_block.rb
@@ -22,70 +22,8 @@ class BreadcrumbsPlugin::ContentBreadcrumbsBlock &lt; Block @@ -22,70 +22,8 @@ class BreadcrumbsPlugin::ContentBreadcrumbsBlock &lt; Block
22 _('This block displays breadcrumb trail.') 22 _('This block displays breadcrumb trail.')
23 end 23 end
24 24
25 - def page_trail(page, params={})  
26 - links = []  
27 - if page  
28 - links = page.ancestors.reverse.map { |p| { :name => p.title, :url => p.url } }  
29 - links << { :name => page.title, :url => page.url }  
30 - elsif params[:controller] == 'cms'  
31 - id = params[:id] || params[:parent_id]  
32 - links = page_trail(Article.find(id)) if id  
33 - links << { :name => cms_action(params[:action]), :url => params } if show_cms_action  
34 - elsif (params[:controller] == 'profile' || params[:controller] == 'events')  
35 - links << { :name => _('Profile'), :url => {:controller=> 'profile', :action =>'index', :profile =>params[:profile]}}  
36 - links << { :name => profile_action(params[:action]), :url => params } unless params[:action] == 'index'  
37 - end  
38 - links  
39 - end  
40 -  
41 - def trail(page, profile=nil, params={})  
42 - links = page_trail(page, params)  
43 - if profile && !links.empty? && show_profile  
44 - [ {:name => profile.name, :url => profile.url} ] + links  
45 - else  
46 - links  
47 - end  
48 - end  
49 -  
50 - def content(args={})  
51 - block = self  
52 - ret = (proc do  
53 - trail = block.trail(@page, @profile, params)  
54 - if !trail.empty?  
55 - separator = content_tag('span', ' > ', :class => 'separator')  
56 -  
57 - breadcrumb = trail.map do |t|  
58 - link_to(t[:name], t[:url], :class => 'item')  
59 - end.join(separator)  
60 -  
61 - if block.show_section_name  
62 - section_name = block.show_profile ? trail.second[:name] : trail.first[:name]  
63 - breadcrumb << content_tag('div', section_name, :class => 'section-name')  
64 - end  
65 -  
66 - breadcrumb.html_safe  
67 - else  
68 - ''  
69 - end  
70 - end)  
71 - ret  
72 - end  
73 -  
74 def cacheable? 25 def cacheable?
75 false 26 false
76 end 27 end
77 28
78 - protected  
79 -  
80 - CMS_ACTIONS = {:edit => c_('Edit'), :upload_files => _('Upload Files'), :new => c_('New')}  
81 - PROFILE_ACTIONS = {:members => _('Members'), :events => _('Events')}  
82 -  
83 - def cms_action(action)  
84 - CMS_ACTIONS[action.to_sym] || action  
85 - end  
86 -  
87 - def profile_action(action)  
88 - PROFILE_ACTIONS[action.to_sym] || action  
89 - end  
90 -  
91 end 29 end
plugins/breadcrumbs/lib/breadcrumbs_plugin_helper.rb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +module BreadcrumbsPluginHelper
  2 +
  3 + def action(action)
  4 + { :edit => c_('Edit'),
  5 + :upload_files => _('Upload Files'),
  6 + :new => c_('New'),
  7 + :members => _('Members'),
  8 + :events => _('Events')
  9 + }[action.to_sym] || action
  10 + end
  11 +
  12 + def page_trail(page)
  13 + links = []
  14 + page.ancestors.reverse.each do |p|
  15 + links << { :name => p.title, :url => p.url }
  16 + end
  17 + links << { :name => page.title, :url => page.url }
  18 + links
  19 + end
  20 +
  21 + def trail(block, page, profile=nil, params={})
  22 + links = []
  23 + if page
  24 + links += page_trail(page)
  25 + elsif params[:controller] == 'cms' && (id = params[:id] || params[:parent_id])
  26 + links += page_trail(Article.find(id))
  27 + if block.show_cms_action
  28 + links << { :name => action(params[:action]), :url => params }
  29 + end
  30 + elsif (params[:controller] == 'profile' || params[:controller] == 'events')
  31 + _params = {:controller=> 'profile', :action =>'index', :profile => params[:profile]}
  32 + links << { :name => _('Profile'), :url => _params }
  33 + unless params[:action] == 'index'
  34 + links << { :name => action(params[:action]), :url => params }
  35 + end
  36 + end
  37 + if !links.empty? && profile && block.show_profile
  38 + links.unshift({:name => profile.name, :url => profile.url})
  39 + end
  40 + links
  41 + end
  42 +
  43 +end
plugins/breadcrumbs/test/unit/breadcrumbs_plugin_helper_test.rb 0 → 100644
@@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
  1 +require 'test_helper'
  2 +
  3 +class BreadcrumbsPluginHelperTest < ActionView::TestCase
  4 + include BreadcrumbsPluginHelper
  5 +
  6 + def setup
  7 + @block = BreadcrumbsPlugin::ContentBreadcrumbsBlock.new
  8 + @profile = fast_create(Community)
  9 + @folder = fast_create(Folder, :profile_id => @profile.id)
  10 + @article = fast_create(Folder, :profile_id => @profile.id, :parent_id => @folder.id)
  11 + @params = {}
  12 + end
  13 +
  14 + attr_reader :params
  15 +
  16 + should 'return path of links to reach a page' do
  17 + links = [{:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}]
  18 + assert_equal links, page_trail(@article)
  19 + end
  20 +
  21 + should 'return path of links when current page is at cms controller' do
  22 + params = {:controller => 'cms', :action => 'edit', :id => @article.id}
  23 + links = [{:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}, {:url=>params, :name=>"Edit"}]
  24 + assert_equal links, trail(@block, nil, nil, params)
  25 + end
  26 +
  27 + should 'not return cms action link when show_cms_action is false' do
  28 + params = {:controller => 'cms', :action => 'edit', :id => @article.id}
  29 + links = [{:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}]
  30 + @block.show_cms_action = false
  31 + assert_equal links, trail(@block, nil, nil, params)
  32 + end
  33 +
  34 + should 'include profile page link on path of links to reach a profile controller page' do
  35 + params = {:controller => 'profile', :action => 'members', :profile => @profile.identifier}
  36 + links = [{:name => 'Profile', :url => {:controller => 'profile', :action => 'index', :profile => @profile.identifier}}, {:name => 'Members', :url => {:controller=>'profile', :action=>'members', :profile=> @profile.identifier}}]
  37 + assert_equal links, trail(@block, nil, nil, params)
  38 + end
  39 +
  40 + should 'include only the profile page link on path links when profile action is index' do
  41 + params = {:controller => 'profile', :action => 'index', :profile => @profile.identifier}
  42 + links = [{:name => 'Profile', :url => {:controller => 'profile', :action => 'index', :profile => @profile.identifier}}]
  43 + assert_equal links, trail(@block, nil, nil, params)
  44 + end
  45 +
  46 + should 'profile page be the ancestor page of event profile page calendar' do
  47 + params = {:controller => 'profile', :action => 'events', :profile => @profile.identifier}
  48 + links = [{:name => 'Profile', :url => {:controller => 'profile', :action => 'index', :profile => @profile.identifier}}, {:name => 'Events', :url => {:controller=>'profile', :action=>'events', :profile=> @profile.identifier}}]
  49 + assert_equal links, trail(@block, nil, nil, params)
  50 + end
  51 +
  52 + should 'include profile link on path of links to reach a page' do
  53 + links = [{:name => @profile.name, :url => @profile.url}, {:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}]
  54 + assert_equal links, trail(@block, @article, @profile)
  55 + end
  56 +
  57 + should 'not include profile link on path of links when show_profile is false' do
  58 + links = [{:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}]
  59 + @block.show_profile = false
  60 + assert_equal links, trail(@block, @article, @profile)
  61 + end
  62 +
  63 + should 'not include profile link on path of links when trail is empty' do
  64 + assert_equal [], trail(@block, nil, @profile)
  65 + end
  66 +end
plugins/breadcrumbs/test/unit/content_breadcrumbs_block_test.rb
@@ -6,14 +6,8 @@ class ContentBreadcrumbsBlockTest &lt; ActiveSupport::TestCase @@ -6,14 +6,8 @@ class ContentBreadcrumbsBlockTest &lt; ActiveSupport::TestCase
6 6
7 def setup 7 def setup
8 @block = BreadcrumbsPlugin::ContentBreadcrumbsBlock.new 8 @block = BreadcrumbsPlugin::ContentBreadcrumbsBlock.new
9 - @profile = fast_create(Community)  
10 - @folder = fast_create(Folder, :profile_id => @profile.id)  
11 - @article = fast_create(Folder, :profile_id => @profile.id, :parent_id => @folder.id)  
12 - @params = {}  
13 end 9 end
14 10
15 - attr_reader :params  
16 -  
17 should 'has a description' do 11 should 'has a description' do
18 assert_not_equal Block.description, BreadcrumbsPlugin::ContentBreadcrumbsBlock.description 12 assert_not_equal Block.description, BreadcrumbsPlugin::ContentBreadcrumbsBlock.description
19 end 13 end
@@ -22,60 +16,28 @@ class ContentBreadcrumbsBlockTest &lt; ActiveSupport::TestCase @@ -22,60 +16,28 @@ class ContentBreadcrumbsBlockTest &lt; ActiveSupport::TestCase
22 assert @block.help 16 assert @block.help
23 end 17 end
24 18
25 - should 'return path of links to reach a page' do  
26 - links = [{:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}]  
27 - assert_equal links, @block.page_trail(@article)  
28 - end  
29 -  
30 - should 'return path of links when current page is at cms controller' do  
31 - params = {:controller => 'cms', :action => 'edit', :id => @article.id}  
32 - links = [{:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}, {:url=>{:controller=>"cms", :action=>"edit", :id=>@article.id}, :name=>"Edit"}]  
33 - assert_equal links, @block.page_trail(nil, params)  
34 - end  
35 -  
36 - should 'not return cms action link when show_cms_action is false' do  
37 - params = {:controller => 'cms', :action => 'edit', :id => @article.id}  
38 - links = [{:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}]  
39 - @block.show_cms_action = false  
40 - assert_equal links, @block.page_trail(nil, params)  
41 - end  
42 -  
43 - should 'include profile page link on path of links to reach a profile controller page' do  
44 - params = {:controller => 'profile', :action => 'members', :profile => @profile.identifier}  
45 - links = [{:name => 'Profile', :url => {:controller => 'profile', :action => 'index', :profile => @profile.identifier}}, {:name => 'Members', :url => {:controller=>'profile', :action=>'members', :profile=> @profile.identifier}}]  
46 - assert_equal links, @block.page_trail(nil, params)  
47 - end  
48 19
49 - should 'include only the profile page link on path links when profile action is index' do  
50 - params = {:controller => 'profile', :action => 'index', :profile => @profile.identifier}  
51 - links = [{:name => 'Profile', :url => {:controller => 'profile', :action => 'index', :profile => @profile.identifier}}]  
52 - assert_equal links, @block.page_trail(nil, params) 20 + should 'not be cacheable' do
  21 + refute @block.cacheable?
53 end 22 end
54 23
55 - should 'profile page be the ancestor page of event profile page calendar' do  
56 - params = {:controller => 'profile', :action => 'events', :profile => @profile.identifier}  
57 - links = [{:name => 'Profile', :url => {:controller => 'profile', :action => 'index', :profile => @profile.identifier}}, {:name => 'Events', :url => {:controller=>'profile', :action=>'events', :profile=> @profile.identifier}}]  
58 - assert_equal links, @block.page_trail(nil, params)  
59 - end 24 +end
60 25
61 - should 'include profile link on path of links to reach a page' do  
62 - links = [{:name => @profile.name, :url => @profile.url}, {:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}]  
63 - assert_equal links, @block.trail(@article, @profile)  
64 - end 26 +require 'boxes_helper'
65 27
66 - should 'not include profile link on path of links when show_profile is false' do  
67 - links = [{:name => @folder.name, :url => @folder.url}, {:name => @article.name, :url => @article.url}]  
68 - @block.show_profile = false  
69 - assert_equal links, @block.trail(@article, @profile)  
70 - end 28 +class ContentBreadcrumbsBlockViewTest < ActionView::TestCase
  29 + include BoxesHelper
71 30
72 - should 'not include profile link on path of links when trail is empty' do  
73 - assert_equal [], @block.trail(nil, @profile) 31 + def setup
  32 + @block = BreadcrumbsPlugin::ContentBreadcrumbsBlock.new
  33 + @profile = fast_create(Community)
  34 + @folder = fast_create(Folder, :profile_id => @profile.id)
  35 + @article = fast_create(Folder, :profile_id => @profile.id, :parent_id => @folder.id)
74 end 36 end
75 37
76 should 'render trail if there is links to show' do 38 should 'render trail if there is links to show' do
77 @page = @article 39 @page = @article
78 - trail = instance_eval(&@block.content) 40 + trail = render_block_content(@block)
79 assert_match /#{@profile.name}/, trail 41 assert_match /#{@profile.name}/, trail
80 assert_match /#{@folder.name}/, trail 42 assert_match /#{@folder.name}/, trail
81 assert_match /#{@page.name}/, trail 43 assert_match /#{@page.name}/, trail
@@ -83,11 +45,6 @@ class ContentBreadcrumbsBlockTest &lt; ActiveSupport::TestCase @@ -83,11 +45,6 @@ class ContentBreadcrumbsBlockTest &lt; ActiveSupport::TestCase
83 45
84 should 'render nothing if there is no links to show' do 46 should 'render nothing if there is no links to show' do
85 @page = nil 47 @page = nil
86 - assert_equal '', instance_eval(&@block.content)  
87 - end  
88 -  
89 - should 'not be cacheable' do  
90 - refute @block.cacheable? 48 + assert_equal '', render_block_content(@block)
91 end 49 end
92 -  
93 end 50 end
plugins/breadcrumbs/views/blocks/_link.html.slim 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +== link_to link[:name], link[:url], :class => 'item'
plugins/breadcrumbs/views/blocks/_separator.slim 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +span class='separator'
  2 + |>
plugins/breadcrumbs/views/blocks/content_breadcrumbs.slim 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +- extend BreadcrumbsPluginHelper
  2 +
  3 +- links = trail(block, @page, @profile, params).flatten
  4 +- unless links.empty?
  5 + == render :partial => 'blocks/link', :collection => links, :as => 'link', :spacer_template => 'blocks/separator'
  6 + - if block.show_section_name
  7 + div class='section-name'
  8 + - if block.show_profile
  9 + = links.second[:name]
  10 + - else
  11 + = links.first[:name]
plugins/comment_paragraph/lib/comment_paragraph_plugin/api.rb
  1 +# Can't be called Api as will result in:
  2 +# warning: toplevel constant Api referenced by CommentParagraphPlugin::Api
  3 +# To fix this CommentParagraphPlugin should be a module
1 class CommentParagraphPlugin::API < Grape::API 4 class CommentParagraphPlugin::API < Grape::API
2 MAX_PER_PAGE = 20 5 MAX_PER_PAGE = 20
3 6
@@ -9,7 +12,7 @@ class CommentParagraphPlugin::API &lt; Grape::API @@ -9,7 +12,7 @@ class CommentParagraphPlugin::API &lt; Grape::API
9 comments = comments.without_spam 12 comments = comments.without_spam
10 comments = comments.in_paragraph(params[:paragraph_uuid]) 13 comments = comments.in_paragraph(params[:paragraph_uuid])
11 comments = comments.without_reply if(params[:without_reply].present?) 14 comments = comments.without_reply if(params[:without_reply].present?)
12 - present paginate(comments), :with => Noosfero::API::Entities::Comment, :current_person => current_person 15 + present paginate(comments), :with => Api::Entities::Comment, :current_person => current_person
13 end 16 end
14 17
15 {activate: true, deactivate: false}.each do |method, value| 18 {activate: true, deactivate: false}.each do |method, value|
@@ -19,7 +22,7 @@ class CommentParagraphPlugin::API &lt; Grape::API @@ -19,7 +22,7 @@ class CommentParagraphPlugin::API &lt; Grape::API
19 return forbidden! unless article.comment_paragraph_plugin_enabled? && article.allow_edit?(current_person) 22 return forbidden! unless article.comment_paragraph_plugin_enabled? && article.allow_edit?(current_person)
20 article.comment_paragraph_plugin_activate = value 23 article.comment_paragraph_plugin_activate = value
21 article.save! 24 article.save!
22 - present_partial article, :with => Noosfero::API::Entities::Article 25 + present_partial article, :with => Api::Entities::Article
23 end 26 end
24 end 27 end
25 28
plugins/comment_paragraph/lib/ext/entities.rb
1 -require File.join(Rails.root,'lib','noosfero','api','entities')  
2 -module Noosfero  
3 - module API  
4 - module Entities  
5 - class Comment < CommentBase  
6 - expose :paragraph_uuid  
7 - expose :comment_paragraph_selected_area  
8 - expose :comment_paragraph_selected_content  
9 - end 1 +require_dependency 'api/entities'
  2 +
  3 +module Api
  4 + module Entities
  5 + class Comment
  6 + expose :paragraph_uuid
  7 + expose :comment_paragraph_selected_area
  8 + expose :comment_paragraph_selected_content
10 end 9 end
11 end 10 end
12 end 11 end