Commit b6cb1220fd6285ac15dcebcea16a13daa6ad3dbb
Exists in
ratings_minor_fixes
and in
4 other branches
Merge branch 'api-blocks' into 'master'
Api endpoint for blocks See merge request !913
Showing
13 changed files
with
254 additions
and
0 deletions
Show diff stats
app/models/block.rb
| @@ -76,6 +76,17 @@ class Block < ApplicationRecord | @@ -76,6 +76,17 @@ class Block < ApplicationRecord | ||
| 76 | true | 76 | true |
| 77 | end | 77 | end |
| 78 | 78 | ||
| 79 | + def visible_to_user?(user) | ||
| 80 | + visible = self.display_to_user?(user) | ||
| 81 | + if self.owner.kind_of?(Profile) | ||
| 82 | + visible &= self.owner.display_info_to?(user) | ||
| 83 | + visible &= (self.visible? || user && user.has_permission?(:edit_profile_design, self.owner)) | ||
| 84 | + elsif self.owner.kind_of?(Environment) | ||
| 85 | + visible &= (self.visible? || user && user.has_permission?(:edit_environment_design, self.owner)) | ||
| 86 | + end | ||
| 87 | + visible | ||
| 88 | + end | ||
| 89 | + | ||
| 79 | def display_to_user?(user) | 90 | def display_to_user?(user) |
| 80 | display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && user.follows?(owner)) | 91 | display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && user.follows?(owner)) |
| 81 | end | 92 | end |
| @@ -314,6 +325,14 @@ class Block < ApplicationRecord | @@ -314,6 +325,14 @@ class Block < ApplicationRecord | ||
| 314 | self.observers << block | 325 | self.observers << block |
| 315 | end | 326 | end |
| 316 | 327 | ||
| 328 | + def api_content | ||
| 329 | + nil | ||
| 330 | + end | ||
| 331 | + | ||
| 332 | + def display_api_content_by_default? | ||
| 333 | + false | ||
| 334 | + end | ||
| 335 | + | ||
| 317 | private | 336 | private |
| 318 | 337 | ||
| 319 | def home_page_path | 338 | def home_page_path |
app/models/raw_html_block.rb
| @@ -20,4 +20,12 @@ class RawHTMLBlock < Block | @@ -20,4 +20,12 @@ class RawHTMLBlock < Block | ||
| 20 | user.has_permission?('edit_raw_html_block', environment) | 20 | user.has_permission?('edit_raw_html_block', environment) |
| 21 | end | 21 | end |
| 22 | 22 | ||
| 23 | + def api_content | ||
| 24 | + { html: html } | ||
| 25 | + end | ||
| 26 | + | ||
| 27 | + def display_api_content_by_default? | ||
| 28 | + true | ||
| 29 | + end | ||
| 30 | + | ||
| 23 | end | 31 | end |
app/models/recent_documents_block.rb
| @@ -29,4 +29,12 @@ class RecentDocumentsBlock < Block | @@ -29,4 +29,12 @@ class RecentDocumentsBlock < Block | ||
| 29 | def self.expire_on | 29 | def self.expire_on |
| 30 | { :profile => [:article], :environment => [:article] } | 30 | { :profile => [:article], :environment => [:article] } |
| 31 | end | 31 | end |
| 32 | + | ||
| 33 | + def api_content | ||
| 34 | + Noosfero::API::Entities::ArticleBase.represent(docs).as_json | ||
| 35 | + end | ||
| 36 | + | ||
| 37 | + def display_api_content_by_default? | ||
| 38 | + false | ||
| 39 | + end | ||
| 32 | end | 40 | end |
lib/noosfero/api/api.rb
| @@ -53,6 +53,7 @@ module Noosfero | @@ -53,6 +53,7 @@ module Noosfero | ||
| 53 | mount V1::Search | 53 | mount V1::Search |
| 54 | mount V1::Contacts | 54 | mount V1::Contacts |
| 55 | mount V1::Boxes | 55 | mount V1::Boxes |
| 56 | + mount V1::Blocks | ||
| 56 | mount V1::Profiles | 57 | mount V1::Profiles |
| 57 | mount V1::Activities | 58 | mount V1::Activities |
| 58 | 59 |
lib/noosfero/api/entities.rb
| @@ -88,6 +88,7 @@ module Noosfero | @@ -88,6 +88,7 @@ module Noosfero | ||
| 88 | root 'blocks', 'block' | 88 | root 'blocks', 'block' |
| 89 | expose :id, :type, :settings, :position, :enabled | 89 | expose :id, :type, :settings, :position, :enabled |
| 90 | expose :mirror, :mirror_block_id, :title | 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? } | ||
| 91 | end | 92 | end |
| 92 | 93 | ||
| 93 | class Box < Entity | 94 | class Box < Entity |
| @@ -0,0 +1,17 @@ | @@ -0,0 +1,17 @@ | ||
| 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 |
plugins/recent_content/lib/recent_content_block.rb
| @@ -48,4 +48,12 @@ class RecentContentBlock < Block | @@ -48,4 +48,12 @@ class RecentContentBlock < Block | ||
| 48 | attr == self.presentation_mode | 48 | attr == self.presentation_mode |
| 49 | end | 49 | end |
| 50 | 50 | ||
| 51 | + def api_content | ||
| 52 | + children = self.articles_of_folder(self.root, self.total_items) | ||
| 53 | + Noosfero::API::Entities::ArticleBase.represent(children).as_json | ||
| 54 | + end | ||
| 55 | + | ||
| 56 | + def display_api_content_by_default? | ||
| 57 | + false | ||
| 58 | + end | ||
| 51 | end | 59 | end |
plugins/recent_content/test/unit/recent_content_block_test.rb
| @@ -142,4 +142,18 @@ class RecentContentBlockViewTest < ActionView::TestCase | @@ -142,4 +142,18 @@ class RecentContentBlockViewTest < ActionView::TestCase | ||
| 142 | 142 | ||
| 143 | assert_match /Block Title/, content | 143 | assert_match /Block Title/, content |
| 144 | end | 144 | end |
| 145 | + | ||
| 146 | + should 'return articles in api_content' do | ||
| 147 | + profile = create_user('testuser').person | ||
| 148 | + | ||
| 149 | + root = fast_create(Blog, name: 'test-blog', profile_id: profile.id) | ||
| 150 | + article = fast_create(TextArticle, parent_id: root.id, profile_id: profile.id) | ||
| 151 | + | ||
| 152 | + block = RecentContentBlock.new | ||
| 153 | + block.stubs(:holder).returns(profile) | ||
| 154 | + block.selected_folder = root.id | ||
| 155 | + block.presentation_mode = '' | ||
| 156 | + assert_equal [article.id], block.api_content['articles'].map {|a| a[:id]} | ||
| 157 | + end | ||
| 158 | + | ||
| 145 | end | 159 | end |
| @@ -0,0 +1,97 @@ | @@ -0,0 +1,97 @@ | ||
| 1 | +require_relative 'test_helper' | ||
| 2 | + | ||
| 3 | +class BlocksTest < ActiveSupport::TestCase | ||
| 4 | + | ||
| 5 | + def setup | ||
| 6 | + create_and_activate_user | ||
| 7 | + login_api | ||
| 8 | + @environment = Environment.default | ||
| 9 | + @profile = fast_create(Profile) | ||
| 10 | + end | ||
| 11 | + | ||
| 12 | + attr_accessor :environment, :profile | ||
| 13 | + | ||
| 14 | + should 'get an environment block' do | ||
| 15 | + box = fast_create(Box, :owner_id => environment.id, :owner_type => Environment.name) | ||
| 16 | + block = fast_create(Block, box_id: box.id) | ||
| 17 | + get "/api/v1/blocks/#{block.id}?#{params.to_query}" | ||
| 18 | + json = JSON.parse(last_response.body) | ||
| 19 | + assert_equal block.id, json["block"]["id"] | ||
| 20 | + end | ||
| 21 | + | ||
| 22 | + should 'get a profile block' do | ||
| 23 | + box = fast_create(Box, :owner_id => profile.id, :owner_type => Profile.name) | ||
| 24 | + block = fast_create(Block, box_id: box.id) | ||
| 25 | + get "/api/v1/blocks/#{block.id}?#{params.to_query}" | ||
| 26 | + json = JSON.parse(last_response.body) | ||
| 27 | + assert_equal block.id, json["block"]["id"] | ||
| 28 | + end | ||
| 29 | + | ||
| 30 | + should 'get a profile block for a not logged in user' do | ||
| 31 | + logout_api | ||
| 32 | + box = fast_create(Box, :owner_id => profile.id, :owner_type => Profile.name) | ||
| 33 | + block = fast_create(Block, box_id: box.id) | ||
| 34 | + get "/api/v1/blocks/#{block.id}?#{params.to_query}" | ||
| 35 | + json = JSON.parse(last_response.body) | ||
| 36 | + assert_equal block.id, json["block"]["id"] | ||
| 37 | + end | ||
| 38 | + | ||
| 39 | + should 'not get a profile block for a not logged in user' do | ||
| 40 | + logout_api | ||
| 41 | + profile = fast_create(Profile, public_profile: false) | ||
| 42 | + box = fast_create(Box, :owner_id => profile.id, :owner_type => Profile.name) | ||
| 43 | + block = fast_create(Block, box_id: box.id) | ||
| 44 | + get "/api/v1/blocks/#{block.id}?#{params.to_query}" | ||
| 45 | + assert_equal 403, last_response.status | ||
| 46 | + end | ||
| 47 | + | ||
| 48 | + should 'not get a profile block for an user without permission' do | ||
| 49 | + profile = fast_create(Profile, public_profile: false) | ||
| 50 | + box = fast_create(Box, :owner_id => profile.id, :owner_type => Profile.name) | ||
| 51 | + block = fast_create(Block, box_id: box.id) | ||
| 52 | + get "/api/v1/blocks/#{block.id}?#{params.to_query}" | ||
| 53 | + assert_equal 403, last_response.status | ||
| 54 | + end | ||
| 55 | + | ||
| 56 | + should 'get a block for an user with permission in a private profile' do | ||
| 57 | + profile = fast_create(Profile, public_profile: false) | ||
| 58 | + profile.add_admin(person) | ||
| 59 | + box = fast_create(Box, :owner_id => profile.id, :owner_type => Profile.name) | ||
| 60 | + block = fast_create(Block, box_id: box.id) | ||
| 61 | + get "/api/v1/blocks/#{block.id}?#{params.to_query}" | ||
| 62 | + json = JSON.parse(last_response.body) | ||
| 63 | + assert_equal block.id, json["block"]["id"] | ||
| 64 | + end | ||
| 65 | + | ||
| 66 | + should 'display api content by default' do | ||
| 67 | + box = fast_create(Box, :owner_id => environment.id, :owner_type => Environment.name) | ||
| 68 | + block = fast_create(Block, box_id: box.id) | ||
| 69 | + get "/api/v1/blocks/#{block.id}?#{params.to_query}" | ||
| 70 | + json = JSON.parse(last_response.body) | ||
| 71 | + assert json["block"].key?('api_content') | ||
| 72 | + end | ||
| 73 | + | ||
| 74 | + should 'display api content of a specific block' do | ||
| 75 | + class SomeBlock < Block | ||
| 76 | + def api_content | ||
| 77 | + {some_content: { name: 'test'} } | ||
| 78 | + end | ||
| 79 | + end | ||
| 80 | + box = fast_create(Box, :owner_id => environment.id, :owner_type => Environment.name) | ||
| 81 | + block = fast_create(SomeBlock, box_id: box.id) | ||
| 82 | + get "/api/v1/blocks/#{block.id}?#{params.to_query}" | ||
| 83 | + json = JSON.parse(last_response.body) | ||
| 84 | + assert_equal "test", json["block"]["api_content"]["some_content"]["name"] | ||
| 85 | + end | ||
| 86 | + | ||
| 87 | + should 'display api content of raw html block' do | ||
| 88 | + box = fast_create(Box, :owner_id => environment.id, :owner_type => Environment.name) | ||
| 89 | + block = fast_create(RawHTMLBlock, box_id: box.id) | ||
| 90 | + block.html = '<div>test</div>' | ||
| 91 | + block.save! | ||
| 92 | + get "/api/v1/blocks/#{block.id}?#{params.to_query}" | ||
| 93 | + json = JSON.parse(last_response.body) | ||
| 94 | + assert_equal "<div>test</div>", json["block"]["api_content"]["html"] | ||
| 95 | + end | ||
| 96 | + | ||
| 97 | +end |
test/api/boxes_test.rb
| @@ -38,4 +38,13 @@ class BoxesTest < ActiveSupport::TestCase | @@ -38,4 +38,13 @@ class BoxesTest < ActiveSupport::TestCase | ||
| 38 | assert_equal box.id, json["boxes"].first["id"] | 38 | assert_equal box.id, json["boxes"].first["id"] |
| 39 | end | 39 | end |
| 40 | 40 | ||
| 41 | + should 'not display block api_content by default' do | ||
| 42 | + Environment.delete_all | ||
| 43 | + environment = fast_create(Environment, :is_default => true) | ||
| 44 | + box = fast_create(Box, :owner_id => environment.id, :owner_type => 'Environment') | ||
| 45 | + block = fast_create(Block, box_id: box.id) | ||
| 46 | + get "/api/v1/environments/default/boxes?#{params.to_query}" | ||
| 47 | + json = JSON.parse(last_response.body) | ||
| 48 | + assert !json["boxes"].first["blocks"].first.key?('api_content') | ||
| 49 | + end | ||
| 41 | end | 50 | end |
test/api/test_helper.rb
| @@ -31,6 +31,10 @@ class ActiveSupport::TestCase | @@ -31,6 +31,10 @@ class ActiveSupport::TestCase | ||
| 31 | @params[:private_token] = @private_token | 31 | @params[:private_token] = @private_token |
| 32 | end | 32 | end |
| 33 | 33 | ||
| 34 | + def logout_api | ||
| 35 | + @params.delete(:private_token) | ||
| 36 | + end | ||
| 37 | + | ||
| 34 | attr_accessor :private_token, :user, :person, :params, :environment | 38 | attr_accessor :private_token, :user, :person, :params, :environment |
| 35 | 39 | ||
| 36 | private | 40 | private |
test/unit/block_test.rb
| @@ -365,4 +365,64 @@ class BlockTest < ActiveSupport::TestCase | @@ -365,4 +365,64 @@ class BlockTest < ActiveSupport::TestCase | ||
| 365 | assert block.get_limit.is_a?(Fixnum) | 365 | assert block.get_limit.is_a?(Fixnum) |
| 366 | end | 366 | end |
| 367 | 367 | ||
| 368 | + should 'return true at visible_to_user? when block is visible' do | ||
| 369 | + block = Block.new | ||
| 370 | + person = create_user('person_one').person | ||
| 371 | + assert block.visible_to_user?(person) | ||
| 372 | + end | ||
| 373 | + | ||
| 374 | + should 'return false at visible_to_user? when block is not visible and user is nil' do | ||
| 375 | + block = Block.new | ||
| 376 | + person = create_user('person_one').person | ||
| 377 | + block.stubs(:owner).returns(person) | ||
| 378 | + block.expects(:visible?).returns(false) | ||
| 379 | + assert !block.visible_to_user?(nil) | ||
| 380 | + end | ||
| 381 | + | ||
| 382 | + should 'return false at visible_to_user? when block is not visible and user does not has permission' do | ||
| 383 | + block = Block.new | ||
| 384 | + person = create_user('person_one').person | ||
| 385 | + community = fast_create(Community) | ||
| 386 | + block.stubs(:owner).returns(community) | ||
| 387 | + block.expects(:visible?).returns(false) | ||
| 388 | + assert !block.visible_to_user?(person) | ||
| 389 | + end | ||
| 390 | + | ||
| 391 | + should 'return true at visible_to_user? when block is not visible and user has permission' do | ||
| 392 | + block = Block.new | ||
| 393 | + person = create_user('person_one').person | ||
| 394 | + community = fast_create(Community) | ||
| 395 | + give_permission(person, 'edit_profile_design', community) | ||
| 396 | + block.stubs(:owner).returns(community) | ||
| 397 | + block.expects(:visible?).returns(false) | ||
| 398 | + assert block.visible_to_user?(person) | ||
| 399 | + end | ||
| 400 | + | ||
| 401 | + should 'return false at visible_to_user? when block is not visible and user does not has permission in environment' do | ||
| 402 | + block = Block.new | ||
| 403 | + environment = Environment.default | ||
| 404 | + person = create_user('person_one').person | ||
| 405 | + block.stubs(:owner).returns(environment) | ||
| 406 | + block.expects(:visible?).returns(false) | ||
| 407 | + assert !block.visible_to_user?(person) | ||
| 408 | + end | ||
| 409 | + | ||
| 410 | + should 'return true at visible_to_user? when block is not visible and user has permission in environment' do | ||
| 411 | + block = Block.new | ||
| 412 | + environment = Environment.default | ||
| 413 | + person = create_user('person_one').person | ||
| 414 | + give_permission(person, 'edit_environment_design', environment) | ||
| 415 | + block.stubs(:owner).returns(environment) | ||
| 416 | + block.expects(:visible?).returns(false) | ||
| 417 | + assert block.visible_to_user?(person) | ||
| 418 | + end | ||
| 419 | + | ||
| 420 | + should 'return false at visible_to_user? when block is not visible to user' do | ||
| 421 | + block = Block.new | ||
| 422 | + person = create_user('person_one').person | ||
| 423 | + block.stubs(:owner).returns(person) | ||
| 424 | + block.expects(:visible?).returns(true) | ||
| 425 | + block.expects(:display_to_user?).returns(false) | ||
| 426 | + assert !block.visible_to_user?(nil) | ||
| 427 | + end | ||
| 368 | end | 428 | end |
test/unit/recent_documents_block_test.rb
| @@ -128,4 +128,12 @@ class RecentDocumentsBlockViewTest < ActionView::TestCase | @@ -128,4 +128,12 @@ class RecentDocumentsBlockViewTest < ActionView::TestCase | ||
| 128 | box.expects(:owner).returns(Environment.new).at_least_once | 128 | box.expects(:owner).returns(Environment.new).at_least_once |
| 129 | assert_equal '', render_block_footer(block) | 129 | assert_equal '', render_block_footer(block) |
| 130 | end | 130 | end |
| 131 | + | ||
| 132 | + should 'return articles in api_content' do | ||
| 133 | + profile = fast_create(Profile) | ||
| 134 | + article = fast_create(TextArticle, profile_id: profile.id) | ||
| 135 | + block = RecentDocumentsBlock.new | ||
| 136 | + block.stubs(:owner).returns(profile) | ||
| 137 | + assert_equal [article.id], block.api_content['articles'].map {|a| a[:id]} | ||
| 138 | + end | ||
| 131 | end | 139 | end |