Merge pull request #22 from frankrousseau/api-openid-updates
WIP: API OpenID Updates
This commit is contained in:
commit
8ffb814166
48 changed files with 1461 additions and 358 deletions
|
|
@ -3,12 +3,12 @@
|
|||
module Api
|
||||
module V1
|
||||
class AspectsController < Api::V1::BaseController
|
||||
before_action only: %i[index show] do
|
||||
require_access_token %w[read]
|
||||
before_action except: %i[create update destroy] do
|
||||
require_access_token %w[contacts:read]
|
||||
end
|
||||
|
||||
before_action only: %i[create update destroy] do
|
||||
require_access_token %w[read write]
|
||||
require_access_token %w[contacts:modify]
|
||||
end
|
||||
|
||||
def index
|
||||
|
|
|
|||
|
|
@ -52,6 +52,14 @@ module Api
|
|||
def time_pager(query)
|
||||
Api::Paging::RestPaginatorBuilder.new(query, request).time_pager(params)
|
||||
end
|
||||
|
||||
def private_read?
|
||||
access_token? %w[private:read]
|
||||
end
|
||||
|
||||
def private_modify?
|
||||
access_token? %w[private:modify]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@
|
|||
module Api
|
||||
module V1
|
||||
class CommentsController < Api::V1::BaseController
|
||||
before_action only: %i[index report] do
|
||||
require_access_token %w[read]
|
||||
before_action do
|
||||
require_access_token %w[interactions public:read]
|
||||
end
|
||||
|
||||
before_action only: %i[create destroy] do
|
||||
require_access_token %w[write]
|
||||
require_access_token %w[interactions public:modify]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
@ -29,6 +29,7 @@ module Api
|
|||
end
|
||||
|
||||
def index
|
||||
find_post
|
||||
comments_query = comment_service.find_for_post(params[:post_id])
|
||||
params[:after] = Time.utc(1900).iso8601 if params.permit(:before, :after).empty?
|
||||
comments_page = time_pager(comments_query).response
|
||||
|
|
@ -37,6 +38,7 @@ module Api
|
|||
end
|
||||
|
||||
def destroy
|
||||
find_post
|
||||
if comment_and_post_validate(params[:post_id], params[:id])
|
||||
comment_service.destroy!(params[:id])
|
||||
head :no_content
|
||||
|
|
@ -46,6 +48,7 @@ module Api
|
|||
end
|
||||
|
||||
def report
|
||||
find_post
|
||||
post_guid = params.require(:post_id)
|
||||
comment_guid = params.require(:comment_id)
|
||||
return unless comment_and_post_validate(post_guid, comment_guid)
|
||||
|
|
@ -94,9 +97,19 @@ module Api
|
|||
@comment_service ||= CommentService.new(current_user)
|
||||
end
|
||||
|
||||
def post_service
|
||||
@post_service ||= PostService.new(current_user)
|
||||
end
|
||||
|
||||
def comment_as_json(comment)
|
||||
CommentPresenter.new(comment).as_api_response
|
||||
end
|
||||
|
||||
def find_post
|
||||
post = post_service.find!(params[:post_id])
|
||||
return post if post.public? || private_read?
|
||||
raise ActiveRecord::RecordNotFound
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ require "api/paging/index_paginator"
|
|||
module Api
|
||||
module V1
|
||||
class ContactsController < Api::V1::BaseController
|
||||
before_action only: %i[index] do
|
||||
require_access_token %w[read]
|
||||
before_action except: %i[create destroy] do
|
||||
require_access_token %w[contacts:read]
|
||||
end
|
||||
|
||||
before_action only: %i[create destroy] do
|
||||
require_access_token %w[read write]
|
||||
require_access_token %w[contacts:modify]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
|
|||
|
|
@ -5,12 +5,8 @@ module Api
|
|||
class ConversationsController < Api::V1::BaseController
|
||||
include ConversationsHelper
|
||||
|
||||
before_action only: %i[create index show] do
|
||||
require_access_token %w[read]
|
||||
end
|
||||
|
||||
before_action only: %i[create destroy] do
|
||||
require_access_token %w[read write]
|
||||
before_action do
|
||||
require_access_token %w[conversations]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
|
|||
|
|
@ -3,12 +3,8 @@
|
|||
module Api
|
||||
module V1
|
||||
class LikesController < Api::V1::BaseController
|
||||
before_action only: %i[show] do
|
||||
require_access_token %w[read]
|
||||
end
|
||||
|
||||
before_action only: %i[create destroy] do
|
||||
require_access_token %w[write]
|
||||
before_action do
|
||||
require_access_token %w[interactions public:read]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
@ -16,10 +12,12 @@ module Api
|
|||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordInvalid do
|
||||
render json: I18n.t("api.endpoint_errors.likes.user_not_allowed_to_like"), status: :not_found
|
||||
render json: I18n.t("api.endpoint_errors.likes.user_not_allowed_to_like"), status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def show
|
||||
post = post_service.find!(params[:post_id])
|
||||
raise ActiveRecord::RecordInvalid unless post.public? || private_read?
|
||||
likes_query = like_service.find_for_post(params[:post_id])
|
||||
likes_page = index_pager(likes_query).response
|
||||
likes_page[:data] = likes_page[:data].map {|x| like_json(x) }
|
||||
|
|
@ -27,6 +25,8 @@ module Api
|
|||
end
|
||||
|
||||
def create
|
||||
post = post_service.find!(params[:post_id])
|
||||
raise ActiveRecord::RecordInvalid unless post.public? || private_modify?
|
||||
like_service.create(params[:post_id])
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
return render json: I18n.t("api.endpoint_errors.likes.like_exists"), status: :unprocessable_entity if
|
||||
|
|
@ -37,6 +37,8 @@ module Api
|
|||
end
|
||||
|
||||
def destroy
|
||||
post = post_service.find!(params[:post_id])
|
||||
raise ActiveRecord::RecordInvalid unless post.public? || private_modify?
|
||||
success = like_service.unlike_post(params[:post_id])
|
||||
if success
|
||||
head :no_content
|
||||
|
|
@ -45,11 +47,15 @@ module Api
|
|||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def like_service
|
||||
@like_service ||= LikeService.new(current_user)
|
||||
end
|
||||
|
||||
private
|
||||
def post_service
|
||||
@post_service ||= PostService.new(current_user)
|
||||
end
|
||||
|
||||
def like_json(like)
|
||||
LikesPresenter.new(like).as_api_json
|
||||
|
|
|
|||
|
|
@ -3,12 +3,8 @@
|
|||
module Api
|
||||
module V1
|
||||
class MessagesController < Api::V1::BaseController
|
||||
before_action only: %i[create] do
|
||||
require_access_token %w[read write]
|
||||
end
|
||||
|
||||
before_action only: %i[index] do
|
||||
require_access_token %w[read]
|
||||
before_action do
|
||||
require_access_token %w[conversations]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
|
|||
|
|
@ -3,12 +3,8 @@
|
|||
module Api
|
||||
module V1
|
||||
class NotificationsController < Api::V1::BaseController
|
||||
before_action except: %i[update] do
|
||||
require_access_token %w[read]
|
||||
end
|
||||
|
||||
before_action only: %i[update] do
|
||||
require_access_token %w[write]
|
||||
before_action do
|
||||
require_access_token %w[notifications]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ module Api
|
|||
module V1
|
||||
class PhotosController < Api::V1::BaseController
|
||||
before_action except: %i[create destroy] do
|
||||
require_access_token %w[read]
|
||||
require_access_token %w[public:read]
|
||||
end
|
||||
|
||||
before_action only: %i[create destroy] do
|
||||
require_access_token %w[read write]
|
||||
require_access_token %w[public:modify]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
@ -16,7 +16,12 @@ module Api
|
|||
end
|
||||
|
||||
def index
|
||||
photos_page = time_pager(current_user.photos).response
|
||||
query = if private_read?
|
||||
current_user.photos
|
||||
else
|
||||
current_user.photos.where(public: true)
|
||||
end
|
||||
photos_page = time_pager(query).response
|
||||
photos_page[:data] = photos_page[:data].map {|photo| PhotoPresenter.new(photo).as_api_json(true) }
|
||||
render json: photos_page
|
||||
end
|
||||
|
|
@ -24,11 +29,14 @@ module Api
|
|||
def show
|
||||
photo = photo_service.visible_photo(params.require(:id))
|
||||
raise ActiveRecord::RecordNotFound unless photo
|
||||
raise ActiveRecord::RecordNotFound unless photo.public? || private_read?
|
||||
render json: PhotoPresenter.new(photo).as_api_json(true)
|
||||
end
|
||||
|
||||
def create
|
||||
image = params.require(:image)
|
||||
public_photo = params.has_key?(:aspect_ids)
|
||||
raise RuntimeError unless public_photo || private_modify?
|
||||
base_params = params.permit(:aspect_ids, :pending, :set_profile_photo)
|
||||
photo = photo_service.create_from_params_and_file(base_params, image)
|
||||
raise RuntimeError unless photo
|
||||
|
|
@ -40,6 +48,7 @@ module Api
|
|||
def destroy
|
||||
photo = current_user.photos.where(guid: params[:id]).first
|
||||
raise ActiveRecord::RecordNotFound unless photo
|
||||
raise ActiveRecord::RecordNotFound unless photo.public? || private_modify?
|
||||
if current_user.retract(photo)
|
||||
head :no_content
|
||||
else
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module Api
|
|||
include PostsHelper
|
||||
|
||||
before_action do
|
||||
require_access_token %w[read write]
|
||||
require_access_token %w[public:read interactions]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
@ -14,7 +14,7 @@ module Api
|
|||
end
|
||||
|
||||
def subscribe
|
||||
post = post_service.find!(params[:post_id])
|
||||
post = find_post
|
||||
current_user.participate!(post)
|
||||
head :no_content
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
|
|
@ -22,13 +22,13 @@ module Api
|
|||
end
|
||||
|
||||
def hide
|
||||
post = post_service.find!(params[:post_id])
|
||||
post = find_post
|
||||
current_user.toggle_hidden_shareable(post)
|
||||
head :no_content
|
||||
end
|
||||
|
||||
def mute
|
||||
post = post_service.find!(params[:post_id])
|
||||
post = find_post
|
||||
participation = current_user.participations.find_by!(target_id: post.id)
|
||||
participation.destroy
|
||||
head :no_content
|
||||
|
|
@ -36,7 +36,7 @@ module Api
|
|||
|
||||
def report
|
||||
reason = params.require(:reason)
|
||||
post = post_service.find!(params[:post_id])
|
||||
post = find_post
|
||||
report = current_user.reports.new(
|
||||
item_id: post.id,
|
||||
item_type: "Post",
|
||||
|
|
@ -53,7 +53,7 @@ module Api
|
|||
|
||||
def vote
|
||||
begin
|
||||
post = post_service.find!(params[:post_id])
|
||||
post = find_post
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render json: I18n.t("api.endpoint_errors.posts.post_not_found"), status: :not_found
|
||||
return
|
||||
|
|
@ -77,6 +77,12 @@ module Api
|
|||
def poll_service
|
||||
@poll_service ||= PollParticipationService.new(current_user)
|
||||
end
|
||||
|
||||
def find_post
|
||||
post = post_service.find!(params[:post_id])
|
||||
raise ActiveRecord::RecordNotFound unless post.public? || private_read?
|
||||
post
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ module Api
|
|||
class PostsController < Api::V1::BaseController
|
||||
include PostsHelper
|
||||
|
||||
before_action only: :show do
|
||||
require_access_token %w[read]
|
||||
before_action except: %i[create destroy] do
|
||||
require_access_token %w[public:read]
|
||||
end
|
||||
|
||||
before_action only: %i[create destroy] do
|
||||
require_access_token %w[read write]
|
||||
require_access_token %w[public:modify]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
@ -18,14 +18,13 @@ module Api
|
|||
end
|
||||
|
||||
def show
|
||||
mark_notifications =
|
||||
params[:mark_notifications].present? && params[:mark_notifications]
|
||||
post = post_service.find!(params[:id])
|
||||
post_service.mark_user_notifications(post.id) if mark_notifications
|
||||
raise ActiveRecord::RecordNotFound unless post.public? || private_read?
|
||||
render json: post_as_json(post)
|
||||
end
|
||||
|
||||
def create
|
||||
raise StandardError unless params.require(:public) || private_modify?
|
||||
status_service = StatusMessageCreationService.new(current_user)
|
||||
creation_params = normalized_create_params
|
||||
@status_message = status_service.create(creation_params)
|
||||
|
|
@ -35,9 +34,9 @@ module Api
|
|||
end
|
||||
|
||||
def destroy
|
||||
post_service.destroy(params[:id])
|
||||
post_service.destroy(params[:id], private_modify?)
|
||||
head :no_content
|
||||
rescue Diaspora::NotMine
|
||||
rescue Diaspora::NotMine, Diaspora::NonPublic
|
||||
render json: I18n.t("api.endpoint_errors.posts.failed_delete"), status: :forbidden
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@
|
|||
module Api
|
||||
module V1
|
||||
class ResharesController < Api::V1::BaseController
|
||||
before_action only: %i[show] do
|
||||
require_access_token %w[read]
|
||||
before_action except: %i[create] do
|
||||
require_access_token %w[public:read]
|
||||
end
|
||||
|
||||
before_action only: %i[create] do
|
||||
require_access_token %w[read write]
|
||||
require_access_token %w[public:modify]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module Api
|
|||
module V1
|
||||
class SearchController < Api::V1::BaseController
|
||||
before_action do
|
||||
require_access_token %w[read]
|
||||
require_access_token %w[public:read]
|
||||
end
|
||||
|
||||
rescue_from ActionController::ParameterMissing, RuntimeError do
|
||||
|
|
@ -15,17 +15,27 @@ module Api
|
|||
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
|
||||
Person.search(params[:name_or_handle], current_user)
|
||||
end
|
||||
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[:data] = user_page[:data].map {|p| PersonPresenter.new(p).as_api_json }
|
||||
render json: user_page
|
||||
end
|
||||
|
||||
def post_index
|
||||
posts_query = Stream::Tag.new(current_user, params.require(:tag)).posts
|
||||
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[:data] = posts_page[:data].map {|post| PostPresenter.new(post).as_api_response }
|
||||
render json: posts_page
|
||||
|
|
|
|||
|
|
@ -4,7 +4,15 @@ module Api
|
|||
module V1
|
||||
class StreamsController < Api::V1::BaseController
|
||||
before_action do
|
||||
require_access_token %w[read]
|
||||
require_access_token %w[public:read]
|
||||
end
|
||||
|
||||
before_action only: %w[aspects] do
|
||||
require_access_token %w[contacts:read private:read]
|
||||
end
|
||||
|
||||
before_action only: %w[followed_tags] do
|
||||
require_access_token %w[tags:read]
|
||||
end
|
||||
|
||||
def aspects
|
||||
|
|
@ -41,7 +49,9 @@ module Api
|
|||
|
||||
def stream_responder(stream_klass=nil, query_time_field="posts.created_at", data_time_field="created_at")
|
||||
@stream = stream_klass.present? ? stream_klass.new(current_user, max_time: stream_max_time) : @stream
|
||||
posts_page = pager(@stream.stream_posts, query_time_field, data_time_field).response
|
||||
query = @stream.stream_posts
|
||||
query = query.where(public: true) unless private_read?
|
||||
posts_page = pager(query, query_time_field, data_time_field).response
|
||||
posts_page[:data] = posts_page[:data].map {|post| PostPresenter.new(post, current_user).as_api_response }
|
||||
posts_page[:links].delete(:previous)
|
||||
render json: posts_page
|
||||
|
|
|
|||
|
|
@ -3,16 +3,12 @@
|
|||
module Api
|
||||
module V1
|
||||
class TagFollowingsController < Api::V1::BaseController
|
||||
before_action only: %i[index] do
|
||||
require_access_token %w[read]
|
||||
before_action except: %i[create destroy] do
|
||||
require_access_token %w[tags:read]
|
||||
end
|
||||
|
||||
before_action only: %i[create destroy] do
|
||||
require_access_token %w[read write]
|
||||
end
|
||||
|
||||
rescue_from StandardError do
|
||||
render json: I18n.t("api.endpoint_errors.tags.cant_process"), status: :bad_request
|
||||
require_access_token %w[tags:modify]
|
||||
end
|
||||
|
||||
def index
|
||||
|
|
@ -22,6 +18,8 @@ module Api
|
|||
def create
|
||||
tag_followings_service.create(params.require(:name))
|
||||
head :no_content
|
||||
rescue StandardError
|
||||
render json: I18n.t("api.endpoint_errors.tags.cant_process"), status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
|
|
|||
|
|
@ -5,12 +5,20 @@ module Api
|
|||
class UsersController < Api::V1::BaseController
|
||||
include TagsHelper
|
||||
|
||||
before_action except: %i[update] do
|
||||
require_access_token %w[read]
|
||||
before_action except: %i[contacts update show] do
|
||||
require_access_token %w[public:read]
|
||||
end
|
||||
|
||||
before_action only: %i[update] do
|
||||
require_access_token %w[write]
|
||||
require_access_token %w[profile:modify]
|
||||
end
|
||||
|
||||
before_action only: %i[contacts] do
|
||||
require_access_token %w[contacts:read]
|
||||
end
|
||||
|
||||
before_action only: %i[show] do
|
||||
require_access_token %w[profile]
|
||||
end
|
||||
|
||||
rescue_from ActiveRecord::RecordNotFound do
|
||||
|
|
@ -19,7 +27,9 @@ module Api
|
|||
|
||||
def show
|
||||
person = if params.has_key?(:id)
|
||||
Person.find_by!(guid: params[:id])
|
||||
found_person = Person.find_by!(guid: params[:id])
|
||||
raise ActiveRecord::RecordNotFound unless found_person.searchable || access_token?("contacts:read")
|
||||
found_person
|
||||
else
|
||||
current_user.person
|
||||
end
|
||||
|
|
@ -52,7 +62,8 @@ module Api
|
|||
|
||||
def photos
|
||||
person = Person.find_by!(guid: params[:user_id])
|
||||
photos_query = Photo.visible(current_user, person, :all, Time.current)
|
||||
user_for_query = current_user if private_read?
|
||||
photos_query = Photo.visible(user_for_query, person, :all, Time.current)
|
||||
photos_page = time_pager(photos_query).response
|
||||
photos_page[:data] = photos_page[:data].map {|photo| PhotoPresenter.new(photo).as_api_json(true) }
|
||||
render json: photos_page
|
||||
|
|
@ -60,7 +71,11 @@ module Api
|
|||
|
||||
def posts
|
||||
person = Person.find_by!(guid: params[:user_id])
|
||||
posts_query = current_user.posts_from(person, false)
|
||||
posts_query = if private_read?
|
||||
current_user.posts_from(person, false)
|
||||
else
|
||||
Post.where(author_id: person.id, public: true)
|
||||
end
|
||||
posts_page = time_pager(posts_query).response
|
||||
posts_page[:data] = posts_page[:data].map {|post| PostPresenter.new(post, current_user).as_api_response }
|
||||
render json: posts_page
|
||||
|
|
|
|||
|
|
@ -18,7 +18,32 @@ module Api
|
|||
|
||||
scope :with_redirect_uri, ->(given_uri) { where redirect_uri: given_uri }
|
||||
|
||||
SCOPES = %w(openid sub aud name nickname profile picture read write)
|
||||
SCOPES = %w[
|
||||
birthdate
|
||||
contacts:modify
|
||||
contacts:read
|
||||
conversations
|
||||
email
|
||||
gender
|
||||
interactions
|
||||
locale
|
||||
name
|
||||
nickname
|
||||
notifications
|
||||
openid
|
||||
picture
|
||||
private:modify
|
||||
private:read
|
||||
profile
|
||||
profile
|
||||
profile:modify
|
||||
public:modify
|
||||
public:read
|
||||
sub
|
||||
tags:modify
|
||||
tags:read
|
||||
updated_at
|
||||
].freeze
|
||||
|
||||
def setup
|
||||
self.refresh_token = SecureRandom.hex(32)
|
||||
|
|
|
|||
|
|
@ -35,8 +35,12 @@ class PostService
|
|||
mark_mention_notifications_read(post_id)
|
||||
end
|
||||
|
||||
def destroy(post_id)
|
||||
post = find!(post_id)
|
||||
def destroy(post_id, private_allowed=true)
|
||||
post = if private_allowed
|
||||
find_non_public_by_guid_or_id_with_user!(post_id)
|
||||
else
|
||||
find_public!(post_id)
|
||||
end
|
||||
raise Diaspora::NotMine unless post.author == user.person
|
||||
user.retract(post)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -905,6 +905,8 @@ en:
|
|||
deny: "Deny"
|
||||
bad_request: "Missing client id or redirect URI"
|
||||
client_id_not_found: "No client with client_id %{client_id} with redirect URI %{redirect_uri} found"
|
||||
private_contacts_linkage_error: "private:read and private:modify require contacts:read as well"
|
||||
unknown_scope: "Unknown scope: #{scope_name}"
|
||||
destroy:
|
||||
fail: "The attempt to revoke the authorization with ID %{id} failed"
|
||||
user_applications:
|
||||
|
|
@ -920,31 +922,73 @@ en:
|
|||
scopes:
|
||||
openid:
|
||||
name: "basic profile"
|
||||
description: "This allows the application to read your basic profile"
|
||||
description: "This grants read access to basic profile information to the application."
|
||||
sub:
|
||||
name: "sub"
|
||||
description: "This grants sub permissions to the application"
|
||||
aud:
|
||||
name: "aud"
|
||||
description: "This grants aud permissions to the application"
|
||||
description: "This grants sub permissions to the application."
|
||||
name:
|
||||
name: "name"
|
||||
description: "This grants name permissions to the application"
|
||||
description: "This grants read access to name data to the application."
|
||||
nickname:
|
||||
name: "nickname"
|
||||
description: "This grants nickname permissions to the application"
|
||||
profile:
|
||||
name: "extended profile"
|
||||
description: "This allows the application to read your extended profile"
|
||||
description: "This grants read access to nickname data to the application."
|
||||
picture:
|
||||
name: "picture"
|
||||
description: "This grants picture permissions to the application"
|
||||
read:
|
||||
name: "read profile, stream and conversations"
|
||||
description: "This allows the application to read your stream, your conversations and your complete profile"
|
||||
write:
|
||||
name: "send posts, conversations and reactions"
|
||||
description: "This allows the application to send new posts, write conversations, and send reactions"
|
||||
description: "This grants read access to user's profile picture data to the application."
|
||||
gender:
|
||||
name: "gender"
|
||||
description: "This grants read access to the user's gendere data to the application."
|
||||
birthdate:
|
||||
name: "birthdate"
|
||||
description: "This grants read access ot the user's birthdate to the application."
|
||||
locale:
|
||||
name: "locale"
|
||||
description: "This grants read access ot the user's locale to the application."
|
||||
updated_at:
|
||||
name: "updated_at"
|
||||
description: "This grants read access to the user's profile update time to the application."
|
||||
'contacts:read':
|
||||
name: "contacts:read"
|
||||
description: "This grants read permissions to contacts and related data (like aspects) to the application."
|
||||
'contacts:modify':
|
||||
name: "contacts:modify"
|
||||
description: "This grants write permissions to contacts and related data (like aspects) to the application."
|
||||
conversations:
|
||||
name: "conversations"
|
||||
description: "This grants read/write permission to private messaging to the application."
|
||||
email:
|
||||
name: "email"
|
||||
description: "This grants read access to the user's email address to the application."
|
||||
interactions:
|
||||
name: "interactions"
|
||||
description: "This grants read and write permissions on interacting wth posts to the application."
|
||||
notifications:
|
||||
name: "notifications"
|
||||
description: "This grants read and write permissions on interactions for the user to the application."
|
||||
'private:read':
|
||||
name: "private:read"
|
||||
description: "This grants read privileges on private posts and streams to the application."
|
||||
'private:modify':
|
||||
name: "private:modify"
|
||||
description: "This grants modification privileges on private posts and streams, including allowing private sharing, to the application."
|
||||
'public:read':
|
||||
name: "public:read"
|
||||
description: "This grants read permissions on public posts, interactions, and user data to the application."
|
||||
'public:modify':
|
||||
name: "updated_at"
|
||||
description: "This grants write permissions on public posts (including public post writing), interactions, and user data to the application."
|
||||
profile:
|
||||
name: "extended profile"
|
||||
description: "This grants read access to extendend profile data to the application."
|
||||
'profile:modify':
|
||||
name: "profile:modify"
|
||||
description: "This grants user profile update permissions to the application."
|
||||
'tags:read':
|
||||
name: "tags:read"
|
||||
description: "This grants read access to user's followed tags and tag streams to the application."
|
||||
'tags:modify':
|
||||
name: "tags:modify"
|
||||
description: "This grants modification access to user's followed tags to the application."
|
||||
error_page:
|
||||
title: "Oh! Something went wrong :("
|
||||
contact_developer: "You should contact the developer of the application and include the following detailed error message:"
|
||||
|
|
|
|||
|
|
@ -50,9 +50,16 @@ module Api
|
|||
replace_profile_scope_with_specific_claims(req)
|
||||
@scopes = req.scope.map {|scope|
|
||||
scope.tap do |scope_name|
|
||||
req.invalid_scope! "Unknown scope: #{scope_name}" unless auth_scopes.include? scope_name
|
||||
req.invalid_scope! I18n.t("api.openid_connect.authorizations.new.unknown_scope") \
|
||||
unless auth_scopes.include?(scope_name)
|
||||
end
|
||||
}
|
||||
|
||||
@scopes.push("public:read") unless @scopes.include?("public:read")
|
||||
has_private_scope = @scopes.include?("private:read") || @scopes.include?("private:modify")
|
||||
has_contacts_scope = @scopes.include? "contacts:read"
|
||||
req.invalid_scope! I18n.t("api.openid_connect.authorizations.new.private_contacts_linkage_error") \
|
||||
if has_private_scope && !has_contacts_scope
|
||||
end
|
||||
|
||||
def auth_scopes
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ module Api
|
|||
end
|
||||
|
||||
def replace_profile_scope_with_specific_claims(req)
|
||||
profile_claims = %w(sub aud name nickname profile picture)
|
||||
profile_claims = %w[sub name nickname profile picture gender birthdate locale updated_at]
|
||||
scopes_as_claims = req.scope.flat_map {|scope| scope == "profile" ? profile_claims : [scope] }.uniq
|
||||
req.update_param("scope", scopes_as_claims)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,11 +29,15 @@ module Api
|
|||
attr_reader :current_token
|
||||
|
||||
def require_access_token(required_scopes)
|
||||
raise Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(:insufficient_scope) unless
|
||||
access_token?(required_scopes)
|
||||
end
|
||||
|
||||
def access_token?(required_scopes)
|
||||
@current_token = request.env[Rack::OAuth2::Server::Resource::ACCESS_TOKEN]
|
||||
raise Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new("Unauthorized user") unless
|
||||
@current_token && @current_token.authorization
|
||||
raise Rack::OAuth2::Server::Resource::Bearer::Forbidden.new(:insufficient_scope) unless
|
||||
@current_token.authorization.try(:accessible?, required_scopes)
|
||||
@current_token.authorization.try(:accessible?, required_scopes)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ module Api
|
|||
auth = Api::OpenidConnect::Authorization.with_redirect_uri(req.redirect_uri).use_code(req.code)
|
||||
req.invalid_grant! if auth.blank?
|
||||
res.access_token = auth.create_access_token
|
||||
res.access_token.refresh_token = auth.refresh_token
|
||||
if auth.accessible? "openid"
|
||||
id_token = auth.create_id_token
|
||||
res.id_token = id_token.to_jwt(access_token: res.access_token)
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
|
|||
before do
|
||||
get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
|
||||
redirect_uri: "http://localhost:3000/", response_type: "id_token",
|
||||
scope: "openid read", nonce: 413_093_098_3, state: 413_093_098_3}
|
||||
scope: "openid interactions", nonce: 413_093_098_3, state: 413_093_098_3}
|
||||
end
|
||||
|
||||
it "should receive another authorization request" do
|
||||
|
|
@ -380,12 +380,71 @@ describe Api::OpenidConnect::AuthorizationsController, type: :request do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "ensure public:read always there" do
|
||||
it "added with only openid" do
|
||||
get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
|
||||
redirect_uri: "http://localhost:3000/",
|
||||
response_type: "id_token token",
|
||||
scope: "openid",
|
||||
nonce: 418_093_098_3,
|
||||
state: 418_093_098_3}
|
||||
post api_openid_connect_authorizations_path, params: {approve: "true"}
|
||||
expect(alice.reload.authorizations.first.scopes).to include("public:read")
|
||||
end
|
||||
end
|
||||
|
||||
context "with contacts:read and private linkage requirement" do
|
||||
it "fails without contacts:read on private:read" do
|
||||
scopes = "openid private:read"
|
||||
get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
|
||||
redirect_uri: "http://localhost:3000/",
|
||||
response_type: "id_token token",
|
||||
scope: scopes,
|
||||
nonce: 418_093_098_3,
|
||||
state: 418_093_098_3}
|
||||
expect(response.status).to eq(302)
|
||||
end
|
||||
|
||||
it "fails without contacts:read on private:modify" do
|
||||
scopes = "openid private:modify"
|
||||
get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
|
||||
redirect_uri: "http://localhost:3000/",
|
||||
response_type: "id_token token",
|
||||
scope: scopes,
|
||||
nonce: 418_093_098_3,
|
||||
state: 418_093_098_3}
|
||||
expect(response.status).to eq(302)
|
||||
end
|
||||
|
||||
it "succeeds with contacts:read on private:read" do
|
||||
scopes = "openid contacts:read private:read"
|
||||
get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
|
||||
redirect_uri: "http://localhost:3000/",
|
||||
response_type: "id_token token",
|
||||
scope: scopes,
|
||||
nonce: 418_093_098_3,
|
||||
state: 418_093_098_3}
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
|
||||
it "succeeds with contacts:read on private:modify" do
|
||||
scopes = "openid contacts:read private:modify"
|
||||
get new_api_openid_connect_authorization_path, params: {client_id: client.client_id,
|
||||
redirect_uri: "http://localhost:3000/",
|
||||
response_type: "id_token token",
|
||||
scope: scopes,
|
||||
nonce: 418_093_098_3,
|
||||
state: 418_093_098_3}
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#destroy" do
|
||||
context "with existent authorization" do
|
||||
it "removes the authorization" do
|
||||
auth_with_read = FactoryGirl.create(:auth_with_read, o_auth_application: client)
|
||||
auth_with_read = FactoryGirl.create(:auth_with_profile_only, o_auth_application: client)
|
||||
delete api_openid_connect_authorization_path(auth_with_read.id)
|
||||
expect(Api::OpenidConnect::Authorization.find_by(id: auth_with_read.id)).to be_nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
describe Api::OpenidConnect::TokenEndpointController, type: :controller, suppress_csrf_verification: :none do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read) }
|
||||
let(:auth) { FactoryGirl.create(:auth_with_profile_only) }
|
||||
|
||||
describe "#create" do
|
||||
it "returns 200 on success" do
|
||||
|
|
@ -15,5 +15,16 @@ describe Api::OpenidConnect::TokenEndpointController, type: :controller, suppres
|
|||
}
|
||||
expect(response.code).to eq("200")
|
||||
end
|
||||
|
||||
it "refresh returns 200 on success" do
|
||||
post :create, params: {
|
||||
grant_type: "refresh_token",
|
||||
refresh_token: auth.refresh_token,
|
||||
client_id: auth.o_auth_application.client_id,
|
||||
client_secret: auth.o_auth_application.client_secret
|
||||
}
|
||||
expect(response.code).to eq("200")
|
||||
puts response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ describe Api::OpenidConnect::UserApplicationsController, type: :controller do
|
|||
before do
|
||||
@app = FactoryGirl.create(:o_auth_application_with_xss)
|
||||
@user = FactoryGirl.create :user
|
||||
FactoryGirl.create :auth_with_read, user: @user, o_auth_application: @app
|
||||
FactoryGirl.create :auth_with_profile_only, user: @user, o_auth_application: @app
|
||||
sign_in @user, scope: :user
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -403,28 +403,59 @@ FactoryGirl.define do
|
|||
redirect_uris %w(http://localhost:3000/)
|
||||
end
|
||||
|
||||
factory :auth_with_read, class: Api::OpenidConnect::Authorization do
|
||||
factory :auth_with_profile_only, class: Api::OpenidConnect::Authorization do
|
||||
o_auth_application
|
||||
user
|
||||
scopes %w(openid sub aud profile picture nickname name read)
|
||||
scopes %w[openid profile]
|
||||
after(:build) {|m|
|
||||
m.redirect_uri = m.o_auth_application.redirect_uris[0]
|
||||
}
|
||||
end
|
||||
|
||||
factory :auth_with_read_and_ppid, class: Api::OpenidConnect::Authorization do
|
||||
factory :auth_with_profile_and_ppid, class: Api::OpenidConnect::Authorization do
|
||||
association :o_auth_application, factory: :o_auth_application_with_ppid
|
||||
user
|
||||
scopes %w(openid sub aud profile picture nickname name read)
|
||||
scopes %w[openid sub profile picture nickname name]
|
||||
after(:build) {|m|
|
||||
m.redirect_uri = m.o_auth_application.redirect_uris[0]
|
||||
}
|
||||
end
|
||||
|
||||
factory :auth_with_read_and_write, class: Api::OpenidConnect::Authorization do
|
||||
factory :auth_with_all_scopes, class: Api::OpenidConnect::Authorization do
|
||||
o_auth_application
|
||||
association :user, factory: :user_with_aspect
|
||||
scopes %w(openid sub aud profile picture nickname name read write)
|
||||
scopes Api::OpenidConnect::Authorization::SCOPES
|
||||
after(:build) {|m|
|
||||
m.redirect_uri = m.o_auth_application.redirect_uris[0]
|
||||
}
|
||||
end
|
||||
|
||||
factory :auth_with_all_scopes_not_private, class: Api::OpenidConnect::Authorization do
|
||||
o_auth_application
|
||||
association :user, factory: :user_with_aspect
|
||||
scopes %w[openid sub name nickname profile picture gender birthdate locale updated_at contacts:read contacts:modify
|
||||
conversations email interactions notifications public:read public:modify profile profile:modify tags:read
|
||||
tags:modify]
|
||||
after(:build) {|m|
|
||||
m.redirect_uri = m.o_auth_application.redirect_uris[0]
|
||||
}
|
||||
end
|
||||
|
||||
factory :auth_with_read_scopes, class: Api::OpenidConnect::Authorization do
|
||||
o_auth_application
|
||||
association :user, factory: :user_with_aspect
|
||||
scopes %w[openid sub name nickname profile picture gender birthdate locale updated_at contacts:read conversations
|
||||
email interactions notifications private:read public:read profile tags:read]
|
||||
after(:build) {|m|
|
||||
m.redirect_uri = m.o_auth_application.redirect_uris[0]
|
||||
}
|
||||
end
|
||||
|
||||
factory :auth_with_read_scopes_not_private, class: Api::OpenidConnect::Authorization do
|
||||
o_auth_application
|
||||
association :user, factory: :user_with_aspect
|
||||
scopes %w[openid sub name nickname profile picture gender birthdate locale updated_at contacts:read conversations
|
||||
email interactions notifications public:read profile tags:read]
|
||||
after(:build) {|m|
|
||||
m.redirect_uri = m.o_auth_application.redirect_uris[0]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,31 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::AspectsController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid contacts:read contacts:modify]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid contacts:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) {
|
||||
FactoryGirl.create(:auth_with_profile_only)
|
||||
}
|
||||
|
||||
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_profile_only) { auth_profile_only.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
@aspect1 = auth.user.aspects.where(name: "generic").first
|
||||
@aspect2 = auth.user.aspects.create(name: "another aspect")
|
||||
@aspect1 = auth.user.aspects.create(name: "first aspect")
|
||||
@aspect2 = auth.user.aspects.create(name: "second aspect")
|
||||
end
|
||||
|
||||
describe "#index" do
|
||||
|
|
@ -29,6 +46,14 @@ describe Api::V1::AspectsController do
|
|||
end
|
||||
end
|
||||
|
||||
it "fails if token doesn't have contacts:read" do
|
||||
get(
|
||||
api_v1_aspects_path,
|
||||
params: {access_token: access_token_profile_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "fails if invalid token" do
|
||||
get(
|
||||
api_v1_aspects_path,
|
||||
|
|
@ -65,6 +90,16 @@ describe Api::V1::AspectsController do
|
|||
end
|
||||
end
|
||||
|
||||
context "without contacts:read in token" do
|
||||
it "fails to return with error" do
|
||||
get(
|
||||
api_v1_aspect_path(@aspect2.id),
|
||||
params: {access_token: access_token_profile_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
end
|
||||
|
||||
context "when not logged in" do
|
||||
it "fails to return with error" do
|
||||
get(
|
||||
|
|
|
|||
|
|
@ -3,8 +3,22 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::CommentsController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify private:read private:modify interactions]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify interactions]
|
||||
)
|
||||
}
|
||||
|
||||
let!(:access_token) { auth.create_access_token.to_s }
|
||||
let!(:access_token_public_only) { auth_public_only.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
@status = alice.post(
|
||||
|
|
@ -24,13 +38,27 @@ describe Api::V1::CommentsController do
|
|||
)
|
||||
|
||||
@comment_on_eves_post = comment_service.create(@eves_post.guid, "Comment on eve's post")
|
||||
|
||||
aspect = auth_public_only.user.aspects.create(name: "first aspect")
|
||||
@private_post = auth_public_only.user.post(
|
||||
"Post",
|
||||
status_message: {text: "This is a private status message"},
|
||||
public: false,
|
||||
to: [aspect.id],
|
||||
type: "Post"
|
||||
)
|
||||
@comment_on_private_post = comment_service(auth_public_only.user).create(@private_post.guid, "Private comment")
|
||||
end
|
||||
|
||||
describe "#create" do
|
||||
context "valid post ID" do
|
||||
it "succeeds in adding a comment" do
|
||||
comment_text = "This is a comment"
|
||||
create_comment(@status.guid, comment_text)
|
||||
post(
|
||||
api_v1_post_comments_path(post_id: @status.guid),
|
||||
params: {body: comment_text, access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(201)
|
||||
comment = response_body(response)
|
||||
confirm_comment_format(comment, auth.user, comment_text)
|
||||
|
|
@ -39,7 +67,10 @@ describe Api::V1::CommentsController do
|
|||
|
||||
context "wrong post id" do
|
||||
it "fails at adding a comment" do
|
||||
create_comment("999_999_999", "This is a comment")
|
||||
post(
|
||||
api_v1_post_comments_path(post_id: "999_999_999"),
|
||||
params: {body: "text", 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
|
||||
|
|
@ -48,9 +79,11 @@ describe Api::V1::CommentsController do
|
|||
context "lack of permissions" do
|
||||
it "fails at adding a comment" do
|
||||
alice.blocks.create(person: auth.user.person)
|
||||
create_comment(@status.guid, "That shouldn't be there because I am ignored by this user")
|
||||
post(
|
||||
api_v1_post_comments_path(post_id: @status.guid),
|
||||
params: {body: "That shouldn't be there because I am ignored by this user", access_token: access_token}
|
||||
)
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.comments.not_allowed"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -59,8 +92,8 @@ describe Api::V1::CommentsController do
|
|||
before do
|
||||
@comment_text1 = "This is a comment"
|
||||
@comment_text2 = "This is a comment 2"
|
||||
create_comment(@status.guid, @comment_text1)
|
||||
create_comment(@status.guid, @comment_text2)
|
||||
comment_service.create(@status.guid, @comment_text1)
|
||||
comment_service.create(@status.guid, @comment_text2)
|
||||
end
|
||||
|
||||
context "valid post ID" do
|
||||
|
|
@ -87,12 +120,23 @@ describe Api::V1::CommentsController do
|
|||
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
|
||||
end
|
||||
end
|
||||
|
||||
context "can't see comment on limited post without private:read token" do
|
||||
it "fails" do
|
||||
get(
|
||||
api_v1_post_comments_path(post_id: @private_post.guid),
|
||||
params: {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
|
||||
end
|
||||
|
||||
describe "#delete" do
|
||||
before do
|
||||
create_comment(@status.guid, "This is a comment")
|
||||
@comment_guid = response_body(response)["guid"]
|
||||
comment = comment_service.create(@status.guid, "This is a comment")
|
||||
@comment_guid = comment.guid
|
||||
end
|
||||
|
||||
context "valid comment ID" do
|
||||
|
|
@ -152,8 +196,8 @@ describe Api::V1::CommentsController do
|
|||
end
|
||||
end
|
||||
|
||||
context "insufficient permissions (not your comment and not owner)" do
|
||||
it "fails at deleting comment" do
|
||||
context "insufficient permissions" do
|
||||
it "fails at deleting other user's comment on other user's post" do
|
||||
alices_comment = comment_service(alice).create(@status.guid, "Alice's comment")
|
||||
delete(
|
||||
api_v1_post_comment_path(
|
||||
|
|
@ -165,13 +209,24 @@ describe Api::V1::CommentsController do
|
|||
expect(response.status).to eq(403)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.comments.no_delete"))
|
||||
end
|
||||
|
||||
it "fails at deleting your comment on post without private:modify token" do
|
||||
delete(
|
||||
api_v1_post_comment_path(
|
||||
post_id: @private_post.guid,
|
||||
id: @comment_on_private_post.guid
|
||||
),
|
||||
params: {access_token: access_token_public_only}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#report" do
|
||||
before do
|
||||
create_comment(@status.guid, "This is a comment")
|
||||
@comment_guid = response_body(response)["guid"]
|
||||
comment = comment_service.create(@status.guid, "This is a comment")
|
||||
@comment_guid = comment.guid
|
||||
end
|
||||
|
||||
context "valid comment ID" do
|
||||
|
|
@ -227,6 +282,40 @@ describe Api::V1::CommentsController do
|
|||
end
|
||||
end
|
||||
|
||||
context "invalid Post ID" do
|
||||
it "fails at reporting comment" do
|
||||
post(
|
||||
api_v1_post_comment_report_path(
|
||||
post_id: "999_999_999",
|
||||
comment_id: @comment_guid
|
||||
),
|
||||
params: {
|
||||
reason: "bad comment",
|
||||
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
|
||||
|
||||
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
|
||||
it "fails at reporting comment" do
|
||||
post(
|
||||
|
|
@ -278,13 +367,6 @@ describe Api::V1::CommentsController do
|
|||
CommentService.new(user)
|
||||
end
|
||||
|
||||
def create_comment(post_guid, text)
|
||||
post(
|
||||
api_v1_post_comments_path(post_id: post_guid),
|
||||
params: {body: text, access_token: access_token}
|
||||
)
|
||||
end
|
||||
|
||||
def response_body(response)
|
||||
JSON.parse(response.body)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,13 +3,31 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::ContactsController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid contacts:read contacts:modify]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid contacts:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) {
|
||||
FactoryGirl.create(:auth_with_profile_only)
|
||||
}
|
||||
|
||||
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_profile_only) { auth_profile_only.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
@aspect1 = auth.user.aspects.where(name: "generic").first
|
||||
@aspect1 = auth.user.aspects.create(name: "generic")
|
||||
auth.user.share_with(eve.person, @aspect1)
|
||||
@aspect2 = auth.user.aspects.create(name: "another aspect")
|
||||
@eve_aspect = eve.aspects.first
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,12 +3,28 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::ConversationsController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid conversations]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_participant) {
|
||||
FactoryGirl.create(:auth_with_all_scopes)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) {
|
||||
FactoryGirl.create(:auth_with_profile_only)
|
||||
}
|
||||
|
||||
let!(:access_token) { auth.create_access_token.to_s }
|
||||
let(:auth_participant) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let!(:access_token_participant) { auth_participant.create_access_token.to_s }
|
||||
let!(:access_token_profile_only) { auth_profile_only.create_access_token.to_s }
|
||||
|
||||
|
||||
before do
|
||||
auth.user.aspects.create(name: "first")
|
||||
auth.user.share_with alice.person, auth.user.aspects[0]
|
||||
alice.share_with auth.user.person, alice.aspects[0]
|
||||
auth.user.disconnected_by(eve)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,27 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::LikesController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify private:read private:modify interactions]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify interactions]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) {
|
||||
FactoryGirl.create(:auth_with_profile_only)
|
||||
}
|
||||
|
||||
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_profile_only) { auth_profile_only.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
@status = auth.user.post(
|
||||
|
|
@ -13,6 +32,15 @@ describe Api::V1::LikesController do
|
|||
public: true,
|
||||
to: "all"
|
||||
)
|
||||
|
||||
aspect = auth_public_only.user.aspects.create(name: "first aspect")
|
||||
@private_status = auth_public_only.user.post(
|
||||
"Post",
|
||||
status_message: {text: "This is a private status message"},
|
||||
public: false,
|
||||
to: [aspect.id],
|
||||
type: "Post"
|
||||
)
|
||||
end
|
||||
|
||||
describe "#show" do
|
||||
|
|
@ -54,6 +82,17 @@ describe Api::V1::LikesController do
|
|||
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
describe "#create" do
|
||||
|
|
@ -87,6 +126,15 @@ describe Api::V1::LikesController do
|
|||
expect(likes.length).to eq(1)
|
||||
expect(likes[0].author.id).to eq(auth.user.person.id)
|
||||
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
|
||||
|
||||
context "with wrong post id" do
|
||||
|
|
@ -103,10 +151,7 @@ describe Api::V1::LikesController do
|
|||
|
||||
describe "#delete" do
|
||||
before do
|
||||
post(
|
||||
api_v1_post_likes_path(post_id: @status.guid),
|
||||
params: {access_token: access_token}
|
||||
)
|
||||
like_service.create(@status.guid)
|
||||
end
|
||||
|
||||
context "with right post id" do
|
||||
|
|
@ -137,6 +182,16 @@ describe Api::V1::LikesController do
|
|||
likes = like_service.find_for_post(@status.guid)
|
||||
expect(likes.length).to eq(0)
|
||||
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
|
||||
|
||||
context "with wrong post id" do
|
||||
|
|
|
|||
|
|
@ -3,7 +3,13 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::MessagesController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid conversations]
|
||||
)
|
||||
}
|
||||
|
||||
let!(:access_token) { auth.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -3,10 +3,16 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::NotificationsController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(:auth_with_all_scopes)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) {
|
||||
FactoryGirl.create(:auth_with_profile_only)
|
||||
}
|
||||
|
||||
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_profile_only) { auth_profile_only.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
@post = auth.user.post(
|
||||
|
|
@ -78,6 +84,14 @@ describe Api::V1::NotificationsController do
|
|||
expect(response.body).to eq(I18n.t("api.endpoint_errors.notifications.cant_process"))
|
||||
end
|
||||
|
||||
it "with insufficient credentials" do
|
||||
get(
|
||||
api_v1_notifications_path,
|
||||
params: {access_token: access_token_profile_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "with improper credentials" do
|
||||
get(
|
||||
api_v1_notifications_path,
|
||||
|
|
@ -128,6 +142,14 @@ describe Api::V1::NotificationsController do
|
|||
expect(response.body).to eq(I18n.t("api.endpoint_errors.notifications.not_found"))
|
||||
end
|
||||
|
||||
it "with insufficient credentials" do
|
||||
get(
|
||||
api_v1_notification_path(@notification.guid),
|
||||
params: {access_token: access_token_profile_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "with improper credentials" do
|
||||
get(
|
||||
api_v1_notification_path(@notification.guid),
|
||||
|
|
@ -175,10 +197,10 @@ describe Api::V1::NotificationsController do
|
|||
expect(response.body).to eq(I18n.t("api.endpoint_errors.notifications.cant_process"))
|
||||
end
|
||||
|
||||
it "with read only credentials" do
|
||||
it "with insufficient credentials" do
|
||||
patch(
|
||||
api_v1_notification_path(@notification.guid),
|
||||
params: {access_token: access_token_read_only}
|
||||
params: {access_token: access_token_profile_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,10 +3,43 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::PhotosController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify private:read private:modify]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read private:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) {
|
||||
FactoryGirl.create(:auth_with_profile_only)
|
||||
}
|
||||
|
||||
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_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_profile_only) { auth_profile_only.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
alice_private_spec = alice.aspects.create(name: "private aspect")
|
||||
|
|
@ -19,6 +52,17 @@ describe Api::V1::PhotosController do
|
|||
message_data = {status_message: {text: "Post with photos"}, public: true, photos: [@user_photo2.id.to_s]}
|
||||
@status_message = StatusMessageCreationService.new(auth.user).create(message_data)
|
||||
@user_photo2.reload
|
||||
|
||||
shared_spec = auth_public_only_read_only.user.aspects.create(name: "shared aspect")
|
||||
auth_public_only_read_only.user.share_with(auth_public_only_read_only.user.person, shared_spec)
|
||||
auth_public_only_read_only.user.share_with(auth_read_only.user.person, shared_spec)
|
||||
|
||||
@shared_photo1 = auth_public_only_read_only.user.post(
|
||||
:photo,
|
||||
pending: false,
|
||||
user_file: File.open(photo_fixture_name),
|
||||
to: shared_spec.id
|
||||
)
|
||||
end
|
||||
|
||||
describe "#show" do
|
||||
|
|
@ -57,6 +101,15 @@ describe Api::V1::PhotosController do
|
|||
end
|
||||
|
||||
context "fails" do
|
||||
it "with other this user's private photo without private:read scope in token" do
|
||||
get(
|
||||
api_v1_photo_path(@shared_photo1.guid),
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.photos.not_found"))
|
||||
end
|
||||
|
||||
it "with other user's private photo" do
|
||||
get(
|
||||
api_v1_photo_path(@private_photo1.guid),
|
||||
|
|
@ -98,6 +151,23 @@ describe Api::V1::PhotosController do
|
|||
end
|
||||
end
|
||||
|
||||
context "only lists public photos" do
|
||||
before do
|
||||
auth_public_only_read_only.user.post(:photo, pending: false, user_file: File.open(photo_fixture_name),
|
||||
public: true)
|
||||
end
|
||||
|
||||
it "with correct only public scope token" do
|
||||
get(
|
||||
api_v1_photos_path,
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
photos = response_body_data(response)
|
||||
expect(photos.length).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "fails" do
|
||||
it "with invalid access token" do
|
||||
delete(
|
||||
|
|
@ -214,6 +284,14 @@ describe Api::V1::PhotosController do
|
|||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "with private photo and no private:modify access token" do
|
||||
post(
|
||||
api_v1_photos_path,
|
||||
params: {image: @encoded_photo, access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -264,6 +342,14 @@ describe Api::V1::PhotosController do
|
|||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "with private photo and no private:modify token" do
|
||||
delete(
|
||||
api_v1_photo_path(@shared_photo1.guid),
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,27 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::PostInteractionsController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify private:read private:modify interactions]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify interactions]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) {
|
||||
FactoryGirl.create(:auth_with_profile_only)
|
||||
}
|
||||
|
||||
let!(:access_token) { auth.create_access_token.to_s }
|
||||
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||
let!(:access_token_read_only) { auth_read_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 }
|
||||
|
||||
before do
|
||||
@status = alice.post(
|
||||
|
|
@ -15,6 +32,13 @@ describe Api::V1::PostInteractionsController do
|
|||
public: true,
|
||||
to: "all"
|
||||
)
|
||||
|
||||
alice_shared_aspect = alice.aspects.create(name: "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_profile_only.user.person, alice_shared_aspect)
|
||||
|
||||
@shared_post = alice.post(:status_message, text: "to aspect only", public: false, to: alice_shared_aspect.id)
|
||||
end
|
||||
|
||||
describe "#subscribe" do
|
||||
|
|
@ -61,16 +85,26 @@ describe Api::V1::PostInteractionsController do
|
|||
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
|
||||
end
|
||||
|
||||
it "with read only token" do
|
||||
it "with insufficient token" do
|
||||
post(
|
||||
api_v1_post_subscribe_path(@status.guid),
|
||||
params: {
|
||||
access_token: access_token_read_only
|
||||
access_token: access_token_profile_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "on private post without private token" do
|
||||
post(
|
||||
api_v1_post_subscribe_path(@shared_post.guid),
|
||||
params: {
|
||||
access_token: access_token_public_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "with invalid token" do
|
||||
post(
|
||||
api_v1_post_subscribe_path(@status.guid),
|
||||
|
|
@ -110,16 +144,26 @@ describe Api::V1::PostInteractionsController do
|
|||
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
|
||||
end
|
||||
|
||||
it "with read only token" do
|
||||
it "with insufficient token" do
|
||||
post(
|
||||
api_v1_post_hide_path(@status.guid),
|
||||
params: {
|
||||
access_token: access_token_read_only
|
||||
access_token: access_token_profile_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "on private post without private token" do
|
||||
post(
|
||||
api_v1_post_hide_path(@shared_post.guid),
|
||||
params: {
|
||||
access_token: access_token_public_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "with invalid token" do
|
||||
post(
|
||||
api_v1_post_hide_path(@status.guid),
|
||||
|
|
@ -186,16 +230,26 @@ describe Api::V1::PostInteractionsController do
|
|||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "with read only token" do
|
||||
it "with insufficient token" do
|
||||
post(
|
||||
api_v1_post_mute_path(@status.guid),
|
||||
params: {
|
||||
access_token: access_token_read_only
|
||||
access_token: access_token_profile_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "on private post without private token" do
|
||||
post(
|
||||
api_v1_post_mute_path(@shared_post.guid),
|
||||
params: {
|
||||
access_token: access_token_public_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "with invalid token" do
|
||||
post(
|
||||
api_v1_post_mute_path(@status.guid),
|
||||
|
|
@ -268,17 +322,28 @@ describe Api::V1::PostInteractionsController do
|
|||
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.cant_report"))
|
||||
end
|
||||
|
||||
it "with read only token" do
|
||||
it "with insufficient token" do
|
||||
post(
|
||||
api_v1_post_report_path(@status.guid),
|
||||
params: {
|
||||
reason: "My reason",
|
||||
access_token: access_token_read_only
|
||||
access_token: access_token_profile_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "on private post without private token" do
|
||||
post(
|
||||
api_v1_post_report_path(@shared_post.guid),
|
||||
params: {
|
||||
reason: "My reason",
|
||||
access_token: access_token_public_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "with invalid token" do
|
||||
post(
|
||||
api_v1_post_report_path(@status.guid),
|
||||
|
|
@ -356,17 +421,29 @@ describe Api::V1::PostInteractionsController do
|
|||
expect(response.status).to eq(404)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
|
||||
end
|
||||
it "with read only token" do
|
||||
|
||||
it "with insufficient token" do
|
||||
post(
|
||||
api_v1_post_vote_path(@poll_post.guid),
|
||||
params: {
|
||||
poll_answer_id: @poll_answer.id,
|
||||
access_token: access_token_read_only
|
||||
access_token: access_token_profile_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "on private post without private token" do
|
||||
post(
|
||||
api_v1_post_vote_path(@shared_post.guid),
|
||||
params: {
|
||||
poll_answer_id: @poll_answer.id,
|
||||
access_token: access_token_public_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "with invalid token" do
|
||||
post(
|
||||
api_v1_post_vote_path(@poll_post.guid),
|
||||
|
|
|
|||
|
|
@ -3,16 +3,41 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::PostsController do
|
||||
let!(:auth_with_read) { FactoryGirl.create(:auth_with_read) }
|
||||
let!(:access_token_with_read) { auth_with_read.create_access_token.to_s }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify private:read private:modify]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_with_read_and_write) {
|
||||
FactoryGirl.create(:auth_with_read_and_write)
|
||||
let(:auth_public_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify]
|
||||
)
|
||||
}
|
||||
let!(:access_token_with_read_and_write) {
|
||||
auth_with_read_and_write.create_access_token.to_s
|
||||
|
||||
let(:auth_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read private:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) { FactoryGirl.create(:auth_with_profile_only) }
|
||||
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_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_profile_only) { auth_profile_only.create_access_token.to_s }
|
||||
|
||||
let(:alice_aspect) { alice.aspects.first }
|
||||
|
||||
let(:alice_photo1) {
|
||||
|
|
@ -36,87 +61,12 @@ describe Api::V1::PostsController do
|
|||
)
|
||||
end
|
||||
|
||||
context "when mark notifications is omitted" do
|
||||
# TODO: Determine if this needs to be added back to the spec or if this is just in the notifications services
|
||||
xit "shows attempts to show the info and mark the user notifications" do
|
||||
@status = auth_with_read.user.post(
|
||||
:status_message,
|
||||
text: "hello @{bob Testing ; bob@example.com}",
|
||||
public: true,
|
||||
to: "all"
|
||||
)
|
||||
get(
|
||||
api_v1_post_path(@status.id),
|
||||
params: {access_token: access_token_with_read}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
post = response_body(response)
|
||||
expect(post["post_type"]).to eq("StatusMessage")
|
||||
expect(post["public"]).to eq(true)
|
||||
expect(post["author"]["id"]).to eq(auth_with_read.user.person.id)
|
||||
expect(post["interactions"]["comments_count"]).to eq(0)
|
||||
|
||||
mention_ids = Mention.where(
|
||||
mentions_container_id: @status.id,
|
||||
mentions_container_type: "Post",
|
||||
person_id: bob.person.id
|
||||
).ids
|
||||
Notification.where(
|
||||
recipient_id: bob.person.id,
|
||||
target_type: "Mention",
|
||||
target_id: mention_ids,
|
||||
unread: true
|
||||
)
|
||||
# expect(notifications.length).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "when mark notifications is false" do
|
||||
# TODO: Determine if this needs to be added back to the spec or if this is just in the notifications services
|
||||
xit "shows attempts to show the info" do
|
||||
@status = auth_with_read.user.post(
|
||||
:status_message,
|
||||
text: "hello @{bob ; bob@example.com}",
|
||||
public: true,
|
||||
to: "all"
|
||||
)
|
||||
|
||||
get(
|
||||
api_v1_post_path(@status.id),
|
||||
params: {
|
||||
access_token: access_token_with_read,
|
||||
mark_notifications: "false"
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
post = response_body(response)
|
||||
|
||||
expect(post["post_type"]).to eq("StatusMessage")
|
||||
expect(post["public"]).to eq(true)
|
||||
expect(post["author"]["id"]).to eq(auth_with_read.user.person.id)
|
||||
expect(post["interactions"]["comments_count"]).to eq(0)
|
||||
|
||||
mention_ids = Mention.where(
|
||||
mentions_container_id: @status.id,
|
||||
mentions_container_type: "Post",
|
||||
person_id: bob.person.id
|
||||
).ids
|
||||
Notification.where(
|
||||
recipient_id: bob.person.id,
|
||||
target_type: "Mention",
|
||||
target_id: mention_ids,
|
||||
unread: true
|
||||
)
|
||||
# expect(notifications.length).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "access simple by post ID" do
|
||||
it "gets post" do
|
||||
get(
|
||||
api_v1_post_path(@status.id),
|
||||
api_v1_post_path(@status.guid),
|
||||
params: {
|
||||
access_token: access_token_with_read
|
||||
access_token: access_token
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
|
|
@ -136,9 +86,9 @@ describe Api::V1::PostsController do
|
|||
status_message = StatusMessageCreationService.new(alice).create(merged_params)
|
||||
|
||||
get(
|
||||
api_v1_post_path(status_message.id),
|
||||
api_v1_post_path(status_message.guid),
|
||||
params: {
|
||||
access_token: access_token_with_read
|
||||
access_token: access_token
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
|
|
@ -151,9 +101,9 @@ describe Api::V1::PostsController do
|
|||
it "gets post" do
|
||||
reshare_post = FactoryGirl.create(:reshare, root: @status, author: bob.person)
|
||||
get(
|
||||
api_v1_post_path(reshare_post.id),
|
||||
api_v1_post_path(reshare_post.guid),
|
||||
params: {
|
||||
access_token: access_token_with_read
|
||||
access_token: access_token
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
|
|
@ -166,9 +116,9 @@ describe Api::V1::PostsController do
|
|||
it "fails to get post" do
|
||||
private_post = alice.post(:status_message, text: "to aspect only", public: false, to: alice.aspects.first.id)
|
||||
get(
|
||||
api_v1_post_path(private_post.id),
|
||||
api_v1_post_path(private_post.guid),
|
||||
params: {
|
||||
access_token: access_token_with_read
|
||||
access_token: access_token
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
|
|
@ -176,12 +126,38 @@ describe Api::V1::PostsController do
|
|||
end
|
||||
end
|
||||
|
||||
context "access private post to reader without private:read scope in token" do
|
||||
it "fails to get post" do
|
||||
alice_shared_aspect = alice.aspects.create(name: "shared aspect")
|
||||
alice.share_with(auth_public_only_read_only.user.person, alice_shared_aspect)
|
||||
alice.share_with(auth_read_only.user.person, alice_shared_aspect)
|
||||
|
||||
shared_post = alice.post(:status_message, text: "to aspect only", public: false, to: alice_shared_aspect.id)
|
||||
get(
|
||||
api_v1_post_path(shared_post.guid),
|
||||
params: {
|
||||
access_token: access_token_public_only_read_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.post_not_found"))
|
||||
|
||||
get(
|
||||
api_v1_post_path(shared_post.guid),
|
||||
params: {
|
||||
access_token: access_token_read_only
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
end
|
||||
end
|
||||
|
||||
context "access post with invalid id" do
|
||||
it "fails to get post" do
|
||||
get(
|
||||
api_v1_post_path("999_999_999"),
|
||||
params: {
|
||||
access_token: access_token_with_read
|
||||
access_token: access_token
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
|
|
@ -192,11 +168,11 @@ describe Api::V1::PostsController do
|
|||
|
||||
describe "#create" do
|
||||
let(:user_photo1) {
|
||||
auth_with_read_and_write.user.build_post(:photo, pending: true,
|
||||
auth.user.build_post(:photo, pending: true,
|
||||
user_file: File.open(photo_fixture_name), to: "all").tap(&:save!)
|
||||
}
|
||||
let(:user_photo2) {
|
||||
auth_with_read_and_write.user.build_post(:photo, pending: true,
|
||||
auth.user.build_post(:photo, pending: true,
|
||||
user_file: File.open(photo_fixture_name), to: "all").tap(&:save!)
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +181,7 @@ describe Api::V1::PostsController do
|
|||
|
||||
context "when given read-write access token" do
|
||||
it "creates a public post" do
|
||||
post_for_ref_only = auth_with_read_and_write.user.post(
|
||||
post_for_ref_only = auth.user.post(
|
||||
:status_message,
|
||||
text: "Hello this is a public post!",
|
||||
public: true,
|
||||
|
|
@ -215,36 +191,51 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: "Hello this is a public post!",
|
||||
public: true
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
post = response_body(response)
|
||||
confirm_post_format(post, auth_with_read_and_write.user, post_for_ref_only)
|
||||
confirm_post_format(post, auth.user, post_for_ref_only)
|
||||
end
|
||||
|
||||
it "or creates a private post" do
|
||||
aspect = Aspect.find_by(user_id: auth_with_read_and_write.user.id)
|
||||
post_for_ref_only = auth_with_read_and_write.user.post(
|
||||
aspect = auth.user.aspects.create(name: "new aspect")
|
||||
post_for_ref_only = auth.user.post(
|
||||
:status_message,
|
||||
text: "Hello this is a private post!",
|
||||
aspect_ids: [aspect[:id]]
|
||||
aspect_ids: [aspect.id]
|
||||
)
|
||||
|
||||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: "Hello this is a private post!",
|
||||
public: false,
|
||||
aspects: [aspect[:id]]
|
||||
aspects: [aspect.id]
|
||||
}
|
||||
)
|
||||
post = response_body(response)
|
||||
expect(response.status).to eq(200)
|
||||
confirm_post_format(post, auth_with_read_and_write.user, post_for_ref_only)
|
||||
confirm_post_format(post, auth.user, post_for_ref_only)
|
||||
end
|
||||
|
||||
it "doesn't creates a private post without private:modify scope in token" do
|
||||
aspect = auth.user.aspects.create(name: "new aspect")
|
||||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_public_only,
|
||||
body: "Hello this is a private post!",
|
||||
public: false,
|
||||
aspects: [aspect.id]
|
||||
}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(422)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -253,12 +244,12 @@ describe Api::V1::PostsController do
|
|||
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_with_read_and_write.user).create(merged_params)
|
||||
post_for_ref_only = StatusMessageCreationService.new(auth.user).create(merged_params)
|
||||
|
||||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: true,
|
||||
photos: user_photo_guids
|
||||
|
|
@ -266,7 +257,7 @@ describe Api::V1::PostsController do
|
|||
)
|
||||
expect(response.status).to eq(200)
|
||||
post = response_body(response)
|
||||
confirm_post_format(post, auth_with_read_and_write.user, post_for_ref_only)
|
||||
confirm_post_format(post, auth.user, post_for_ref_only)
|
||||
end
|
||||
|
||||
it "fails to add other's photos" do
|
||||
|
|
@ -275,7 +266,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: true,
|
||||
photos: alice_photo_guids
|
||||
|
|
@ -292,7 +283,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: true,
|
||||
photos: ["999_999_999"]
|
||||
|
|
@ -307,12 +298,12 @@ describe Api::V1::PostsController do
|
|||
poll_params = {poll_question: "something?", poll_answers: %w[yes no maybe]}
|
||||
base_params = {status_message: {text: message_text}, public: true}
|
||||
merged_params = base_params.merge(poll_params)
|
||||
post_for_ref_only = StatusMessageCreationService.new(auth_with_read_and_write.user).create(merged_params)
|
||||
post_for_ref_only = StatusMessageCreationService.new(auth.user).create(merged_params)
|
||||
|
||||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: true,
|
||||
poll: {
|
||||
|
|
@ -323,7 +314,7 @@ describe Api::V1::PostsController do
|
|||
)
|
||||
post = response_body(response)
|
||||
expect(response.status).to eq(200)
|
||||
confirm_post_format(post, auth_with_read_and_write.user, post_for_ref_only)
|
||||
confirm_post_format(post, auth.user, post_for_ref_only)
|
||||
end
|
||||
|
||||
it "fails poll with no answers" do
|
||||
|
|
@ -331,7 +322,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: true,
|
||||
poll: {
|
||||
|
|
@ -349,7 +340,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: true,
|
||||
poll: {
|
||||
|
|
@ -366,7 +357,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: "",
|
||||
public: true,
|
||||
poll: {
|
||||
|
|
@ -384,12 +375,12 @@ describe Api::V1::PostsController do
|
|||
base_params = {status_message: {text: message_text}, public: true}
|
||||
location_params = {location_address: "somewhere", location_coords: "1,2"}
|
||||
merged_params = base_params.merge(location_params)
|
||||
post_for_ref_only = StatusMessageCreationService.new(auth_with_read_and_write.user).create(merged_params)
|
||||
post_for_ref_only = StatusMessageCreationService.new(auth.user).create(merged_params)
|
||||
|
||||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: true,
|
||||
location: {
|
||||
|
|
@ -401,12 +392,12 @@ describe Api::V1::PostsController do
|
|||
)
|
||||
post = response_body(response)
|
||||
expect(response.status).to eq(200)
|
||||
confirm_post_format(post, auth_with_read_and_write.user, post_for_ref_only)
|
||||
confirm_post_format(post, auth.user, post_for_ref_only)
|
||||
end
|
||||
|
||||
it "creates with mentions" do
|
||||
message_text = "hello @{#{alice.diaspora_handle}} from Bob!"
|
||||
post_for_ref_only = auth_with_read_and_write.user.post(
|
||||
post_for_ref_only = auth.user.post(
|
||||
:status_message,
|
||||
text: message_text,
|
||||
public: true
|
||||
|
|
@ -415,14 +406,14 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: true
|
||||
}
|
||||
)
|
||||
post = response_body(response)
|
||||
expect(response.status).to eq(200)
|
||||
confirm_post_format(post, auth_with_read_and_write.user, post_for_ref_only, [alice])
|
||||
confirm_post_format(post, auth.user, post_for_ref_only, [alice])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -432,7 +423,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: true
|
||||
}
|
||||
|
|
@ -459,7 +450,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
public: true
|
||||
}
|
||||
)
|
||||
|
|
@ -472,7 +463,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text
|
||||
}
|
||||
)
|
||||
|
|
@ -485,7 +476,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: false
|
||||
}
|
||||
|
|
@ -499,7 +490,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
public: false,
|
||||
aspects: ["-1"]
|
||||
|
|
@ -510,14 +501,15 @@ describe Api::V1::PostsController do
|
|||
end
|
||||
|
||||
it "fails when no public field but aspects" do
|
||||
aspect = Aspect.find_by(user_id: auth_with_read_and_write.user.id)
|
||||
aspect = auth.user.aspects.create(name: "new aspect")
|
||||
auth.user.share_with(alice.person, aspect)
|
||||
message_text = "hello @{#{alice.diaspora_handle}} from Bob!"
|
||||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read_and_write,
|
||||
access_token: access_token,
|
||||
body: message_text,
|
||||
aspects: [aspect[:id]]
|
||||
aspects: [aspect.id]
|
||||
}
|
||||
)
|
||||
expect(response.status).to eq(422)
|
||||
|
|
@ -530,7 +522,7 @@ describe Api::V1::PostsController do
|
|||
post(
|
||||
api_v1_posts_path,
|
||||
params: {
|
||||
access_token: access_token_with_read,
|
||||
access_token: access_token_read_only,
|
||||
status_message: {text: "Hello this is a post!"},
|
||||
public: true
|
||||
}
|
||||
|
|
@ -543,15 +535,15 @@ describe Api::V1::PostsController do
|
|||
describe "#destroy" do
|
||||
context "when given read-write access token" do
|
||||
it "attempts to destroy the post" do
|
||||
@status = auth_with_read_and_write.user.post(
|
||||
@status = auth.user.post(
|
||||
:status_message,
|
||||
text: "hello",
|
||||
public: true,
|
||||
to: "all"
|
||||
)
|
||||
delete(
|
||||
api_v1_post_path(@status.id),
|
||||
params: {access_token: access_token_with_read_and_write}
|
||||
api_v1_post_path(@status.guid),
|
||||
params: {access_token: access_token}
|
||||
)
|
||||
expect(response.status).to eq(204)
|
||||
end
|
||||
|
|
@ -559,14 +551,31 @@ describe Api::V1::PostsController do
|
|||
|
||||
context "when given read only access token" do
|
||||
it "doesn't delete the post" do
|
||||
@status = auth_with_read.user.post(
|
||||
@status = auth.user.post(
|
||||
:status_message,
|
||||
text: "hello",
|
||||
public: true
|
||||
)
|
||||
delete(
|
||||
api_v1_post_path(@status.id),
|
||||
params: {access_token: access_token_with_read}
|
||||
api_v1_post_path(@status.guid),
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
end
|
||||
|
||||
context "when post is private but no private:modify scope in token" do
|
||||
it "doesn't delete the post" do
|
||||
aspect = auth_public_only.user.aspects.create(name: "new aspect")
|
||||
@status = auth_public_only.user.post(
|
||||
:status_message,
|
||||
text: "hello",
|
||||
aspects: [aspect.id]
|
||||
)
|
||||
delete(
|
||||
api_v1_post_path(@status.guid),
|
||||
params: {access_token: access_token_public_only}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(403)
|
||||
|
|
@ -577,7 +586,7 @@ describe Api::V1::PostsController do
|
|||
it "doesn't delete a post" do
|
||||
delete(
|
||||
api_v1_post_path("999_999_999"),
|
||||
params: {access_token: access_token_with_read_and_write}
|
||||
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"))
|
||||
|
|
@ -595,7 +604,7 @@ describe Api::V1::PostsController do
|
|||
|
||||
delete(
|
||||
api_v1_post_path(status.guid),
|
||||
params: {access_token: access_token_with_read_and_write}
|
||||
params: {access_token: access_token}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.posts.failed_delete"))
|
||||
|
|
|
|||
|
|
@ -3,10 +3,21 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::ResharesController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(:auth_with_all_scopes)
|
||||
}
|
||||
|
||||
let(:auth_read_only) {
|
||||
FactoryGirl.create(:auth_with_read_scopes)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) {
|
||||
FactoryGirl.create(:auth_with_profile_only)
|
||||
}
|
||||
|
||||
let!(:access_token) { auth.create_access_token.to_s }
|
||||
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||
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 }
|
||||
|
||||
before do
|
||||
@user_post = auth.user.post(
|
||||
|
|
|
|||
|
|
@ -3,10 +3,30 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::SearchController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify private:read private:modify]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read private:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read]
|
||||
)
|
||||
}
|
||||
|
||||
let!(:access_token) { auth.create_access_token.to_s }
|
||||
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||
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 }
|
||||
|
||||
describe "#user_index" do
|
||||
before do
|
||||
|
|
@ -40,7 +60,7 @@ describe Api::V1::SearchController do
|
|||
)
|
||||
expect(response.status).to eq(200)
|
||||
users = response_body_data(response)
|
||||
expect(users.length).to eq(14)
|
||||
expect(users.length).to eq(15)
|
||||
end
|
||||
|
||||
it "succeeds by name" do
|
||||
|
|
@ -83,6 +103,19 @@ describe Api::V1::SearchController do
|
|||
expect(users.length).to eq(0)
|
||||
end
|
||||
|
||||
it "doesn't return hidden accounts who are linked without contacts:read token" do
|
||||
aspect_to = auth_public_only_read_only.user.aspects.create(name: "shared aspect")
|
||||
auth_public_only_read_only.user.share_with(@unsearchable_user, aspect_to)
|
||||
|
||||
get(
|
||||
"/api/v1/search/users",
|
||||
params: {name_or_handle: "unsearchable@example.org", access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
users = response_body_data(response)
|
||||
expect(users.length).to eq(0)
|
||||
end
|
||||
|
||||
it "fails if ask for both" do
|
||||
get(
|
||||
"/api/v1/search/users",
|
||||
|
|
@ -123,16 +156,44 @@ describe Api::V1::SearchController do
|
|||
text: "This is Eve's status message #tag2 #tag3",
|
||||
public: true
|
||||
)
|
||||
|
||||
aspect = eve.aspects.create(name: "shared aspect")
|
||||
eve.share_with(auth_public_only_read_only.user.person, aspect)
|
||||
eve.share_with(auth.user.person, aspect)
|
||||
@eve_private_post = eve.post(
|
||||
:status_message,
|
||||
text: "This is Eve's status message #tag2 #tag3",
|
||||
public: false,
|
||||
to: aspect.id
|
||||
)
|
||||
end
|
||||
|
||||
it "succeeds by tag" do
|
||||
get(
|
||||
"/api/v1/search/posts",
|
||||
params: {tag: "tag2", access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
posts = response_body_data(response)
|
||||
expect(posts.length).to eq(2)
|
||||
end
|
||||
|
||||
it "only returns public posts without private scope" do
|
||||
get(
|
||||
"/api/v1/search/posts",
|
||||
params: {tag: "tag2", access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
posts = response_body_data(response)
|
||||
expect(posts.length).to eq(2)
|
||||
|
||||
get(
|
||||
"/api/v1/search/posts",
|
||||
params: {tag: "tag2", access_token: access_token}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
posts = response_body_data(response)
|
||||
expect(posts.length).to eq(2)
|
||||
expect(posts.length).to eq(3)
|
||||
end
|
||||
|
||||
it "fails with missing parameters" do
|
||||
|
|
|
|||
|
|
@ -3,57 +3,158 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::StreamsController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let!(:access_token) { auth.create_access_token.to_s }
|
||||
let(:auth_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read private:read contacts:read tags:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only_tags) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read tags:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read]
|
||||
)
|
||||
}
|
||||
|
||||
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_read_only) { auth_public_only_read_only.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
@aspect = auth.user.aspects.first
|
||||
@created_status = auth.user.post(:status_message, text: "This is a status message #test", public: true, to: "all")
|
||||
auth.user.like!(@created_status)
|
||||
@status = PostService.new(auth.user).find(@created_status.id)
|
||||
@aspect = auth_read_only.user.aspects.create(name: "new aspect")
|
||||
auth_read_only.user.share_with(auth_public_only_read_only.user.person, @aspect)
|
||||
|
||||
@created_status = auth_read_only.user.post(
|
||||
:status_message,
|
||||
text: "This is a status message #test @{#{auth_read_only.user.diaspora_handle}}",
|
||||
public: true
|
||||
)
|
||||
comment_service(auth_read_only.user).create(@created_status.guid, "Comment")
|
||||
auth_read_only.user.like!(@created_status)
|
||||
@status = PostService.new(auth_read_only.user).find(@created_status.id)
|
||||
|
||||
@private_post = auth_read_only.user.post(
|
||||
:status_message,
|
||||
text: "This is a private status message #test @{#{auth_read_only.user.diaspora_handle}}",
|
||||
public: false,
|
||||
to: @aspect.id
|
||||
)
|
||||
comment_service(auth_read_only.user).create(@private_post.guid, "Comment")
|
||||
auth_read_only.user.like!(@private_post)
|
||||
|
||||
@created_status2 = auth_public_only_read_only.user.post(
|
||||
:status_message,
|
||||
text: "This is a status message #test @{#{auth_public_only_read_only.user.diaspora_handle}}",
|
||||
public: true
|
||||
)
|
||||
auth_public_only_read_only.user.like!(@created_status2)
|
||||
comment_service(auth_public_only_read_only.user).create(@created_status2.guid, "Comment")
|
||||
@created_status3 = auth_public_only_read_only.user.post(
|
||||
:status_message,
|
||||
text: "This is a status message #test @{#{auth_public_only_read_only.user.diaspora_handle}}",
|
||||
public: false,
|
||||
to: "all"
|
||||
)
|
||||
auth_public_only_read_only.user.like!(@created_status3)
|
||||
comment_service(auth_public_only_read_only.user).create(@created_status3.guid, "Comment")
|
||||
|
||||
add_tag("test", auth_read_only.user)
|
||||
add_tag("test", auth_public_only_tags.user)
|
||||
end
|
||||
|
||||
describe "#aspect" do
|
||||
it "contains expected aspect message" do
|
||||
get(
|
||||
api_v1_aspects_stream_path(aspect_ids: JSON.generate([@aspect.id])),
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 1
|
||||
confirm_post_format(post[0], auth.user, @status)
|
||||
expect(post.length).to eq 3
|
||||
json_post = post.select {|p| p["guid"] == @status.guid }.first
|
||||
confirm_post_format(json_post, auth_read_only.user, @status)
|
||||
end
|
||||
|
||||
it "all aspects expected aspect message" do
|
||||
get(
|
||||
api_v1_aspects_stream_path,
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 1
|
||||
confirm_post_format(post[0], auth.user, @status)
|
||||
expect(post.length).to eq 3
|
||||
json_post = post.select {|p| p["guid"] == @status.guid }.first
|
||||
confirm_post_format(json_post, auth_read_only.user, @status)
|
||||
end
|
||||
|
||||
it "does not save to requested aspects to session" do
|
||||
get(
|
||||
api_v1_aspects_stream_path(a_ids: [@aspect.id]),
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(session[:a_ids]).to be_nil
|
||||
end
|
||||
|
||||
it "fails without impromper credentials" do
|
||||
get(
|
||||
api_v1_aspects_stream_path(a_ids: [@aspect.id]),
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "fails with invalid credentials" do
|
||||
get(
|
||||
api_v1_aspects_stream_path(a_ids: [@aspect.id]),
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#tags" do
|
||||
it "all tags expected aspect message" do
|
||||
it "all tags expected" do
|
||||
get(
|
||||
api_v1_followed_tags_stream_path,
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
expect(response.status).to eq(200)
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 0
|
||||
expect(post.length).to eq(3)
|
||||
end
|
||||
|
||||
it "public posts only tags expected" do
|
||||
get(
|
||||
api_v1_followed_tags_stream_path,
|
||||
params: {access_token: access_token_public_only_tags}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq(2)
|
||||
end
|
||||
|
||||
it "fails with improper credentials" do
|
||||
get(
|
||||
api_v1_followed_tags_stream_path,
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "fails with invalid credentials" do
|
||||
get(
|
||||
api_v1_followed_tags_stream_path,
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -61,12 +162,31 @@ describe Api::V1::StreamsController do
|
|||
it "contains activity message" do
|
||||
get(
|
||||
api_v1_activity_stream_path,
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 1
|
||||
confirm_post_format(post[0], auth.user, @status)
|
||||
expect(post.length).to eq 2
|
||||
json_post = post.select {|p| p["guid"] == @status.guid }.first
|
||||
confirm_post_format(json_post, auth_read_only.user, @status)
|
||||
end
|
||||
|
||||
it "public posts only expected" do
|
||||
get(
|
||||
api_v1_activity_stream_path,
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq(1)
|
||||
end
|
||||
|
||||
it "fails with invalid credentials" do
|
||||
get(
|
||||
api_v1_activity_stream_path,
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -74,12 +194,31 @@ describe Api::V1::StreamsController do
|
|||
it "contains main message" do
|
||||
get(
|
||||
api_v1_stream_path,
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 3
|
||||
json_post = post.select {|p| p["guid"] == @status.guid }.first
|
||||
confirm_post_format(json_post, auth_read_only.user, @status)
|
||||
end
|
||||
|
||||
it "public posts only expected" do
|
||||
get(
|
||||
api_v1_stream_path,
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 1
|
||||
confirm_post_format(post[0], auth.user, @status)
|
||||
end
|
||||
|
||||
it "fails with invalid credentials" do
|
||||
get(
|
||||
api_v1_stream_path,
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq 401
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -87,11 +226,29 @@ describe Api::V1::StreamsController do
|
|||
it "contains commented message" do
|
||||
get(
|
||||
api_v1_commented_stream_path,
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 0
|
||||
expect(post.length).to eq 2
|
||||
end
|
||||
|
||||
it "public posts only expected" do
|
||||
get(
|
||||
api_v1_commented_stream_path,
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 1
|
||||
end
|
||||
|
||||
it "fails with invalid credentials" do
|
||||
get(
|
||||
api_v1_commented_stream_path,
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq 401
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -99,11 +256,29 @@ describe Api::V1::StreamsController do
|
|||
it "contains mentions message" do
|
||||
get(
|
||||
api_v1_mentions_stream_path,
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 0
|
||||
expect(post.length).to eq 2
|
||||
end
|
||||
|
||||
it "public posts only expected" do
|
||||
get(
|
||||
api_v1_mentions_stream_path,
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 1
|
||||
end
|
||||
|
||||
it "fails with invalid credentials" do
|
||||
get(
|
||||
api_v1_mentions_stream_path,
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq 401
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -111,12 +286,31 @@ describe Api::V1::StreamsController do
|
|||
it "contains liked message" do
|
||||
get(
|
||||
api_v1_liked_stream_path,
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 2
|
||||
json_post = post.select {|p| p["guid"] == @status.guid }.first
|
||||
confirm_post_format(json_post, auth_read_only.user, @status)
|
||||
end
|
||||
|
||||
it "public posts only expected" do
|
||||
get(
|
||||
api_v1_liked_stream_path,
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq 200
|
||||
post = response_body_data(response)
|
||||
expect(post.length).to eq 1
|
||||
confirm_post_format(post[0], auth.user, @status)
|
||||
end
|
||||
|
||||
it "fails with invalid credentials" do
|
||||
get(
|
||||
api_v1_liked_stream_path,
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq 401
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -209,4 +403,15 @@ describe Api::V1::StreamsController do
|
|||
def response_body_data(response)
|
||||
JSON.parse(response.body)["data"]
|
||||
end
|
||||
|
||||
def add_tag(name, user)
|
||||
tag = ActsAsTaggableOn::Tag.find_or_create_by(name: name)
|
||||
tag_following = user.tag_followings.new(tag_id: tag.id)
|
||||
tag_following.save
|
||||
tag_following
|
||||
end
|
||||
|
||||
def comment_service(user)
|
||||
CommentService.new(user)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,12 +3,29 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Api::V1::TagFollowingsController do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid tags:read tags:modify]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid tags:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) { FactoryGirl.create(:auth_with_profile_only) }
|
||||
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_profile_only) { auth_profile_only.create_access_token.to_s }
|
||||
|
||||
before do
|
||||
@expected_tags = %w[tag1 tag2 tag3]
|
||||
@expected_tags.each {|tag| add_tag(tag, auth.user) }
|
||||
@expected_tags.each {|tag| add_tag(tag, auth_read_only.user) }
|
||||
@initial_count = @expected_tags.length
|
||||
end
|
||||
|
||||
|
|
@ -38,7 +55,7 @@ describe Api::V1::TagFollowingsController do
|
|||
params: {access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(400)
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.tags.cant_process"))
|
||||
end
|
||||
end
|
||||
|
|
@ -50,10 +67,28 @@ describe Api::V1::TagFollowingsController do
|
|||
params: {name: "tag3", access_token: access_token}
|
||||
)
|
||||
|
||||
expect(response.status).to eq(400)
|
||||
expect(response.status).to eq(422)
|
||||
expect(response.body).to eq(I18n.t("api.endpoint_errors.tags.cant_process"))
|
||||
end
|
||||
end
|
||||
|
||||
context "fails with credentials" do
|
||||
it "insufficient scopes in token" do
|
||||
post(
|
||||
api_v1_tag_followings_path,
|
||||
params: {name: "tag4", access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "invalid token" do
|
||||
post(
|
||||
api_v1_tag_followings_path,
|
||||
params: {name: "tag4", access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#index" do
|
||||
|
|
@ -61,7 +96,7 @@ describe Api::V1::TagFollowingsController do
|
|||
it "succeeds" do
|
||||
get(
|
||||
api_v1_tag_followings_path,
|
||||
params: {access_token: access_token}
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
items = JSON.parse(response.body)
|
||||
|
|
@ -69,6 +104,24 @@ describe Api::V1::TagFollowingsController do
|
|||
@expected_tags.each {|tag| expect(items.find(tag)).to be_truthy }
|
||||
end
|
||||
end
|
||||
|
||||
context "fails with credentials" do
|
||||
it "insufficient scopes in token" do
|
||||
get(
|
||||
api_v1_tag_followings_path,
|
||||
params: {access_token: access_token_profile_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "invalid token" do
|
||||
get(
|
||||
api_v1_tag_followings_path,
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#delete" do
|
||||
|
|
@ -107,6 +160,24 @@ describe Api::V1::TagFollowingsController do
|
|||
expect(items.length).to eq(@initial_count)
|
||||
end
|
||||
end
|
||||
|
||||
context "fails with credentials" do
|
||||
it "insufficient scopes in token" do
|
||||
delete(
|
||||
api_v1_tag_following_path("tag1"),
|
||||
params: {access_token: access_token_read_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "invalid token" do
|
||||
delete(
|
||||
api_v1_tag_following_path("tag1"),
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
describe Api::OpenidConnect::UserInfoController do
|
||||
let!(:auth_with_read_and_ppid) { FactoryGirl.create(:auth_with_read_and_ppid) }
|
||||
let!(:auth_with_read_and_ppid) {
|
||||
FactoryGirl.create(:auth_with_profile_and_ppid)
|
||||
}
|
||||
|
||||
let!(:access_token_with_read) { auth_with_read_and_ppid.create_access_token.to_s }
|
||||
|
||||
describe "#show" do
|
||||
|
|
|
|||
|
|
@ -5,10 +5,46 @@ require "spec_helper"
|
|||
describe Api::V1::UsersController do
|
||||
include PeopleHelper
|
||||
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read_and_write) }
|
||||
let(:auth_read_only) { FactoryGirl.create(:auth_with_read) }
|
||||
let(:full_scopes) {
|
||||
%w[openid public:read public:modify private:read private:modify contacts:read profile profile:modify]
|
||||
}
|
||||
|
||||
let(:auth) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: full_scopes
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read public:modify]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read private:read contacts:read profile]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_public_only_read_only) {
|
||||
FactoryGirl.create(
|
||||
:auth_with_profile_only,
|
||||
scopes: %w[openid public:read]
|
||||
)
|
||||
}
|
||||
|
||||
let(:auth_profile_only) {
|
||||
FactoryGirl.create(:auth_with_profile_only)
|
||||
}
|
||||
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_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_profile_only) { auth_profile_only.create_access_token.to_s }
|
||||
|
||||
describe "#show" do
|
||||
context "Current User" do
|
||||
|
|
@ -49,7 +85,8 @@ describe Api::V1::UsersController do
|
|||
it "succeeds with in Aspect valid user" do
|
||||
alice.profile[:public_details] = true
|
||||
alice.profile.save
|
||||
auth.user.share_with(alice.person, auth.user.aspects.first)
|
||||
aspect = auth.user.aspects.create(name: "first")
|
||||
auth.user.share_with(alice.person, aspect)
|
||||
get(
|
||||
"/api/v1/users/#{alice.guid}",
|
||||
params: {access_token: access_token}
|
||||
|
|
@ -86,12 +123,31 @@ describe Api::V1::UsersController do
|
|||
|
||||
it "fails if invalid token" do
|
||||
get(
|
||||
api_v1_user_path(alice.person.guid),
|
||||
"/api/v1/users/#{alice.guid}",
|
||||
params: {access_token: "999_999_999"}
|
||||
)
|
||||
expect(response.status).to eq(401)
|
||||
end
|
||||
|
||||
it "fails for private profile if don't have contacts:read" do
|
||||
unsearchable_user = FactoryGirl.create(
|
||||
:person,
|
||||
diaspora_handle: "unsearchable@example.org",
|
||||
profile: FactoryGirl.build(
|
||||
:profile,
|
||||
first_name: "Unsearchable",
|
||||
last_name: "Person",
|
||||
searchable: false
|
||||
)
|
||||
)
|
||||
|
||||
get(
|
||||
"/api/v1/users/#{unsearchable_user.guid}",
|
||||
params: {access_token: access_token_profile_only}
|
||||
)
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it "fails with invalid user GUID" do
|
||||
get(
|
||||
"/api/v1/users/999_999_999",
|
||||
|
|
@ -240,7 +296,8 @@ describe Api::V1::UsersController do
|
|||
contacts = response_body_data(response)
|
||||
expect(contacts.length).to eq(0)
|
||||
|
||||
auth.user.share_with(alice.person, auth.user.aspects.first)
|
||||
aspect = auth.user.aspects.create(name: "first")
|
||||
auth.user.share_with(alice.person, aspect)
|
||||
get(
|
||||
api_v1_user_contacts_path(auth.user.guid),
|
||||
params: {access_token: access_token}
|
||||
|
|
@ -269,6 +326,14 @@ describe Api::V1::UsersController do
|
|||
expect(response.body).to eq(I18n.t("api.endpoint_errors.users.not_found"))
|
||||
end
|
||||
|
||||
it "fails if insufficient scope token" do
|
||||
get(
|
||||
api_v1_user_contacts_path(alice.guid),
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it "fails if invalid token" do
|
||||
get(
|
||||
api_v1_user_contacts_path(alice.guid),
|
||||
|
|
@ -284,10 +349,10 @@ describe Api::V1::UsersController do
|
|||
alice.share_with(eve.person, alice_private_spec)
|
||||
alice.share_with(auth.user.person, alice.aspects.first)
|
||||
|
||||
auth.user.post(:photo, pending: false, user_file: File.open(photo_fixture_name), to: "all")
|
||||
auth.user.post(:photo, pending: false, user_file: File.open(photo_fixture_name), to: "all")
|
||||
@public_photo1 = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name), to: "all")
|
||||
@public_photo2 = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name), to: "all")
|
||||
auth.user.post(:photo, pending: false, user_file: File.open(photo_fixture_name), public: true)
|
||||
auth.user.post(:photo, pending: false, user_file: File.open(photo_fixture_name), public: true)
|
||||
@public_photo1 = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name), public: true)
|
||||
@public_photo2 = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name), public: true)
|
||||
@shared_photo1 = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name),
|
||||
to: alice.aspects.first.id)
|
||||
@private_photo1 = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name),
|
||||
|
|
@ -309,6 +374,19 @@ describe Api::V1::UsersController do
|
|||
confirm_photos(photos)
|
||||
end
|
||||
|
||||
it "returns only public photos of other user without private:read scope in token" do
|
||||
get(
|
||||
api_v1_user_photos_path(alice.guid),
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
photos = response_body_data(response)
|
||||
expect(photos.length).to eq(2)
|
||||
guids = photos.map {|photo| photo["guid"] }
|
||||
expect(guids).to include(@public_photo1.guid, @public_photo2.guid)
|
||||
expect(guids).not_to include(@private_photo1.guid, @shared_photo1.guid)
|
||||
end
|
||||
|
||||
it "returns logged in user's photos" do
|
||||
get(
|
||||
api_v1_user_photos_path(auth.user.guid),
|
||||
|
|
@ -344,10 +422,11 @@ describe Api::V1::UsersController do
|
|||
alice.share_with(eve.person, alice_private_spec)
|
||||
alice.share_with(auth.user.person, alice.aspects.first)
|
||||
|
||||
auth.user.post(:status_message, text: "auth user message1", public: true, to: "all")
|
||||
auth.user.post(:status_message, text: "auth user message2", public: true, to: "all")
|
||||
@public_post1 = alice.post(:status_message, text: "alice public message1", public: true, to: "all")
|
||||
@public_post2 = alice.post(:status_message, text: "alice public message2", public: true, to: "all")
|
||||
auth.user.post(:status_message, text: "auth user message1", public: true)
|
||||
auth.user.post(:status_message, text: "auth user message2", public: true)
|
||||
auth.user.post(:status_message, text: "auth user message3", public: false, to: "all")
|
||||
@public_post1 = alice.post(:status_message, text: "alice public message1", public: true)
|
||||
@public_post2 = alice.post(:status_message, text: "alice public message2", public: true)
|
||||
@shared_post1 = alice.post(:status_message, text: "alice limited to auth user message",
|
||||
public: false, to: alice.aspects.first.id)
|
||||
@private_post1 = alice.post(:status_message, text: "alice limited hidden from auth user message",
|
||||
|
|
@ -377,6 +456,16 @@ describe Api::V1::UsersController do
|
|||
)
|
||||
expect(response.status).to eq(200)
|
||||
posts = response_body_data(response)
|
||||
expect(posts.length).to eq(3)
|
||||
end
|
||||
|
||||
it "returns public posts only without private:read scope in token" do
|
||||
get(
|
||||
api_v1_user_posts_path(auth.user.guid),
|
||||
params: {access_token: access_token_public_only_read_only}
|
||||
)
|
||||
expect(response.status).to eq(200)
|
||||
posts = response_body_data(response)
|
||||
expect(posts.length).to eq(2)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
describe Api::OpenidConnect::ProtectedResourceEndpoint, type: :request do
|
||||
let(:auth_with_read) { FactoryGirl.create(:auth_with_read) }
|
||||
let(:auth_with_read) { FactoryGirl.create(:auth_with_read_scopes) }
|
||||
let!(:access_token_with_read) { auth_with_read.create_access_token.to_s }
|
||||
let!(:expired_access_token) do
|
||||
access_token = auth_with_read.o_auth_access_tokens.create!
|
||||
|
|
|
|||
|
|
@ -64,9 +64,11 @@ describe Api::OpenidConnect::TokenEndpoint, type: :request do
|
|||
end
|
||||
|
||||
it "should not allow a nil code" do
|
||||
post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
|
||||
client_id: client.client_id, client_secret: client.client_secret,
|
||||
redirect_uri: "http://localhost:3000/", code: nil}
|
||||
post api_openid_connect_access_tokens_path, params: {grant_type: "authorization_code",
|
||||
client_id: client.client_id,
|
||||
client_secret: client.client_secret,
|
||||
redirect_uri: "http://localhost:3000/",
|
||||
code: nil}
|
||||
expect(JSON.parse(response.body)["error"]).to eq("invalid_request")
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
describe Api::OpenidConnect::IdToken, type: :model do
|
||||
describe "#to_jwt" do
|
||||
let(:auth) { FactoryGirl.create(:auth_with_read) }
|
||||
let(:auth) { FactoryGirl.create(:auth_with_profile_only) }
|
||||
let(:id_token) { Api::OpenidConnect::IdToken.new(auth, "nonce") }
|
||||
|
||||
describe "decoded data" do
|
||||
|
|
|
|||
|
|
@ -181,6 +181,13 @@ describe PostService do
|
|||
PostService.new(alice).destroy(post.id)
|
||||
end
|
||||
|
||||
it "won't delete private post if explicitly unallowed" do
|
||||
expect {
|
||||
PostService.new(alice).destroy(post.id, false)
|
||||
}.to raise_error Diaspora::NonPublic
|
||||
expect(StatusMessage.find_by(id: post.id)).not_to be_nil
|
||||
end
|
||||
|
||||
it "will not let you destroy posts visible to you but that you do not own" do
|
||||
expect {
|
||||
PostService.new(bob).destroy(post.id)
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ shared_examples_for "it updates user references" do
|
|||
end
|
||||
|
||||
it "updates authorization refrences" do
|
||||
authorization = FactoryGirl.create(:auth_with_read, user: old_user)
|
||||
authorization = FactoryGirl.create(:auth_with_read_scopes, user: old_user)
|
||||
run_migration
|
||||
expect(authorization.reload.user).to eq(new_user)
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue