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