Commit 8e288dc4ba346546c091b64d6f8596b1a87384e6
1 parent
4add5179
Exists in
theme-brasil-digital-from-staging
and in
9 other branches
Added swagger-ui support to Grape API documentation and request runner
Showing
8 changed files
with
130 additions
and
10 deletions
Show diff stats
Gemfile
@@ -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' |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +<%= render 'swagger_ui/swagger_ui', discovery_url: '/api/v1/api_docs' %> |
@@ -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) |