diff --git a/app/models/article.rb b/app/models/article.rb index 1ce070a..04516a7 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -790,12 +790,6 @@ class Article < ActiveRecord::Base true end - #FIXME make this test - #Define which parameters will be returned in json object - def as_json(options = {}) - super(:only => [:id, :name, :body, :created_at], :methods => [:title]) - end - private def sanitize_tag_list diff --git a/app/models/user.rb b/app/models/user.rb index c44a4d5..e9043e8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,6 @@ require 'digest/sha1' require 'user_activation_job' +require 'securerandom' # User models the system users, and is generated by the acts_as_authenticated # Rails generator. @@ -119,6 +120,18 @@ class User < ActiveRecord::Base self.update_attribute :last_login_at, Time.now end + #FIXME make this test + def generate_private_token! + self.private_token = SecureRandom.hex + self.private_token_generated_at = DateTime.now + save(false) + end + + #FIXME make this test + def private_token_expired? + self.generate_private_token! if self.private_token.nil? || (self.private_token_generated_at + 2.weeks < DateTime.now) + end + # Activates the user in the database. def activate return false unless self.person diff --git a/db/migrate/20140407013817_add_private_token_info_to_users.rb b/db/migrate/20140407013817_add_private_token_info_to_users.rb index ed011e0..82b21d2 100644 --- a/db/migrate/20140407013817_add_private_token_info_to_users.rb +++ b/db/migrate/20140407013817_add_private_token_info_to_users.rb @@ -1,6 +1,6 @@ class AddPrivateTokenInfoToUsers < ActiveRecord::Migration def self.up - add_column :users, :private_token + add_column :users, :private_token, :string add_column :users, :private_token_generated_at, :datetime end diff --git a/lib/api/api.rb b/lib/api/api.rb index 0ef7fdf..f0c3617 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -1,4 +1,5 @@ require 'grape' +Dir["#{Rails.root}/lib/api/*.rb"].each {|file| require file} module API class API < Grape::API @@ -9,10 +10,10 @@ module API mount V1::Articles mount V1::Comments + mount V1::Users + mount Session -# helpers APIHelpers - -# require Articles + helpers APIHelpers end end diff --git a/lib/api/entities.rb b/lib/api/entities.rb new file mode 100644 index 0000000..ed5ff0d --- /dev/null +++ b/lib/api/entities.rb @@ -0,0 +1,27 @@ +module API + module Entities + class Article < Grape::Entity + expose :id, :name, :body, :created_at +# expose :is_admin?, as: :is_admin + +# expose :avatar_url do |user, options| +# if user.avatar.present? +# user.avatar.url +# end +# end + end + + class Comment < Grape::Entity + expose :author_id, :body, :title, :created_at + end + + class User < Grape::Entity + expose :login + end + + class UserLogin < User + expose :private_token + end + + end +end diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb new file mode 100644 index 0000000..dc76c27 --- /dev/null +++ b/lib/api/helpers.rb @@ -0,0 +1,108 @@ +module API + module APIHelpers + PRIVATE_TOKEN_PARAM = :private_token + + def current_user + private_token = params[PRIVATE_TOKEN_PARAM].to_s + @current_user ||= User.find_by_private_token(private_token) + @current_user = nil if !@current_user.nil? && @current_user.private_token_expired? + @current_user + end + + def logout + @current_user = nil + end + + +# def paginate(relation) +# per_page = params[:per_page].to_i +# paginated = relation.page(params[:page]).per(per_page) +# add_pagination_headers(paginated, per_page) +# +# paginated +# end + + def authenticate! + unauthorized! unless current_user + end + +# def authenticated_as_admin! +# forbidden! unless current_user.is_admin? +# end +# +# def authorize! action, subject +# unless abilities.allowed?(current_user, action, subject) +# forbidden! +# end +# end +# +# def can?(object, action, subject) +# abilities.allowed?(object, action, subject) +# end + + # Checks the occurrences of required attributes, each attribute must be present in the params hash + # or a Bad Request error is invoked. + # + # Parameters: + # keys (required) - A hash consisting of keys that must be present + def required_attributes!(keys) + keys.each do |key| + bad_request!(key) unless params[key].present? + end + end + + def attributes_for_keys(keys) + attrs = {} + keys.each do |key| + attrs[key] = params[key] if params[key].present? or (params.has_key?(key) and params[key] == false) + end + attrs + end + + # error helpers + + def forbidden! + render_api_error!('403 Forbidden', 403) + end + + def bad_request!(attribute) + message = ["400 (Bad request)"] + message << "\"" + attribute.to_s + "\" not given" + render_api_error!(message.join(' '), 400) + end + + def not_found!(resource = nil) + message = ["404"] + message << resource if resource + message << "Not Found" + render_api_error!(message.join(' '), 404) + end + + def unauthorized! + render_api_error!('401 Unauthorized', 401) + end + + def not_allowed! + render_api_error!('Method Not Allowed', 405) + end + + def render_api_error!(message, status) + error!({'message' => message}, status) + end + +# private +# +# def add_pagination_headers(paginated, per_page) +# request_url = request.url.split('?').first +# +# links = [] +# links << %(<#{request_url}?page=#{paginated.current_page - 1}&per_page=#{per_page}>; rel="prev") unless paginated.first_page? +# links << %(<#{request_url}?page=#{paginated.current_page + 1}&per_page=#{per_page}>; rel="next") unless paginated.last_page? +# links << %(<#{request_url}?page=1&per_page=#{per_page}>; rel="first") +# links << %(<#{request_url}?page=#{paginated.total_pages}&per_page=#{per_page}>; rel="last") +# +# header 'Link', links.join(', ') +# end + + end +end diff --git a/lib/api/session.rb b/lib/api/session.rb new file mode 100644 index 0000000..ffbab2a --- /dev/null +++ b/lib/api/session.rb @@ -0,0 +1,60 @@ +module API + +# require 'api/validations/uniqueness' + + # Users API + class Session < Grape::API +#params do +# requires :login, :uniqueness => true +#end + + # Login to get token + # + # Parameters: + # login (*required) - user login or email + # password (required) - user password + # + # Example Request: + # POST /session + get "/login" do +# post "/session" do +environment = nil #FIXME load the correct environment create a method in helper + user ||= User.authenticate(params[:login], params[:password], environment) + + return unauthorized! unless user + user.generate_private_token! + present user, :with => Entities::UserLogin + end + + # Create user. + # + # Parameters: + # email (required) - Email + # password (required) - Password + # name - Name + # Example Request: + # POST /users +# post do + get "register" do + required_attributes! [:email, :login, :password] + attrs = attributes_for_keys [:email, :login, :password] + attrs[:password_confirmation] = attrs[:password] + user = User.new(attrs) +begin + if user.save + present user, :with => Entities::User + else + not_found! + end +rescue +# not_found! +#FIXME See why notfound is not working +{} +end +# user + end + + + + end +end diff --git a/lib/api/v1/articles.rb b/lib/api/v1/articles.rb index c35499c..9a49cf2 100644 --- a/lib/api/v1/articles.rb +++ b/lib/api/v1/articles.rb @@ -1,34 +1,50 @@ module API module V1 - class Articles < Grape::API - - resource :articles do + class Articles < Grape::API - get do - first_update = DateTime.parse(params[:first_update]) if params[:first_update] - last_update = DateTime.parse(params[:last_update]) if params[:last_update] + before { authenticate! } + + resource :articles do - if first_update.nil? - begin_date = Article.first.created_at - end_date = last_update.nil? ? DateTime.now : last_update - else - begin_date = first_update - end_date = DateTime.now + #FIXME See if it's possible to use pagination instead of DateTime control. see a way to use this pagination logic genericaly + get do + first_update = DateTime.parse(params[:first_update]) if params[:first_update] + last_update = DateTime.parse(params[:last_update]) if params[:last_update] + + if first_update.nil? + begin_date = Article.first.created_at + end_date = last_update.nil? ? DateTime.now : last_update + else + begin_date = first_update + end_date = DateTime.now + end + + limit = params[:limit].to_i + limit = 20 if limit == 0 + conditions = {} + conditions[:type] = params[:content_type] if params[:content_type] #FIXME validate type + conditions[:created_at] = begin_date...end_date + present Article.find(:all, :conditions => conditions, :offset => (first_update.nil? ? 0 : 1), :limit => limit, :order => "created_at DESC"), :with => Entities::Article + end + + #FIXME load article with environment context + get ':id' do + present Article.find(params[:id]), :with => Entities::Article end - limit = params[:limit].to_i - limit = 20 if limit == 0 - conditions = {} - conditions[:type] = params[:content_type] if params[:content_type] #FIXME validate type - conditions[:created_at] = begin_date...end_date - Article.find(:all, :conditions => conditions, :offset => (first_update.nil? ? 0 : 1), :limit => limit, :order => "created_at DESC") - end - - get ':id' do - Article.find(params[:id]) + #FIXME load article with environment context + get ':id/children' do + present Article.find(params[:id]).children, :with => Entities::Article + end + + #FIXME load article with environment context + get ':id/children/:child_id' do + present Article.find(params[:id]).children.find(params[:child_id]), :with => Entities::Article + end + + end + end - - end end end diff --git a/lib/api/v1/comments.rb b/lib/api/v1/comments.rb index 6c6d9ad..3b9f386 100644 --- a/lib/api/v1/comments.rb +++ b/lib/api/v1/comments.rb @@ -1,15 +1,18 @@ module API module V1 class Comments < Grape::API + + before { authenticate! } resource :articles do - + #FIXME make the pagination + #FIXME put it on environment context get ":id/comments" do - Article.find(params[:id]).comments + present Article.find(params[:id]).comments, :with => Entities::Comment end get ":id/comments/:comment_id" do - Article.find(params[:id]).comments.find(params[:comment_id]) + present Article.find(params[:id]).comments.find(params[:comment_id]), :with => Entities::Comment end end diff --git a/lib/api/v1/users.rb b/lib/api/v1/users.rb new file mode 100644 index 0000000..bcbbb87 --- /dev/null +++ b/lib/api/v1/users.rb @@ -0,0 +1,43 @@ +module API + module V1 + class Users < Grape::API + + before { authenticate! } + + resource :users do + + #FIXME make the pagination + #FIXME put it on environment context +# get do +# Users.all +# end + + get ":id" do + present Article.find(params[:id]).comments.find(params[:comment_id]), :with => Entities::User + end + + # Create user. + # + # Parameters: + # email (required) - Email + # password (required) - Password + # name - Name + # Example Request: + # POST /users +# post do + get do +# authenticated_as_admin! + required_attributes! [:email, :login, :password] + attrs = attributes_for_keys [:email, :login, :password] + user = User.new(attrs) + if user.save + present user, :with => Entities::User + else + not_found! + end + end + end + + end + end +end -- libgit2 0.21.2