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 class UserIdentity < ActiveRecord::Base
belongs_to :user belongs_to :user
validates :provider, uniqueness: { scope: :user_id } validates :provider, presence: true, uniqueness: { scope: :user_id }
validates :uid, uniqueness: { scope: :provider } validates :uid, presence: true, uniqueness: { scope: :provider }
end 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_ttl
attr_accessor :core_api_token_iss attr_accessor :core_api_token_iss
attr_accessor :azure_ad_apps attr_accessor :azure_ad_apps
attr_accessor :core_api_v1_preview
def initialize def initialize
@core_api_sign_alg = 'HS256' @core_api_sign_alg = 'HS256'
@core_api_token_ttl = 30.minutes @core_api_token_ttl = 30.minutes
@core_api_token_iss = 'SciNote' @core_api_token_iss = 'SciNote'
@azure_ad_apps = {} @azure_ad_apps = {}
@core_api_v1_preview = false
end end
end end
end end

View file

@ -9,6 +9,8 @@ Api.configure do |config|
config.core_api_token_iss = ENV['CORE_API_TOKEN_ISS'] config.core_api_token_iss = ENV['CORE_API_TOKEN_ISS']
end end
config.core_api_v1_preview = true if ENV['CORE_API_V1_PREVIEW']
vars = ENV.select { |name, _| name =~ /^[[:alnum:]]*_AZURE_AD_APP_ID/ } vars = ENV.select { |name, _| name =~ /^[[:alnum:]]*_AZURE_AD_APP_ID/ }
vars.each do |name, value| vars.each do |name, value|
app_name = name.sub('_AZURE_AD_APP_ID', '') 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 'health', to: 'api#health'
get 'status', to: 'api#status' get 'status', to: 'api#status'
post 'auth/token', to: 'api#authenticate' post 'auth/token', to: 'api#authenticate'
namespace :v1 do if Api.configuration.core_api_v1_preview
resources :teams, only: %i(index show) do namespace :v1 do
resources :inventories, only: %i(index show) do resources :teams, only: %i(index show) do
get 'columns', to: 'inventory_columns#index' resources :inventories, only: %i(index show) do
get 'items', to: 'inventory_items#index' 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
end
resources :users, only: %i(show) do
end end
end 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 'devise'
require_relative 'support/controller_macros' require_relative 'support/controller_macros'
ENV['RAILS_ENV'] = 'test' ENV['RAILS_ENV'] = 'test'
ENV['CORE_API_V1_PREVIEW'] = 'true'
require File.expand_path('../../config/environment', __FILE__) require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production # Prevent database truncation if the environment is production
abort('The Rails environment is running in production mode!') if Rails.env.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 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 hash_body = nil
get api_v1_user_path(id: @user3.id), headers: @valid_headers get api_v1_user_path(id: @user3.id), headers: @valid_headers
expect(response).to have_http_status(403) 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