Commit 8e288dc4ba346546c091b64d6f8596b1a87384e6

Authored by Michel Felipe
1 parent 4add5179

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

Gemfile
... ... @@ -23,6 +23,10 @@ gem 'eita-jrails', '~> 0.9.5', require: 'jrails'
23 23 # API dependencies
24 24 gem 'grape', '~> 0.12'
25 25 gem 'grape-entity'
  26 +gem 'grape-swagger'
  27 +gem 'swagger-ui_rails'
  28 +gem 'kramdown'
  29 +
26 30 #FIXME Get the Grape Loggin from master yo solve this issue https://github.com/intridea/grape/issues/1059
27 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 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 @@
  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 @@
  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 @@
  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 23  
24 24 match 'site(/:action)', :controller => 'home'
25 25 match 'api(/:action)', :controller => 'api'
  26 + match 'api_docs(/:action)', :controller => 'api_docs'
26 27  
27 28 match 'images(/*stuff)' => 'not_found#nothing'
28 29 match 'stylesheets(/*stuff)' => 'not_found#nothing'
... ...
lib/noosfero/api/api.rb
... ... @@ -52,6 +52,8 @@ module Noosfero
52 52  
53 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 57 # hook point which allow plugins to add Grape::API extensions to API::API
56 58 #finds for plugins which has api mount points classes defined (the class should extends Grape::API)
57 59 @plugins = Noosfero::Plugin.all.map { |p| p.constantize }
... ...
lib/noosfero/api/entities.rb
... ... @@ -43,7 +43,7 @@ module Noosfero
43 43  
44 44 class Person < Profile
45 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 47 end
48 48  
49 49 class Enterprise < Profile
... ... @@ -74,11 +74,11 @@ module Noosfero
74 74 root 'articles', 'article'
75 75 expose :id
76 76 expose :body
77   - expose :abstract
  77 + expose :abstract, documentation: {type: 'String', desc: 'Teaser of the body'}
78 78 expose :created_at, :format_with => :timestamp
79 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 82 expose :categories, :using => Category
83 83 expose :image, :using => Image
84 84 #TODO Apply vote stuff in core and make this test
... ... @@ -88,7 +88,7 @@ module Noosfero
88 88 expose :position
89 89 expose :hits
90 90 expose :start_date
91   - expose :end_date
  91 + expose :end_date, :documentation => {type: 'DateTime', desc: 'The date of finish of the article'}
92 92 expose :tag_list
93 93 end
94 94  
... ... @@ -98,6 +98,7 @@ module Noosfero
98 98 expose :children, using: ArticleBase do |article, options|
99 99 article.children.limit(Noosfero::API::V1::Articles::MAX_PER_PAGE)
100 100 end
  101 + expose :slug, :documentation => {:type => "String", :desc => "Trimmed and parsed name of a article"}
101 102 end
102 103  
103 104 class Comment < Entity
... ... @@ -127,7 +128,7 @@ module Noosfero
127 128 end
128 129  
129 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 132 end
132 133  
133 134 class Task < Entity
... ...
lib/noosfero/api/v1/articles.rb
... ... @@ -21,15 +21,40 @@ module Noosfero
21 21 # Example Request:
22 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 37 get do
25 38 present_articles(environment)
26 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 48 get ':id', requirements: {id: /[0-9]+/} do
30 49 present_article(environment)
31 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 58 post ':id/report_abuse' do
34 59 article = find_article(environment.articles, params[:id])
35 60 profile = article.profile
... ... @@ -58,14 +83,23 @@ module Noosfero
58 83  
59 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 91 get ':id/followers' do
63 92 article = find_article(environment.articles, params[:id])
64 93 total = article.person_followers.count
65 94 {:total_followers => total}
66 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 103 post ':id/follow' do
70 104 authenticate!
71 105 article = find_article(environment.articles, params[:id])
... ... @@ -80,6 +114,12 @@ module Noosfero
80 114 end
81 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 123 post ':id/vote' do
84 124 authenticate!
85 125 value = (params[:value] || 1).to_i
... ... @@ -90,6 +130,12 @@ module Noosfero
90 130 {:vote => vote.save}
91 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 139 get ':id/children' do
94 140 article = find_article(environment.articles, params[:id])
95 141  
... ... @@ -108,6 +154,13 @@ module Noosfero
108 154 present articles, :with => Entities::Article, :fields => params[:fields]
109 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 164 get ':id/children/:child_id' do
112 165 article = find_article(environment.articles, params[:id])
113 166 child = find_article(article.children, params[:child_id])
... ... @@ -115,6 +168,13 @@ module Noosfero
115 168 present child, :with => Entities::Article, :fields => params[:fields]
116 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 178 post ':id/children/suggest' do
119 179 authenticate!
120 180 parent_article = environment.articles.find(params[:id])
... ... @@ -133,6 +193,13 @@ module Noosfero
133 193  
134 194 # Example Request:
135 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 203 post ':id/children' do
137 204 authenticate!
138 205 parent_article = environment.articles.find(params[:id])
... ... @@ -162,6 +229,14 @@ module Noosfero
162 229 resource kind.pluralize.to_sym do
163 230 segment "/:#{kind}_id" do
164 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 240 get do
166 241 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
167 242  
... ... @@ -178,6 +253,13 @@ module Noosfero
178 253 end
179 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 263 get ':id' do
182 264 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
183 265 present_article(profile)
... ... @@ -185,6 +267,13 @@ module Noosfero
185 267  
186 268 # Example Request:
187 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 277 post do
189 278 profile = environment.send(kind.pluralize).find(params["#{kind}_id"])
190 279 post_article(profile, params)
... ...