Commit f04df39e5360a895b9e1c15d3ed169901a2e97ef
Committed by
Rodrigo Souto
1 parent
8c1e8d15
Exists in
api_tasks
and in
4 other branches
api: refactoring api to put it at noosfero module
Showing
26 changed files
with
836 additions
and
817 deletions
Show diff stats
Rakefile
@@ -26,7 +26,7 @@ plugins_tasks.each{ |ext| load ext } | @@ -26,7 +26,7 @@ plugins_tasks.each{ |ext| load ext } | ||
26 | desc "Print out grape routes" | 26 | desc "Print out grape routes" |
27 | task :grape_routes => :environment do | 27 | task :grape_routes => :environment do |
28 | #require 'api/api.rb' | 28 | #require 'api/api.rb' |
29 | - API::API.routes.each do |route| | 29 | + Noosfero::API::API.routes.each do |route| |
30 | puts route | 30 | puts route |
31 | method = route.route_method | 31 | method = route.route_method |
32 | path = route.route_path | 32 | path = route.route_path |
config.ru
1 | # This file is used by Rack-based servers to start the application. | 1 | # This file is used by Rack-based servers to start the application. |
2 | 2 | ||
3 | require ::File.expand_path('../config/environment', __FILE__) | 3 | require ::File.expand_path('../config/environment', __FILE__) |
4 | -run Noosfero::Application | ||
5 | -require "config/environment" | ||
6 | - | ||
7 | 4 | ||
8 | #use Rails::Rack::LogTailer | 5 | #use Rails::Rack::LogTailer |
9 | #use Rails::Rack::Static | 6 | #use Rails::Rack::Static |
@@ -14,6 +11,6 @@ rails_app = Rack::Builder.new do | @@ -14,6 +11,6 @@ rails_app = Rack::Builder.new do | ||
14 | end | 11 | end |
15 | 12 | ||
16 | run Rack::Cascade.new([ | 13 | run Rack::Cascade.new([ |
17 | - API::API, | 14 | + Noosfero::API::API, |
18 | rails_app | 15 | rails_app |
19 | ]) | 16 | ]) |
lib/api/api.rb
@@ -1,38 +0,0 @@ | @@ -1,38 +0,0 @@ | ||
1 | -require 'grape' | ||
2 | -Dir["#{Rails.root}/lib/api/*.rb"].each {|file| require file} | ||
3 | - | ||
4 | -module API | ||
5 | - class API < Grape::API | ||
6 | - before { start_log } | ||
7 | - before { setup_multitenancy } | ||
8 | - before { detect_stuff_by_domain } | ||
9 | - after { end_log } | ||
10 | - | ||
11 | - version 'v1' | ||
12 | - prefix "api" | ||
13 | - format :json | ||
14 | - content_type :txt, "text/plain" | ||
15 | - | ||
16 | - helpers APIHelpers | ||
17 | - | ||
18 | - mount V1::Articles | ||
19 | - mount V1::Comments | ||
20 | - mount V1::Users | ||
21 | - mount V1::Communities | ||
22 | - mount V1::People | ||
23 | - mount V1::Enterprises | ||
24 | - mount V1::Categories | ||
25 | - mount Session | ||
26 | - | ||
27 | - # hook point which allow plugins to add Grape::API extensions to API::API | ||
28 | - #finds for plugins which has api mount points classes defined (the class should extends Grape::API) | ||
29 | - @plugins = Noosfero::Plugin.all.map { |p| p.constantize } | ||
30 | - @plugins.each do |klass| | ||
31 | - if klass.public_methods.include? 'api_mount_points' | ||
32 | - klass.api_mount_points.each do |mount_class| | ||
33 | - mount mount_class if mount_class && ( mount_class < Grape::API ) | ||
34 | - end | ||
35 | - end | ||
36 | - end | ||
37 | - end | ||
38 | -end |
lib/api/entities.rb
@@ -1,92 +0,0 @@ | @@ -1,92 +0,0 @@ | ||
1 | -module API | ||
2 | - module Entities | ||
3 | - | ||
4 | - Grape::Entity.format_with :timestamp do |date| | ||
5 | - date.strftime('%Y/%m/%d %H:%M:%S') if date | ||
6 | - end | ||
7 | - | ||
8 | - class Image < Grape::Entity | ||
9 | - root 'images', 'image' | ||
10 | - | ||
11 | - expose :icon_url do |image, options| | ||
12 | - image.public_filename(:icon) | ||
13 | - end | ||
14 | - | ||
15 | - expose :minor_url do |image, options| | ||
16 | - image.public_filename(:minor) | ||
17 | - end | ||
18 | - | ||
19 | - expose :portrait_url do |image, options| | ||
20 | - image.public_filename(:portrait) | ||
21 | - end | ||
22 | - | ||
23 | - expose :thumb_url do |image, options| | ||
24 | - image.public_filename(:thumb) | ||
25 | - end | ||
26 | - end | ||
27 | - | ||
28 | - class Profile < Grape::Entity | ||
29 | - expose :identifier, :name, :id | ||
30 | - expose :created_at, :format_with => :timestamp | ||
31 | - expose :image, :using => Image | ||
32 | - end | ||
33 | - | ||
34 | - class Person < Profile | ||
35 | - root 'people', 'person' | ||
36 | - end | ||
37 | - class Enterprise < Profile | ||
38 | - root 'enterprises', 'enterprise' | ||
39 | - end | ||
40 | - class Community < Profile | ||
41 | - root 'communities', 'community' | ||
42 | - expose :description | ||
43 | - end | ||
44 | - | ||
45 | - class Category < Grape::Entity | ||
46 | - root 'categories', 'category' | ||
47 | - expose :name, :id, :slug | ||
48 | - expose :image, :using => Image | ||
49 | - end | ||
50 | - | ||
51 | - | ||
52 | - class Article < Grape::Entity | ||
53 | - root 'articles', 'article' | ||
54 | - expose :id, :body | ||
55 | - expose :created_at, :format_with => :timestamp | ||
56 | - expose :title, :documentation => {:type => "String", :desc => "Title of the article"} | ||
57 | - expose :created_by, :as => :author, :using => Profile | ||
58 | - expose :profile, :using => Profile | ||
59 | - expose :categories, :using => Category | ||
60 | - expose :parent, :using => Article | ||
61 | - end | ||
62 | - | ||
63 | - class Comment < Grape::Entity | ||
64 | - root 'comments', 'comment' | ||
65 | - expose :body, :title, :id | ||
66 | - expose :created_at, :format_with => :timestamp | ||
67 | - expose :author, :using => Profile | ||
68 | - end | ||
69 | - | ||
70 | - | ||
71 | - class User < Grape::Entity | ||
72 | - root 'users', 'user' | ||
73 | - expose :id | ||
74 | - expose :login | ||
75 | - expose :person, :using => Profile | ||
76 | - expose :permissions do |user, options| | ||
77 | - output = {} | ||
78 | - user.person.role_assignments.map do |role_assigment| | ||
79 | - if role_assigment.resource.respond_to?(:identifier) | ||
80 | - output[role_assigment.resource.identifier] = role_assigment.role.permissions | ||
81 | - end | ||
82 | - end | ||
83 | - output | ||
84 | - end | ||
85 | - end | ||
86 | - | ||
87 | - class UserLogin < User | ||
88 | - expose :private_token | ||
89 | - end | ||
90 | - | ||
91 | - end | ||
92 | -end |
lib/api/helpers.rb
@@ -1,187 +0,0 @@ | @@ -1,187 +0,0 @@ | ||
1 | -module API | ||
2 | - module APIHelpers | ||
3 | - PRIVATE_TOKEN_PARAM = :private_token | ||
4 | - | ||
5 | - def logger | ||
6 | - @logger ||= Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV']}_api.log")) | ||
7 | - end | ||
8 | - | ||
9 | - def current_user | ||
10 | - private_token = params[PRIVATE_TOKEN_PARAM].to_s if params | ||
11 | - @current_user ||= User.find_by_private_token(private_token) | ||
12 | - @current_user = nil if !@current_user.nil? && @current_user.private_token_expired? | ||
13 | - @current_user | ||
14 | - end | ||
15 | - | ||
16 | - def current_person | ||
17 | - current_user.person unless current_user.nil? | ||
18 | - end | ||
19 | - | ||
20 | - def logout | ||
21 | - @current_user = nil | ||
22 | - end | ||
23 | - | ||
24 | - def environment | ||
25 | - @environment | ||
26 | - end | ||
27 | - | ||
28 | - def limit | ||
29 | - limit = params[:limit].to_i | ||
30 | - limit = default_limit if limit <= 0 | ||
31 | - limit | ||
32 | - end | ||
33 | - | ||
34 | - def period(from_date, until_date) | ||
35 | - return nil if from_date.nil? && until_date.nil? | ||
36 | - | ||
37 | - begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date | ||
38 | - end_period = until_date.nil? ? DateTime.now : until_date | ||
39 | - | ||
40 | - begin_period..end_period | ||
41 | - end | ||
42 | - | ||
43 | - def parse_content_type(content_type) | ||
44 | - return nil if content_type.blank? | ||
45 | - content_type.split(',').map do |content_type| | ||
46 | - content_type.camelcase | ||
47 | - end | ||
48 | - end | ||
49 | - | ||
50 | - def find_article(articles, id) | ||
51 | - article = articles.find(id) | ||
52 | - article.display_to?(current_user.person) ? article : forbidden! | ||
53 | - end | ||
54 | - | ||
55 | - def make_conditions_with_parameter(params = {}) | ||
56 | - conditions = {} | ||
57 | - from_date = DateTime.parse(params[:from]) if params[:from] | ||
58 | - until_date = DateTime.parse(params[:until]) if params[:until] | ||
59 | - | ||
60 | - conditions[:type] = parse_content_type(params[:content_type]) unless params[:content_type].nil? | ||
61 | - | ||
62 | - conditions[:created_at] = period(from_date, until_date) if from_date || until_date | ||
63 | - | ||
64 | - conditions | ||
65 | - end | ||
66 | - | ||
67 | - | ||
68 | - def select_filtered_collection_of(object, method, params) | ||
69 | - conditions = make_conditions_with_parameter(params) | ||
70 | - | ||
71 | - if params[:reference_id] | ||
72 | - objects = object.send(method).send("#{params.key?(:oldest) ? 'older_than' : 'newer_than'}", params[:reference_id]).where(conditions).limit(limit).order("created_at DESC") | ||
73 | - else | ||
74 | - objects = object.send(method).where(conditions).limit(limit).order("created_at DESC") | ||
75 | - end | ||
76 | - objects | ||
77 | - end | ||
78 | - | ||
79 | - def authenticate! | ||
80 | - unauthorized! unless current_user | ||
81 | - end | ||
82 | - | ||
83 | - # Checks the occurrences of uniqueness of attributes, each attribute must be present in the params hash | ||
84 | - # or a Bad Request error is invoked. | ||
85 | - # | ||
86 | - # Parameters: | ||
87 | - # keys (unique) - A hash consisting of keys that must be unique | ||
88 | - def unique_attributes!(obj, keys) | ||
89 | - keys.each do |key| | ||
90 | - cant_be_saved_request!(key) if obj.send("find_by_#{key.to_s}", params[key]) | ||
91 | - end | ||
92 | - end | ||
93 | - | ||
94 | - def attributes_for_keys(keys) | ||
95 | - attrs = {} | ||
96 | - keys.each do |key| | ||
97 | - attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false) | ||
98 | - end | ||
99 | - attrs | ||
100 | - end | ||
101 | - | ||
102 | - ########################################## | ||
103 | - # error helpers # | ||
104 | - ########################################## | ||
105 | - | ||
106 | - def forbidden! | ||
107 | - render_api_error!('403 Forbidden', 403) | ||
108 | - end | ||
109 | - | ||
110 | - def cant_be_saved_request!(attribute) | ||
111 | - message = _("(Invalid request) #{attribute} can't be saved") | ||
112 | - render_api_error!(message, 400) | ||
113 | - end | ||
114 | - | ||
115 | - def bad_request!(attribute) | ||
116 | - message = _("(Bad request) #{attribute} not given") | ||
117 | - render_api_error!(message, 400) | ||
118 | - end | ||
119 | - | ||
120 | - def something_wrong! | ||
121 | - message = _("Something wrong happened") | ||
122 | - render_api_error!(message, 400) | ||
123 | - end | ||
124 | - | ||
125 | - def unauthorized! | ||
126 | - render_api_error!(_('Unauthorized'), 401) | ||
127 | - end | ||
128 | - | ||
129 | - def not_allowed! | ||
130 | - render_api_error!(_('Method Not Allowed'), 405) | ||
131 | - end | ||
132 | - | ||
133 | - def render_api_error!(message, status) | ||
134 | - error!({'message' => message, :code => status}, status) | ||
135 | - end | ||
136 | - | ||
137 | - def render_api_errors!(messages) | ||
138 | - render_api_error!(messages.join(','), 400) | ||
139 | - end | ||
140 | - protected | ||
141 | - | ||
142 | - def start_log | ||
143 | - logger.info "Started #{request.path} #{request.params.except('password')}" | ||
144 | - end | ||
145 | - def end_log | ||
146 | - logger.info "Completed #{request.path}" | ||
147 | - end | ||
148 | - | ||
149 | - def setup_multitenancy | ||
150 | - Noosfero::MultiTenancy.setup!(request.host) | ||
151 | - end | ||
152 | - | ||
153 | - def detect_stuff_by_domain | ||
154 | - @domain = Domain.find_by_name(request.host) | ||
155 | - if @domain.nil? | ||
156 | - @environment = Environment.default | ||
157 | - if @environment.nil? && Rails.env.development? | ||
158 | - # This should only happen in development ... | ||
159 | - @environment = Environment.create!(:name => "Noosfero", :is_default => true) | ||
160 | - end | ||
161 | - else | ||
162 | - @environment = @domain.environment | ||
163 | - end | ||
164 | - end | ||
165 | - | ||
166 | - private | ||
167 | - | ||
168 | - def default_limit | ||
169 | - 20 | ||
170 | - end | ||
171 | - | ||
172 | - def parse_content_type(content_type) | ||
173 | - return nil if content_type.blank? | ||
174 | - content_type.split(',').map do |content_type| | ||
175 | - content_type.camelcase | ||
176 | - end | ||
177 | - end | ||
178 | - | ||
179 | - def period(from_date, until_date) | ||
180 | - begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date | ||
181 | - end_period = until_date.nil? ? DateTime.now : until_date | ||
182 | - | ||
183 | - begin_period..end_period | ||
184 | - end | ||
185 | - | ||
186 | - end | ||
187 | -end |
lib/api/session.rb
@@ -1,48 +0,0 @@ | @@ -1,48 +0,0 @@ | ||
1 | -module API | ||
2 | - | ||
3 | - class Session < Grape::API | ||
4 | - | ||
5 | - # Login to get token | ||
6 | - # | ||
7 | - # Parameters: | ||
8 | - # login (*required) - user login or email | ||
9 | - # password (required) - user password | ||
10 | - # | ||
11 | - # Example Request: | ||
12 | - # POST http://localhost:3000/api/v1/login?login=adminuser&password=admin | ||
13 | - post "/login" do | ||
14 | - user ||= User.authenticate(params[:login], params[:password], environment) | ||
15 | - | ||
16 | - return unauthorized! unless user | ||
17 | - user.generate_private_token! | ||
18 | - present user, :with => Entities::UserLogin | ||
19 | - end | ||
20 | - | ||
21 | - # Create user. | ||
22 | - # | ||
23 | - # Parameters: | ||
24 | - # email (required) - Email | ||
25 | - # password (required) - Password | ||
26 | - # login - login | ||
27 | - # Example Request: | ||
28 | - # POST /register?email=some@mail.com&password=pas&login=some | ||
29 | - params do | ||
30 | - requires :email, type: String, desc: _("Email") | ||
31 | - requires :login, type: String, desc: _("Login") | ||
32 | - requires :password, type: String, desc: _("Password") | ||
33 | - end | ||
34 | - post "/register" do | ||
35 | - unique_attributes! User, [:email, :login] | ||
36 | - attrs = attributes_for_keys [:email, :login, :password] | ||
37 | - attrs[:password_confirmation] = attrs[:password] | ||
38 | - user = User.new(attrs) | ||
39 | - if user.save | ||
40 | - user.activate | ||
41 | - present user, :with => Entities::User | ||
42 | - else | ||
43 | - something_wrong! | ||
44 | - end | ||
45 | - end | ||
46 | - | ||
47 | - end | ||
48 | -end |
lib/api/v1/articles.rb
@@ -1,167 +0,0 @@ | @@ -1,167 +0,0 @@ | ||
1 | -module API | ||
2 | - module V1 | ||
3 | - class Articles < Grape::API | ||
4 | - before { authenticate! } | ||
5 | - | ||
6 | - ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} | ||
7 | - | ||
8 | - resource :articles do | ||
9 | - | ||
10 | - # Collect articles | ||
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/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317 | ||
19 | - get do | ||
20 | - articles = select_filtered_collection_of(environment, 'articles', params) | ||
21 | - articles = articles.display_filter(current_person, nil) | ||
22 | - present articles, :with => Entities::Article | ||
23 | - end | ||
24 | - | ||
25 | - desc "Return the article id" | ||
26 | - get ':id' do | ||
27 | - article = find_article(environment.articles, params[:id]) | ||
28 | - present article, :with => Entities::Article | ||
29 | - end | ||
30 | - | ||
31 | - get ':id/children' do | ||
32 | - article = find_article(environment.articles, params[:id]) | ||
33 | - articles = select_filtered_collection_of(article, 'children', params) | ||
34 | - articles = articles.display_filter(current_person, nil) | ||
35 | - present articles, :with => Entities::Article | ||
36 | - end | ||
37 | - | ||
38 | - get ':id/children/:child_id' do | ||
39 | - article = find_article(environment.articles, params[:id]) | ||
40 | - present find_article(article.children, params[:child_id]), :with => Entities::Article | ||
41 | - end | ||
42 | - | ||
43 | - end | ||
44 | - | ||
45 | - resource :communities do | ||
46 | - segment '/:community_id' do | ||
47 | - resource :articles do | ||
48 | - get do | ||
49 | - community = environment.communities.find(params[:community_id]) | ||
50 | - articles = select_filtered_collection_of(community, 'articles', params) | ||
51 | - articles = articles.display_filter(current_person, community) | ||
52 | - present articles, :with => Entities::Article | ||
53 | - end | ||
54 | - | ||
55 | - get ':id' do | ||
56 | - community = environment.communities.find(params[:community_id]) | ||
57 | - article = find_article(community.articles, params[:id]) | ||
58 | - present article, :with => Entities::Article | ||
59 | - end | ||
60 | - | ||
61 | - # Example Request: | ||
62 | - # POST api/v1/communites/:community_id/articles?private_token=234298743290432&article[name]=title&article[body]=body | ||
63 | - post do | ||
64 | - community = environment.communities.find(params[:community_id]) | ||
65 | - return forbidden! unless current_person.can_post_content?(community) | ||
66 | - | ||
67 | - klass_type= params[:content_type].nil? ? 'TinyMceArticle' : params[:content_type] | ||
68 | - return forbidden! unless ARTICLE_TYPES.include?(klass_type) | ||
69 | - | ||
70 | - article = klass_type.constantize.new(params[:article]) | ||
71 | - article.last_changed_by = current_person | ||
72 | - article.created_by= current_person | ||
73 | - article.profile = community | ||
74 | - | ||
75 | - if !article.save | ||
76 | - render_api_errors!(article.errors.full_messages) | ||
77 | - end | ||
78 | - present article, :with => Entities::Article | ||
79 | - end | ||
80 | - | ||
81 | - end | ||
82 | - end | ||
83 | - | ||
84 | - end | ||
85 | - | ||
86 | - resource :people do | ||
87 | - segment '/:person_id' do | ||
88 | - resource :articles do | ||
89 | - get do | ||
90 | - person = environment.people.find(params[:person_id]) | ||
91 | - articles = select_filtered_collection_of(person, 'articles', params) | ||
92 | - articles = articles.display_filter(current_person, person) | ||
93 | - present articles, :with => Entities::Article | ||
94 | - end | ||
95 | - | ||
96 | - get ':id' do | ||
97 | - person = environment.people.find(params[:person_id]) | ||
98 | - article = find_article(person.articles, params[:id]) | ||
99 | - present article, :with => Entities::Article | ||
100 | - end | ||
101 | - | ||
102 | - post do | ||
103 | - person = environment.people.find(params[:person_id]) | ||
104 | - return forbidden! unless current_person.can_post_content?(person) | ||
105 | - | ||
106 | - klass_type= params[:content_type].nil? ? 'TinyMceArticle' : params[:content_type] | ||
107 | - return forbidden! unless ARTICLE_TYPES.include?(klass_type) | ||
108 | - | ||
109 | - article = klass_type.constantize.new(params[:article]) | ||
110 | - article.last_changed_by = current_person | ||
111 | - article.created_by= current_person | ||
112 | - article.profile = person | ||
113 | - | ||
114 | - if !article.save | ||
115 | - render_api_errors!(article.errors.full_messages) | ||
116 | - end | ||
117 | - present article, :with => Entities::Article | ||
118 | - end | ||
119 | - | ||
120 | - end | ||
121 | - end | ||
122 | - | ||
123 | - end | ||
124 | - | ||
125 | - resource :enterprises do | ||
126 | - segment '/:enterprise_id' do | ||
127 | - resource :articles do | ||
128 | - get do | ||
129 | - enterprise = environment.enterprises.find(params[:enterprise_id]) | ||
130 | - articles = select_filtered_collection_of(enterprise, 'articles', params) | ||
131 | - articles = articles.display_filter(current_person, enterprise) | ||
132 | - present articles, :with => Entities::Article | ||
133 | - end | ||
134 | - | ||
135 | - get ':id' do | ||
136 | - enterprise = environment.enterprises.find(params[:enterprise_id]) | ||
137 | - article = find_article(enterprise.articles, params[:id]) | ||
138 | - present article, :with => Entities::Article | ||
139 | - end | ||
140 | - | ||
141 | - post do | ||
142 | - enterprise = environment.enterprises.find(params[:enterprise_id]) | ||
143 | - return forbidden! unless current_person.can_post_content?(enterprise) | ||
144 | - | ||
145 | - klass_type= params[:content_type].nil? ? 'TinyMceArticle' : params[:content_type] | ||
146 | - return forbidden! unless ARTICLE_TYPES.include?(klass_type) | ||
147 | - | ||
148 | - article = klass_type.constantize.new(params[:article]) | ||
149 | - article.last_changed_by = current_person | ||
150 | - article.created_by= current_person | ||
151 | - article.profile = enterprise | ||
152 | - | ||
153 | - if !article.save | ||
154 | - render_api_errors!(article.errors.full_messages) | ||
155 | - end | ||
156 | - present article, :with => Entities::Article | ||
157 | - end | ||
158 | - | ||
159 | - end | ||
160 | - end | ||
161 | - | ||
162 | - end | ||
163 | - | ||
164 | - | ||
165 | - end | ||
166 | - end | ||
167 | -end |
lib/api/v1/categories.rb
@@ -1,23 +0,0 @@ | @@ -1,23 +0,0 @@ | ||
1 | -module API | ||
2 | - module V1 | ||
3 | - class Categories < Grape::API | ||
4 | - before { authenticate! } | ||
5 | - | ||
6 | - resource :categories do | ||
7 | - | ||
8 | - get do | ||
9 | - type = params[:category_type] | ||
10 | - categories = type.nil? ? environment.categories : environment.categories.find(:all, :conditions => {:type => type}) | ||
11 | - present categories, :with => Entities::Category | ||
12 | - end | ||
13 | - | ||
14 | - desc "Return the category by id" | ||
15 | - get ':id' do | ||
16 | - present environment.categories.find(params[:id]), :with => Entities::Category | ||
17 | - end | ||
18 | - | ||
19 | - end | ||
20 | - | ||
21 | - end | ||
22 | - end | ||
23 | -end |
lib/api/v1/comments.rb
@@ -1,45 +0,0 @@ | @@ -1,45 +0,0 @@ | ||
1 | -module API | ||
2 | - module V1 | ||
3 | - class Comments < Grape::API | ||
4 | - before { authenticate! } | ||
5 | - | ||
6 | - resource :articles do | ||
7 | - # Collect comments from articles | ||
8 | - # | ||
9 | - # Parameters: | ||
10 | - # reference_id - comment id used as reference to collect comment | ||
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 /articles/12/comments?oldest&limit=10&reference_id=23 | ||
16 | - get ":id/comments" do | ||
17 | - | ||
18 | - conditions = make_conditions_with_parameter(params) | ||
19 | - article = find_article(environment.articles, params[:id]) | ||
20 | - | ||
21 | - if params[:reference_id] | ||
22 | - comments = article.comments.send("#{params.key?(:oldest) ? 'older_than' : 'newer_than'}", params[:reference_id]).reorder("created_at DESC").find(:all, :conditions => conditions, :limit => limit) | ||
23 | - else | ||
24 | - comments = article.comments.reorder("created_at DESC").find(:all, :conditions => conditions, :limit => limit) | ||
25 | - end | ||
26 | - present comments, :with => Entities::Comment | ||
27 | - | ||
28 | - end | ||
29 | - | ||
30 | - get ":id/comments/:comment_id" do | ||
31 | - article = find_article(environment.articles, params[:id]) | ||
32 | - present article.comments.find(params[:comment_id]), :with => Entities::Comment | ||
33 | - end | ||
34 | - | ||
35 | - # Example Request: | ||
36 | - # POST api/v1/articles/12/comments?private_toke=234298743290432&body=new comment | ||
37 | - post ":id/comments" do | ||
38 | - article = find_article(environment.articles, params[:id]) | ||
39 | - present article.comments.create(:author => current_person, :body => params[:body]), :with => Entities::Comment | ||
40 | - end | ||
41 | - end | ||
42 | - | ||
43 | - end | ||
44 | - end | ||
45 | -end |
lib/api/v1/communities.rb
@@ -1,70 +0,0 @@ | @@ -1,70 +0,0 @@ | ||
1 | -module API | ||
2 | - module V1 | ||
3 | - class Communities < Grape::API | ||
4 | - before { authenticate! } | ||
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 = communities.visible_for_person(current_person) | ||
21 | - present communities, :with => Entities::Community | ||
22 | - end | ||
23 | - | ||
24 | - | ||
25 | - # Example Request: | ||
26 | - # POST api/v1/communties?private_token=234298743290432&community[name]=some_name | ||
27 | - post do | ||
28 | - params[:community] ||= {} | ||
29 | - begin | ||
30 | - community = Community.create_after_moderation(current_person, params[:community].merge({:environment => environment})) | ||
31 | - rescue | ||
32 | - community = Community.new(params[:community]) | ||
33 | - end | ||
34 | - | ||
35 | - if !community.save | ||
36 | - render_api_errors!(community.errors.full_messages) | ||
37 | - end | ||
38 | - | ||
39 | - present community, :with => Entities::Community | ||
40 | - end | ||
41 | - | ||
42 | - get ':id' do | ||
43 | - community = environment.communities.visible.find_by_id(params[:id]) | ||
44 | - present community, :with => Entities::Community | ||
45 | - end | ||
46 | - | ||
47 | - end | ||
48 | - | ||
49 | - resource :people do | ||
50 | - | ||
51 | - segment '/:person_id' do | ||
52 | - | ||
53 | - resource :communities do | ||
54 | - | ||
55 | - get do | ||
56 | - person = environment.people.find(params[:person_id]) | ||
57 | - communities = select_filtered_collection_of(person, 'communities', params) | ||
58 | - communities = communities.visible | ||
59 | - present communities, :with => Entities::Community | ||
60 | - end | ||
61 | - | ||
62 | - end | ||
63 | - | ||
64 | - end | ||
65 | - | ||
66 | - end | ||
67 | - | ||
68 | - end | ||
69 | - end | ||
70 | -end |
lib/api/v1/enterprises.rb
@@ -1,54 +0,0 @@ | @@ -1,54 +0,0 @@ | ||
1 | -module API | ||
2 | - module V1 | ||
3 | - class Enterprises < Grape::API | ||
4 | - before { authenticate! } | ||
5 | - | ||
6 | - resource :enterprises 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 /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_for_person(current_person) | ||
21 | - present enterprises, :with => Entities::Enterprise | ||
22 | - end | ||
23 | - | ||
24 | - desc "Return one enterprise by id" | ||
25 | - get ':id' do | ||
26 | - enterprise = environment.enterprises.visible.find_by_id(params[:id]) | ||
27 | - present enterprise, :with => Entities::Enterprise | ||
28 | - end | ||
29 | - | ||
30 | - end | ||
31 | - | ||
32 | - resource :people do | ||
33 | - | ||
34 | - segment '/:person_id' do | ||
35 | - | ||
36 | - resource :enterprises do | ||
37 | - | ||
38 | - get do | ||
39 | - person = environment.people.find(params[:person_id]) | ||
40 | - enterprises = select_filtered_collection_of(person, 'enterprises', params) | ||
41 | - enterprises = enterprises.visible | ||
42 | - present enterprises, :with => Entities::Enterprise | ||
43 | - end | ||
44 | - | ||
45 | - end | ||
46 | - | ||
47 | - end | ||
48 | - | ||
49 | - end | ||
50 | - | ||
51 | - | ||
52 | - end | ||
53 | - end | ||
54 | -end |
lib/api/v1/people.rb
@@ -1,40 +0,0 @@ | @@ -1,40 +0,0 @@ | ||
1 | -module API | ||
2 | - module V1 | ||
3 | - class People < Grape::API | ||
4 | - before { authenticate! } | ||
5 | - | ||
6 | - resource :people 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 /people?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10 | ||
17 | - # GET /people?reference_id=10&limit=10&oldest | ||
18 | - get do | ||
19 | - people = select_filtered_collection_of(environment, 'people', params) | ||
20 | - people = people.visible_for_person(current_person) | ||
21 | - present people, :with => Entities::Person | ||
22 | - end | ||
23 | - | ||
24 | - desc "Return the person information" | ||
25 | - get ':id' do | ||
26 | - person = environment.people.visible.find_by_id(params[:id]) | ||
27 | - present person, :with => Entities::Person | ||
28 | - end | ||
29 | - | ||
30 | - desc "Return the person friends" | ||
31 | - get ':id/friends' do | ||
32 | - friends = current_person.friends.visible | ||
33 | - present friends, :with => Entities::Person | ||
34 | - end | ||
35 | - | ||
36 | - end | ||
37 | - | ||
38 | - end | ||
39 | - end | ||
40 | -end |
lib/api/v1/users.rb
@@ -1,46 +0,0 @@ | @@ -1,46 +0,0 @@ | ||
1 | -module API | ||
2 | - module V1 | ||
3 | - class Users < Grape::API | ||
4 | - before { authenticate! } | ||
5 | - | ||
6 | - resource :users do | ||
7 | - | ||
8 | - #FIXME make the pagination | ||
9 | - #FIXME put it on environment context | ||
10 | - get do | ||
11 | - present environment.users, :with => Entities::User | ||
12 | - end | ||
13 | - | ||
14 | - # Example Request: | ||
15 | - # POST api/v1/users?user[login]=some_login&user[password]=some | ||
16 | - post do | ||
17 | - user = User.new(params[:user]) | ||
18 | - user.terms_of_use = environment.terms_of_use | ||
19 | - user.environment = environment | ||
20 | - if !user.save | ||
21 | - render_api_errors!(user.errors.full_messages) | ||
22 | - end | ||
23 | - | ||
24 | - present user, :with => Entities::User | ||
25 | - end | ||
26 | - | ||
27 | - get ":id" do | ||
28 | - present environment.users.find_by_id(params[:id]), :with => Entities::User | ||
29 | - end | ||
30 | - | ||
31 | - get ":id/permissions" do | ||
32 | - user = environment.users.find(params[:id]) | ||
33 | - output = {} | ||
34 | - user.person.role_assignments.map do |role_assigment| | ||
35 | - if role_assigment.resource.respond_to?(:identifier) && role_assigment.resource.identifier == params[:profile] | ||
36 | - output[:permissions] = role_assigment.role.permissions | ||
37 | - end | ||
38 | - end | ||
39 | - present output | ||
40 | - end | ||
41 | - | ||
42 | - end | ||
43 | - | ||
44 | - end | ||
45 | - end | ||
46 | -end |
@@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
1 | +require 'grape' | ||
2 | +Dir["#{Rails.root}/lib/noosfero/api/*.rb"].each {|file| require file} | ||
3 | +module Noosfero | ||
4 | + module API | ||
5 | + class API < Grape::API | ||
6 | + before { start_log } | ||
7 | + before { setup_multitenancy } | ||
8 | + before { detect_stuff_by_domain } | ||
9 | + after { end_log } | ||
10 | + | ||
11 | + version 'v1' | ||
12 | + prefix "api" | ||
13 | + format :json | ||
14 | + content_type :txt, "text/plain" | ||
15 | + | ||
16 | + helpers APIHelpers | ||
17 | + | ||
18 | + mount V1::Articles | ||
19 | + mount V1::Comments | ||
20 | + mount V1::Users | ||
21 | + mount V1::Communities | ||
22 | + mount V1::People | ||
23 | + mount V1::Enterprises | ||
24 | + mount V1::Categories | ||
25 | + mount Session | ||
26 | + | ||
27 | + # hook point which allow plugins to add Grape::API extensions to API::API | ||
28 | + #finds for plugins which has api mount points classes defined (the class should extends Grape::API) | ||
29 | + @plugins = Noosfero::Plugin.all.map { |p| p.constantize } | ||
30 | + @plugins.each do |klass| | ||
31 | + if klass.public_methods.include? 'api_mount_points' | ||
32 | + klass.api_mount_points.each do |mount_class| | ||
33 | + mount mount_class if mount_class && ( mount_class < Grape::API ) | ||
34 | + end | ||
35 | + end | ||
36 | + end | ||
37 | + end | ||
38 | + end | ||
39 | +end |
@@ -0,0 +1,94 @@ | @@ -0,0 +1,94 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module Entities | ||
4 | + | ||
5 | + Grape::Entity.format_with :timestamp do |date| | ||
6 | + date.strftime('%Y/%m/%d %H:%M:%S') if date | ||
7 | + end | ||
8 | + | ||
9 | + class Image < Grape::Entity | ||
10 | + root 'images', 'image' | ||
11 | + | ||
12 | + expose :icon_url do |image, options| | ||
13 | + image.public_filename(:icon) | ||
14 | + end | ||
15 | + | ||
16 | + expose :minor_url do |image, options| | ||
17 | + image.public_filename(:minor) | ||
18 | + end | ||
19 | + | ||
20 | + expose :portrait_url do |image, options| | ||
21 | + image.public_filename(:portrait) | ||
22 | + end | ||
23 | + | ||
24 | + expose :thumb_url do |image, options| | ||
25 | + image.public_filename(:thumb) | ||
26 | + end | ||
27 | + end | ||
28 | + | ||
29 | + class Profile < Grape::Entity | ||
30 | + expose :identifier, :name, :id | ||
31 | + expose :created_at, :format_with => :timestamp | ||
32 | + expose :image, :using => Image | ||
33 | + end | ||
34 | + | ||
35 | + class Person < Profile | ||
36 | + root 'people', 'person' | ||
37 | + end | ||
38 | + class Enterprise < Profile | ||
39 | + root 'enterprises', 'enterprise' | ||
40 | + end | ||
41 | + class Community < Profile | ||
42 | + root 'communities', 'community' | ||
43 | + expose :description | ||
44 | + end | ||
45 | + | ||
46 | + class Category < Grape::Entity | ||
47 | + root 'categories', 'category' | ||
48 | + expose :name, :id, :slug | ||
49 | + expose :image, :using => Image | ||
50 | + end | ||
51 | + | ||
52 | + | ||
53 | + class Article < Grape::Entity | ||
54 | + root 'articles', 'article' | ||
55 | + expose :id, :body | ||
56 | + expose :created_at, :format_with => :timestamp | ||
57 | + expose :title, :documentation => {:type => "String", :desc => "Title of the article"} | ||
58 | + expose :created_by, :as => :author, :using => Profile | ||
59 | + expose :profile, :using => Profile | ||
60 | + expose :categories, :using => Category | ||
61 | + expose :parent, :using => Article | ||
62 | + end | ||
63 | + | ||
64 | + class Comment < Grape::Entity | ||
65 | + root 'comments', 'comment' | ||
66 | + expose :body, :title, :id | ||
67 | + expose :created_at, :format_with => :timestamp | ||
68 | + expose :author, :using => Profile | ||
69 | + end | ||
70 | + | ||
71 | + | ||
72 | + class User < Grape::Entity | ||
73 | + root 'users', 'user' | ||
74 | + expose :id | ||
75 | + expose :login | ||
76 | + expose :person, :using => Profile | ||
77 | + expose :permissions do |user, options| | ||
78 | + output = {} | ||
79 | + user.person.role_assignments.map do |role_assigment| | ||
80 | + if role_assigment.resource.respond_to?(:identifier) | ||
81 | + output[role_assigment.resource.identifier] = role_assigment.role.permissions | ||
82 | + end | ||
83 | + end | ||
84 | + output | ||
85 | + end | ||
86 | + end | ||
87 | + | ||
88 | + class UserLogin < User | ||
89 | + expose :private_token | ||
90 | + end | ||
91 | + | ||
92 | + end | ||
93 | + end | ||
94 | +end |
@@ -0,0 +1,189 @@ | @@ -0,0 +1,189 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module APIHelpers | ||
4 | + PRIVATE_TOKEN_PARAM = :private_token | ||
5 | + | ||
6 | + def logger | ||
7 | + @logger ||= Logger.new(File.join(Rails.root, 'log', "#{ENV['RAILS_ENV']}_api.log")) | ||
8 | + end | ||
9 | + | ||
10 | + def current_user | ||
11 | + private_token = params[PRIVATE_TOKEN_PARAM].to_s if params | ||
12 | + @current_user ||= User.find_by_private_token(private_token) | ||
13 | + @current_user = nil if !@current_user.nil? && @current_user.private_token_expired? | ||
14 | + @current_user | ||
15 | + end | ||
16 | + | ||
17 | + def current_person | ||
18 | + current_user.person unless current_user.nil? | ||
19 | + end | ||
20 | + | ||
21 | + def logout | ||
22 | + @current_user = nil | ||
23 | + end | ||
24 | + | ||
25 | + def environment | ||
26 | + @environment | ||
27 | + end | ||
28 | + | ||
29 | + def limit | ||
30 | + limit = params[:limit].to_i | ||
31 | + limit = default_limit if limit <= 0 | ||
32 | + limit | ||
33 | + end | ||
34 | + | ||
35 | + def period(from_date, until_date) | ||
36 | + return nil if from_date.nil? && until_date.nil? | ||
37 | + | ||
38 | + begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date | ||
39 | + end_period = until_date.nil? ? DateTime.now : until_date | ||
40 | + | ||
41 | + begin_period..end_period | ||
42 | + end | ||
43 | + | ||
44 | + def parse_content_type(content_type) | ||
45 | + return nil if content_type.blank? | ||
46 | + content_type.split(',').map do |content_type| | ||
47 | + content_type.camelcase | ||
48 | + end | ||
49 | + end | ||
50 | + | ||
51 | + def find_article(articles, id) | ||
52 | + article = articles.find(id) | ||
53 | + article.display_to?(current_user.person) ? article : forbidden! | ||
54 | + end | ||
55 | + | ||
56 | + def make_conditions_with_parameter(params = {}) | ||
57 | + conditions = {} | ||
58 | + from_date = DateTime.parse(params[:from]) if params[:from] | ||
59 | + until_date = DateTime.parse(params[:until]) if params[:until] | ||
60 | + | ||
61 | + conditions[:type] = parse_content_type(params[:content_type]) unless params[:content_type].nil? | ||
62 | + | ||
63 | + conditions[:created_at] = period(from_date, until_date) if from_date || until_date | ||
64 | + | ||
65 | + conditions | ||
66 | + end | ||
67 | + | ||
68 | + | ||
69 | + def select_filtered_collection_of(object, method, params) | ||
70 | + conditions = make_conditions_with_parameter(params) | ||
71 | + | ||
72 | + if params[:reference_id] | ||
73 | + objects = object.send(method).send("#{params.key?(:oldest) ? 'older_than' : 'newer_than'}", params[:reference_id]).where(conditions).limit(limit).order("created_at DESC") | ||
74 | + else | ||
75 | + objects = object.send(method).where(conditions).limit(limit).order("created_at DESC") | ||
76 | + end | ||
77 | + objects | ||
78 | + end | ||
79 | + | ||
80 | + def authenticate! | ||
81 | + unauthorized! unless current_user | ||
82 | + end | ||
83 | + | ||
84 | + # Checks the occurrences of uniqueness of attributes, each attribute must be present in the params hash | ||
85 | + # or a Bad Request error is invoked. | ||
86 | + # | ||
87 | + # Parameters: | ||
88 | + # keys (unique) - A hash consisting of keys that must be unique | ||
89 | + def unique_attributes!(obj, keys) | ||
90 | + keys.each do |key| | ||
91 | + cant_be_saved_request!(key) if obj.send("find_by_#{key.to_s}", params[key]) | ||
92 | + end | ||
93 | + end | ||
94 | + | ||
95 | + def attributes_for_keys(keys) | ||
96 | + attrs = {} | ||
97 | + keys.each do |key| | ||
98 | + attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false) | ||
99 | + end | ||
100 | + attrs | ||
101 | + end | ||
102 | + | ||
103 | + ########################################## | ||
104 | + # error helpers # | ||
105 | + ########################################## | ||
106 | + | ||
107 | + def forbidden! | ||
108 | + render_api_error!('403 Forbidden', 403) | ||
109 | + end | ||
110 | + | ||
111 | + def cant_be_saved_request!(attribute) | ||
112 | + message = _("(Invalid request) #{attribute} can't be saved") | ||
113 | + render_api_error!(message, 400) | ||
114 | + end | ||
115 | + | ||
116 | + def bad_request!(attribute) | ||
117 | + message = _("(Bad request) #{attribute} not given") | ||
118 | + render_api_error!(message, 400) | ||
119 | + end | ||
120 | + | ||
121 | + def something_wrong! | ||
122 | + message = _("Something wrong happened") | ||
123 | + render_api_error!(message, 400) | ||
124 | + end | ||
125 | + | ||
126 | + def unauthorized! | ||
127 | + render_api_error!(_('Unauthorized'), 401) | ||
128 | + end | ||
129 | + | ||
130 | + def not_allowed! | ||
131 | + render_api_error!(_('Method Not Allowed'), 405) | ||
132 | + end | ||
133 | + | ||
134 | + def render_api_error!(message, status) | ||
135 | + error!({'message' => message, :code => status}, status) | ||
136 | + end | ||
137 | + | ||
138 | + def render_api_errors!(messages) | ||
139 | + render_api_error!(messages.join(','), 400) | ||
140 | + end | ||
141 | + protected | ||
142 | + | ||
143 | + def start_log | ||
144 | + logger.info "Started #{request.path} #{request.params.except('password')}" | ||
145 | + end | ||
146 | + def end_log | ||
147 | + logger.info "Completed #{request.path}" | ||
148 | + end | ||
149 | + | ||
150 | + def setup_multitenancy | ||
151 | + Noosfero::MultiTenancy.setup!(request.host) | ||
152 | + end | ||
153 | + | ||
154 | + def detect_stuff_by_domain | ||
155 | + @domain = Domain.find_by_name(request.host) | ||
156 | + if @domain.nil? | ||
157 | + @environment = Environment.default | ||
158 | + if @environment.nil? && Rails.env.development? | ||
159 | + # This should only happen in development ... | ||
160 | + @environment = Environment.create!(:name => "Noosfero", :is_default => true) | ||
161 | + end | ||
162 | + else | ||
163 | + @environment = @domain.environment | ||
164 | + end | ||
165 | + end | ||
166 | + | ||
167 | + private | ||
168 | + | ||
169 | + def default_limit | ||
170 | + 20 | ||
171 | + end | ||
172 | + | ||
173 | + def parse_content_type(content_type) | ||
174 | + return nil if content_type.blank? | ||
175 | + content_type.split(',').map do |content_type| | ||
176 | + content_type.camelcase | ||
177 | + end | ||
178 | + end | ||
179 | + | ||
180 | + def period(from_date, until_date) | ||
181 | + begin_period = from_date.nil? ? Time.at(0).to_datetime : from_date | ||
182 | + end_period = until_date.nil? ? DateTime.now : until_date | ||
183 | + | ||
184 | + begin_period..end_period | ||
185 | + end | ||
186 | + | ||
187 | + end | ||
188 | + end | ||
189 | +end |
@@ -0,0 +1,50 @@ | @@ -0,0 +1,50 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + | ||
4 | + class Session < Grape::API | ||
5 | + | ||
6 | + # Login to get token | ||
7 | + # | ||
8 | + # Parameters: | ||
9 | + # login (*required) - user login or email | ||
10 | + # password (required) - user password | ||
11 | + # | ||
12 | + # Example Request: | ||
13 | + # POST http://localhost:3000/api/v1/login?login=adminuser&password=admin | ||
14 | + post "/login" do | ||
15 | + user ||= User.authenticate(params[:login], params[:password], environment) | ||
16 | + | ||
17 | + return unauthorized! unless user | ||
18 | + user.generate_private_token! | ||
19 | + present user, :with => Entities::UserLogin | ||
20 | + end | ||
21 | + | ||
22 | + # Create user. | ||
23 | + # | ||
24 | + # Parameters: | ||
25 | + # email (required) - Email | ||
26 | + # password (required) - Password | ||
27 | + # login - login | ||
28 | + # Example Request: | ||
29 | + # POST /register?email=some@mail.com&password=pas&login=some | ||
30 | + params do | ||
31 | + requires :email, type: String, desc: _("Email") | ||
32 | + requires :login, type: String, desc: _("Login") | ||
33 | + requires :password, type: String, desc: _("Password") | ||
34 | + end | ||
35 | + post "/register" do | ||
36 | + unique_attributes! User, [:email, :login] | ||
37 | + attrs = attributes_for_keys [:email, :login, :password] | ||
38 | + attrs[:password_confirmation] = attrs[:password] | ||
39 | + user = User.new(attrs) | ||
40 | + if user.save | ||
41 | + user.activate | ||
42 | + present user, :with => Entities::User | ||
43 | + else | ||
44 | + something_wrong! | ||
45 | + end | ||
46 | + end | ||
47 | + | ||
48 | + end | ||
49 | + end | ||
50 | +end |
@@ -0,0 +1,169 @@ | @@ -0,0 +1,169 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + class Articles < Grape::API | ||
5 | + before { authenticate! } | ||
6 | + | ||
7 | + ARTICLE_TYPES = Article.descendants.map{|a| a.to_s} | ||
8 | + | ||
9 | + resource :articles do | ||
10 | + | ||
11 | + # Collect articles | ||
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/articles?from=2013-04-04-14:41:43&until=2015-04-04-14:41:43&limit=10&private_token=e96fff37c2238fdab074d1dcea8e6317 | ||
20 | + get do | ||
21 | + articles = select_filtered_collection_of(environment, 'articles', params) | ||
22 | + articles = articles.display_filter(current_person, nil) | ||
23 | + present articles, :with => Entities::Article | ||
24 | + end | ||
25 | + | ||
26 | + desc "Return the article id" | ||
27 | + get ':id' do | ||
28 | + article = find_article(environment.articles, params[:id]) | ||
29 | + present article, :with => Entities::Article | ||
30 | + end | ||
31 | + | ||
32 | + get ':id/children' do | ||
33 | + article = find_article(environment.articles, params[:id]) | ||
34 | + articles = select_filtered_collection_of(article, 'children', params) | ||
35 | + articles = articles.display_filter(current_person, nil) | ||
36 | + present articles, :with => Entities::Article | ||
37 | + end | ||
38 | + | ||
39 | + get ':id/children/:child_id' do | ||
40 | + article = find_article(environment.articles, params[:id]) | ||
41 | + present find_article(article.children, params[:child_id]), :with => Entities::Article | ||
42 | + end | ||
43 | + | ||
44 | + end | ||
45 | + | ||
46 | + resource :communities do | ||
47 | + segment '/:community_id' do | ||
48 | + resource :articles do | ||
49 | + get do | ||
50 | + community = environment.communities.find(params[:community_id]) | ||
51 | + articles = select_filtered_collection_of(community, 'articles', params) | ||
52 | + articles = articles.display_filter(current_person, community) | ||
53 | + present articles, :with => Entities::Article | ||
54 | + end | ||
55 | + | ||
56 | + get ':id' do | ||
57 | + community = environment.communities.find(params[:community_id]) | ||
58 | + article = find_article(community.articles, params[:id]) | ||
59 | + present article, :with => Entities::Article | ||
60 | + end | ||
61 | + | ||
62 | + # Example Request: | ||
63 | + # POST api/v1/communites/:community_id/articles?private_token=234298743290432&article[name]=title&article[body]=body | ||
64 | + post do | ||
65 | + community = environment.communities.find(params[:community_id]) | ||
66 | + return forbidden! unless current_person.can_post_content?(community) | ||
67 | + | ||
68 | + klass_type= params[:content_type].nil? ? 'TinyMceArticle' : params[:content_type] | ||
69 | + return forbidden! unless ARTICLE_TYPES.include?(klass_type) | ||
70 | + | ||
71 | + article = klass_type.constantize.new(params[:article]) | ||
72 | + article.last_changed_by = current_person | ||
73 | + article.created_by= current_person | ||
74 | + article.profile = community | ||
75 | + | ||
76 | + if !article.save | ||
77 | + render_api_errors!(article.errors.full_messages) | ||
78 | + end | ||
79 | + present article, :with => Entities::Article | ||
80 | + end | ||
81 | + | ||
82 | + end | ||
83 | + end | ||
84 | + | ||
85 | + end | ||
86 | + | ||
87 | + resource :people do | ||
88 | + segment '/:person_id' do | ||
89 | + resource :articles do | ||
90 | + get do | ||
91 | + person = environment.people.find(params[:person_id]) | ||
92 | + articles = select_filtered_collection_of(person, 'articles', params) | ||
93 | + articles = articles.display_filter(current_person, person) | ||
94 | + present articles, :with => Entities::Article | ||
95 | + end | ||
96 | + | ||
97 | + get ':id' do | ||
98 | + person = environment.people.find(params[:person_id]) | ||
99 | + article = find_article(person.articles, params[:id]) | ||
100 | + present article, :with => Entities::Article | ||
101 | + end | ||
102 | + | ||
103 | + post do | ||
104 | + person = environment.people.find(params[:person_id]) | ||
105 | + return forbidden! unless current_person.can_post_content?(person) | ||
106 | + | ||
107 | + klass_type= params[:content_type].nil? ? 'TinyMceArticle' : params[:content_type] | ||
108 | + return forbidden! unless ARTICLE_TYPES.include?(klass_type) | ||
109 | + | ||
110 | + article = klass_type.constantize.new(params[:article]) | ||
111 | + article.last_changed_by = current_person | ||
112 | + article.created_by= current_person | ||
113 | + article.profile = person | ||
114 | + | ||
115 | + if !article.save | ||
116 | + render_api_errors!(article.errors.full_messages) | ||
117 | + end | ||
118 | + present article, :with => Entities::Article | ||
119 | + end | ||
120 | + | ||
121 | + end | ||
122 | + end | ||
123 | + | ||
124 | + end | ||
125 | + | ||
126 | + resource :enterprises do | ||
127 | + segment '/:enterprise_id' do | ||
128 | + resource :articles do | ||
129 | + get do | ||
130 | + enterprise = environment.enterprises.find(params[:enterprise_id]) | ||
131 | + articles = select_filtered_collection_of(enterprise, 'articles', params) | ||
132 | + articles = articles.display_filter(current_person, enterprise) | ||
133 | + present articles, :with => Entities::Article | ||
134 | + end | ||
135 | + | ||
136 | + get ':id' do | ||
137 | + enterprise = environment.enterprises.find(params[:enterprise_id]) | ||
138 | + article = find_article(enterprise.articles, params[:id]) | ||
139 | + present article, :with => Entities::Article | ||
140 | + end | ||
141 | + | ||
142 | + post do | ||
143 | + enterprise = environment.enterprises.find(params[:enterprise_id]) | ||
144 | + return forbidden! unless current_person.can_post_content?(enterprise) | ||
145 | + | ||
146 | + klass_type= params[:content_type].nil? ? 'TinyMceArticle' : params[:content_type] | ||
147 | + return forbidden! unless ARTICLE_TYPES.include?(klass_type) | ||
148 | + | ||
149 | + article = klass_type.constantize.new(params[:article]) | ||
150 | + article.last_changed_by = current_person | ||
151 | + article.created_by= current_person | ||
152 | + article.profile = enterprise | ||
153 | + | ||
154 | + if !article.save | ||
155 | + render_api_errors!(article.errors.full_messages) | ||
156 | + end | ||
157 | + present article, :with => Entities::Article | ||
158 | + end | ||
159 | + | ||
160 | + end | ||
161 | + end | ||
162 | + | ||
163 | + end | ||
164 | + | ||
165 | + | ||
166 | + end | ||
167 | + end | ||
168 | + end | ||
169 | +end |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + class Categories < Grape::API | ||
5 | + before { authenticate! } | ||
6 | + | ||
7 | + resource :categories do | ||
8 | + | ||
9 | + get do | ||
10 | + type = params[:category_type] | ||
11 | + categories = type.nil? ? environment.categories : environment.categories.find(:all, :conditions => {:type => type}) | ||
12 | + present categories, :with => Entities::Category | ||
13 | + end | ||
14 | + | ||
15 | + desc "Return the category by id" | ||
16 | + get ':id' do | ||
17 | + present environment.categories.find(params[:id]), :with => Entities::Category | ||
18 | + end | ||
19 | + | ||
20 | + end | ||
21 | + | ||
22 | + end | ||
23 | + end | ||
24 | + end | ||
25 | +end |
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + class Comments < Grape::API | ||
5 | + before { authenticate! } | ||
6 | + | ||
7 | + resource :articles do | ||
8 | + # Collect comments from articles | ||
9 | + # | ||
10 | + # Parameters: | ||
11 | + # reference_id - comment id used as reference to collect comment | ||
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 /articles/12/comments?oldest&limit=10&reference_id=23 | ||
17 | + get ":id/comments" do | ||
18 | + | ||
19 | + conditions = make_conditions_with_parameter(params) | ||
20 | + article = find_article(environment.articles, params[:id]) | ||
21 | + | ||
22 | + if params[:reference_id] | ||
23 | + comments = article.comments.send("#{params.key?(:oldest) ? 'older_than' : 'newer_than'}", params[:reference_id]).reorder("created_at DESC").find(:all, :conditions => conditions, :limit => limit) | ||
24 | + else | ||
25 | + comments = article.comments.reorder("created_at DESC").find(:all, :conditions => conditions, :limit => limit) | ||
26 | + end | ||
27 | + present comments, :with => Entities::Comment | ||
28 | + | ||
29 | + end | ||
30 | + | ||
31 | + get ":id/comments/:comment_id" do | ||
32 | + article = find_article(environment.articles, params[:id]) | ||
33 | + present article.comments.find(params[:comment_id]), :with => Entities::Comment | ||
34 | + end | ||
35 | + | ||
36 | + # Example Request: | ||
37 | + # POST api/v1/articles/12/comments?private_toke=234298743290432&body=new comment | ||
38 | + post ":id/comments" do | ||
39 | + article = find_article(environment.articles, params[:id]) | ||
40 | + present article.comments.create(:author => current_person, :body => params[:body]), :with => Entities::Comment | ||
41 | + end | ||
42 | + end | ||
43 | + | ||
44 | + end | ||
45 | + end | ||
46 | + end | ||
47 | +end |
@@ -0,0 +1,72 @@ | @@ -0,0 +1,72 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + class Communities < Grape::API | ||
5 | + before { authenticate! } | ||
6 | + | ||
7 | + resource :communities do | ||
8 | + | ||
9 | + # Collect comments from articles | ||
10 | + # | ||
11 | + # Parameters: | ||
12 | + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created | ||
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 /communities?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10 | ||
18 | + # GET /communities?reference_id=10&limit=10&oldest | ||
19 | + get do | ||
20 | + communities = select_filtered_collection_of(environment, 'communities', params) | ||
21 | + communities = communities.visible_for_person(current_person) | ||
22 | + present communities, :with => Entities::Community | ||
23 | + end | ||
24 | + | ||
25 | + | ||
26 | + # Example Request: | ||
27 | + # POST api/v1/communties?private_token=234298743290432&community[name]=some_name | ||
28 | + post do | ||
29 | + params[:community] ||= {} | ||
30 | + begin | ||
31 | + community = Community.create_after_moderation(current_person, params[:community].merge({:environment => environment})) | ||
32 | + rescue | ||
33 | + community = Community.new(params[:community]) | ||
34 | + end | ||
35 | + | ||
36 | + if !community.save | ||
37 | + render_api_errors!(community.errors.full_messages) | ||
38 | + end | ||
39 | + | ||
40 | + present community, :with => Entities::Community | ||
41 | + end | ||
42 | + | ||
43 | + get ':id' do | ||
44 | + community = environment.communities.visible.find_by_id(params[:id]) | ||
45 | + present community, :with => Entities::Community | ||
46 | + end | ||
47 | + | ||
48 | + end | ||
49 | + | ||
50 | + resource :people do | ||
51 | + | ||
52 | + segment '/:person_id' do | ||
53 | + | ||
54 | + resource :communities do | ||
55 | + | ||
56 | + get do | ||
57 | + person = environment.people.find(params[:person_id]) | ||
58 | + communities = select_filtered_collection_of(person, 'communities', params) | ||
59 | + communities = communities.visible | ||
60 | + present communities, :with => Entities::Community | ||
61 | + end | ||
62 | + | ||
63 | + end | ||
64 | + | ||
65 | + end | ||
66 | + | ||
67 | + end | ||
68 | + | ||
69 | + end | ||
70 | + end | ||
71 | + end | ||
72 | +end |
@@ -0,0 +1,56 @@ | @@ -0,0 +1,56 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + class Enterprises < Grape::API | ||
5 | + before { authenticate! } | ||
6 | + | ||
7 | + resource :enterprises do | ||
8 | + | ||
9 | + # Collect comments from articles | ||
10 | + # | ||
11 | + # Parameters: | ||
12 | + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created | ||
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 /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_for_person(current_person) | ||
22 | + present enterprises, :with => Entities::Enterprise | ||
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 | ||
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 | ||
43 | + present enterprises, :with => Entities::Enterprise | ||
44 | + end | ||
45 | + | ||
46 | + end | ||
47 | + | ||
48 | + end | ||
49 | + | ||
50 | + end | ||
51 | + | ||
52 | + | ||
53 | + end | ||
54 | + end | ||
55 | + end | ||
56 | +end |
@@ -0,0 +1,42 @@ | @@ -0,0 +1,42 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + class People < Grape::API | ||
5 | + before { authenticate! } | ||
6 | + | ||
7 | + resource :people do | ||
8 | + | ||
9 | + # Collect comments from articles | ||
10 | + # | ||
11 | + # Parameters: | ||
12 | + # from - date where the search will begin. If nothing is passed the default date will be the date of the first article created | ||
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 /people?from=2013-04-04-14:41:43&until=2014-04-04-14:41:43&limit=10 | ||
18 | + # GET /people?reference_id=10&limit=10&oldest | ||
19 | + get do | ||
20 | + people = select_filtered_collection_of(environment, 'people', params) | ||
21 | + people = people.visible_for_person(current_person) | ||
22 | + present people, :with => Entities::Person | ||
23 | + end | ||
24 | + | ||
25 | + desc "Return the person information" | ||
26 | + get ':id' do | ||
27 | + person = environment.people.visible.find_by_id(params[:id]) | ||
28 | + present person, :with => Entities::Person | ||
29 | + end | ||
30 | + | ||
31 | + desc "Return the person friends" | ||
32 | + get ':id/friends' do | ||
33 | + friends = current_person.friends.visible | ||
34 | + present friends, :with => Entities::Person | ||
35 | + end | ||
36 | + | ||
37 | + end | ||
38 | + | ||
39 | + end | ||
40 | + end | ||
41 | + end | ||
42 | +end |
@@ -0,0 +1,48 @@ | @@ -0,0 +1,48 @@ | ||
1 | +module Noosfero | ||
2 | + module API | ||
3 | + module V1 | ||
4 | + class Users < Grape::API | ||
5 | + before { authenticate! } | ||
6 | + | ||
7 | + resource :users do | ||
8 | + | ||
9 | + #FIXME make the pagination | ||
10 | + #FIXME put it on environment context | ||
11 | + get do | ||
12 | + present environment.users, :with => Entities::User | ||
13 | + end | ||
14 | + | ||
15 | + # Example Request: | ||
16 | + # POST api/v1/users?user[login]=some_login&user[password]=some | ||
17 | + post do | ||
18 | + user = User.new(params[:user]) | ||
19 | + user.terms_of_use = environment.terms_of_use | ||
20 | + user.environment = environment | ||
21 | + if !user.save | ||
22 | + render_api_errors!(user.errors.full_messages) | ||
23 | + end | ||
24 | + | ||
25 | + present user, :with => Entities::User | ||
26 | + end | ||
27 | + | ||
28 | + get ":id" do | ||
29 | + present environment.users.find_by_id(params[:id]), :with => Entities::User | ||
30 | + end | ||
31 | + | ||
32 | + get ":id/permissions" do | ||
33 | + user = environment.users.find(params[:id]) | ||
34 | + output = {} | ||
35 | + user.person.role_assignments.map do |role_assigment| | ||
36 | + if role_assigment.resource.respond_to?(:identifier) && role_assigment.resource.identifier == params[:profile] | ||
37 | + output[:permissions] = role_assigment.role.permissions | ||
38 | + end | ||
39 | + end | ||
40 | + present output | ||
41 | + end | ||
42 | + | ||
43 | + end | ||
44 | + | ||
45 | + end | ||
46 | + end | ||
47 | + end | ||
48 | +end |
test/unit/api/helpers_test.rb
1 | require File.dirname(__FILE__) + '/test_helper' | 1 | require File.dirname(__FILE__) + '/test_helper' |
2 | +require File.expand_path(File.dirname(__FILE__) + "/../../../lib/noosfero/api/helpers") | ||
2 | 3 | ||
3 | class APITest < ActiveSupport::TestCase | 4 | class APITest < ActiveSupport::TestCase |
4 | 5 | ||
5 | - include API::APIHelpers | 6 | + include Noosfero::API::APIHelpers |
6 | 7 | ||
7 | should 'get the current user with valid token' do | 8 | should 'get the current user with valid token' do |
8 | user = create_user('someuser') | 9 | user = create_user('someuser') |
test/unit/api/test_helper.rb