Merge pull request #1278 from okriuchykhin/ok_SCI_2664

Add user_identities CRUD endpoints, make API V1 togglable [SCI-2664][SCI-2686]
This commit is contained in:
Alex Kriuchykhin 2018-08-24 15:28:34 +02:00 committed by GitHub
commit 818129df1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 215 additions and 10 deletions

View file

@ -0,0 +1,69 @@
# frozen_string_literal: true
module Api
module V1
class UserIdentitiesController < BaseController
before_action :load_user
before_action :load_user_identity, only: %i(show update destroy)
def index
identities =
@user.user_identities.page(params[:page]).per(params[:page_size])
render json: identities, each_serializer: UserIdentitySerializer
end
def create
identity = @user.user_identities.create!(user_identity_params)
render json: identity,
serializer: UserIdentitySerializer,
status: :created
end
def show
render json: @identity, serializer: UserIdentitySerializer
end
def update
@identity.attributes = update_user_identity_params
if @identity.changed? && @identity.save!
render json: @identity, serializer: UserIdentitySerializer
else
render body: nil
end
end
def destroy
@identity.destroy!
render body: nil
end
private
def load_user
@user = current_user if current_user.id == params[:user_id].to_i
return render body: nil, status: :forbidden unless @user
end
def load_user_identity
@identity = @user.user_identities.find(params[:id].to_i)
end
def user_identity_params
unless params.require(:data).require(:type) == 'user_identities'
raise ActionController::BadRequest,
'Wrong object type within parameters'
end
params.require(:data).require(:attributes)
params.permit(data: { attributes: %i(provider uid) })[:data]
end
def update_user_identity_params
unless params.require(:data).require(:id).to_i == params[:id].to_i
raise ActionController::BadRequest,
'Object ID mismatch in URL and request body'
end
user_identity_params
end
end
end
end

View file

@ -1,5 +1,5 @@
class UserIdentity < ActiveRecord::Base
belongs_to :user
validates :provider, uniqueness: { scope: :user_id }
validates :uid, uniqueness: { scope: :provider }
validates :provider, presence: true, uniqueness: { scope: :user_id }
validates :uid, presence: true, uniqueness: { scope: :provider }
end

View file

@ -0,0 +1,7 @@
module Api
module V1
class UserIdentitySerializer < ActiveModel::Serializer
attributes :provider, :uid
end
end
end

View file

@ -16,12 +16,14 @@ module Api
attr_accessor :core_api_token_ttl
attr_accessor :core_api_token_iss
attr_accessor :azure_ad_apps
attr_accessor :core_api_v1_preview
def initialize
@core_api_sign_alg = 'HS256'
@core_api_token_ttl = 30.minutes
@core_api_token_iss = 'SciNote'
@azure_ad_apps = {}
@core_api_v1_preview = false
end
end
end

View file

@ -9,6 +9,8 @@ Api.configure do |config|
config.core_api_token_iss = ENV['CORE_API_TOKEN_ISS']
end
config.core_api_v1_preview = true if ENV['CORE_API_V1_PREVIEW']
vars = ENV.select { |name, _| name =~ /^[[:alnum:]]*_AZURE_AD_APP_ID/ }
vars.each do |name, value|
app_name = name.sub('_AZURE_AD_APP_ID', '')

View file

@ -540,14 +540,17 @@ Rails.application.routes.draw do
get 'health', to: 'api#health'
get 'status', to: 'api#status'
post 'auth/token', to: 'api#authenticate'
namespace :v1 do
resources :teams, only: %i(index show) do
resources :inventories, only: %i(index show) do
get 'columns', to: 'inventory_columns#index'
get 'items', to: 'inventory_items#index'
if Api.configuration.core_api_v1_preview
namespace :v1 do
resources :teams, only: %i(index show) do
resources :inventories, only: %i(index show) do
get 'columns', to: 'inventory_columns#index'
get 'items', to: 'inventory_items#index'
end
end
resources :users, only: %i(show) do
resources :user_identities, only: %i(index create show update destroy)
end
end
resources :users, only: %i(show) do
end
end
end

View file

@ -0,0 +1,6 @@
FactoryBot.define do
factory :user_identity do
uid Faker::Crypto.unique.sha1
provider Faker::App.unique.name
end
end

View file

@ -5,6 +5,9 @@ require 'database_cleaner'
require 'devise'
require_relative 'support/controller_macros'
ENV['RAILS_ENV'] = 'test'
ENV['CORE_API_V1_PREVIEW'] = 'true'
require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production
abort('The Rails environment is running in production mode!') if Rails.env.production?

View file

@ -30,7 +30,7 @@ RSpec.describe 'Api::V1::UsersController', type: :request do
)
end
it 'When invalid request, requested user in not member of the same teams' do
it 'When invalid request, requested user is not member of the same teams' do
hash_body = nil
get api_v1_user_path(id: @user3.id), headers: @valid_headers
expect(response).to have_http_status(403)

View file

@ -0,0 +1,113 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Api::V1::UsersIdentitiesController', type: :request do
before :all do
@user1 = create(:user, email: Faker::Internet.unique.email)
@user2 = create(:user, email: Faker::Internet.unique.email)
create(:user_identity, user: @user1,
uid: Faker::Crypto.unique.sha1, provider: Faker::App.unique.name)
@valid_headers =
{ 'Authorization': 'Bearer ' + generate_token(@user1.id) }
end
describe 'GET user_identities, #index' do
it 'When valid request, requested identities for current user' do
hash_body = nil
get api_v1_user_user_identities_path(user_id: @user1.id),
headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data]).to match(
ActiveModelSerializers::SerializableResource
.new(@user1.user_identities,
each_serializer: Api::V1::UserIdentitySerializer)
.as_json[:data]
)
end
it 'When invalid request, requested user is not signed in user' do
hash_body = nil
get api_v1_user_user_identities_path(user_id: @user2.id),
headers: @valid_headers
expect(response).to have_http_status(403)
expect(hash_body).to match(nil)
end
it 'When invalid request, non existing user' do
hash_body = nil
get api_v1_user_user_identities_path(user_id: 123),
headers: @valid_headers
expect(response).to have_http_status(403)
expect(hash_body).to match(nil)
end
end
describe 'POST user_identities, #create' do
it 'When valid request, create new identity for current user' do
hash_body = nil
post api_v1_user_user_identities_path(user_id: @user1.id),
params: {
data: { type: 'user_identities',
attributes: { uid: Faker::Crypto.unique.sha1,
provider: Faker::App.unique.name } }
},
headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data]).to match(
ActiveModelSerializers::SerializableResource
.new(@user1.user_identities.order(:id).last,
serializer: Api::V1::UserIdentitySerializer)
.as_json[:data]
)
end
end
describe 'GET user_identity, #show' do
it 'When valid request, requested specific identity for current user' do
hash_body = nil
get api_v1_user_user_identity_path(
user_id: @user1.id, id: @user1.user_identities.order(:id).last
), headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data]).to match(
ActiveModelSerializers::SerializableResource
.new(@user1.user_identities.order(:id).last,
serializer: Api::V1::UserIdentitySerializer)
.as_json[:data]
)
end
end
describe 'PUT user_identities, #update' do
it 'When valid request, update identity for current user' do
hash_body = nil
put api_v1_user_user_identity_path(user_id: @user1.id,
id: @user1.user_identities.order(:id).last),
params: {
data: { id: @user1.user_identities.order(:id).last.id,
type: 'user_identities',
attributes: { uid: Faker::Crypto.unique.sha1 } }
},
headers: @valid_headers
expect { hash_body = json }.not_to raise_exception
expect(hash_body[:data]).to match(
ActiveModelSerializers::SerializableResource
.new(@user1.user_identities.order(:id).last,
serializer: Api::V1::UserIdentitySerializer)
.as_json[:data]
)
end
end
describe 'DELETE user_identity, #destroy' do
it 'When valid request, destroy specified identity for current user' do
identity = @user1.user_identities.order(:id).last
delete api_v1_user_user_identity_path(user_id: @user1.id, id: identity),
headers: @valid_headers
expect(response).to have_http_status(200)
expect(response.body).to eq('')
expect(UserIdentity.find_by_id(identity.id)).to eq(nil)
end
end
end