Commit 8e288dc4ba346546c091b64d6f8596b1a87384e6

Authored by Michel Felipe
1 parent 4add5179

Added swagger-ui support to Grape API documentation and request runner

@@ -23,6 +23,10 @@ gem 'eita-jrails', '~> 0.9.5', require: 'jrails' @@ -23,6 +23,10 @@ gem 'eita-jrails', '~> 0.9.5', require: 'jrails'
23 # API dependencies 23 # API dependencies
24 gem 'grape', '~> 0.12' 24 gem 'grape', '~> 0.12'
25 gem 'grape-entity' 25 gem 'grape-entity'
  26 +gem 'grape-swagger'
  27 +gem 'swagger-ui_rails'
  28 +gem 'kramdown'
  29 +
26 #FIXME Get the Grape Loggin from master yo solve this issue https://github.com/intridea/grape/issues/1059 30 #FIXME Get the Grape Loggin from master yo solve this issue https://github.com/intridea/grape/issues/1059
27 #We have to remove this commit referenve code when update the next release of grape_logging. Actualy we are using (1.1.2) 31 #We have to remove this commit referenve code when update the next release of grape_logging. Actualy we are using (1.1.2)
28 gem 'grape_logging', :git => 'https://github.com/aceunreal/grape_logging.git', :ref => 'f1755ae' 32 gem 'grape_logging', :git => 'https://github.com/aceunreal/grape_logging.git', :ref => 'f1755ae'
app/controllers/api_docs_controller.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +class ApiDocsController < ApplicationController
  2 + layout :api_layout
  3 +
  4 + private
  5 + def api_layout
  6 + params[:controller]
  7 + end
  8 +end
app/views/api_docs/index.html.erb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= render 'swagger_ui/swagger_ui', discovery_url: '/api/v1/api_docs' %>
app/views/layouts/api_docs.html.erb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +<!DOCTYPE html>
  2 +<html>
  3 + <head>
  4 + <meta charset="utf-8">
  5 + <title></title>
  6 + <%= stylesheet_link_tag 'swagger-ui' %>
  7 + <%= javascript_include_tag 'swagger-ui' %>
  8 + </head>
  9 + <body>
  10 + <div id="content">
  11 + <%= yield %>
  12 + </div>
  13 + </body>
  14 +</html>
config/routes.rb
@@ -23,6 +23,7 @@ Noosfero::Application.routes.draw do @@ -23,6 +23,7 @@ Noosfero::Application.routes.draw do
23 23
24 match 'site(/:action)', :controller => 'home' 24 match 'site(/:action)', :controller => 'home'
25 match 'api(/:action)', :controller => 'api' 25 match 'api(/:action)', :controller => 'api'
  26 + match 'api_docs(/:action)', :controller => 'api_docs'
26 27
27 match 'images(/*stuff)' => 'not_found#nothing' 28 match 'images(/*stuff)' => 'not_found#nothing'
28 match 'stylesheets(/*stuff)' => 'not_found#nothing' 29 match 'stylesheets(/*stuff)' => 'not_found#nothing'
lib/noosfero/api/api.rb
@@ -52,6 +52,8 @@ module Noosfero @@ -52,6 +52,8 @@ module Noosfero
52 52
53 mount Session 53 mount Session
54 54
  55 + add_swagger_documentation api_version: 'v1', mount_path: '/api_docs', markdown: GrapeSwagger::Markdown::KramdownAdapter unless Rails.env.production?
  56 +
55 # hook point which allow plugins to add Grape::API extensions to API::API 57 # hook point which allow plugins to add Grape::API extensions to API::API
56 #finds for plugins which has api mount points classes defined (the class should extends Grape::API) 58 #finds for plugins which has api mount points classes defined (the class should extends Grape::API)
57 @plugins = Noosfero::Plugin.all.map { |p| p.constantize } 59 @plugins = Noosfero::Plugin.all.map { |p| p.constantize }
lib/noosfero/api/entities.rb
@@ -43,7 +43,7 @@ module Noosfero @@ -43,7 +43,7 @@ module Noosfero
43 43
44 class Person < Profile 44 class Person < Profile
45 root 'people', 'person' 45 root 'people', 'person'
46 - expose :user, :using => UserBasic 46 + expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' }
47 end 47 end
48 48
49 class Enterprise < Profile 49 class Enterprise < Profile
@@ -74,11 +74,11 @@ module Noosfero @@ -74,11 +74,11 @@ module Noosfero
74 root 'articles', 'article' 74 root 'articles', 'article'
75 expose :id 75 expose :id
76 expose :body 76 expose :body
77 - expose :abstract 77 + expose :abstract, documentation: {type: 'String', desc: 'Teaser of the body'}
78 expose :created_at, :format_with => :timestamp 78 expose :created_at, :format_with => :timestamp
79 expose :title, :documentation => {:type => "String", :desc => "Title of the article"} 79 expose :title, :documentation => {:type => "String", :desc => "Title of the article"}
80 - expose :created_by, :as => :author, :using => Profile  
81 - expose :profile, :using => Profile 80 + expose :created_by, :as => :author, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile author that create the article'}
  81 + expose :profile, :using => Profile, :documentation => {type: 'Profile', desc: 'The profile associated with the article'}
82 expose :categories, :using => Category 82 expose :categories, :using => Category
83 expose :image, :using => Image 83 expose :image, :using => Image
84 #TODO Apply vote stuff in core and make this test 84 #TODO Apply vote stuff in core and make this test
@@ -88,7 +88,7 @@ module Noosfero @@ -88,7 +88,7 @@ module Noosfero
88 expose :position 88 expose :position
89 expose :hits 89 expose :hits
90 expose :start_date 90 expose :start_date
91 - expose :end_date 91 + expose :end_date, :documentation => {type: 'DateTime', desc: 'The date of finish of the article'}
92 expose :tag_list 92 expose :tag_list
93 end 93 end
94 94
@@ -98,6 +98,7 @@ module Noosfero @@ -98,6 +98,7 @@ module Noosfero
98 expose :children, using: ArticleBase do |article, options| 98 expose :children, using: ArticleBase do |article, options|
99 article.children.limit(Noosfero::API::V1::Articles::MAX_PER_PAGE) 99 article.children.limit(Noosfero::API::V1::Articles::MAX_PER_PAGE)
100 end 100 end
  101 + expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"}
101 end 102 end
102 103
103 class Comment < Entity 104 class Comment < Entity
@@ -127,7 +128,7 @@ module Noosfero @@ -127,7 +128,7 @@ module Noosfero
127 end 128 end
128 129
129 class UserLogin < User 130 class UserLogin < User
130 - expose :private_token 131 + expose :private_token, documentation: {type: 'String', desc: 'A valid authentication code for post/delete api actions'}
131 end 132 end
132 133
133 class Task < Entity 134 class Task < Entity
lib/noosfero/api/v1/articles.rb
@@ -21,15 +21,40 @@ module Noosfero @@ -21,15 +21,40 @@ module Noosfero
21 # Example Request: 21 # Example Request:
22 # 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 # GET host/api/v1/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317
23 23
  24 + desc 'Return all articles of all kinds' do
  25 + detail 'Get all articles filtered by fields in query params'
  26 + params Noosfero::API::Entities::Article.documentation
  27 + success Noosfero::API::Entities::Article
  28 + failure [[403, 'Forbidden']]
  29 + named 'ArticlesList'
  30 + headers [
  31 + 'Per-Page' => {
  32 + description: 'Total number of records',
  33 + required: false
  34 + }
  35 + ]
  36 + end
24 get do 37 get do
25 present_articles(environment) 38 present_articles(environment)
26 end 39 end
27 40
28 - desc "Return the article id" 41 + desc "Return one article by id" do
  42 + detail 'Get only one article by id. If not found the "forbidden" http error is showed'
  43 + params Noosfero::API::Entities::Article.documentation
  44 + success Noosfero::API::Entities::Article
  45 + failure [[403, 'Forbidden']]
  46 + named 'ArticleById'
  47 + end
29 get ':id', requirements: {id: /[0-9]+/} do 48 get ':id', requirements: {id: /[0-9]+/} do
30 present_article(environment) 49 present_article(environment)
31 end 50 end
32 - 51 +
  52 + desc 'Report a abuse and/or violent content in a article by id' do
  53 + detail 'Submit a abuse (in general, a content violation) report about a specific article'
  54 + params Noosfero::API::Entities::Article.documentation
  55 + failure [[400, 'Bad Request']]
  56 + named 'ArticleReportAbuse'
  57 + end
33 post ':id/report_abuse' do 58 post ':id/report_abuse' do
34 article = find_article(environment.articles, params[:id]) 59 article = find_article(environment.articles, params[:id])
35 profile = article.profile 60 profile = article.profile
@@ -58,14 +83,23 @@ module Noosfero @@ -58,14 +83,23 @@ module Noosfero
58 83
59 end 84 end
60 85
61 - desc "Returns the total followers for the article" 86 + desc "Returns the total followers for the article" do
  87 + detail 'Get the followers of a specific article by id'
  88 + failure [[403, 'Forbidden']]
  89 + named 'ArticleFollowers'
  90 + end
62 get ':id/followers' do 91 get ':id/followers' do
63 article = find_article(environment.articles, params[:id]) 92 article = find_article(environment.articles, params[:id])
64 total = article.person_followers.count 93 total = article.person_followers.count
65 {:total_followers => total} 94 {:total_followers => total}
66 end 95 end
67 96
68 - desc "Add a follower for the article" 97 + desc "Add a follower for the article" do
  98 + detail 'Add the current user identified by private token, like a follower of a article'
  99 + params Noosfero::API::Entities::UserLogin.documentation
  100 + failure [[401, 'Unauthorized']]
  101 + named 'ArticleFollow'
  102 + end
69 post ':id/follow' do 103 post ':id/follow' do
70 authenticate! 104 authenticate!
71 article = find_article(environment.articles, params[:id]) 105 article = find_article(environment.articles, params[:id])
@@ -80,6 +114,12 @@ module Noosfero @@ -80,6 +114,12 @@ module Noosfero
80 end 114 end
81 end 115 end
82 116
  117 + desc 'Perform a vote on a article by id' do
  118 + detail 'Vote on a specific article with values: 1 (if you like) or -1 (if not)'
  119 + params Noosfero::API::Entities::UserLogin.documentation
  120 + failure [[401,'Unauthorized']]
  121 + named 'ArticleVote'
  122 + end
83 post ':id/vote' do 123 post ':id/vote' do
84 authenticate! 124 authenticate!
85 value = (params[:value] || 1).to_i 125 value = (params[:value] || 1).to_i
@@ -90,6 +130,12 @@ module Noosfero @@ -90,6 +130,12 @@ module Noosfero
90 {:vote => vote.save} 130 {:vote => vote.save}
91 end 131 end
92 132
  133 + desc 'Return the children of a article identified by id' do
  134 + detail 'Get all children articles of a specific article'
  135 + params Noosfero::API::Entities::Article.documentation
  136 + failure [[403, 'Forbidden']]
  137 + named 'ArticleChildren'
  138 + end
93 get ':id/children' do 139 get ':id/children' do
94 article = find_article(environment.articles, params[:id]) 140 article = find_article(environment.articles, params[:id])
95 141
@@ -108,6 +154,13 @@ module Noosfero @@ -108,6 +154,13 @@ module Noosfero
108 present articles, :with => Entities::Article, :fields => params[:fields] 154 present articles, :with => Entities::Article, :fields => params[:fields]
109 end 155 end
110 156
  157 + desc 'Return one child of a article identified by id' do
  158 + detail 'Get a child of a specific article'
  159 + params Noosfero::API::Entities::Article.documentation
  160 + success Noosfero::API::Entities::Article
  161 + failure [[403, 'Forbidden']]
  162 + named 'ArticleChild'
  163 + end
111 get ':id/children/:child_id' do 164 get ':id/children/:child_id' do
112 article = find_article(environment.articles, params[:id]) 165 article = find_article(environment.articles, params[:id])
113 child = find_article(article.children, params[:child_id]) 166 child = find_article(article.children, params[:child_id])
@@ -115,6 +168,13 @@ module Noosfero @@ -115,6 +168,13 @@ module Noosfero
115 present child, :with => Entities::Article, :fields => params[:fields] 168 present child, :with => Entities::Article, :fields => params[:fields]
116 end 169 end
117 170
  171 + desc 'Suggest a article to another profile' do
  172 + detail 'Suggest a article to another profile (person, community...)'
  173 + params Noosfero::API::Entities::Article.documentation
  174 + success Noosfero::API::Entities::Task
  175 + failure [[401,'Unauthorized']]
  176 + named 'ArticleSuggest'
  177 + end
118 post ':id/children/suggest' do 178 post ':id/children/suggest' do
119 authenticate! 179 authenticate!
120 parent_article = environment.articles.find(params[:id]) 180 parent_article = environment.articles.find(params[:id])
@@ -133,6 +193,13 @@ module Noosfero @@ -133,6 +193,13 @@ module Noosfero
133 193
134 # Example Request: 194 # Example Request:
135 # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body 195 # POST api/v1/articles/:id/children?private_token=234298743290432&article[name]=title&article[body]=body
  196 + desc 'Add a child article to a parent identified by id' do
  197 + detail 'Create a new article and associate to a parent'
  198 + params Noosfero::API::Entities::Article.documentation
  199 + success Noosfero::API::Entities::Article
  200 + failure [[401,'Unauthorized']]
  201 + named 'ArticleAddChild'
  202 + end
136 post ':id/children' do 203 post ':id/children' do
137 authenticate! 204 authenticate!
138 parent_article = environment.articles.find(params[:id]) 205 parent_article = environment.articles.find(params[:id])
@@ -162,6 +229,14 @@ module Noosfero @@ -162,6 +229,14 @@ module Noosfero
162 resource kind.pluralize.to_sym do 229 resource kind.pluralize.to_sym do
163 segment "/:#{kind}_id" do 230 segment "/:#{kind}_id" do
164 resource :articles do 231 resource :articles do
  232 +
  233 + desc "Return all articles associate with a profile of type #{kind}" do
  234 + detail 'Get a list of articles of a profile'
  235 + params Noosfero::API::Entities::Article.documentation
  236 + success Noosfero::API::Entities::Article
  237 + failure [[403, 'Forbidden']]
  238 + named 'ArticlesOfProfile'
  239 + end
165 get do 240 get do
166 profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) 241 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
167 242
@@ -178,6 +253,13 @@ module Noosfero @@ -178,6 +253,13 @@ module Noosfero
178 end 253 end
179 end 254 end
180 255
  256 + desc "Return a article associate with a profile of type #{kind}" do
  257 + detail 'Get only one article of a profile'
  258 + params Noosfero::API::Entities::Article.documentation
  259 + success Noosfero::API::Entities::Article
  260 + failure [[403, 'Forbidden']]
  261 + named 'ArticleOfProfile'
  262 + end
181 get ':id' do 263 get ':id' do
182 profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) 264 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
183 present_article(profile) 265 present_article(profile)
@@ -185,6 +267,13 @@ module Noosfero @@ -185,6 +267,13 @@ module Noosfero
185 267
186 # Example Request: 268 # Example Request:
187 # POST api/v1/{people,communities,enterprises}/:asset_id/articles?private_token=234298743290432&article[name]=title&article[body]=body 269 # POST api/v1/{people,communities,enterprises}/:asset_id/articles?private_token=234298743290432&article[name]=title&article[body]=body
  270 + desc "Add a new article associated with a profile of type #{kind}" do
  271 + detail 'Create a new article and associate with a profile'
  272 + params Noosfero::API::Entities::Article.documentation
  273 + success Noosfero::API::Entities::Article
  274 + failure [[403, 'Forbidden']]
  275 + named 'ArticleCreateToProfile'
  276 + end
188 post do 277 post do
189 profile = environment.send(kind.pluralize).find(params["#{kind}_id"]) 278 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
190 post_article(profile, params) 279 post_article(profile, params)