API Branch Final Cleanup Before PR

This commit is contained in:
Hank Grabowski 2018-12-30 11:34:53 -05:00
parent 8ffb814166
commit f07912ebdd
50 changed files with 859 additions and 455 deletions

View file

@ -14,14 +14,14 @@ module Api
def index def index
aspects_query = current_user.aspects aspects_query = current_user.aspects
aspects_page = index_pager(aspects_query).response aspects_page = index_pager(aspects_query).response
aspects_page[:data] = aspects_page[:data].map {|a| AspectPresenter.new(a).as_api_json(false) } aspects_page[:data] = aspects_page[:data].map {|a| aspect_as_json(a, false) }
render json: aspects_page render json: aspects_page
end end
def show def show
aspect = current_user.aspects.where(id: params[:id]).first aspect = current_user.aspects.where(id: params[:id]).first
if aspect if aspect
render json: AspectPresenter.new(aspect).as_api_json(true) render json: aspect_as_json(aspect, true)
else else
render json: I18n.t("api.endpoint_errors.aspects.not_found"), status: :not_found render json: I18n.t("api.endpoint_errors.aspects.not_found"), status: :not_found
end end
@ -31,7 +31,7 @@ module Api
params.require(%i[name chat_enabled]) params.require(%i[name chat_enabled])
aspect = current_user.aspects.build(name: params[:name], chat_enabled: params[:chat_enabled]) aspect = current_user.aspects.build(name: params[:name], chat_enabled: params[:chat_enabled])
if aspect&.save if aspect&.save
render json: AspectPresenter.new(aspect).as_api_json(true) render json: aspect_as_json(aspect, true)
else else
render json: I18n.t("api.endpoint_errors.aspects.cant_create"), status: :unprocessable_entity render json: I18n.t("api.endpoint_errors.aspects.cant_create"), status: :unprocessable_entity
end end
@ -45,7 +45,7 @@ module Api
if !aspect if !aspect
render json: I18n.t("api.endpoint_errors.aspects.cant_update"), status: :not_found render json: I18n.t("api.endpoint_errors.aspects.cant_update"), status: :not_found
elsif aspect.update!(aspect_params(true)) elsif aspect.update!(aspect_params(true))
render json: AspectPresenter.new(aspect).as_api_json(true) render json: aspect_as_json(aspect, true)
else else
render json: I18n.t("api.endpoint_errors.aspects.cant_update"), status: :unprocessable_entity render json: I18n.t("api.endpoint_errors.aspects.cant_update"), status: :unprocessable_entity
end end
@ -67,8 +67,13 @@ module Api
def aspect_params(allow_order=false) def aspect_params(allow_order=false)
parameters = params.permit(:name, :chat_enabled) parameters = params.permit(:name, :chat_enabled)
parameters[:order_id] = params[:order] if params.has_key?(:order) && allow_order parameters[:order_id] = params[:order] if params.has_key?(:order) && allow_order
parameters parameters
end end
def aspect_as_json(aspect, as_full)
AspectPresenter.new(aspect).as_api_json(as_full)
end
end end
end end
end end

View file

@ -3,8 +3,8 @@
module Api module Api
module V1 module V1
class CommentsController < Api::V1::BaseController class CommentsController < Api::V1::BaseController
before_action do before_action except: %i[create destroy] do
require_access_token %w[interactions public:read] require_access_token %w[public:read]
end end
before_action only: %i[create destroy] do before_action only: %i[create destroy] do
@ -20,18 +20,19 @@ module Api
end end
def create def create
@comment = comment_service.create(params[:post_id], params[:body]) find_post
comment = comment_as_json(@comment) comment = comment_service.create(params.require(:post_id), params.require(:body))
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
render json: I18n.t("api.endpoint_errors.posts.post_not_found"), status: :not_found render json: I18n.t("api.endpoint_errors.posts.post_not_found"), status: :not_found
else else
render json: comment, status: :created render json: comment_as_json(comment), status: :created
end end
def index def index
find_post find_post
comments_query = comment_service.find_for_post(params[:post_id]) comments_query = comment_service.find_for_post(params.require(:post_id))
params[:after] = Time.utc(1900).iso8601 if params.permit(:before, :after).empty? params[:after] = Time.utc(1900).iso8601 if params.permit(:before, :after).empty?
comments_page = time_pager(comments_query).response comments_page = time_pager(comments_query).response
comments_page[:data] = comments_page[:data].map {|x| comment_as_json(x) } comments_page[:data] = comments_page[:data].map {|x| comment_as_json(x) }
render json: comments_page render json: comments_page
@ -39,7 +40,7 @@ module Api
def destroy def destroy
find_post find_post
if comment_and_post_validate(params[:post_id], params[:id]) if comment_and_post_validate(params.require(:post_id), params[:id])
comment_service.destroy!(params[:id]) comment_service.destroy!(params[:id])
head :no_content head :no_content
end end
@ -52,6 +53,7 @@ module Api
post_guid = params.require(:post_id) post_guid = params.require(:post_id)
comment_guid = params.require(:comment_id) comment_guid = params.require(:comment_id)
return unless comment_and_post_validate(post_guid, comment_guid) return unless comment_and_post_validate(post_guid, comment_guid)
reason = params.require(:reason) reason = params.require(:reason)
comment = comment_service.find!(comment_guid) comment = comment_service.find!(comment_guid)
report = current_user.reports.new( report = current_user.reports.new(

View file

@ -18,7 +18,7 @@ module Api
end end
def index def index
contacts_query = aspects_membership_service.contacts_in_aspect(params[:aspect_id]) contacts_query = aspects_membership_service.contacts_in_aspect(params.require(:aspect_id))
contacts_page = index_pager(contacts_query).response contacts_page = index_pager(contacts_query).response
contacts_page[:data] = contacts_page[:data].map do |c| contacts_page[:data] = contacts_page[:data].map do |c|
ContactPresenter.new(c, current_user).as_api_json_without_contact ContactPresenter.new(c, current_user).as_api_json_without_contact
@ -27,9 +27,10 @@ module Api
end end
def create def create
aspect_id = params[:aspect_id] aspect_id = params.require(:aspect_id)
person = Person.find_by(guid: params[:person_guid]) person = Person.find_by(guid: params.require(:person_guid))
aspect_membership = aspects_membership_service.create(aspect_id, person.id) if person.present? aspect_membership = aspects_membership_service.create(aspect_id, person.id) if person.present?
if aspect_membership if aspect_membership
head :no_content head :no_content
else else
@ -40,9 +41,10 @@ module Api
end end
def destroy def destroy
aspect_id = params[:aspect_id] aspect_id = params.require(:aspect_id)
person = Person.find_by(guid: params[:id]) person = Person.find_by(guid: params[:id])
result = aspects_membership_service.destroy_by_ids(aspect_id, person.id) if person.present? result = aspects_membership_service.destroy_by_ids(aspect_id, person.id) if person.present?
if result && result[:success] if result && result[:success]
head :no_content head :no_content
else else

View file

@ -14,10 +14,11 @@ module Api
end end
def index def index
params.permit(:only_after, :only_unread)
mapped_params = {} mapped_params = {}
mapped_params[:only_after] = params[:only_after] if params.has_key?(:only_after) mapped_params[:only_after] = params[:only_after] if params.has_key?(:only_after)
mapped_params[:unread] = params[:only_unread] if params.has_key?(:only_unread) mapped_params[:unread] = params[:only_unread] if params.has_key?(:only_unread)
conversations_query = conversation_service.all_for_user(mapped_params) conversations_query = conversation_service.all_for_user(mapped_params)
conversations_page = pager(conversations_query, "conversations.created_at").response conversations_page = pager(conversations_query, "conversations.created_at").response
conversations_page[:data] = conversations_page[:data].map {|x| conversation_as_json(x) } conversations_page[:data] = conversations_page[:data].map {|x| conversation_as_json(x) }
@ -31,34 +32,27 @@ module Api
def create def create
params.require(%i[subject body recipients]) params.require(%i[subject body recipients])
recipient_ids = params[:recipients].map {|p| Person.find_from_guid_or_username(id: p).id } recipients = recipient_ids
conversation = conversation_service.build( conversation = conversation_service.build(params[:subject], params[:body], recipients)
params[:subject], raise ActiveRecord::RecordInvalid unless conversation_valid?(conversation, recipients)
params[:body],
recipient_ids
)
raise ActiveRecord::RecordInvalid unless conversation.participants.length == (recipient_ids.length + 1)
conversation.save!
Diaspora::Federation::Dispatcher.defer_dispatch(
current_user,
conversation
)
conversation.save!
Diaspora::Federation::Dispatcher.defer_dispatch(current_user, conversation)
render json: conversation_as_json(conversation), status: :created render json: conversation_as_json(conversation), status: :created
rescue ActiveRecord::RecordInvalid, ActionController::ParameterMissing, ActiveRecord::RecordNotFound rescue ActiveRecord::RecordInvalid, ActionController::ParameterMissing, ActiveRecord::RecordNotFound
render json: I18n.t("api.endpoint_errors.conversations.cant_process"), status: :unprocessable_entity render json: I18n.t("api.endpoint_errors.conversations.cant_process"), status: :unprocessable_entity
end end
def destroy def destroy
vis = conversation_service.get_visibility(params[:id]) conversation = conversation_service.get_visibility(params[:id])
vis.destroy! conversation.destroy!
head :no_content head :no_content
end end
private private
def conversation_service def conversation_service
ConversationService.new(current_user) @conversation_service ||= ConversationService.new(current_user)
end end
def conversation_as_json(conversation) def conversation_as_json(conversation)
@ -68,6 +62,14 @@ module Api
def pager(query, sort_field) def pager(query, sort_field)
Api::Paging::RestPaginatorBuilder.new(query, request).time_pager(params, sort_field) Api::Paging::RestPaginatorBuilder.new(query, request).time_pager(params, sort_field)
end end
def recipient_ids
params[:recipients].map {|p| Person.find_from_guid_or_username(id: p).id }
end
def conversation_valid?(conversation, recipients)
conversation.participants.length == (recipients.length + 1)
end
end end
end end
end end

View file

@ -4,7 +4,11 @@ module Api
module V1 module V1
class LikesController < Api::V1::BaseController class LikesController < Api::V1::BaseController
before_action do before_action do
require_access_token %w[interactions public:read] require_access_token %w[public:read]
end
before_action only: %i[create destroy] do
require_access_token %w[interactions]
end end
rescue_from ActiveRecord::RecordNotFound do rescue_from ActiveRecord::RecordNotFound do
@ -16,8 +20,9 @@ module Api
end end
def show def show
post = post_service.find!(params[:post_id]) post = post_service.find!(params.require(:post_id))
raise ActiveRecord::RecordInvalid unless post.public? || private_read? raise ActiveRecord::RecordInvalid unless post.public? || private_read?
likes_query = like_service.find_for_post(params[:post_id]) likes_query = like_service.find_for_post(params[:post_id])
likes_page = index_pager(likes_query).response likes_page = index_pager(likes_query).response
likes_page[:data] = likes_page[:data].map {|x| like_json(x) } likes_page[:data] = likes_page[:data].map {|x| like_json(x) }
@ -25,20 +30,23 @@ module Api
end end
def create def create
post = post_service.find!(params[:post_id]) post = post_service.find!(params.require(:post_id))
raise ActiveRecord::RecordInvalid unless post.public? || private_modify? raise ActiveRecord::RecordInvalid unless post.public? || private_modify?
like_service.create(params[:post_id]) like_service.create(params[:post_id])
rescue ActiveRecord::RecordInvalid => e rescue ActiveRecord::RecordInvalid => e
return render json: I18n.t("api.endpoint_errors.likes.like_exists"), status: :unprocessable_entity if return render json: I18n.t("api.endpoint_errors.likes.like_exists"), status: :unprocessable_entity if
e.message == "Validation failed: Target has already been taken" e.message == "Validation failed: Target has already been taken"
raise raise
else else
head :no_content head :no_content
end end
def destroy def destroy
post = post_service.find!(params[:post_id]) post = post_service.find!(params.require(:post_id))
raise ActiveRecord::RecordInvalid unless post.public? || private_modify? raise ActiveRecord::RecordInvalid unless post.public? || private_modify?
success = like_service.unlike_post(params[:post_id]) success = like_service.unlike_post(params[:post_id])
if success if success
head :no_content head :no_content

View file

@ -12,7 +12,7 @@ module Api
end end
def create def create
conversation = conversation_service.find!(params[:conversation_id]) conversation = conversation_service.find!(params.require(:conversation_id))
text = params.require(:body) text = params.require(:body)
message = current_user.build_message(conversation, text: text) message = current_user.build_message(conversation, text: text)
message.save! message.save!
@ -23,7 +23,7 @@ module Api
end end
def index def index
conversation = conversation_service.find!(params[:conversation_id]) conversation = conversation_service.find!(params.require(:conversation_id))
conversation.set_read(current_user) conversation.set_read(current_user)
messages_page = index_pager(conversation.messages).response messages_page = index_pager(conversation.messages).response
messages_page[:data] = messages_page[:data].map {|x| message_json(x) } messages_page[:data] = messages_page[:data].map {|x| message_json(x) }

View file

@ -23,6 +23,7 @@ module Api
def index def index
after_date = Date.iso8601(params[:only_after]) if params.has_key?(:only_after) after_date = Date.iso8601(params[:only_after]) if params.has_key?(:only_after)
notifications_query = service.index(params[:only_unread], after_date) notifications_query = service.index(params[:only_unread], after_date)
notifications_page = time_pager(notifications_query).response notifications_page = time_pager(notifications_query).response
notifications_page[:data] = notifications_page[:data].map do |note| notifications_page[:data] = notifications_page[:data].map do |note|

View file

@ -22,25 +22,29 @@ module Api
current_user.photos.where(public: true) current_user.photos.where(public: true)
end end
photos_page = time_pager(query).response photos_page = time_pager(query).response
photos_page[:data] = photos_page[:data].map {|photo| PhotoPresenter.new(photo).as_api_json(true) } photos_page[:data] = photos_page[:data].map {|photo| photo_json(photo) }
render json: photos_page render json: photos_page
end end
def show def show
photo = photo_service.visible_photo(params.require(:id)) photo = photo_service.visible_photo(params.require(:id))
raise ActiveRecord::RecordNotFound unless photo raise ActiveRecord::RecordNotFound unless photo
raise ActiveRecord::RecordNotFound unless photo.public? || private_read? raise ActiveRecord::RecordNotFound unless photo.public? || private_read?
render json: PhotoPresenter.new(photo).as_api_json(true)
render json: photo_json(photo)
end end
def create def create
image = params.require(:image) image = params.require(:image)
public_photo = params.has_key?(:aspect_ids) public_photo = params.has_key?(:aspect_ids)
raise RuntimeError unless public_photo || private_modify? raise RuntimeError unless public_photo || private_modify?
base_params = params.permit(:aspect_ids, :pending, :set_profile_photo) base_params = params.permit(:aspect_ids, :pending, :set_profile_photo)
photo = photo_service.create_from_params_and_file(base_params, image) photo = photo_service.create_from_params_and_file(base_params, image)
raise RuntimeError unless photo raise RuntimeError unless photo
render json: PhotoPresenter.new(photo).as_api_json(true)
render json: photo_json(photo)
rescue CarrierWave::IntegrityError, ActionController::ParameterMissing, RuntimeError rescue CarrierWave::IntegrityError, ActionController::ParameterMissing, RuntimeError
render json: I18n.t("api.endpoint_errors.photos.failed_create"), status: :unprocessable_entity render json: I18n.t("api.endpoint_errors.photos.failed_create"), status: :unprocessable_entity
end end
@ -48,7 +52,9 @@ module Api
def destroy def destroy
photo = current_user.photos.where(guid: params[:id]).first photo = current_user.photos.where(guid: params[:id]).first
raise ActiveRecord::RecordNotFound unless photo raise ActiveRecord::RecordNotFound unless photo
raise ActiveRecord::RecordNotFound unless photo.public? || private_modify? raise ActiveRecord::RecordNotFound unless photo.public? || private_modify?
if current_user.retract(photo) if current_user.retract(photo)
head :no_content head :no_content
else else
@ -61,6 +67,10 @@ module Api
def photo_service def photo_service
@photo_service ||= PhotoService.new(current_user) @photo_service ||= PhotoService.new(current_user)
end end
def photo_json(photo)
PhotoPresenter.new(photo).as_api_json(true)
end
end end
end end
end end

View file

@ -20,14 +20,15 @@ module Api
def show def show
post = post_service.find!(params[:id]) post = post_service.find!(params[:id])
raise ActiveRecord::RecordNotFound unless post.public? || private_read? raise ActiveRecord::RecordNotFound unless post.public? || private_read?
render json: post_as_json(post) render json: post_as_json(post)
end end
def create def create
raise StandardError unless params.require(:public) || private_modify?
status_service = StatusMessageCreationService.new(current_user)
creation_params = normalized_create_params creation_params = normalized_create_params
@status_message = status_service.create(creation_params) raise StandardError unless creation_params[:public] || private_modify?
@status_message = creation_service.create(creation_params)
render json: PostPresenter.new(@status_message, current_user).as_api_response render json: PostPresenter.new(@status_message, current_user).as_api_response
rescue StandardError rescue StandardError
render json: I18n.t("api.endpoint_errors.posts.failed_create"), status: :unprocessable_entity render json: I18n.t("api.endpoint_errors.posts.failed_create"), status: :unprocessable_entity
@ -40,6 +41,8 @@ module Api
render json: I18n.t("api.endpoint_errors.posts.failed_delete"), status: :forbidden render json: I18n.t("api.endpoint_errors.posts.failed_delete"), status: :forbidden
end end
private
def normalized_create_params def normalized_create_params
mapped_parameters = { mapped_parameters = {
status_message: { status_message: {
@ -54,8 +57,6 @@ module Api
mapped_parameters mapped_parameters
end end
private
def add_location_params(mapped_parameters) def add_location_params(mapped_parameters)
return unless params.has_key?(:location) return unless params.has_key?(:location)
location = params.require(:location) location = params.require(:location)
@ -65,20 +66,27 @@ module Api
def add_photo_ids(mapped_parameters) def add_photo_ids(mapped_parameters)
return unless params.has_key?(:photos) return unless params.has_key?(:photos)
photo_guids = params[:photos] photo_guids = params[:photos]
return if photo_guids.empty? return if photo_guids.empty?
photo_ids = photo_guids.map {|guid| Photo.find_by!(guid: guid) }
raise InvalidArgument if photo_ids.length != photo_guids.length photos = photo_guids.map {|guid| Photo.find_by!(guid: guid) }
mapped_parameters[:photos] = photo_ids .select {|p| p.author_id == current_user.person.id && p.pending }
raise InvalidArgument if photos.length != photo_guids.length
mapped_parameters[:photos] = photos
end end
def add_poll_params(mapped_parameters) def add_poll_params(mapped_parameters)
return unless params.has_key?(:poll) return unless params.has_key?(:poll)
poll_data = params.require(:poll) poll_data = params.require(:poll)
question = poll_data[:question] question = poll_data[:question]
answers = poll_data[:poll_answers] answers = poll_data[:poll_answers]
raise InvalidArgument if question.blank? raise InvalidArgument if question.blank?
raise InvalidArgument if answers.empty? raise InvalidArgument if answers.empty?
answers.each do |a| answers.each do |a|
raise InvalidArgument if a.blank? raise InvalidArgument if a.blank?
end end
@ -94,6 +102,10 @@ module Api
@post_service ||= PostService.new(current_user) @post_service ||= PostService.new(current_user)
end end
def creation_service
@creation_service ||= StatusMessageCreationService.new(current_user)
end
def post_as_json(post) def post_as_json(post)
PostPresenter.new(post).as_api_response PostPresenter.new(post).as_api_response
end end

View file

@ -20,7 +20,7 @@ module Api
end end
def show def show
reshares_query = reshare_service.find_for_post(params[:post_id]) reshares_query = reshare_service.find_for_post(params.require(:post_id))
reshares_page = index_pager(reshares_query).response reshares_page = index_pager(reshares_query).response
reshares_page[:data] = reshares_page[:data].map do |r| reshares_page[:data] = reshares_page[:data].map do |r|
{ {
@ -32,7 +32,7 @@ module Api
end end
def create def create
reshare = reshare_service.create(params[:post_id]) reshare = reshare_service.create(params.require(:post_id))
rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid, RuntimeError rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid, RuntimeError
render plain: I18n.t("reshares.create.error"), status: :unprocessable_entity render plain: I18n.t("reshares.create.error"), status: :unprocessable_entity
else else

View file

@ -12,30 +12,12 @@ module Api
end end
def user_index def user_index
parameters = params.permit(:tag, :name_or_handle)
raise RuntimeError if parameters.keys.length != 1
people_query = if params.has_key?(:tag)
Person.profile_tagged_with(params[:tag])
else
connected_only = !private_read?
Person.search(
params[:name_or_handle],
current_user,
only_contacts: connected_only,
mutual: connected_only
)
end
user_page = index_pager(people_query).response user_page = index_pager(people_query).response
user_page[:data] = user_page[:data].map {|p| PersonPresenter.new(p).as_api_json } user_page[:data] = user_page[:data].map {|p| PersonPresenter.new(p).as_api_json }
render json: user_page render json: user_page
end end
def post_index def post_index
posts_query = if private_read?
Stream::Tag.new(current_user, params.require(:tag)).posts
else
Stream::Tag.new(nil, params.require(:tag)).posts
end
posts_page = time_pager(posts_query, "posts.created_at", "created_at").response posts_page = time_pager(posts_query, "posts.created_at", "created_at").response
posts_page[:data] = posts_page[:data].map {|post| PostPresenter.new(post).as_api_response } posts_page[:data] = posts_page[:data].map {|post| PostPresenter.new(post).as_api_response }
render json: posts_page render json: posts_page
@ -46,6 +28,31 @@ module Api
def time_pager(query, query_time_field, data_time_field) def time_pager(query, query_time_field, data_time_field)
Api::Paging::RestPaginatorBuilder.new(query, request).time_pager(params, query_time_field, data_time_field) Api::Paging::RestPaginatorBuilder.new(query, request).time_pager(params, query_time_field, data_time_field)
end end
def people_query
parameters = params.permit(:tag, :name_or_handle)
raise RuntimeError if parameters.keys.length != 1
if params.has_key?(:tag)
Person.profile_tagged_with(params[:tag])
else
connected_only = !private_read?
Person.search(
params[:name_or_handle],
current_user,
only_contacts: connected_only,
mutual: connected_only
)
end
end
def posts_query
if private_read?
Stream::Tag.new(current_user, params.require(:tag)).posts
else
Stream::Tag.new(nil, params.require(:tag)).posts
end
end
end end
end end
end end

View file

@ -30,7 +30,7 @@ module Api
private private
def tag_followings_service def tag_followings_service
TagFollowingService.new(current_user) @tag_followings_service ||= TagFollowingService.new(current_user)
end end
end end
end end

View file

@ -37,7 +37,6 @@ module Api
end end
def update def update
raise RuntimeError if params.has_key?(:id)
params_to_update = profile_update_params params_to_update = profile_update_params
if params_to_update && current_user.update_profile(params_to_update) if params_to_update && current_user.update_profile(params_to_update)
render json: PersonPresenter.new(current_user.person, current_user).profile_hash_as_api_json render json: PersonPresenter.new(current_user.person, current_user).profile_hash_as_api_json
@ -49,12 +48,12 @@ module Api
end end
def contacts def contacts
if params[:user_id] != current_user.guid if params.require(:user_id) != current_user.guid
render json: I18n.t("api.endpoint_errors.users.not_found"), status: :not_found render json: I18n.t("api.endpoint_errors.users.not_found"), status: :not_found
return return
end end
contacts_query = AspectsMembershipService.new(current_user).all_contacts contacts_query = aspects_service.all_contacts
contacts_page = index_pager(contacts_query).response contacts_page = index_pager(contacts_query).response
contacts_page[:data] = contacts_page[:data].map {|c| PersonPresenter.new(c.person).as_api_json } contacts_page[:data] = contacts_page[:data].map {|c| PersonPresenter.new(c.person).as_api_json }
render json: contacts_page render json: contacts_page
@ -83,7 +82,13 @@ module Api
private private
def aspects_service
@aspects_service ||= AspectsMembershipService.new(current_user)
end
def profile_update_params def profile_update_params
raise RuntimeError if params.has_key?(:id)
updates = params.permit(:bio, :birthday, :gender, :location, :first_name, :last_name, updates = params.permit(:bio, :birthday, :gender, :location, :first_name, :last_name,
:searchable, :show_profile_info, :nsfw, :tags).to_h || {} :searchable, :show_profile_info, :nsfw, :tags).to_h || {}
if updates.has_key?(:show_profile_info) if updates.has_key?(:show_profile_info)
@ -96,7 +101,9 @@ module Api
def process_tags_updates(updates) def process_tags_updates(updates)
return unless params.has_key?(:tags) return unless params.has_key?(:tags)
raise RuntimeError if params[:tags].length > Profile::MAX_TAGS raise RuntimeError if params[:tags].length > Profile::MAX_TAGS
tags = params[:tags].map {|tag| "#" + normalize_tag_name(tag) }.join(" ") tags = params[:tags].map {|tag| "#" + normalize_tag_name(tag) }.join(" ")
updates[:tag_string] = tags updates[:tag_string] = tags
updates.delete(:tags) updates.delete(:tags)

View file

@ -6,7 +6,8 @@ class AspectMembershipPresenter < BasePresenter
end end
def base_hash def base_hash
{ id: @membership.id, {
id: @membership.id,
aspect: AspectPresenter.new(@membership.aspect).as_json, aspect: AspectPresenter.new(@membership.aspect).as_json,
} }
end end

View file

@ -2,15 +2,16 @@
class ContactPresenter < BasePresenter class ContactPresenter < BasePresenter
def base_hash def base_hash
{ id: id, {
id: id,
person_id: person_id person_id: person_id
} }
end end
def full_hash def full_hash
base_hash.merge({ base_hash.merge(
aspect_memberships: aspect_memberships.map{ |membership| AspectMembershipPresenter.new(membership).base_hash } aspect_memberships: aspect_memberships.map{ |membership| AspectMembershipPresenter.new(membership).base_hash }
}) )
end end
def full_hash_with_person def full_hash_with_person
@ -20,6 +21,7 @@ class ContactPresenter < BasePresenter
def as_api_json_without_contact def as_api_json_without_contact
PersonPresenter.new(person, current_user).as_api_json PersonPresenter.new(person, current_user).as_api_json
end end
private private
def person_without_contact def person_without_contact

View file

@ -3,7 +3,7 @@
class NotificationPresenter < BasePresenter class NotificationPresenter < BasePresenter
def as_api_json(include_target=true) def as_api_json(include_target=true)
data = base_hash data = base_hash
data = data.merge(target: target_json) if include_target && target data = data.merge(target: target_json) if include_target && linked_object
data data
end end
@ -20,10 +20,9 @@ class NotificationPresenter < BasePresenter
end end
def target_json def target_json
{ json = {guid: linked_object.guid}
guid: target.guid, json[:author] = PersonPresenter.new(linked_object.author).as_api_json if linked_object.author
author: PersonPresenter.new(target.author).as_api_json json
}
end end
def creators_json def creators_json

View file

@ -101,6 +101,7 @@ class PersonPresenter < BasePresenter
def aspects_detailed def aspects_detailed
return [] unless current_user_person_contact return [] unless current_user_person_contact
aspects_for_person = current_user.aspects_with_person(@presentable) aspects_for_person = current_user.aspects_with_person(@presentable)
aspects_for_person.map {|a| AspectPresenter.new(a).as_api_json(false) } aspects_for_person.map {|a| AspectPresenter.new(a).as_api_json(false) }
end end

View file

@ -30,6 +30,7 @@ class PostInteractionPresenter
def participations def participations
return @post.participations.none unless @current_user return @post.participations.none unless @current_user
@post.participations.where(author: @current_user.person) @post.participations.where(author: @current_user.person)
end end

View file

@ -53,6 +53,7 @@ class AspectsMembershipService
def destroy(aspect, contact) def destroy(aspect, contact)
raise ActiveRecord::RecordNotFound unless aspect.present? && contact.present? raise ActiveRecord::RecordNotFound unless aspect.present? && contact.present?
raise Diaspora::NotMine unless @user.mine?(aspect) && @user.mine?(contact) raise Diaspora::NotMine unless @user.mine?(aspect) && @user.mine?(contact)
membership = contact.aspect_memberships.where(aspect_id: aspect.id).first membership = contact.aspect_memberships.where(aspect_id: aspect.id).first

View file

@ -12,28 +12,16 @@ class PhotoService
def create_from_params_and_file(base_params, uploaded_file) def create_from_params_and_file(base_params, uploaded_file)
photo_params = build_params(base_params) photo_params = build_params(base_params)
raise RuntimeError if @deny_raw_files && !confirm_uploaded_file_settings(uploaded_file) raise RuntimeError if @deny_raw_files && !confirm_uploaded_file_settings(uploaded_file)
photo_params[:user_file] = uploaded_file photo_params[:user_file] = uploaded_file
photo = @user.build_post(:photo, photo_params)
raise RuntimeError unless photo.save
@photo = @user.build_post(:photo, photo_params) send_messages(photo, photo_params)
raise RuntimeError unless @photo.save update_profile_photo(photo) if photo_params[:set_profile_photo]
unless @photo.pending
unless @photo.public?
aspects = @user.aspects_from_ids(photo_params[:aspect_ids])
@user.add_to_streams(@photo, aspects)
end
@user.dispatch_post(@photo, to: photo_params[:aspect_ids])
end
if photo_params[:set_profile_photo] photo
profile_params = {image_url: @photo.url(:thumb_large),
image_url_medium: @photo.url(:thumb_medium),
image_url_small: @photo.url(:thumb_small)}
@user.update_profile(profile_params)
end
@photo
end end
private private
@ -53,7 +41,29 @@ class PhotoService
return false return false
end end
return false if uploaded_file.original_filename.empty? return false if uploaded_file.original_filename.empty?
return false if uploaded_file.content_type.empty? return false if uploaded_file.content_type.empty?
true true
end end
def send_messages(photo, photo_params)
send_to_streams(photo, photo_params) unless photo.pending && photo.public?
@user.dispatch_post(photo, to: photo_params[:aspect_ids]) unless photo.pending
end
def update_profile_photo(photo)
profile_params = {
image_url: photo.url(:thumb_large),
image_url_medium: photo.url(:thumb_medium),
image_url_small: photo.url(:thumb_small)
}
@user.update_profile(profile_params)
end
def send_to_streams(photo, photo_params)
aspects = @user.aspects_from_ids(photo_params[:aspect_ids])
@user.add_to_streams(photo, aspects)
end
end end

View file

@ -42,6 +42,7 @@ class PostService
find_public!(post_id) find_public!(post_id)
end end
raise Diaspora::NotMine unless post.author == user.person raise Diaspora::NotMine unless post.author == user.person
user.retract(post) user.retract(post)
end end

View file

@ -11,8 +11,8 @@ class TagFollowingService
tag = ActsAsTaggableOn::Tag.find_or_create_by(name: name_normalized) tag = ActsAsTaggableOn::Tag.find_or_create_by(name: name_normalized)
tag_following = @user.tag_followings.new(tag_id: tag.id) tag_following = @user.tag_followings.new(tag_id: tag.id)
raise "Can't process tag entity" unless tag_following.save raise "Can't process tag entity" unless tag_following.save
tag tag
end end

View file

@ -19,14 +19,18 @@ module Api
def next_page(for_url=true) def next_page(for_url=true)
page_data page_data
return nil if for_url && @current_page == @max_page return nil if for_url && @current_page == @max_page
return "page=#{@current_page + 1}" if for_url return "page=#{@current_page + 1}" if for_url
IndexPaginator.new(@query_base, @current_page + 1, @limit) IndexPaginator.new(@query_base, @current_page + 1, @limit)
end end
def previous_page(for_url=true) def previous_page(for_url=true)
page_data page_data
return nil if for_url && @current_page == 1 return nil if for_url && @current_page == 1
return "page=#{@current_page - 1}" if for_url return "page=#{@current_page - 1}" if for_url
IndexPaginator.new(@query_base, @current_page - 1, @limit) IndexPaginator.new(@query_base, @current_page - 1, @limit)
end end

View file

@ -28,8 +28,10 @@ module Api
previous_page = @pager.previous_page previous_page = @pager.previous_page
links = {} links = {}
links[:previous] = link_builder(previous_page) if previous_page links[:previous] = link_builder(previous_page) if previous_page
next_page = @pager.next_page next_page = @pager.next_page
links[:next] = link_builder(next_page) if next_page links[:next] = link_builder(next_page) if next_page
links links
end end
@ -40,6 +42,7 @@ module Api
def filtered_original_parameters def filtered_original_parameters
@pager.filter_parameters(@query_parameters) @pager.filter_parameters(@query_parameters)
return "" if @query_parameters.empty? return "" if @query_parameters.empty?
@query_parameters.map {|k, v| "#{k}=#{v}" }.join("&") + "&" @query_parameters.map {|k, v| "#{k}=#{v}" }.join("&") + "&"
end end
end end

View file

@ -57,7 +57,9 @@ module Api
def time_settings(params) def time_settings(params)
time_params = params.permit("before", "after") time_params = params.permit("before", "after")
time_params["before"] = (Time.current + 1.year).iso8601 if time_params.empty? && @allow_default_page time_params["before"] = (Time.current + 1.year).iso8601 if time_params.empty? && @allow_default_page
raise "Missing time parameters for query building" if time_params.empty? raise "Missing time parameters for query building" if time_params.empty?
if time_params["before"] if time_params["before"]
is_descending = true is_descending = true
current_time = Time.iso8601(time_params["before"]) current_time = Time.iso8601(time_params["before"])
@ -71,6 +73,7 @@ module Api
def limit_settings(params) def limit_settings(params)
requested_limit = params["per_page"] requested_limit = params["per_page"]
return @default_limit unless requested_limit return @default_limit unless requested_limit
requested_limit = [1, requested_limit].max requested_limit = [1, requested_limit].max
[requested_limit, MAX_LIMIT].min [requested_limit, MAX_LIMIT].min
end end

View file

@ -25,17 +25,21 @@ module Api
def page_data def page_data
return @data if @data return @data if @data
@data = @query_base.where([@time_query_string, @current_time.iso8601(3)]).limit(@limit).order(@sort_string) @data = @query_base.where([@time_query_string, @current_time.iso8601(3)]).limit(@limit).order(@sort_string)
time_data = @data.map {|d| d[@data_time_field] }.sort time_data = @data.map {|d| d[@data_time_field] }.sort
@min_time = time_data.first @min_time = time_data.first
@max_time = time_data.last + 0.001.seconds if time_data.last @max_time = time_data.last + 0.001.seconds if time_data.last
@data @data
end end
def next_page(for_url=true) def next_page(for_url=true)
page_data page_data
return nil unless next_time return nil unless next_time
return next_page_as_query_parameter if for_url return next_page_as_query_parameter if for_url
TimePaginator.new( TimePaginator.new(
query_base: @query_base, query_base: @query_base,
query_time_field: @query_time_field, query_time_field: @query_time_field,
@ -49,7 +53,9 @@ module Api
def previous_page(for_url=true) def previous_page(for_url=true)
page_data page_data
return nil unless previous_time return nil unless previous_time
return previous_page_as_query_parameter if for_url return previous_page_as_query_parameter if for_url
TimePaginator.new( TimePaginator.new(
query_base: @query_base, query_base: @query_base,
query_time_field: @query_time_field, query_time_field: @query_time_field,

View file

@ -444,7 +444,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
describe "#destroy" do describe "#destroy" do
context "with existent authorization" do context "with existent authorization" do
it "removes the authorization" do it "removes the authorization" do
auth_with_read = FactoryGirl.create(:auth_with_profile_only, o_auth_application: client) auth_with_read = FactoryGirl.create(:auth_with_default_scopes, o_auth_application: client)
delete api_openid_connect_authorization_path(auth_with_read.id) delete api_openid_connect_authorization_path(auth_with_read.id)
expect(Api::OpenidConnect::Authorization.find_by(id: auth_with_read.id)).to be_nil expect(Api::OpenidConnect::Authorization.find_by(id: auth_with_read.id)).to be_nil
end end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
describe Api::OpenidConnect::TokenEndpointController, type: :controller, suppress_csrf_verification: :none do describe Api::OpenidConnect::TokenEndpointController, type: :controller, suppress_csrf_verification: :none do
let(:auth) { FactoryGirl.create(:auth_with_profile_only) } let(:auth) { FactoryGirl.create(:auth_with_default_scopes) }
describe "#create" do describe "#create" do
it "returns 200 on success" do it "returns 200 on success" do
@ -24,7 +24,6 @@ describe Api::OpenidConnect::TokenEndpointController, type: :controller, suppres
client_secret: auth.o_auth_application.client_secret client_secret: auth.o_auth_application.client_secret
} }
expect(response.code).to eq("200") expect(response.code).to eq("200")
puts response.body
end end
end end
end end

View file

@ -4,7 +4,7 @@ describe Api::OpenidConnect::UserApplicationsController, type: :controller do
before do before do
@app = FactoryGirl.create(:o_auth_application_with_xss) @app = FactoryGirl.create(:o_auth_application_with_xss)
@user = FactoryGirl.create :user @user = FactoryGirl.create :user
FactoryGirl.create :auth_with_profile_only, user: @user, o_auth_application: @app FactoryGirl.create :auth_with_default_scopes, user: @user, o_auth_application: @app
sign_in @user, scope: :user sign_in @user, scope: :user
end end

View file

@ -403,10 +403,10 @@ FactoryGirl.define do
redirect_uris %w(http://localhost:3000/) redirect_uris %w(http://localhost:3000/)
end end
factory :auth_with_profile_only, class: Api::OpenidConnect::Authorization do factory :auth_with_default_scopes, class: Api::OpenidConnect::Authorization do
o_auth_application o_auth_application
user user
scopes %w[openid profile] scopes %w[openid public:read]
after(:build) {|m| after(:build) {|m|
m.redirect_uri = m.o_auth_application.redirect_uris[0] m.redirect_uri = m.o_auth_application.redirect_uris[0]
} }

View file

@ -5,25 +5,26 @@ require "spec_helper"
describe Api::V1::AspectsController do describe Api::V1::AspectsController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid contacts:read contacts:modify] scopes: %w[openid contacts:read contacts:modify]
) )
} }
let(:auth_read_only) { let(:auth_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid contacts:read] scopes: %w[openid contacts:read]
) )
} }
let(:auth_profile_only) { let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_profile_only) FactoryGirl.create(:auth_with_default_scopes)
} }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s } let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
@aspect1 = auth.user.aspects.create(name: "first aspect") @aspect1 = auth.user.aspects.create(name: "first aspect")
@ -46,20 +47,22 @@ describe Api::V1::AspectsController do
end end
end end
it "fails if token doesn't have contacts:read" do context "without impromper credentials" do
get( it "fails if token doesn't have contacts:read" do
api_v1_aspects_path, get(
params: {access_token: access_token_profile_only} api_v1_aspects_path,
) params: {access_token: access_token_minimum_scopes}
expect(response.status).to eq(403) )
end expect(response.status).to eq(403)
end
it "fails if invalid token" do it "fails if invalid token" do
get( get(
api_v1_aspects_path, api_v1_aspects_path,
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end
end end
end end
@ -90,21 +93,19 @@ describe Api::V1::AspectsController do
end end
end end
context "without contacts:read in token" do context "without impromper credentials" do
it "fails to return with error" do it "fails without contacts:read in token" do
get( get(
api_v1_aspect_path(@aspect2.id), api_v1_aspect_path(@aspect2.id),
params: {access_token: access_token_profile_only} params: {access_token: access_token_minimum_scopes}
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
end
context "when not logged in" do it "fails when not logged in" do
it "fails to return with error" do
get( get(
api_v1_aspect_path(@aspect2.id), api_v1_aspect_path(@aspect2.id),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -165,7 +166,7 @@ describe Api::V1::AspectsController do
it "fails when not logged in" do it "fails when not logged in" do
post( post(
api_v1_aspects_path, api_v1_aspects_path,
params: {name: "new_name", chat_enabled: true, access_token: "999_999_999"} params: {name: "new_name", chat_enabled: true, access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -186,17 +187,17 @@ describe Api::V1::AspectsController do
it "updates full aspect" do it "updates full aspect" do
new_name = "NewAspectName" new_name = "NewAspectName"
new_chat = @aspect2.chat_enabled new_chat = @aspect2.chat_enabled
order = @aspect2.order_id + 1 new_order = @aspect2.order_id + 1
patch( patch(
api_v1_aspect_path(@aspect2.id), api_v1_aspect_path(@aspect2.id),
params: {name: new_name, chat_enabled: new_chat, order: order, access_token: access_token} params: {name: new_name, chat_enabled: new_chat, order: new_order, access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
aspect = JSON.parse(response.body) aspect = JSON.parse(response.body)
expect(aspect["name"]).to eq(new_name) expect(aspect["name"]).to eq(new_name)
expect(aspect["chat_enabled"]).to eq(new_chat) expect(aspect["chat_enabled"]).to eq(new_chat)
expect(aspect["order"]).to eq(order) expect(aspect["order"]).to eq(new_order)
expect(aspect["id"]).to eq(@aspect2.id) expect(aspect["id"]).to eq(@aspect2.id)
end end
@ -227,15 +228,15 @@ describe Api::V1::AspectsController do
end end
it "updates order only" do it "updates order only" do
order = @aspect2.order_id + 1 new_order = @aspect2.order_id + 1
patch( patch(
api_v1_aspect_path(@aspect2.id), api_v1_aspect_path(@aspect2.id),
params: {order: order, access_token: access_token} params: {order: new_order, access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
aspect = JSON.parse(response.body) aspect = JSON.parse(response.body)
expect(aspect["order"]).to eq(order) expect(aspect["order"]).to eq(new_order)
expect(aspect["id"]).to eq(@aspect2.id) expect(aspect["id"]).to eq(@aspect2.id)
end end
@ -279,7 +280,7 @@ describe Api::V1::AspectsController do
it "fails when not logged in" do it "fails when not logged in" do
patch( patch(
api_v1_aspect_path(@aspect2.id), api_v1_aspect_path(@aspect2.id),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -302,6 +303,7 @@ describe Api::V1::AspectsController do
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq(204) expect(response.status).to eq(204)
expect(auth.user.aspects.find_by(id: @aspect2.id)).to be_nil
end end
end end
@ -320,7 +322,7 @@ describe Api::V1::AspectsController do
it "fails when not logged in" do it "fails when not logged in" do
delete( delete(
api_v1_aspect_path(@aspect2.id), api_v1_aspect_path(@aspect2.id),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end

View file

@ -5,20 +5,26 @@ require "spec_helper"
describe Api::V1::CommentsController do describe Api::V1::CommentsController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify private:read private:modify interactions] scopes: %w[openid public:read public:modify private:read interactions]
) )
} }
let(:auth_public_only) { let(:auth_public_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify interactions] scopes: %w[openid public:read public:modify interactions]
) )
} }
let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_default_scopes)
}
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_public_only) { auth_public_only.create_access_token.to_s } let!(:access_token_public_only) { auth_public_only.create_access_token.to_s }
let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
@status = alice.post( @status = alice.post(
@ -58,7 +64,6 @@ describe Api::V1::CommentsController do
api_v1_post_comments_path(post_id: @status.guid), api_v1_post_comments_path(post_id: @status.guid),
params: {body: comment_text, access_token: access_token} params: {body: comment_text, access_token: access_token}
) )
expect(response.status).to eq(201) expect(response.status).to eq(201)
comment = response_body(response) comment = response_body(response)
confirm_comment_format(comment, auth.user, comment_text) confirm_comment_format(comment, auth.user, comment_text)
@ -86,6 +91,33 @@ describe Api::V1::CommentsController do
expect(response.status).to eq(422) expect(response.status).to eq(422)
end end
end end
context "with improper credentials" do
it "fails on private post without private:read" do
post(
api_v1_post_comments_path(post_id: @private_post.guid),
params: {body: "comment text", access_token: access_token_public_only}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end
it "fails without interactions scope" do
post(
api_v1_post_comments_path(post_id: @status.guid),
params: {body: "comment text", access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails without valid token" do
post(
api_v1_post_comments_path(post_id: @status.guid),
params: {body: "comment text", access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end end
describe "#read" do describe "#read" do
@ -100,7 +132,7 @@ describe Api::V1::CommentsController do
it "retrieves related comments" do it "retrieves related comments" do
get( get(
api_v1_post_comments_path(post_id: @status.guid), api_v1_post_comments_path(post_id: @status.guid),
params: {access_token: access_token} params: {access_token: access_token_minimum_scopes}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
comments = response_body_data(response) comments = response_body_data(response)
@ -121,8 +153,8 @@ describe Api::V1::CommentsController do
end end
end end
context "can't see comment on limited post without private:read token" do context "improper credentials" do
it "fails" do it "fails on private post without private:read" do
get( get(
api_v1_post_comments_path(post_id: @private_post.guid), api_v1_post_comments_path(post_id: @private_post.guid),
params: {access_token: access_token_public_only} params: {access_token: access_token_public_only}
@ -130,6 +162,14 @@ describe Api::V1::CommentsController do
expect(response.status).to eq(404) expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found")) expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end end
it "fails without valid token" do
get(
api_v1_post_comments_path(post_id: @status.guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end end
end end
@ -209,8 +249,10 @@ describe Api::V1::CommentsController do
expect(response.status).to eq(403) expect(response.status).to eq(403)
expect(response.body).to eq(I18n.t("api.endpoint_errors.comments.no_delete")) expect(response.body).to eq(I18n.t("api.endpoint_errors.comments.no_delete"))
end end
end
it "fails at deleting your comment on post without private:modify token" do context "improper credentials" do
it "fails at deleting your comment on post without private:read token" do
delete( delete(
api_v1_post_comment_path( api_v1_post_comment_path(
post_id: @private_post.guid, post_id: @private_post.guid,
@ -220,6 +262,14 @@ describe Api::V1::CommentsController do
) )
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
it "fails without valid token" do
get(
api_v1_post_comments_path(post_id: @status.guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end end
end end
@ -299,23 +349,6 @@ describe Api::V1::CommentsController do
end end
end end
context "lack of private permissions on private post" do
it "fails at reporting comment" do
post(
api_v1_post_comment_report_path(
post_id: @private_post.guid,
comment_id: @comment_on_private_post.guid
),
params: {
reason: "bad comment",
access_token: access_token_public_only
}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end
end
context "mismatched post-to-comment ID" do context "mismatched post-to-comment ID" do
it "fails at reporting comment" do it "fails at reporting comment" do
post( post(
@ -361,6 +394,31 @@ describe Api::V1::CommentsController do
expect(response.body).to eq(I18n.t("api.endpoint_errors.comments.duplicate_report")) expect(response.body).to eq(I18n.t("api.endpoint_errors.comments.duplicate_report"))
end end
end end
context "improper credentials" do
it "fails on private post without private:read" do
post(
api_v1_post_comment_report_path(
post_id: @private_post.guid,
comment_id: @comment_on_private_post.guid
),
params: {
reason: "bad comment",
access_token: access_token_public_only
}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end
it "fails without valid token" do
get(
api_v1_post_comments_path(post_id: @status.guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end end
def comment_service(user=auth.user) def comment_service(user=auth.user)

View file

@ -5,25 +5,26 @@ require "spec_helper"
describe Api::V1::ContactsController do describe Api::V1::ContactsController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid contacts:read contacts:modify] scopes: %w[openid contacts:read contacts:modify]
) )
} }
let(:auth_read_only) { let(:auth_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid contacts:read] scopes: %w[openid contacts:read]
) )
} }
let(:auth_profile_only) { let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_profile_only) FactoryGirl.create(:auth_with_default_scopes)
} }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s } let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
@aspect1 = auth.user.aspects.create(name: "generic") @aspect1 = auth.user.aspects.create(name: "generic")
@ -79,10 +80,19 @@ describe Api::V1::ContactsController do
end end
context "improper credentials" do context "improper credentials" do
it "fails without contacts:read" do
aspect = auth_minimum_scopes.user.aspects.create(name: "new aspect")
get(
api_v1_aspect_contacts_path(aspect.id),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails when not logged in" do it "fails when not logged in" do
get( get(
api_v1_aspect_contacts_path(@aspect2.id), api_v1_aspect_contacts_path(@aspect2.id),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -146,7 +156,7 @@ describe Api::V1::ContactsController do
it "fails when not logged in" do it "fails when not logged in" do
post( post(
api_v1_aspect_contacts_path(@aspect2.id), api_v1_aspect_contacts_path(@aspect2.id),
params: {person_guid: alice.guid, access_token: "999_999_999"} params: {person_guid: alice.guid, access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -221,14 +231,16 @@ describe Api::V1::ContactsController do
it "fails when not logged in" do it "fails when not logged in" do
delete( delete(
api_v1_aspect_contact_path(@aspect2.id, alice.guid), api_v1_aspect_contact_path(@aspect2.id, alice.guid),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
it "fails when only read only token" do it "fails when only read only token" do
aspect = auth_read_only.user.aspects.create(name: "new")
aspects_membership_service(auth_read_only.user).create(aspect.id, alice.person.id)
delete( delete(
api_v1_aspect_contact_path(@aspect2.id, alice.guid), api_v1_aspect_contact_path(aspect.id, alice.guid),
params: {access_token: access_token_read_only} params: {access_token: access_token_read_only}
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)

View file

@ -5,7 +5,7 @@ require "spec_helper"
describe Api::V1::ConversationsController do describe Api::V1::ConversationsController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid conversations] scopes: %w[openid conversations]
) )
} }
@ -14,21 +14,25 @@ describe Api::V1::ConversationsController do
FactoryGirl.create(:auth_with_all_scopes) FactoryGirl.create(:auth_with_all_scopes)
} }
let(:auth_profile_only) { let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_profile_only) FactoryGirl.create(:auth_with_default_scopes)
} }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_participant) { auth_participant.create_access_token.to_s } let!(:access_token_participant) { auth_participant.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
auth.user.aspects.create(name: "first") auth.user.aspects.create(name: "first")
auth.user.share_with alice.person, auth.user.aspects[0] auth.user.share_with(alice.person, auth.user.aspects[0])
alice.share_with auth.user.person, alice.aspects[0] alice.share_with(auth.user.person, alice.aspects[0])
auth.user.disconnected_by(eve) auth.user.disconnected_by(eve)
auth_minimum_scopes.user.aspects.create(name: "first")
auth_minimum_scopes.user.share_with(alice.person, auth_minimum_scopes.user.aspects[0])
alice.share_with(auth_minimum_scopes.user.person, alice.aspects[0])
@conversation_request = { @conversation_request = {
subject: "new conversation", subject: "new conversation",
body: "first message", body: "first message",
@ -41,8 +45,8 @@ describe Api::V1::ConversationsController do
context "with valid data" do context "with valid data" do
it "creates the conversation" do it "creates the conversation" do
post api_v1_conversations_path, params: @conversation_request post api_v1_conversations_path, params: @conversation_request
expect(response.status).to eq 201 expect(response.status).to eq(201)
conversation = JSON.parse(response.body) conversation = response_body(response)
confirm_conversation_format(conversation, @conversation_request, [auth.user, alice]) confirm_conversation_format(conversation, @conversation_request, [auth.user, alice])
end end
end end
@ -50,7 +54,7 @@ describe Api::V1::ConversationsController do
context "without valid data" do context "without valid data" do
it "fails with empty body" do it "fails with empty body" do
post api_v1_conversations_path, params: {access_token: access_token} post api_v1_conversations_path, params: {access_token: access_token}
expect(response.status).to eq 422 expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process")) expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process"))
end end
@ -61,7 +65,7 @@ describe Api::V1::ConversationsController do
access_token: access_token access_token: access_token
} }
post api_v1_conversations_path, params: incomplete_conversation post api_v1_conversations_path, params: incomplete_conversation
expect(response.status).to eq 422 expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process")) expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process"))
end end
@ -72,7 +76,7 @@ describe Api::V1::ConversationsController do
access_token: access_token access_token: access_token
} }
post api_v1_conversations_path, params: incomplete_conversation post api_v1_conversations_path, params: incomplete_conversation
expect(response.status).to eq 422 expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process")) expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process"))
end end
@ -83,7 +87,7 @@ describe Api::V1::ConversationsController do
access_token: access_token access_token: access_token
} }
post api_v1_conversations_path, params: incomplete_conversation post api_v1_conversations_path, params: incomplete_conversation
expect(response.status).to eq 422 expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process")) expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process"))
end end
@ -95,7 +99,7 @@ describe Api::V1::ConversationsController do
access_token: access_token access_token: access_token
} }
post api_v1_conversations_path, params: incomplete_conversation post api_v1_conversations_path, params: incomplete_conversation
expect(response.status).to eq 422 expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process")) expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process"))
end end
@ -107,21 +111,45 @@ describe Api::V1::ConversationsController do
access_token: access_token access_token: access_token
} }
post api_v1_conversations_path, params: incomplete_conversation post api_v1_conversations_path, params: incomplete_conversation
expect(response.status).to eq 422 expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process")) expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.cant_process"))
end end
end end
context "with improper credentials" do
it "fails without conversation scope" do
conversation_request = {
subject: "new conversation",
body: "first message",
recipients: [alice.guid],
access_token: access_token_minimum_scopes
}
post api_v1_conversations_path, params: conversation_request
expect(response.status).to eq(403)
end
it "fails without valid token" do
conversation_request = {
subject: "new conversation",
body: "first message",
recipients: [alice.guid],
access_token: invalid_token
}
post api_v1_conversations_path, params: conversation_request
expect(response.status).to eq(401)
end
end
end end
describe "#index" do describe "#index" do
before do before do
post api_v1_conversations_path, params: @conversation_request post api_v1_conversations_path, params: @conversation_request
@read_conversation_guid = JSON.parse(response.body)["guid"] @read_conversation_guid = response_body(response)["guid"]
@read_conversation = conversation_service.find!(@read_conversation_guid) @read_conversation = conversation_service.find!(@read_conversation_guid)
post api_v1_conversations_path, params: @conversation_request post api_v1_conversations_path, params: @conversation_request
sleep(1) sleep(1)
post api_v1_conversations_path, params: @conversation_request post api_v1_conversations_path, params: @conversation_request
@conversation_guid = JSON.parse(response.body)["guid"] @conversation_guid = response_body(response)["guid"]
@conversation = conversation_service.find!(@conversation_guid) @conversation = conversation_service.find!(@conversation_guid)
@conversation.conversation_visibilities[0].unread = 1 @conversation.conversation_visibilities[0].unread = 1
@conversation.conversation_visibilities[0].save! @conversation.conversation_visibilities[0].save!
@ -132,9 +160,9 @@ describe Api::V1::ConversationsController do
it "returns all the user conversations" do it "returns all the user conversations" do
get api_v1_conversations_path, params: {access_token: access_token} get api_v1_conversations_path, params: {access_token: access_token}
expect(response.status).to eq 200 expect(response.status).to eq(200)
returned_conversations = response_body_data(response) returned_conversations = response_body_data(response)
expect(returned_conversations.length).to eq 3 expect(returned_conversations.length).to eq(3)
actual_conversation = returned_conversations.select {|c| c["guid"] == @read_conversation_guid }[0] actual_conversation = returned_conversations.select {|c| c["guid"] == @read_conversation_guid }[0]
confirm_conversation_format(actual_conversation, @read_conversation, [auth.user, alice]) confirm_conversation_format(actual_conversation, @read_conversation, [auth.user, alice])
end end
@ -144,8 +172,8 @@ describe Api::V1::ConversationsController do
api_v1_conversations_path, api_v1_conversations_path,
params: {only_unread: true, access_token: access_token} params: {only_unread: true, access_token: access_token}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
expect(response_body_data(response).length).to eq 2 expect(response_body_data(response).length).to eq(2)
end end
it "returns all the user conversations after a given date" do it "returns all the user conversations after a given date" do
@ -153,27 +181,44 @@ describe Api::V1::ConversationsController do
api_v1_conversations_path, api_v1_conversations_path,
params: {only_after: @date, access_token: access_token} params: {only_after: @date, access_token: access_token}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
expect(response_body_data(response).length).to eq 1 expect(response_body_data(response).length).to eq(1)
end
context "with improper credentials" do
it "fails without conversation scope" do
get(
api_v1_conversations_path,
params: {only_after: @date, access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails without valid token" do
get(
api_v1_conversations_path,
params: {only_after: @date, access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end end
end end
describe "#show" do describe "#show" do
context "valid conversation ID" do before do
before do post api_v1_conversations_path, params: @conversation_request
post api_v1_conversations_path, params: @conversation_request @conversation_guid = response_body(response)["guid"]
@conversation_guid = JSON.parse(response.body)["guid"] @conversation = conversation_service.find!(@conversation_guid)
@conversation = conversation_service.find!(@conversation_guid) end
end
context "valid conversation ID" do
it "returns the corresponding conversation" do it "returns the corresponding conversation" do
conversation_guid = JSON.parse(response.body)["guid"]
get( get(
api_v1_conversation_path(conversation_guid), api_v1_conversation_path(@conversation_guid),
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
conversation = JSON.parse(response.body) conversation = response_body(response)
confirm_conversation_format(conversation, @conversation, [auth.user, alice]) confirm_conversation_format(conversation, @conversation, [auth.user, alice])
end end
end end
@ -181,13 +226,32 @@ describe Api::V1::ConversationsController do
context "non existing conversation ID" do context "non existing conversation ID" do
it "returns a not found error (404)" do it "returns a not found error (404)" do
get( get(
api_v1_conversation_path(42), api_v1_conversation_path(-1),
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq 404 expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.not_found")) expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.not_found"))
end end
end end
context "with improper credentials" do
it "fails without conversation scope" do
get(
api_v1_conversation_path(@conversation_guid),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails without valid token" do
conversation_guid = response_body(response)["guid"]
get(
api_v1_conversation_path(conversation_guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end end
describe "#destroy " do describe "#destroy " do
@ -205,7 +269,7 @@ describe Api::V1::ConversationsController do
access_token: access_token access_token: access_token
} }
post api_v1_conversations_path, params: @conversation_request post api_v1_conversations_path, params: @conversation_request
@conversation_guid = JSON.parse(response.body)["guid"] @conversation_guid = response_body(response)["guid"]
end end
context "destroy" do context "destroy" do
@ -264,6 +328,24 @@ describe Api::V1::ConversationsController do
expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.not_found")) expect(response.body).to eq(I18n.t("api.endpoint_errors.conversations.not_found"))
end end
end end
context "with improper credentials" do
it "fails without conversation scope" do
delete(
api_v1_conversation_path(@conversation_guid),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails without valid token" do
delete(
api_v1_conversation_path(@conversation_guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end end
def conversation_service def conversation_service
@ -272,6 +354,10 @@ describe Api::V1::ConversationsController do
private private
def response_body(response)
JSON.parse(response.body)
end
def response_body_data(response) def response_body_data(response)
JSON.parse(response.body)["data"] JSON.parse(response.body)["data"]
end end

View file

@ -5,25 +5,26 @@ require "spec_helper"
describe Api::V1::LikesController do describe Api::V1::LikesController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify private:read private:modify interactions] scopes: %w[openid public:read public:modify private:read private:modify interactions]
) )
} }
let(:auth_public_only) { let(:auth_public_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify interactions] scopes: %w[openid public:read public:modify interactions]
) )
} }
let(:auth_profile_only) { let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_profile_only) FactoryGirl.create(:auth_with_default_scopes)
} }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_public_only) { auth_public_only.create_access_token.to_s } let!(:access_token_public_only) { auth_public_only.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
@status = auth.user.post( @status = auth.user.post(
@ -48,7 +49,7 @@ describe Api::V1::LikesController do
it "succeeds in getting empty likes" do it "succeeds in getting empty likes" do
get( get(
api_v1_post_likes_path(post_id: @status.guid), api_v1_post_likes_path(post_id: @status.guid),
params: {access_token: access_token} params: {access_token: access_token_minimum_scopes}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
likes = response_body_data(response) likes = response_body_data(response)
@ -61,7 +62,7 @@ describe Api::V1::LikesController do
like_service(alice).create(@status.guid) like_service(alice).create(@status.guid)
get( get(
api_v1_post_likes_path(post_id: @status.guid), api_v1_post_likes_path(post_id: @status.guid),
params: {access_token: access_token} params: {access_token: access_token_minimum_scopes}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
likes = response_body_data(response) likes = response_body_data(response)
@ -83,14 +84,24 @@ describe Api::V1::LikesController do
end end
end end
context "without private:read scope in token" do context "with improper credentials" do
it "fails at getting likes" do context "without private:read scope in token" do
it "fails at getting likes" do
get(
api_v1_post_likes_path(post_id: @private_status.guid),
params: {access_token: access_token_public_only}
)
expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.likes.user_not_allowed_to_like"))
end
end
it "fails without valid token" do
get( get(
api_v1_post_likes_path(post_id: @private_status.guid), api_v1_post_likes_path(post_id: @private_status.guid),
params: {access_token: access_token_public_only} params: {access_token: invalid_token}
) )
expect(response.status).to eq(422) expect(response.status).to eq(401)
expect(response.body).to eq(I18n.t("api.endpoint_errors.likes.user_not_allowed_to_like"))
end end
end end
end end
@ -126,15 +137,6 @@ describe Api::V1::LikesController do
expect(likes.length).to eq(1) expect(likes.length).to eq(1)
expect(likes[0].author.id).to eq(auth.user.person.id) expect(likes[0].author.id).to eq(auth.user.person.id)
end end
it "fails in liking private post without private:modify" do
post(
api_v1_post_likes_path(post_id: @private_status.guid),
params: {access_token: access_token_public_only}
)
expect(response.status).to eq(422)
expect(response.body).to eq(I18n.t("api.endpoint_errors.likes.user_not_allowed_to_like"))
end
end end
context "with wrong post id" do context "with wrong post id" do
@ -147,6 +149,32 @@ describe Api::V1::LikesController do
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found")) expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end end
end end
context "with improper credentials" do
it "fails in liking private post without private:read" do
post(
api_v1_post_likes_path(post_id: @private_status.guid),
params: {access_token: access_token_public_only}
)
expect(response.status).to eq(422)
end
it "fails in liking post without interactions" do
post(
api_v1_post_likes_path(post_id: @private_status.guid),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails without valid token" do
get(
api_v1_post_likes_path(post_id: @private_status.guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end end
describe "#delete" do describe "#delete" do
@ -182,16 +210,6 @@ describe Api::V1::LikesController do
likes = like_service.find_for_post(@status.guid) likes = like_service.find_for_post(@status.guid)
expect(likes.length).to eq(0) expect(likes.length).to eq(0)
end end
it "fails at unliking private post without private:modify" do
like_service(auth_public_only.user).create(@private_status.guid)
delete(
api_v1_post_likes_path(post_id: @private_status.guid),
params: {access_token: access_token}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end
end end
context "with wrong post id" do context "with wrong post id" do
@ -204,6 +222,35 @@ describe Api::V1::LikesController do
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found")) expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end end
end end
context "with improper credentials" do
it "fails at unliking private post without private:read" do
like_service(auth_public_only.user).create(@private_status.guid)
delete(
api_v1_post_likes_path(post_id: @private_status.guid),
params: {access_token: access_token}
)
expect(response.status).to eq(404)
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end
it "fails in unliking post without interactions" do
like_service(auth_minimum_scopes.user).create(@status.guid)
delete(
api_v1_post_likes_path(post_id: @status.guid),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails without valid token" do
get(
api_v1_post_likes_path(post_id: @private_status.guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end end
private private

View file

@ -5,18 +5,27 @@ require "spec_helper"
describe Api::V1::MessagesController do describe Api::V1::MessagesController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid conversations] scopes: %w[openid conversations]
) )
} }
let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_default_scopes)
}
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
auth.user.seed_aspects auth.user.seed_aspects
auth.user.share_with bob.person, auth.user.aspects[1] auth.user.share_with(bob.person, auth.user.aspects[0])
auth.user.share_with alice.person, auth.user.aspects[1] auth.user.share_with(alice.person, auth.user.aspects[0])
auth.user.share_with(auth_minimum_scopes.user.person, auth.user.aspects[0])
alice.share_with auth.user.person, alice.aspects[0] alice.share_with auth.user.person, alice.aspects[0]
auth_minimum_scopes.user.seed_aspects
auth_minimum_scopes.user.share_with(auth.user.person, auth_minimum_scopes.user.aspects[0])
@conversation = { @conversation = {
subject: "new conversation", subject: "new conversation",
@ -40,7 +49,7 @@ describe Api::V1::MessagesController do
api_v1_conversation_messages_path(@conversation_guid), api_v1_conversation_messages_path(@conversation_guid),
params: {body: @message_text, access_token: access_token} params: {body: @message_text, access_token: access_token}
) )
expect(response.status).to eq 201 expect(response.status).to eq(201)
message = JSON.parse(response.body) message = JSON.parse(response.body)
confirm_message_format(message, @message_text, auth.user) confirm_message_format(message, @message_text, auth.user)
@ -50,7 +59,7 @@ describe Api::V1::MessagesController do
params: {access_token: access_token} params: {access_token: access_token}
) )
messages = response_body_data(response) messages = response_body_data(response)
expect(messages.length).to eq 2 expect(messages.length).to eq(2)
confirm_message_format(messages[1], @message_text, auth.user) confirm_message_format(messages[1], @message_text, auth.user)
end end
end end
@ -61,7 +70,7 @@ describe Api::V1::MessagesController do
api_v1_conversation_messages_path(@conversation_guid), api_v1_conversation_messages_path(@conversation_guid),
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq 422 expect(response.status).to eq(422)
expect(response.body).to eq I18n.t("api.endpoint_errors.conversations.cant_process") expect(response.body).to eq I18n.t("api.endpoint_errors.conversations.cant_process")
end end
@ -70,7 +79,7 @@ describe Api::V1::MessagesController do
api_v1_conversation_messages_path(@conversation_guid), api_v1_conversation_messages_path(@conversation_guid),
params: {body: "", access_token: access_token} params: {body: "", access_token: access_token}
) )
expect(response.status).to eq 422 expect(response.status).to eq(422)
expect(response.body).to eq I18n.t("api.endpoint_errors.conversations.cant_process") expect(response.body).to eq I18n.t("api.endpoint_errors.conversations.cant_process")
end end
end end
@ -81,10 +90,28 @@ describe Api::V1::MessagesController do
api_v1_conversation_messages_path(42), api_v1_conversation_messages_path(42),
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq 404 expect(response.status).to eq(404)
expect(response.body).to eq I18n.t("api.endpoint_errors.conversations.not_found") expect(response.body).to eq I18n.t("api.endpoint_errors.conversations.not_found")
end end
end end
context "improper credentials" do
it "fails without conversation token" do
post(
api_v1_conversation_messages_path(@conversation_guid),
params: {body: @message_text, access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails when not logged in" do
post(
api_v1_conversation_messages_path(@conversation_guid),
params: {body: @message_text, access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end end
describe "#index " do describe "#index " do
@ -99,14 +126,32 @@ describe Api::V1::MessagesController do
api_v1_conversation_messages_path(@conversation_guid), api_v1_conversation_messages_path(@conversation_guid),
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
messages = response_body_data(response) messages = response_body_data(response)
expect(messages.length).to eq 1 expect(messages.length).to eq(1)
confirm_message_format(messages[0], "first message", auth.user) confirm_message_format(messages[0], "first message", auth.user)
conversation = get_conversation(@conversation_guid) conversation = get_conversation(@conversation_guid)
expect(conversation[:read]).to be_truthy expect(conversation[:read]).to be_truthy
end end
context "improper credentials" do
it "fails without conversation token" do
get(
api_v1_conversation_messages_path(@conversation_guid),
params: {access_token: access_token_minimum_scopes}
)
expect(response.status).to eq(403)
end
it "fails when not logged in" do
get(
api_v1_conversation_messages_path(@conversation_guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
end end
end end

View file

@ -7,21 +7,26 @@ describe Api::V1::NotificationsController do
FactoryGirl.create(:auth_with_all_scopes) FactoryGirl.create(:auth_with_all_scopes)
} }
let(:auth_profile_only) { let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_profile_only) FactoryGirl.create(:auth_with_default_scopes)
} }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
before do before do
@post = auth.user.post( @post = auth.user.post(
:status_message, :status_message,
text: "This is a status message", text: "This is a status message",
public: true, public: true
to: "all" )
@mentioned_post = alice.post(
:status_message,
text: "This is a status message mentioning @{#{auth.user.diaspora_handle}}"
) )
@notification = FactoryGirl.create(:notification, recipient: auth.user, target: @post) @notification = FactoryGirl.create(:notification, recipient: auth.user, target: @post)
@mentioned = FactoryGirl.create(:notification_mentioned_in_comment, recipient: auth.user, target: @post)
end end
describe "#index" do describe "#index" do
@ -33,8 +38,8 @@ describe Api::V1::NotificationsController do
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
notification = response_body_data(response) notification = response_body_data(response)
expect(notification.length).to eq(1) expect(notification.length).to eq(2)
confirm_notification_format(notification[0], @notification, "also_commented", nil) confirm_notification_format(notification[1], @notification, "also_commented", nil)
end end
it "with proper credentials and unread only" do it "with proper credentials and unread only" do
@ -44,7 +49,7 @@ describe Api::V1::NotificationsController do
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
notification = response_body_data(response) notification = response_body_data(response)
expect(notification.length).to eq(1) expect(notification.length).to eq(2)
@notification.set_read_state(true) @notification.set_read_state(true)
get( get(
api_v1_notifications_path, api_v1_notifications_path,
@ -52,7 +57,7 @@ describe Api::V1::NotificationsController do
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
notification = response_body_data(response) notification = response_body_data(response)
expect(notification.length).to eq(0) expect(notification.length).to eq(1)
end end
it "with proper credentials and after certain date" do it "with proper credentials and after certain date" do
@ -62,7 +67,7 @@ describe Api::V1::NotificationsController do
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
notification = response_body_data(response) notification = response_body_data(response)
expect(notification.length).to eq(1) expect(notification.length).to eq(2)
@notification.set_read_state(true) @notification.set_read_state(true)
get( get(
api_v1_notifications_path, api_v1_notifications_path,
@ -87,7 +92,7 @@ describe Api::V1::NotificationsController do
it "with insufficient credentials" do it "with insufficient credentials" do
get( get(
api_v1_notifications_path, api_v1_notifications_path,
params: {access_token: access_token_profile_only} params: {access_token: access_token_minimum_scopes}
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
@ -145,7 +150,7 @@ describe Api::V1::NotificationsController do
it "with insufficient credentials" do it "with insufficient credentials" do
get( get(
api_v1_notification_path(@notification.guid), api_v1_notification_path(@notification.guid),
params: {access_token: access_token_profile_only} params: {access_token: access_token_minimum_scopes}
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
@ -200,7 +205,7 @@ describe Api::V1::NotificationsController do
it "with insufficient credentials" do it "with insufficient credentials" do
patch( patch(
api_v1_notification_path(@notification.guid), api_v1_notification_path(@notification.guid),
params: {access_token: access_token_profile_only} params: {access_token: access_token_minimum_scopes}
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end

View file

@ -5,41 +5,42 @@ require "spec_helper"
describe Api::V1::PhotosController do describe Api::V1::PhotosController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify private:read private:modify] scopes: %w[openid public:read public:modify private:read private:modify]
) )
} }
let(:auth_public_only) { let(:auth_public_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify] scopes: %w[openid public:read public:modify]
) )
} }
let(:auth_read_only) { let(:auth_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read private:read] scopes: %w[openid public:read private:read]
) )
} }
let(:auth_public_only_read_only) { let(:auth_public_only_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read] scopes: %w[openid public:read]
) )
} }
let(:auth_profile_only) { let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_profile_only) FactoryGirl.create(:auth_with_default_scopes)
} }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_public_only) { auth_public_only.create_access_token.to_s } let!(:access_token_public_only) { auth_public_only.create_access_token.to_s }
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s } let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s } let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
alice_private_spec = alice.aspects.create(name: "private aspect") alice_private_spec = alice.aspects.create(name: "private aspect")
@ -73,7 +74,7 @@ describe Api::V1::PhotosController do
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
photo = JSON.parse(response.body) photo = response_body(response)
expect(photo.has_key?("post")).to be_falsey expect(photo.has_key?("post")).to be_falsey
confirm_photo_format(photo, @user_photo1, auth.user) confirm_photo_format(photo, @user_photo1, auth.user)
end end
@ -84,7 +85,7 @@ describe Api::V1::PhotosController do
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
photo = JSON.parse(response.body) photo = response_body(response)
expect(photo.has_key?("post")).to be_truthy expect(photo.has_key?("post")).to be_truthy
confirm_photo_format(photo, @user_photo2, auth.user) confirm_photo_format(photo, @user_photo2, auth.user)
end end
@ -95,7 +96,7 @@ describe Api::V1::PhotosController do
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
photo = JSON.parse(response.body) photo = response_body(response)
confirm_photo_format(photo, @alice_public_photo, alice) confirm_photo_format(photo, @alice_public_photo, alice)
end end
end end
@ -131,7 +132,7 @@ describe Api::V1::PhotosController do
it "with invalid access token" do it "with invalid access token" do
delete( delete(
api_v1_photo_path(@user_photo1.guid), api_v1_photo_path(@user_photo1.guid),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -172,7 +173,7 @@ describe Api::V1::PhotosController do
it "with invalid access token" do it "with invalid access token" do
delete( delete(
api_v1_photos_path, api_v1_photos_path,
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -194,7 +195,7 @@ describe Api::V1::PhotosController do
params: {image: @encoded_photo, access_token: access_token} params: {image: @encoded_photo, access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
photo = JSON.parse(response.body) photo = response_body(response)
ref_photo = auth.user.photos.reload.find_by(guid: photo["guid"]) ref_photo = auth.user.photos.reload.find_by(guid: photo["guid"])
expect(ref_photo.pending).to be_falsey expect(ref_photo.pending).to be_falsey
confirm_photo_format(photo, ref_photo, auth.user) confirm_photo_format(photo, ref_photo, auth.user)
@ -206,7 +207,7 @@ describe Api::V1::PhotosController do
params: {image: @encoded_photo, pending: false, access_token: access_token} params: {image: @encoded_photo, pending: false, access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
photo = JSON.parse(response.body) photo = response_body(response)
expect(photo.has_key?("post")).to be_falsey expect(photo.has_key?("post")).to be_falsey
ref_photo = auth.user.photos.reload.find_by(guid: photo["guid"]) ref_photo = auth.user.photos.reload.find_by(guid: photo["guid"])
expect(ref_photo.pending).to be_falsey expect(ref_photo.pending).to be_falsey
@ -217,7 +218,7 @@ describe Api::V1::PhotosController do
params: {image: @encoded_photo, pending: true, access_token: access_token} params: {image: @encoded_photo, pending: true, access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
photo = JSON.parse(response.body) photo = response_body(response)
ref_photo = auth.user.photos.reload.find_by(guid: photo["guid"]) ref_photo = auth.user.photos.reload.find_by(guid: photo["guid"])
expect(ref_photo.pending).to be_truthy expect(ref_photo.pending).to be_truthy
end end
@ -228,7 +229,7 @@ describe Api::V1::PhotosController do
params: {image: @encoded_photo, set_profile_photo: true, access_token: access_token} params: {image: @encoded_photo, set_profile_photo: true, access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
photo = JSON.parse(response.body) photo = response_body(response)
expect(auth.user.reload.person.profile.image_url_small).to eq(photo["sizes"]["small"]) expect(auth.user.reload.person.profile.image_url_small).to eq(photo["sizes"]["small"])
end end
end end
@ -272,7 +273,7 @@ describe Api::V1::PhotosController do
it "with invalid access token" do it "with invalid access token" do
post( post(
api_v1_photos_path, api_v1_photos_path,
params: {image: @encoded_photo, access_token: "999_999_999"} params: {image: @encoded_photo, access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -330,7 +331,7 @@ describe Api::V1::PhotosController do
it "with invalid access token" do it "with invalid access token" do
delete( delete(
api_v1_photo_path(@user_photo1.guid), api_v1_photo_path(@user_photo1.guid),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -353,8 +354,12 @@ describe Api::V1::PhotosController do
end end
end end
def response_body(response)
JSON.parse(response.body)
end
def response_body_data(response) def response_body_data(response)
JSON.parse(response.body)["data"] response_body(response)["data"]
end end
# rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/AbcSize

View file

@ -5,25 +5,26 @@ require "spec_helper"
describe Api::V1::PostInteractionsController do describe Api::V1::PostInteractionsController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify private:read private:modify interactions] scopes: %w[openid public:read public:modify private:read private:modify interactions]
) )
} }
let(:auth_public_only) { let(:auth_public_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify interactions] scopes: %w[openid public:read public:modify interactions]
) )
} }
let(:auth_profile_only) { let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_profile_only) FactoryGirl.create(:auth_with_default_scopes)
} }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_public_only) { auth_public_only.create_access_token.to_s } let!(:access_token_public_only) { auth_public_only.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
@status = alice.post( @status = alice.post(
@ -36,7 +37,7 @@ describe Api::V1::PostInteractionsController do
alice_shared_aspect = alice.aspects.create(name: "shared aspect") alice_shared_aspect = alice.aspects.create(name: "shared aspect")
alice.share_with(auth_public_only.user.person, alice_shared_aspect) alice.share_with(auth_public_only.user.person, alice_shared_aspect)
alice.share_with(auth.user.person, alice_shared_aspect) alice.share_with(auth.user.person, alice_shared_aspect)
alice.share_with(auth_profile_only.user.person, alice_shared_aspect) alice.share_with(auth_minimum_scopes.user.person, alice_shared_aspect)
@shared_post = alice.post(:status_message, text: "to aspect only", public: false, to: alice_shared_aspect.id) @shared_post = alice.post(:status_message, text: "to aspect only", public: false, to: alice_shared_aspect.id)
end end
@ -89,7 +90,7 @@ describe Api::V1::PostInteractionsController do
post( post(
api_v1_post_subscribe_path(@status.guid), api_v1_post_subscribe_path(@status.guid),
params: { params: {
access_token: access_token_profile_only access_token: access_token_minimum_scopes
} }
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
@ -109,7 +110,7 @@ describe Api::V1::PostInteractionsController do
post( post(
api_v1_post_subscribe_path(@status.guid), api_v1_post_subscribe_path(@status.guid),
params: { params: {
access_token: "999_999_999" access_token: invalid_token
} }
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
@ -148,7 +149,7 @@ describe Api::V1::PostInteractionsController do
post( post(
api_v1_post_hide_path(@status.guid), api_v1_post_hide_path(@status.guid),
params: { params: {
access_token: access_token_profile_only access_token: access_token_minimum_scopes
} }
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
@ -168,7 +169,7 @@ describe Api::V1::PostInteractionsController do
post( post(
api_v1_post_hide_path(@status.guid), api_v1_post_hide_path(@status.guid),
params: { params: {
access_token: "999_999_999" access_token: invalid_token
} }
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
@ -234,7 +235,7 @@ describe Api::V1::PostInteractionsController do
post( post(
api_v1_post_mute_path(@status.guid), api_v1_post_mute_path(@status.guid),
params: { params: {
access_token: access_token_profile_only access_token: access_token_minimum_scopes
} }
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
@ -254,7 +255,7 @@ describe Api::V1::PostInteractionsController do
post( post(
api_v1_post_mute_path(@status.guid), api_v1_post_mute_path(@status.guid),
params: { params: {
access_token: "999_999_999" access_token: invalid_token
} }
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
@ -327,7 +328,7 @@ describe Api::V1::PostInteractionsController do
api_v1_post_report_path(@status.guid), api_v1_post_report_path(@status.guid),
params: { params: {
reason: "My reason", reason: "My reason",
access_token: access_token_profile_only access_token: access_token_minimum_scopes
} }
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
@ -349,7 +350,7 @@ describe Api::V1::PostInteractionsController do
api_v1_post_report_path(@status.guid), api_v1_post_report_path(@status.guid),
params: { params: {
reason: "My reason", reason: "My reason",
access_token: "999_999_999" access_token: invalid_token
} }
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
@ -427,7 +428,7 @@ describe Api::V1::PostInteractionsController do
api_v1_post_vote_path(@poll_post.guid), api_v1_post_vote_path(@poll_post.guid),
params: { params: {
poll_answer_id: @poll_answer.id, poll_answer_id: @poll_answer.id,
access_token: access_token_profile_only access_token: access_token_minimum_scopes
} }
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
@ -449,7 +450,7 @@ describe Api::V1::PostInteractionsController do
api_v1_post_vote_path(@poll_post.guid), api_v1_post_vote_path(@poll_post.guid),
params: { params: {
poll_answer_id: @poll_answer.id, poll_answer_id: @poll_answer.id,
access_token: "999_999_999" access_token: invalid_token
} }
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)

View file

@ -5,51 +5,47 @@ require "spec_helper"
describe Api::V1::PostsController do describe Api::V1::PostsController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify private:read private:modify] scopes: %w[openid public:read public:modify private:read private:modify]
) )
} }
let(:auth_public_only) { let(:auth_public_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify] scopes: %w[openid public:read public:modify]
) )
} }
let(:auth_read_only) { let(:auth_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read private:read] scopes: %w[openid public:read private:read]
) )
} }
let(:auth_public_only_read_only) { let(:auth_public_only_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read] scopes: %w[openid public:read]
) )
} }
let(:auth_profile_only) { FactoryGirl.create(:auth_with_profile_only) } let(:auth_minimum_scopes) { FactoryGirl.create(:auth_with_default_scopes) }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_public_only) { auth_public_only.create_access_token.to_s } let!(:access_token_public_only) { auth_public_only.create_access_token.to_s }
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s } let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s } let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
let(:alice_aspect) { alice.aspects.first } before do
@alice_aspect = alice.aspects.first
let(:alice_photo1) { @alice_photo1 = alice.post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: @alice_aspect.id)
alice.build_post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: alice_aspect.id).tap(&:save!) @alice_photo2 = alice.post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: @alice_aspect.id)
} @alice_photo_ids = [@alice_photo1.id.to_s, @alice_photo2.id.to_s]
@alice_photo_guids = [@alice_photo1.guid, @alice_photo2.guid]
let(:alice_photo2) { end
alice.build_post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: alice_aspect.id).tap(&:save!)
}
let(:alice_photo_ids) { [alice_photo1.id.to_s, alice_photo2.id.to_s] }
let(:alice_photo_guids) { [alice_photo1.guid, alice_photo2.guid] }
describe "#show" do describe "#show" do
before do before do
@ -82,7 +78,7 @@ describe Api::V1::PostsController do
location_params = {location_address: "somewhere", location_coords: "1,2"} location_params = {location_address: "somewhere", location_coords: "1,2"}
merged_params = base_params.merge(location_params) merged_params = base_params.merge(location_params)
merged_params = merged_params.merge(poll_params) merged_params = merged_params.merge(poll_params)
merged_params = merged_params.merge(photos: alice_photo_ids) merged_params = merged_params.merge(photos: @alice_photo_ids)
status_message = StatusMessageCreationService.new(alice).create(merged_params) status_message = StatusMessageCreationService.new(alice).create(merged_params)
get( get(
@ -164,28 +160,35 @@ describe Api::V1::PostsController do
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found")) expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
end end
end end
context "access with invalid token" do
it "fails" do
get(
api_v1_post_path(@status.guid),
params: {
access_token: invalid_token
}
)
expect(response.status).to eq(401)
end
end
end end
describe "#create" do describe "#create" do
let(:user_photo1) { before do
auth.user.build_post(:photo, pending: true, @user_photo1 = auth.user.post(:photo, pending: true, user_file: File.open(photo_fixture_name), public: true)
user_file: File.open(photo_fixture_name), to: "all").tap(&:save!) @user_photo2 = auth.user.post(:photo, pending: true, user_file: File.open(photo_fixture_name), public: true)
} @user_photo3 = auth.user.post(:photo, pending: false, user_file: File.open(photo_fixture_name), public: true)
let(:user_photo2) { @user_photo_ids = [@user_photo1.id.to_s, @user_photo2.id.to_s]
auth.user.build_post(:photo, pending: true, @user_photo_guids = [@user_photo1.guid, @user_photo2.guid]
user_file: File.open(photo_fixture_name), to: "all").tap(&:save!) end
}
let(:user_photo_ids) { [user_photo1.id.to_s, user_photo2.id.to_s] }
let(:user_photo_guids) { [user_photo1.guid, user_photo2.guid] }
context "when given read-write access token" do context "when given read-write access token" do
it "creates a public post" do it "creates a public post" do
post_for_ref_only = auth.user.post( post_for_ref_only = auth.user.post(
:status_message, :status_message,
text: "Hello this is a public post!", text: "Hello this is a public post!",
public: true, public: true
to: "all"
) )
post( post(
@ -242,9 +245,6 @@ describe Api::V1::PostsController do
context "with fully populated post" do context "with fully populated post" do
it "creates with photos" do it "creates with photos" do
message_text = "Post with photos" message_text = "Post with photos"
base_params = {status_message: {text: message_text}, public: true}
merged_params = base_params.merge(photos: user_photo_ids)
post_for_ref_only = StatusMessageCreationService.new(auth.user).create(merged_params)
post( post(
api_v1_posts_path, api_v1_posts_path,
@ -252,11 +252,20 @@ describe Api::V1::PostsController do
access_token: access_token, access_token: access_token,
body: message_text, body: message_text,
public: true, public: true,
photos: user_photo_guids photos: @user_photo_guids
} }
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
post = response_body(response) post = response_body(response)
@user_photo1[:pending] = true
@user_photo1.save
@user_photo2[:pending] = true
@user_photo2.save
base_params = {status_message: {text: message_text}, public: true}
merged_params = base_params.merge(photos: @user_photo_ids)
post_for_ref_only = StatusMessageCreationService.new(auth.user).create(merged_params)
confirm_post_format(post, auth.user, post_for_ref_only) confirm_post_format(post, auth.user, post_for_ref_only)
end end
@ -269,15 +278,28 @@ describe Api::V1::PostsController do
access_token: access_token, access_token: access_token,
body: message_text, body: message_text,
public: true, public: true,
photos: alice_photo_guids photos: @alice_photo_guids
} }
) )
expect(response.status).to eq(200) expect(response.status).to eq(422)
post = JSON.parse(response.body)
expect(post["photos"].empty?).to be_truthy
end end
it "fails to add bad guid" do it "fails to add non-pending photos" do
message_text = "Post with photos"
post(
api_v1_posts_path,
params: {
access_token: access_token,
body: message_text,
public: true,
photos: [@user_photo3.guid]
}
)
expect(response.status).to eq(422)
end
it "fails to add bad photo guids" do
message_text = "Post with photos" message_text = "Post with photos"
post( post(
@ -434,17 +456,6 @@ describe Api::V1::PostsController do
end end
end end
# TODO: Add when doing reshares endpoint
xcontext "when reshared" do
it "creates post with identical fields plus root" do
raise NotImplementedError
end
it "fails to reshare post user can't see" do
raise NotImplementedError
end
end
context "when given missing format" do context "when given missing format" do
it "fails when no body" do it "fails when no body" do
post( post(
@ -517,8 +528,8 @@ describe Api::V1::PostsController do
end end
end end
context "when given read only access token" do context "improper credentials" do
it "doesn't create the post" do it "fails without modify token" do
post( post(
api_v1_posts_path, api_v1_posts_path,
params: { params: {
@ -529,6 +540,18 @@ describe Api::V1::PostsController do
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
it "fails without invalid token" do
post(
api_v1_posts_path,
params: {
access_token: invalid_token,
status_message: {text: "Hello this is a post!"},
public: true
}
)
expect(response.status).to eq(401)
end
end end
end end
@ -565,6 +588,22 @@ describe Api::V1::PostsController do
end end
end end
context "when given invalid token" do
it "doesn't delete the post" do
@status = auth.user.post(
:status_message,
text: "hello",
public: true
)
delete(
api_v1_post_path(@status.guid),
params: {access_token: invalid_token}
)
expect(response.status).to eq(401)
end
end
context "when post is private but no private:modify scope in token" do context "when post is private but no private:modify scope in token" do
it "doesn't delete the post" do it "doesn't delete the post" do
aspect = auth_public_only.user.aspects.create(name: "new aspect") aspect = auth_public_only.user.aspects.create(name: "new aspect")

View file

@ -11,13 +11,14 @@ describe Api::V1::ResharesController do
FactoryGirl.create(:auth_with_read_scopes) FactoryGirl.create(:auth_with_read_scopes)
} }
let(:auth_profile_only) { let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_profile_only) FactoryGirl.create(:auth_with_default_scopes)
} }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s } let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
@user_post = auth.user.post( @user_post = auth.user.post(
@ -102,7 +103,7 @@ describe Api::V1::ResharesController do
get( get(
api_v1_post_reshares_path(@user_post.id), api_v1_post_reshares_path(@user_post.id),
params: { params: {
access_token: "999_999_999" access_token: invalid_token
} }
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
@ -190,7 +191,7 @@ describe Api::V1::ResharesController do
post( post(
api_v1_post_reshares_path(@eve_post.id), api_v1_post_reshares_path(@eve_post.id),
params: { params: {
access_token: "999_999_999" access_token: invalid_token
} }
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
@ -200,10 +201,10 @@ describe Api::V1::ResharesController do
post( post(
api_v1_post_reshares_path(@eve_post.id), api_v1_post_reshares_path(@eve_post.id),
params: { params: {
access_token: auth_read_only access_token: access_token_read_only
} }
) )
expect(response.status).to eq(401) expect(response.status).to eq(403)
end end
end end
end end

View file

@ -5,21 +5,21 @@ require "spec_helper"
describe Api::V1::SearchController do describe Api::V1::SearchController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify private:read private:modify] scopes: %w[openid public:read public:modify private:read private:modify]
) )
} }
let(:auth_read_only) { let(:auth_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read private:read] scopes: %w[openid public:read private:read]
) )
} }
let(:auth_public_only_read_only) { let(:auth_public_only_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read] scopes: %w[openid public:read]
) )
} }
@ -27,6 +27,7 @@ describe Api::V1::SearchController do
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s } let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s } let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
describe "#user_index" do describe "#user_index" do
before do before do
@ -137,7 +138,7 @@ describe Api::V1::SearchController do
it "fails with bad credentials" do it "fails with bad credentials" do
get( get(
"/api/v1/search/users", "/api/v1/search/users",
params: {tag: "tag1", access_token: "999_999_999"} params: {tag: "tag1", access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -208,7 +209,7 @@ describe Api::V1::SearchController do
it "fails with bad credentials" do it "fails with bad credentials" do
get( get(
"/api/v1/search/users", "/api/v1/search/users",
params: {tag: "tag1", access_token: "999_999_999"} params: {tag: "tag1", access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end

View file

@ -5,21 +5,21 @@ require "spec_helper"
describe Api::V1::StreamsController do describe Api::V1::StreamsController do
let(:auth_read_only) { let(:auth_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read private:read contacts:read tags:read] scopes: %w[openid public:read private:read contacts:read tags:read]
) )
} }
let(:auth_public_only_tags) { let(:auth_public_only_tags) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read tags:read] scopes: %w[openid public:read tags:read]
) )
} }
let(:auth_public_only_read_only) { let(:auth_public_only_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read] scopes: %w[openid public:read]
) )
} }
@ -27,6 +27,7 @@ describe Api::V1::StreamsController do
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s } let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
let!(:access_token_public_only_tags) { auth_public_only_tags.create_access_token.to_s } let!(:access_token_public_only_tags) { auth_public_only_tags.create_access_token.to_s }
let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s } let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
@aspect = auth_read_only.user.aspects.create(name: "new aspect") @aspect = auth_read_only.user.aspects.create(name: "new aspect")
@ -76,7 +77,7 @@ describe Api::V1::StreamsController do
api_v1_aspects_stream_path(aspect_ids: JSON.generate([@aspect.id])), api_v1_aspects_stream_path(aspect_ids: JSON.generate([@aspect.id])),
params: {access_token: access_token_read_only} params: {access_token: access_token_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 3 expect(post.length).to eq 3
json_post = post.select {|p| p["guid"] == @status.guid }.first json_post = post.select {|p| p["guid"] == @status.guid }.first
@ -88,9 +89,9 @@ describe Api::V1::StreamsController do
api_v1_aspects_stream_path, api_v1_aspects_stream_path,
params: {access_token: access_token_read_only} params: {access_token: access_token_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 3 expect(post.length).to eq(3)
json_post = post.select {|p| p["guid"] == @status.guid }.first json_post = post.select {|p| p["guid"] == @status.guid }.first
confirm_post_format(json_post, auth_read_only.user, @status) confirm_post_format(json_post, auth_read_only.user, @status)
end end
@ -114,7 +115,7 @@ describe Api::V1::StreamsController do
it "fails with invalid credentials" do it "fails with invalid credentials" do
get( get(
api_v1_aspects_stream_path(a_ids: [@aspect.id]), api_v1_aspects_stream_path(a_ids: [@aspect.id]),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -164,9 +165,9 @@ describe Api::V1::StreamsController do
api_v1_activity_stream_path, api_v1_activity_stream_path,
params: {access_token: access_token_read_only} params: {access_token: access_token_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 2 expect(post.length).to eq(2)
json_post = post.select {|p| p["guid"] == @status.guid }.first json_post = post.select {|p| p["guid"] == @status.guid }.first
confirm_post_format(json_post, auth_read_only.user, @status) confirm_post_format(json_post, auth_read_only.user, @status)
end end
@ -184,7 +185,7 @@ describe Api::V1::StreamsController do
it "fails with invalid credentials" do it "fails with invalid credentials" do
get( get(
api_v1_activity_stream_path, api_v1_activity_stream_path,
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -196,9 +197,9 @@ describe Api::V1::StreamsController do
api_v1_stream_path, api_v1_stream_path,
params: {access_token: access_token_read_only} params: {access_token: access_token_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 3 expect(post.length).to eq(3)
json_post = post.select {|p| p["guid"] == @status.guid }.first json_post = post.select {|p| p["guid"] == @status.guid }.first
confirm_post_format(json_post, auth_read_only.user, @status) confirm_post_format(json_post, auth_read_only.user, @status)
end end
@ -208,17 +209,17 @@ describe Api::V1::StreamsController do
api_v1_stream_path, api_v1_stream_path,
params: {access_token: access_token_public_only_read_only} params: {access_token: access_token_public_only_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 1 expect(post.length).to eq(1)
end end
it "fails with invalid credentials" do it "fails with invalid credentials" do
get( get(
api_v1_stream_path, api_v1_stream_path,
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq 401 expect(response.status).to eq(401)
end end
end end
@ -228,9 +229,9 @@ describe Api::V1::StreamsController do
api_v1_commented_stream_path, api_v1_commented_stream_path,
params: {access_token: access_token_read_only} params: {access_token: access_token_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 2 expect(post.length).to eq(2)
end end
it "public posts only expected" do it "public posts only expected" do
@ -238,17 +239,17 @@ describe Api::V1::StreamsController do
api_v1_commented_stream_path, api_v1_commented_stream_path,
params: {access_token: access_token_public_only_read_only} params: {access_token: access_token_public_only_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 1 expect(post.length).to eq(1)
end end
it "fails with invalid credentials" do it "fails with invalid credentials" do
get( get(
api_v1_commented_stream_path, api_v1_commented_stream_path,
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq 401 expect(response.status).to eq(401)
end end
end end
@ -258,9 +259,9 @@ describe Api::V1::StreamsController do
api_v1_mentions_stream_path, api_v1_mentions_stream_path,
params: {access_token: access_token_read_only} params: {access_token: access_token_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 2 expect(post.length).to eq(2)
end end
it "public posts only expected" do it "public posts only expected" do
@ -268,17 +269,17 @@ describe Api::V1::StreamsController do
api_v1_mentions_stream_path, api_v1_mentions_stream_path,
params: {access_token: access_token_public_only_read_only} params: {access_token: access_token_public_only_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 1 expect(post.length).to eq(1)
end end
it "fails with invalid credentials" do it "fails with invalid credentials" do
get( get(
api_v1_mentions_stream_path, api_v1_mentions_stream_path,
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq 401 expect(response.status).to eq(401)
end end
end end
@ -288,9 +289,9 @@ describe Api::V1::StreamsController do
api_v1_liked_stream_path, api_v1_liked_stream_path,
params: {access_token: access_token_read_only} params: {access_token: access_token_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 2 expect(post.length).to eq(2)
json_post = post.select {|p| p["guid"] == @status.guid }.first json_post = post.select {|p| p["guid"] == @status.guid }.first
confirm_post_format(json_post, auth_read_only.user, @status) confirm_post_format(json_post, auth_read_only.user, @status)
end end
@ -300,17 +301,17 @@ describe Api::V1::StreamsController do
api_v1_liked_stream_path, api_v1_liked_stream_path,
params: {access_token: access_token_public_only_read_only} params: {access_token: access_token_public_only_read_only}
) )
expect(response.status).to eq 200 expect(response.status).to eq(200)
post = response_body_data(response) post = response_body_data(response)
expect(post.length).to eq 1 expect(post.length).to eq(1)
end end
it "fails with invalid credentials" do it "fails with invalid credentials" do
get( get(
api_v1_liked_stream_path, api_v1_liked_stream_path,
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq 401 expect(response.status).to eq(401)
end end
end end

View file

@ -5,22 +5,23 @@ require "spec_helper"
describe Api::V1::TagFollowingsController do describe Api::V1::TagFollowingsController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid tags:read tags:modify] scopes: %w[openid tags:read tags:modify]
) )
} }
let(:auth_read_only) { let(:auth_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid tags:read] scopes: %w[openid tags:read]
) )
} }
let(:auth_profile_only) { FactoryGirl.create(:auth_with_profile_only) } let(:auth_minimum_scopes) { FactoryGirl.create(:auth_with_default_scopes) }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s } let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
before do before do
@expected_tags = %w[tag1 tag2 tag3] @expected_tags = %w[tag1 tag2 tag3]
@ -84,7 +85,7 @@ describe Api::V1::TagFollowingsController do
it "invalid token" do it "invalid token" do
post( post(
api_v1_tag_followings_path, api_v1_tag_followings_path,
params: {name: "tag4", access_token: "999_999_999"} params: {name: "tag4", access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -109,7 +110,7 @@ describe Api::V1::TagFollowingsController do
it "insufficient scopes in token" do it "insufficient scopes in token" do
get( get(
api_v1_tag_followings_path, api_v1_tag_followings_path,
params: {access_token: access_token_profile_only} params: {access_token: access_token_minimum_scopes}
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
@ -117,7 +118,7 @@ describe Api::V1::TagFollowingsController do
it "invalid token" do it "invalid token" do
get( get(
api_v1_tag_followings_path, api_v1_tag_followings_path,
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -173,7 +174,7 @@ describe Api::V1::TagFollowingsController do
it "invalid token" do it "invalid token" do
delete( delete(
api_v1_tag_following_path("tag1"), api_v1_tag_following_path("tag1"),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end

View file

@ -11,40 +11,41 @@ describe Api::V1::UsersController do
let(:auth) { let(:auth) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: full_scopes scopes: full_scopes
) )
} }
let(:auth_public_only) { let(:auth_public_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read public:modify] scopes: %w[openid public:read public:modify]
) )
} }
let(:auth_read_only) { let(:auth_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read private:read contacts:read profile] scopes: %w[openid public:read private:read contacts:read profile]
) )
} }
let(:auth_public_only_read_only) { let(:auth_public_only_read_only) {
FactoryGirl.create( FactoryGirl.create(
:auth_with_profile_only, :auth_with_default_scopes,
scopes: %w[openid public:read] scopes: %w[openid public:read]
) )
} }
let(:auth_profile_only) { let(:auth_minimum_scopes) {
FactoryGirl.create(:auth_with_profile_only) FactoryGirl.create(:auth_with_default_scopes)
} }
let!(:access_token) { auth.create_access_token.to_s } let!(:access_token) { auth.create_access_token.to_s }
let!(:access_token_public_only) { auth_public_only.create_access_token.to_s } let!(:access_token_public_only) { auth_public_only.create_access_token.to_s }
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s } let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s } let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s }
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s } let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
let(:invalid_token) { SecureRandom.hex(9) }
describe "#show" do describe "#show" do
context "Current User" do context "Current User" do
@ -53,7 +54,7 @@ describe Api::V1::UsersController do
api_v1_user_path, api_v1_user_path,
params: {access_token: access_token} params: {access_token: access_token}
) )
user = JSON.parse(response.body) user = response_body(response)
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(user["guid"]).to eq(auth.user.guid) expect(user["guid"]).to eq(auth.user.guid)
confirm_self_data_format(user) confirm_self_data_format(user)
@ -62,7 +63,7 @@ describe Api::V1::UsersController do
it "fails if invalid token" do it "fails if invalid token" do
get( get(
api_v1_user_path, api_v1_user_path,
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -76,7 +77,7 @@ describe Api::V1::UsersController do
"/api/v1/users/#{alice.guid}", "/api/v1/users/#{alice.guid}",
params: {access_token: access_token} params: {access_token: access_token}
) )
user = JSON.parse(response.body) user = response_body(response)
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(user["guid"]).to eq(alice.person.guid) expect(user["guid"]).to eq(alice.person.guid)
confirm_public_profile_hash(user) confirm_public_profile_hash(user)
@ -91,7 +92,7 @@ describe Api::V1::UsersController do
"/api/v1/users/#{alice.guid}", "/api/v1/users/#{alice.guid}",
params: {access_token: access_token} params: {access_token: access_token}
) )
user = JSON.parse(response.body) user = response_body(response)
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(user["guid"]).to eq(alice.person.guid) expect(user["guid"]).to eq(alice.person.guid)
confirm_public_profile_hash(user) confirm_public_profile_hash(user)
@ -104,7 +105,7 @@ describe Api::V1::UsersController do
"/api/v1/users/#{eve.guid}", "/api/v1/users/#{eve.guid}",
params: {access_token: access_token} params: {access_token: access_token}
) )
user = JSON.parse(response.body) user = response_body(response)
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(user["guid"]).to eq(eve.person.guid) expect(user["guid"]).to eq(eve.person.guid)
confirm_private_profile_hash(user) confirm_private_profile_hash(user)
@ -115,7 +116,7 @@ describe Api::V1::UsersController do
"/api/v1/users/#{eve.guid}", "/api/v1/users/#{eve.guid}",
params: {access_token: access_token} params: {access_token: access_token}
) )
user = JSON.parse(response.body) user = response_body(response)
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(user["guid"]).to eq(eve.person.guid) expect(user["guid"]).to eq(eve.person.guid)
confirm_public_profile_hash(user) confirm_public_profile_hash(user)
@ -124,7 +125,7 @@ describe Api::V1::UsersController do
it "fails if invalid token" do it "fails if invalid token" do
get( get(
"/api/v1/users/#{alice.guid}", "/api/v1/users/#{alice.guid}",
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -143,9 +144,9 @@ describe Api::V1::UsersController do
get( get(
"/api/v1/users/#{unsearchable_user.guid}", "/api/v1/users/#{unsearchable_user.guid}",
params: {access_token: access_token_profile_only} params: {access_token: access_token_minimum_scopes}
) )
expect(response.status).to eq(404) expect(response.status).to eq(403)
end end
it "fails with invalid user GUID" do it "fails with invalid user GUID" do
@ -169,7 +170,7 @@ describe Api::V1::UsersController do
params: {location: new_location, bio: new_bio, access_token: access_token} params: {location: new_location, bio: new_bio, access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
user = JSON.parse(response.body) user = response_body(response)
confirm_self_data_format(user) confirm_self_data_format(user)
expect(user["bio"]).to eq(new_bio) expect(user["bio"]).to eq(new_bio)
expect(user["location"]).to eq(new_location) expect(user["location"]).to eq(new_location)
@ -208,7 +209,7 @@ describe Api::V1::UsersController do
} }
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
user = JSON.parse(response.body) user = response_body(response)
confirm_self_data_format(user) confirm_self_data_format(user)
expect(user["bio"]).to eq(new_bio) expect(user["bio"]).to eq(new_bio)
expect(user["birthday"]).to eq(birthday_format(new_birthday)) expect(user["birthday"]).to eq(birthday_format(new_birthday))
@ -246,7 +247,7 @@ describe Api::V1::UsersController do
} }
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
user = JSON.parse(response.body) user = response_body(response)
expect(user["bio"]).to eq(new_bio) expect(user["bio"]).to eq(new_bio)
expect(user.has_key?("no_idea_what_field_this_is")).to be_falsey expect(user.has_key?("no_idea_what_field_this_is")).to be_falsey
end end
@ -263,7 +264,7 @@ describe Api::V1::UsersController do
} }
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
user = JSON.parse(response.body) user = response_body(response)
expect(user["bio"]).to eq(new_bio) expect(user["bio"]).to eq(new_bio)
expect(user["guid"]).to eq(original_guid) expect(user["guid"]).to eq(original_guid)
end end
@ -271,7 +272,11 @@ describe Api::V1::UsersController do
it "fails if invalid token" do it "fails if invalid token" do
patch( patch(
api_v1_user_path, api_v1_user_path,
params: {location: "New Location", bio: "New Bio", access_token: "999_999_999"} params: {
location: "New Location",
bio: "New Bio",
access_token: invalid_token
}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -279,7 +284,11 @@ describe Api::V1::UsersController do
it "fails if read only token" do it "fails if read only token" do
patch( patch(
api_v1_user_path, api_v1_user_path,
params: {location: "New Location", bio: "New Bio", access_token: access_token_read_only} params: {
location: "New Location",
bio: "New Bio",
access_token: access_token_read_only
}
) )
expect(response.status).to eq(403) expect(response.status).to eq(403)
end end
@ -337,7 +346,7 @@ describe Api::V1::UsersController do
it "fails if invalid token" do it "fails if invalid token" do
get( get(
api_v1_user_contacts_path(alice.guid), api_v1_user_contacts_path(alice.guid),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -393,7 +402,7 @@ describe Api::V1::UsersController do
params: {access_token: access_token} params: {access_token: access_token}
) )
expect(response.status).to eq(200) expect(response.status).to eq(200)
photos = JSON.parse(response.body) photos = response_body(response)
expect(photos.length).to eq(2) expect(photos.length).to eq(2)
end end
end end
@ -410,7 +419,7 @@ describe Api::V1::UsersController do
it "fails if invalid token" do it "fails if invalid token" do
get( get(
api_v1_user_photos_path(alice.guid), api_v1_user_photos_path(alice.guid),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -482,7 +491,7 @@ describe Api::V1::UsersController do
it "fails if invalid token" do it "fails if invalid token" do
get( get(
api_v1_user_posts_path(alice.person.guid), api_v1_user_posts_path(alice.person.guid),
params: {access_token: "999_999_999"} params: {access_token: invalid_token}
) )
expect(response.status).to eq(401) expect(response.status).to eq(401)
end end
@ -573,7 +582,11 @@ describe Api::V1::UsersController do
end end
# rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/AbcSize
def response_body(response)
JSON.parse(response.body)
end
def response_body_data(response) def response_body_data(response)
JSON.parse(response.body)["data"] response_body(response)["data"]
end end
end end

View file

@ -3,7 +3,7 @@
describe Api::Paging::IndexPaginator do describe Api::Paging::IndexPaginator do
before do before do
(1..7).each do |i| (1..7).each do |i|
public = !(i == 1 || i == 6) public = ![1, 6].include?(i)
alice.post( alice.post(
:status_message, :status_message,
text: "Post #{i}", text: "Post #{i}",

View file

@ -3,7 +3,7 @@
describe Api::Paging::TimePaginator do describe Api::Paging::TimePaginator do
before do before do
(1..7).each do |i| (1..7).each do |i|
public = !(i == 1 || i == 6) public = ![1, 6].include?(i)
alice.post( alice.post(
:status_message, :status_message,
text: "Post #{i}", text: "Post #{i}",

View file

@ -2,7 +2,7 @@
describe Api::OpenidConnect::IdToken, type: :model do describe Api::OpenidConnect::IdToken, type: :model do
describe "#to_jwt" do describe "#to_jwt" do
let(:auth) { FactoryGirl.create(:auth_with_profile_only) } let(:auth) { FactoryGirl.create(:auth_with_default_scopes) }
let(:id_token) { Api::OpenidConnect::IdToken.new(auth, "nonce") } let(:id_token) { Api::OpenidConnect::IdToken.new(auth, "nonce") }
describe "decoded data" do describe "decoded data" do

View file

@ -20,4 +20,12 @@ describe NotificationPresenter do
json = NotificationPresenter.new(@notification).as_api_json(false) json = NotificationPresenter.new(@notification).as_api_json(false)
expect(json.has_key?(:target)).to be_falsey expect(json.has_key?(:target)).to be_falsey
end end
it "Makes target on mentioned" do
mentioned_post = FactoryGirl.create(:status_message_in_aspect, author: alice.person, text: text_mentioning(bob))
Notifications::MentionedInPost.notify(mentioned_post, [bob.id])
notification = Notifications::MentionedInPost.last
json = NotificationPresenter.new(notification).as_api_json(true)
expect(json[:target][:guid]).to eq(mentioned_post.guid)
end
end end

View file

@ -10,8 +10,8 @@ describe PhotoService do
to: alice_eve_spec.id) to: alice_eve_spec.id)
@alice_bob_photo = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name), @alice_bob_photo = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name),
to: alice_bob_spec.id) to: alice_bob_spec.id)
@alice_public_photo = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name), to: "all") @alice_public_photo = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name), public: true)
@bob_photo1 = bob.post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: "all") @bob_photo1 = bob.post(:photo, pending: true, user_file: File.open(photo_fixture_name), public: true)
end end
describe "visible_photo" do describe "visible_photo" do
@ -38,10 +38,7 @@ describe PhotoService do
describe "create" do describe "create" do
before do before do
@image_file = Rack::Test::UploadedFile.new( @image_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "button.png").to_s, "image/png")
Rails.root.join("spec", "fixtures", "button.png").to_s,
"image/png"
)
end end
context "succeeds" do context "succeeds" do
@ -61,7 +58,7 @@ describe PhotoService do
expect(photo.public?).to be_falsey expect(photo.public?).to be_falsey
end end
it "accepts sets a user profile when requested" do it "sets a user profile when requested" do
original_profile_pic = bob.person.profile.image_url original_profile_pic = bob.person.profile.image_url
params = ActionController::Parameters.new(set_profile_photo: true) params = ActionController::Parameters.new(set_profile_photo: true)
photo = photo_service.create_from_params_and_file(params, @image_file) photo = photo_service.create_from_params_and_file(params, @image_file)
@ -79,10 +76,11 @@ describe PhotoService do
it "allow raw file if explicitly allowing" do it "allow raw file if explicitly allowing" do
params = ActionController::Parameters.new params = ActionController::Parameters.new
photo = PhotoService.new(bob, false).create_from_params_and_file(params, uploaded_photo) photo = photo_service(bob, false).create_from_params_and_file(params, uploaded_photo)
expect(photo).not_to be_nil expect(photo).not_to be_nil
end end
end end
context "fails" do context "fails" do
before do before do
@params = ActionController::Parameters.new @params = ActionController::Parameters.new
@ -95,18 +93,12 @@ describe PhotoService do
end end
it "file type isn't an image" do it "file type isn't an image" do
text_file = Rack::Test::UploadedFile.new( text_file = Rack::Test::UploadedFile.new(Rails.root.join("README.md").to_s, "text/plain")
Rails.root.join("README.md").to_s,
"text/plain"
)
expect { expect {
photo_service.create_from_params_and_file(@params, text_file) photo_service.create_from_params_and_file(@params, text_file)
}.to raise_error CarrierWave::IntegrityError }.to raise_error CarrierWave::IntegrityError
text_file = Rack::Test::UploadedFile.new( text_file = Rack::Test::UploadedFile.new(Rails.root.join("README.md").to_s, "image/png")
Rails.root.join("README.md").to_s,
"image/png"
)
expect { expect {
photo_service.create_from_params_and_file(@params, text_file) photo_service.create_from_params_and_file(@params, text_file)
}.to raise_error CarrierWave::IntegrityError }.to raise_error CarrierWave::IntegrityError
@ -114,7 +106,7 @@ describe PhotoService do
end end
end end
def photo_service(user=bob) def photo_service(user=bob, deny_raw_files=true)
PhotoService.new(user, true) PhotoService.new(user, deny_raw_files)
end end
end end