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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 13 private
14 14  
15 15 def endpoints
16   - Noosfero::API::API.endpoints(environment)
  16 + Api::App.endpoints(environment)
17 17 end
18 18  
19 19 end
... ...
app/jobs/activities_counter_cache_job.rb 0 → 100644
... ... @@ -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 @@
  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 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 6 # an ActionView instance for rendering views on models
10 7 def self.action_view
... ... @@ -25,7 +22,7 @@ class ApplicationRecord &lt; ActiveRecord::Base
25 22 alias :meta_cache_key :cache_key
26 23 def cache_key
27 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 26 key.join('/')
30 27 end
31 28  
... ...
app/models/profile.rb
... ... @@ -1093,6 +1093,11 @@ private :generate_url, :url_options
1093 1093 self.data[:fields_privacy]
1094 1094 end
1095 1095  
  1096 + # abstract
  1097 + def active_fields
  1098 + []
  1099 + end
  1100 +
1096 1101 def public_fields
1097 1102 self.active_fields
1098 1103 end
... ...
app/models/recent_documents_block.rb
... ... @@ -31,7 +31,7 @@ class RecentDocumentsBlock &lt; Block
31 31 end
32 32  
33 33 def api_content
34   - Noosfero::API::Entities::ArticleBase.represent(docs).as_json
  34 + Api::Entities::ArticleBase.represent(docs).as_json
35 35 end
36 36  
37 37 def display_api_content_by_default?
... ...
app/views/admin_panel/set_portal_community.html.erb
... ... @@ -9,7 +9,7 @@
9 9 <% end %>
10 10 <% end %>
11 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 14 <% button_bar do %>
15 15 <%if @portal_community.environment.enabled?('use_portal_community') %>
... ...
app/views/api/playground.html.erb
1 1 <h1>API Playground</h1>
2 2  
3 3 <script>
4   -<% prefix = Noosfero::API::API.prefix %>
  4 +<% prefix = Api::App.prefix %>
5 5 var prefix = <%= prefix.to_json %>;
6 6 var endpoints = <%=
7 7 endpoints.map do |endpoint|
... ...
config.ru
... ... @@ -20,6 +20,6 @@ rails_app = Rack::Builder.new do
20 20 end
21 21  
22 22 run Rack::Cascade.new([
23   - Noosfero::API::API,
  23 + Api::App,
24 24 rails_app
25 25 ])
... ...
config/application.rb
1   -require File.expand_path('../boot', __FILE__)
  1 +require_relative 'boot'
2 2  
3 3 require 'rails/all'
4 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 7 ActiveSupport::Deprecation.silenced = true
10 8  
11 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 16 module Noosfero
14 17 class Application < Rails::Application
15 18  
16   - require 'noosfero/plugin'
17   -
18 19 # The plugin xss_terminator(located in vendor/plugins/xss_terminator) and the helper
19 20 # SanitizeHelper(located in app/helpers/sanitize_helper.rb) use
20 21 # ALLOWED_TAGS and ALLOWED_ATTRIBUTES to make a sanitize with html.
... ... @@ -30,9 +31,6 @@ module Noosfero
30 31 config.action_view.sanitized_allowed_tags = ALLOWED_TAGS
31 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 34 config.action_controller.include_all_helpers = false
37 35  
38 36 # Settings in config/environments/* take precedence over those specified here.
... ... @@ -40,10 +38,12 @@ module Noosfero
40 38 # -- all .rb files in that directory are automatically loaded.
41 39  
42 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 48 # Only load the plugins named here, in the order given (default is alphabetical).
49 49 # :all can be used as a placeholder for all plugins not explicitly named.
... ... @@ -119,7 +119,8 @@ module Noosfero
119 119  
120 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 125 end
125 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 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 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 9 end
44 10  
45   -Noosfero::Application.initialize!
... ...
config/initializers/00_dependencies.rb 0 → 100644
... ... @@ -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   -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 5 require 'noosfero/plugin/settings'
6 6 require 'noosfero/plugin/spammable'
7 7 Noosfero::Plugin.initialize!
  8 +
... ...
lib/activities_counter_cache_job.rb
... ... @@ -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 122 end
123 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 33 module ClassMethods
34 34  
35 35 def build_ancestry(parent_id = nil, ancestry = '')
36   - ApplicationRecord.transaction do
  36 + ActiveRecord::Base.transaction do
37 37 self.base_class.where(parent_id: parent_id).each do |node|
38 38 node.update_column :ancestry, ancestry
39 39  
... ... @@ -263,5 +263,5 @@ module ActsAsFileSystem
263 263 end
264 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 35  
36 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 23  
24 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 47  
48 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 87  
88 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 55 end
56 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   -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 52 end
53 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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 4 module Noosfero
4 5  
... ... @@ -106,6 +107,3 @@ module Noosfero
106 107  
107 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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -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   -
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   -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   -# 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 12 def self.db_by_host=(host)
13 13 if host != @db_by_host
14 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 16 end
17 17 end
18 18  
19 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 22 end
24 23  
25 24 class Middleware
... ...
lib/noosfero/unicorn.rb
... ... @@ -7,11 +7,11 @@ GC.respond_to?(:copy_on_write_friendly=) and
7 7 GC.copy_on_write_friendly = true
8 8  
9 9 before_fork do |server, worker|
10   - ApplicationRecord.connection.disconnect! if defined?(ApplicationRecord)
  10 + ActiveRecord::Base.connection.disconnect! if defined? ActiveRecord::Base
11 11 end
12 12  
13 13 after_fork do |server, worker|
14   - ApplicationRecord.establish_connection if defined?(ApplicationRecord)
  14 + ActiveRecord::Base.establish_connection if defined? ActiveRecord::Base
15 15 end
16 16  
17 17 # load local configuration file, if it exists
... ...
lib/postgresql_attachment_fu.rb
... ... @@ -9,12 +9,12 @@ module PostgresqlAttachmentFu
9 9 module InstanceMethods
10 10 def full_filename(thumbnail = nil)
11 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 13 Rails.root.join(file_system_path, *partitioned_path(thumbnail_name_for(thumbnail))).to_s
14 14 end
15 15 end
16 16  
17 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 69 end
70 70  
71 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   -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 115  
116 116 desc 'Removes emails from database'
117 117 task 'restore:remove_emails' => :environment do
118   - connection = ApplicationRecord.connection
  118 + connection = ActiveRecord::Base.connection
119 119 [
120 120 "UPDATE users SET email = concat('user', id, '@localhost.localdomain')",
121 121 "UPDATE environments SET contact_email = concat('environment', id, '@localhost.localdomain')",
... ...
lib/tasks/grape_routes.rb
1 1 desc "Print out grape routes"
2 2 task :grape_routes => :environment do
3 3 #require 'api/api.rb'
4   - Noosfero::API::API.routes.each do |route|
  4 + Api::App.routes.each do |route|
5 5 puts route
6 6 method = route.route_method
7 7 path = route.route_path
... ...
lib/tasks/multitenancy.rake
1 1 namespace :multitenancy do
2 2  
3 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 5 cd Rails.root.join('config', 'environments'), :verbose => true
6 6 file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}"
7 7 (db_envs.map{ |e| e + '.rb' } - file_envs).each { |env| ln_s env.split('_').last, env }
8 8 end
9 9  
10 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 12 cd Rails.root.join('config', 'environments'), :verbose => true
13 13 file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}"
14 14 (file_envs - db_envs.map{ |e| e + '.rb' }).each { |env| safe_unlink env }
... ... @@ -19,7 +19,7 @@ end
19 19 namespace :db do
20 20  
21 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 23 envs.each do |e|
24 24 puts "*** Migrating #{e}" if Rake.application.options.trace
25 25 system "rake db:migrate RAILS_ENV=#{e} SCHEMA=/dev/null"
... ...
lib/upload_sanitizer.rb
... ... @@ -10,4 +10,4 @@ module UploadSanitizer
10 10 end
11 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 2 self.table_name = "admin_notifications_plugin_notifications_users"
3 3  
4 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 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 9 </div>
10 10 </div>
11 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 13 </div>
14 14 <% else %>
15 15 <div class="<%= notification.type.gsub("AdminNotificationsPlugin::", "").downcase %> notification notification-without-title" data-notification="<%=notification.id%>">
16 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 18 </div>
19 19 </div>
20 20 <% end %>
... ...
plugins/admin_notifications/views/shared/_notifications_list.html.erb
... ... @@ -23,7 +23,7 @@
23 23 <% @notifications.each do |notification| %>
24 24 <div class="notification-line">
25 25 <div class="notification-message">
26   - <%= truncate(notification.message, length: 50) %>
  26 + <%= truncate(notification.message.html_safe, length: 50) %>
27 27 </div>
28 28 <div class="notification-action">
29 29 <% if notification.active? %>
... ...
plugins/admin_notifications/views/shared/show_notification.html.erb
... ... @@ -22,7 +22,7 @@
22 22 <% @notifications.each do |notification| %>
23 23 <div class="<%= notification.type.gsub("AdminNotificationsPlugin::", "").downcase %> notification" data-notification="<%=notification.id%>" notification-display-popup="<%=notification.display_popup?%>">
24 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 26 </div>
27 27 <% if logged_in? %>
28 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 22 _('This block displays breadcrumb trail.')
23 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 25 def cacheable?
75 26 false
76 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 29 end
... ...
plugins/breadcrumbs/lib/breadcrumbs_plugin_helper.rb 0 → 100644
... ... @@ -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 @@
  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 6  
7 7 def setup
8 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 9 end
14 10  
15   - attr_reader :params
16   -
17 11 should 'has a description' do
18 12 assert_not_equal Block.description, BreadcrumbsPlugin::ContentBreadcrumbsBlock.description
19 13 end
... ... @@ -22,60 +16,28 @@ class ContentBreadcrumbsBlockTest &lt; ActiveSupport::TestCase
22 16 assert @block.help
23 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 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 36 end
75 37  
76 38 should 'render trail if there is links to show' do
77 39 @page = @article
78   - trail = instance_eval(&@block.content)
  40 + trail = render_block_content(@block)
79 41 assert_match /#{@profile.name}/, trail
80 42 assert_match /#{@folder.name}/, trail
81 43 assert_match /#{@page.name}/, trail
... ... @@ -83,11 +45,6 @@ class ContentBreadcrumbsBlockTest &lt; ActiveSupport::TestCase
83 45  
84 46 should 'render nothing if there is no links to show' do
85 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 49 end
92   -
93 50 end
... ...
plugins/breadcrumbs/views/blocks/_link.html.slim 0 → 100644
... ... @@ -0,0 +1 @@
  1 +== link_to link[:name], link[:url], :class => 'item'
... ...
plugins/breadcrumbs/views/blocks/_separator.slim 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +span class='separator'
  2 + |>
... ...
plugins/breadcrumbs/views/blocks/content_breadcrumbs.slim 0 → 100644
... ... @@ -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 4 class CommentParagraphPlugin::API < Grape::API
2 5 MAX_PER_PAGE = 20
3 6  
... ... @@ -9,7 +12,7 @@ class CommentParagraphPlugin::API &lt; Grape::API
9 12 comments = comments.without_spam
10 13 comments = comments.in_paragraph(params[:paragraph_uuid])
11 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 16 end
14 17  
15 18 {activate: true, deactivate: false}.each do |method, value|
... ... @@ -19,7 +22,7 @@ class CommentParagraphPlugin::API &lt; Grape::API
19 22 return forbidden! unless article.comment_paragraph_plugin_enabled? && article.allow_edit?(current_person)
20 23 article.comment_paragraph_plugin_activate = value
21 24 article.save!
22   - present_partial article, :with => Noosfero::API::Entities::Article
  25 + present_partial article, :with => Api::Entities::Article
23 26 end
24 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 9 end
11 10 end
12 11 end
... ...