Initial commit

This commit is contained in:
Yaser
2026-08-13 19:56:46 +03:30
commit de1d57a67b
474 changed files with 43185 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
# frozen_string_literal: true
require 'spec_helper'
describe 'Addresses API test' do
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
let!(:image) { fixture_file_upload('/files/documents_test.jpg', 'image/jpg') }
before do
allow(Barong::App.config).to receive_messages(required_docs_expire: false)
end
describe 'POST /api/v2/resource/addresses/' do
let(:params) do
{
country: 'UA',
address: 'Yaroslaviv Val 15',
city: 'Kiev',
postcode: '101010',
upload: [
image
]
}
end
let(:last_document) { Document.last }
it 'saves 10 address documents successfully' do
10.times do
post '/api/v2/resource/addresses', headers: auth_header,
params: {
country: 'UA',
address: 'Yaroslaviv Val 15',
city: 'Kiev',
postcode: '101010',
upload: [fixture_file_upload('/files/documents_test.jpg', 'image/jpg')]
}
end
expect(response.status).to eq(201)
end
it 'uploads 2 files at once' do
post '/api/v2/resource/addresses', headers: auth_header,
params: {
country: 'UA',
address: 'Yaroslaviv Val 15',
city: 'Kiev',
postcode: '101010',
upload: [
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg')
]
}
expect(response.status).to eq(201)
expect(test_user.documents.length).to eq(2)
end
it 'uploads 3 files at once' do
post '/api/v2/resource/addresses', headers: auth_header,
params: {
country: 'UA',
address: 'Yaroslaviv Val 15',
city: 'Kiev',
postcode: '101010',
upload: [
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg')
]
}
expect(response.status).to eq(201)
expect(test_user.documents.length).to eq(3)
end
it 'Checks if params are ok and returns success' do
post '/api/v2/resource/addresses', headers: auth_header, params: params
expect(response.status).to eq(201)
end
it 'Creates a pending address label' do
expect(test_user.labels.find_by(key: :address)).to eq(nil)
post '/api/v2/resource/addresses', headers: auth_header, params: params
expect(response.status).to eq(201)
expect(test_user.labels.find_by(key: :address)).not_to eq(nil)
expect(test_user.labels.find_by(key: :address).value).to eq('pending')
end
it 'Update rejected or verified label to pending documents label on new doc' do
expect(test_user.labels.find_by(key: :address)).to eq(nil)
test_user.labels.create(key: :address, value: 'verified')
test_user.reload
post '/api/v2/resource/addresses', headers: auth_header, params: params
expect(response.status).to eq(201)
expect(test_user.labels.find_by(key: :address)).not_to eq(nil)
expect(test_user.labels.find_by(key: :address).value).to eq('pending')
end
it 'triggers KYCService' do
expect(KycService).to receive(:address_step)
post '/api/v2/resource/addresses', headers: auth_header, params: params
expect(response.status).to eq(201)
end
end
context 'event API behavior' do
let!(:url) { '/api/v2/resource/addresses' }
let(:request_params) do
{
country: 'UA',
address: 'Yaroslaviv Val 15',
city: 'Kiev',
postcode: '101010',
upload: [
image
]
}
end
before do
allow(EventAPI).to receive(:notify)
end
it 'receive model.document.created notify' do
expect(EventAPI).to receive(:notify).ordered.with('model.user.created', hash_including(:record))
expect(EventAPI).to receive(:notify).ordered.with('model.document.created', hash_including(:record))
post url, headers: auth_header, params: request_params
end
end
end

View File

@@ -0,0 +1,263 @@
# frozen_string_literal: true
describe 'Api::V2::APIKeys' do
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
let!(:create_admin_permission) do
create :permission,
role: 'admin'
end
let!(:test_user) { create(:user, otp: otp_enabled) }
let(:otp_enabled) { true }
let!(:first_api_key) { create :api_key, key_holder_account: test_user }
let!(:second_api_key) { create :api_key, key_holder_account: test_user }
let(:valid_otp_code) { '1357' }
let(:invalid_otp_code) { '1234' }
let(:otp_code) { valid_otp_code }
before do
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, valid_otp_code) { true }
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, invalid_otp_code) { false }
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, nil) { false }
end
describe 'GET /api/v2/resource/api_keys/' do
let(:get_params) do
{
ordering: 'asc',
oreder_by: 'id'
}
end
let(:post_params) do
{
scope: 'trade',
algorithm: 'HS256'
}
end
let(:do_request) do
post '/api/v2/resource/api_keys',
params: post_params.merge(totp_code: otp_code),
headers: auth_header
end
let(:do_get_request) { get "/api/v2/resource/api_keys", params: get_params, headers: auth_header }
let(:expected_fields) do
{
kid: first_api_key.kid,
state: first_api_key.state,
scope: %w[trade]
}
end
let(:totp_code) { valid_otp_code }
it 'Return api key for current account in ASC order' do
do_get_request
expect(json_body.count).to eq 2
expect(response.status).to eq(200)
expect(json_body.first).to include(expected_fields)
end
it 'Return api key for current account in DESC order' do
get_params.merge!(ordering: 'desc')
do_get_request
expect(json_body.count).to eq 2
expect(response.status).to eq(200)
expect(json_body.second).to include(expected_fields)
end
context 'when invalid ordering' do
it 'renders an error' do
get_params.merge!(ordering: 'resc')
do_get_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.api_key.invalid_ordering"])
end
end
context 'when invalid order_by' do
it 'renders an error' do
get_params.merge!(order_by: 'invalid')
do_get_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.api_key.invalid_attribute"])
end
end
context 'when otp is not enabled' do
let(:otp_enabled) { false }
it 'renders an error' do
do_request
expect(response.status).to eq(400)
expect_body.to eq(errors: ["resource.api_key.2fa_disabled"])
end
end
context 'when code is invalid' do
let(:otp_code) { invalid_otp_code }
it 'renders an error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.api_key.invalid_totp"])
end
end
end
describe 'POST /api/v2/resource/api_keys' do
let(:do_request) do
post '/api/v2/resource/api_keys',
params: params.merge(totp_code: otp_code),
headers: auth_header
end
let(:otp_code) { valid_otp_code }
context 'when fields are valid' do
let(:params) do
{
scope: 'trade',
algorithm: 'HS256'
}
end
let(:expected_fields) do
{
state: 'active',
scope: params[:scope].split(','),
algorithm: 'HS256'
}
end
it 'Create an api key' do
expect { do_request }.to change { APIKey.count }.by(1)
expect(response.status).to eq(201)
expect_body.to include(expected_fields)
end
it 'does not create api key if vault is down' do
allow(Vault::Rails).to receive(:encrypt).and_raise(Vault::VaultError)
expect { do_request }.not_to change { APIKey.count }
expect(response.status).to eq(422)
expect_body.to eq(errors: ["api_key.could_not_save_secret"])
end
context 'when otp is not enabled' do
let(:otp_enabled) { false }
it 'renders an error' do
do_request
expect(response.status).to eq(400)
expect_body.to eq(errors: ["resource.api_key.2fa_disabled"])
end
end
context 'when code is invalid' do
let(:otp_code) { invalid_otp_code }
it 'renders an error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.api_key.invalid_totp"])
end
end
context 'when algorithm is invalid' do
it 'renders an error' do
params[:algorithm] = 'kek'
do_request
expect_body.to eq(errors: ["kid.blank", "algorithm.inclusion"])
end
end
end
end
describe 'PATCH /api/v2/resource/api_keys/:kid' do
let(:do_request) do
patch "/api/v2/resource/api_keys/#{first_api_key.kid}", params: params.merge(totp_code: otp_code),
headers: auth_header
end
let(:otp_code) { valid_otp_code }
context 'when valid fields' do
let(:params) do
{
state: 'inactive',
scope: 'sell',
algorithm: 'HS256'
}
end
it 'Updates a state' do
expect { do_request }.to change { first_api_key.reload.state }
.from('active').to('inactive')
expect(response.status).to eq(200)
end
it 'Updates a scope' do
expect { do_request }.to change { first_api_key.reload.scope }
.from(['trade']).to(['sell'])
expect(response.status).to eq(200)
end
context 'when otp is not enabled' do
let(:otp_enabled) { false }
it 'renders an error' do
do_request
expect(response.status).to eq(400)
expect_body.to eq(errors: ["resource.api_key.2fa_disabled"])
end
end
context 'when code is invalid' do
let(:otp_code) { invalid_otp_code }
it 'renders an error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.api_key.invalid_totp"])
end
end
end
end
describe 'DELETE /api/v2/resource/api_keys/:uid' do
let(:do_request) do
delete "/api/v2/resource/api_keys/#{first_api_key.kid}?totp_code=#{otp_code}",
headers: auth_header
end
let(:otp_code) { valid_otp_code }
it 'Removes an api key' do
do_request
expect(response.status).to eq(204)
end
context 'when otp is not enabled' do
let(:otp_enabled) { false }
it 'renders an error' do
do_request
expect(response.status).to eq(400)
expect_body.to eq(errors: ["resource.api_key.2fa_disabled"])
end
end
context 'when code is invalid' do
let(:otp_code) { invalid_otp_code }
it 'renders an error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.api_key.invalid_totp"])
end
end
end
end

View File

@@ -0,0 +1,58 @@
# frozen_string_literal: true
describe 'Api::V2::Resource::DataStorage' do
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
describe 'POST /api/v2/resource/data_storage' do
let(:url) { '/api/v2/resource/data_storage' }
context 'successful creation' do
let(:valid_params) do
{
title: 'personal',
data: { wife_last_name: Faker::Name.last_name, wife_first_name: Faker::Name.first_name }.to_json
}
end
it 'creates data_storage record' do
expect { post url, params: valid_params, headers: auth_header }.to change { DataStorage.count }.by(1)
expect(response.status).to eq(201)
end
it 'creates a label when recording data_storage' do
expect { post url, params: valid_params, headers: auth_header }.to change { Label.count }.by(1)
expect(response.status).to eq(201)
expect(test_user.labels.find_by(key: valid_params[:title])).not_to be_nil
end
end
context 'errors' do
let(:non_json_data_params) { { title: 'personal', data: 'My name is John Doe. Hello, World!' } }
let(:non_whitelisted_params) { { title: 'family_info', data: { wife_first_name: Faker::Name.first_name }.to_json } }
let(:blacklisted_params) { { title: 'document', data: { approved: true }.to_json } }
it 'doesnt accept non-json data' do
expect { post url, params: non_json_data_params, headers: auth_header }.not_to change { DataStorage.count }
expect(response.status).to eq(422)
expect(json_body).to eq({errors: ['data.invalid_format']})
end
it 'doesnt accept non-whitelisted title' do
expect { post url, params: non_whitelisted_params, headers: auth_header }.not_to change { DataStorage.count }
expect(response.status).to eq(422)
expect(json_body).to eq({errors: ['title.inclusion']})
end
it 'doesnt accept blacklisted title' do
expect { post url, params: blacklisted_params, headers: auth_header }.not_to change { DataStorage.count }
expect(response.status).to eq(422)
expect(json_body).to eq({errors: ['title.inclusion', 'title.exclusion']})
end
end
end
end

View File

@@ -0,0 +1,288 @@
# frozen_string_literal: true
require 'spec_helper'
describe 'Documents API test' do
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
let!(:image) { fixture_file_upload('/files/documents_test.jpg', 'image/jpg') }
describe 'POST /api/v2/resource/documents/' do
let(:params) do
{
doc_type: 'Passport',
doc_expire: '3020-01-22',
doc_number: 'AA1234BB',
doc_category: 'front_side',
upload: [
image
]
}
end
let!(:optional_params) do
{
metadata: { country: Faker::Address.country }.to_json
}
end
let(:last_document) { Document.last }
it 'saves 10 documents successfully' do
10.times do
post '/api/v2/resource/documents', headers: auth_header,
params: {
doc_type: 'Passport',
doc_expire: '3020-01-22',
doc_number: 'AA1234BB',
upload: [fixture_file_upload('/files/documents_test.jpg', 'image/jpg')]
}
end
expect(response.status).to eq(201)
end
it 'renders an error when max documents already reached' do
11.times do
post '/api/v2/resource/documents', headers: auth_header,
params: {
doc_type: 'Passport',
doc_expire: '3020-01-22',
doc_number: 'AA1234BB',
upload: [fixture_file_upload('/files/documents_test.jpg', 'image/jpg')]
}
end
expect(response.status).to eq(400)
expect_body.to eq(errors: ['resource.documents.limit_will_be_reached'])
end
it 'uploads 2 files at once' do
post '/api/v2/resource/documents', headers: auth_header,
params: {
doc_type: 'Passport',
doc_expire: '3020-01-22',
doc_number: 'AA1234BB',
upload: [
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg')
]
}
expect(response.status).to eq(201)
expect(test_user.documents.length).to eq(2)
end
it 'uploads 3 files at once' do
post '/api/v2/resource/documents', headers: auth_header,
params: {
doc_type: 'Passport',
doc_expire: '3020-01-22',
doc_number: 'AA1234BB',
upload: [
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg')
]
}
expect(response.status).to eq(201)
expect(test_user.documents.length).to eq(3)
end
it 'doesn\'t upload more than 10 files at once' do
post '/api/v2/resource/documents', headers: auth_header,
params: {
doc_type: 'Passport',
doc_expire: '3020-01-22',
doc_number: 'AA1234BB',
upload: [
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg'),
fixture_file_upload('/files/documents_test.jpg', 'image/jpg')
]
}
expect(response.status).to eq(400)
end
it 'Checks if params are ok and returns success' do
post '/api/v2/resource/documents', headers: auth_header, params: params
expect(response.status).to eq(201)
end
it 'Creates a pending documents label' do
expect(test_user.labels.find_by(key: :document)).to eq(nil)
post '/api/v2/resource/documents', headers: auth_header, params: params
expect(response.status).to eq(201)
expect(test_user.labels.find_by(key: :document)).to eq(nil)
post '/api/v2/resource/documents', headers: auth_header,
params: params.merge({ doc_category: 'selfie',
upload: [fixture_file_upload('/files/documents_test.jpg', 'image/jpg')],
identificator: test_user.documents.last.identificator })
expect(test_user.labels.find_by(key: :document).value).to eq('pending')
end
it 'Update rejected or verified label to pending documents label on new doc' do
expect(test_user.labels.find_by(key: :document)).to eq(nil)
test_user.labels.create(key: :document, value: 'verified')
test_user.reload
post '/api/v2/resource/documents', headers: auth_header, params: params
expect(response.status).to eq(201)
expect(test_user.labels.find_by(key: :document)).not_to eq(nil)
expect(test_user.labels.find_by(key: :document).value).to eq('verified')
post '/api/v2/resource/documents', headers: auth_header,
params: params.merge({ doc_category: 'selfie',
upload: [fixture_file_upload('/files/documents_test.jpg', 'image/jpg')],
identificator: test_user.documents.last.identificator })
expect(test_user.labels.find_by(key: :document).value).to eq('pending')
end
it 'triggers KYCService' do
expect(KycService).to receive(:document_step)
post '/api/v2/resource/documents', headers: auth_header, params: params
expect(response.status).to eq(201)
end
it 'Creates document with optional params and returns success' do
post '/api/v2/resource/documents', headers: auth_header, params: params.merge(optional_params)
expect(response.status).to eq(201)
expect(last_document.metadata).to eq(optional_params[:metadata])
end
it 'renders an error if metadata is not json' do
post '/api/v2/resource/documents', headers: auth_header, params: params.merge({ metadata: '{ bar: baz }' })
expect_status_to_eq 422
expect_body.to eq(errors: ['metadata.invalid_format'])
end
it 'Checks provided params and returns error, cause some of them are not valid or absent' do
post '/api/v2/resource/documents', params: params.except(:doc_type), headers: auth_header
expect_body.to eq(errors: ['resource.document.missing_doc_type', 'resource.document.empty_doc_type'])
expect(response.status).to eq(422)
post '/api/v2/resource/documents', params: params.except(:doc_number), headers: auth_header
expect_body.to eq(errors: ['resource.document.missing_doc_number', 'resource.document.empty_doc_number'])
expect(response.status).to eq(422)
post '/api/v2/resource/documents', params: params.except(:upload), headers: auth_header
expect_body.to eq(errors: ['resource.document.missing_upload'])
expect(response.status).to eq(422)
post '/api/v2/resource/documents', params: params.except(:doc_expire).merge(doc_expire: 'blah'), headers: auth_header
expect_body.to eq(errors: ['resource.documents.expire_not_a_date'])
expect(response.status).to eq(422)
params0 = params
params0[:upload] = [Faker::Avatar.image]
post '/api/v2/resource/documents', params: params0, headers: auth_header
expect_body.to eq(errors: ['upload.blank'])
expect(response.status).to eq(422)
end
it 'Does not return error when docs expire is optional' do
allow(Barong::App.config).to receive(:required_docs_expire).and_return(false)
post '/api/v2/resource/documents', params: params.except(:doc_expire), headers: auth_header
expect(response.status).to eq(201)
end
it 'Returns error when docs expire is not optional' do
allow(Barong::App.config).to receive(:required_docs_expire).and_return(true)
post '/api/v2/resource/documents', params: params.except(:doc_expire), headers: auth_header
expect(response.status).to eq(422)
expect_body.to eq({ errors: ['resource.documents.invalid_format'] })
end
it 'Returns error when docs expire is not optional and date in past' do
allow(Barong::App.config).to receive(:required_docs_expire).and_return(true)
post '/api/v2/resource/documents', params: params.merge({ doc_expire: DateTime.now.to_date - 1 }), headers: auth_header
expect(response.status).to eq(422)
expect_body.to eq({ errors: ['resource.documents.already_expired'] })
end
it 'Doesnt return error when docs expire is optional and date in past' do
allow(Barong::App.config).to receive(:required_docs_expire).and_return(false)
post '/api/v2/resource/documents', params: params.merge({ doc_expire: DateTime.now.to_date - 1 }), headers: auth_header
expect(response.status).to eq(201)
end
it 'Returns user all his documents' do
post '/api/v2/resource/documents', params: params, headers: auth_header
expect(response.status).to eq(201)
get '/api/v2/resource/documents', headers: auth_header
response_arr = JSON.parse(response.body)
expect(response_arr.count).to eq(1)
expect(response_arr.last['upload']).to_not be_nil
expect(response_arr.last['doc_type']).to eq('Passport')
expect(response_arr.last['doc_expire']).to eq('3020-01-22')
expect(response_arr.last['doc_number']).to eq('AA****BB')
expect(response.status).to eq(200)
end
context 'without masking' do
before do
Barong::App.config.stub(:api_data_masking_enabled).and_return(false)
end
it 'Returns user all his documents' do
post '/api/v2/resource/documents', params: params, headers: auth_header
expect(response.status).to eq(201)
get '/api/v2/resource/documents', headers: auth_header
response_arr = JSON.parse(response.body)
expect(response_arr.count).to eq(1)
expect(response_arr.last['upload']).to_not be_nil
expect(response_arr.last['doc_type']).to eq('Passport')
expect(response_arr.last['doc_expire']).to eq('3020-01-22')
expect(response_arr.last['doc_number']).to eq('AA1234BB')
expect(response.status).to eq(200)
end
end
it 'Returns error without token' do
post '/api/v2/resource/documents', params: params
expect(response.status).to eq(401)
get '/api/v2/resource/documents', params: params
expect(response.status).to eq(401)
end
after(:all) { User.destroy_all }
end
context 'event API behavior' do
let!(:url) { '/api/v2/resource/documents' }
let(:request_params) do
{
doc_type: 'Passport',
doc_expire: '3020-01-22',
doc_number: 'AA1234BB',
upload: [
image
]
}
end
before do
allow(EventAPI).to receive(:notify)
end
it 'receive model.document.created notify' do
expect(EventAPI).to receive(:notify).ordered.with('model.user.created', hash_including(:record))
expect(EventAPI).to receive(:notify).ordered.with('model.document.created', hash_including(:record))
post url, headers: auth_header, params: request_params
end
end
end

View File

@@ -0,0 +1,88 @@
# frozen_string_literal: true
require 'spec_helper'
describe 'Labels API.' do
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
let!(:create_admin_permission) do
create :permission,
role: 'admin'
end
let(:post_params) do
{
key: ::Faker::Internet.slug(glue: '-'),
value: ::Faker::Internet.slug(glue: '-')
}
end
context 'Happy paths for the current user.' do
let(:test_user) { create(:user, role: "admin") }
let!(:label) { create :label, user: test_user }
let!(:label2) { create :label, user: test_user }
let!(:label3) { create :label, user: test_user }
it 'Return lables for current user' do
get '/api/v2/resource/labels', headers: auth_header
expect(response.status).to eq(200)
expect(json_body.size).to eq(3)
expect(json_body.last[:key]).to eq(label3.key)
end
it 'Return a label by key' do
get "/api/v2/resource/labels/#{label.key}", headers: auth_header
expect(response.status).to eq(200)
expect(json_body[:key]).to eq(label.key)
end
it 'Create a label' do
post '/api/v2/resource/labels', params: post_params, headers: auth_header
expect(response.status).to eq(201)
persisted = Label.find_by(key: json_body[:key])
expect(persisted.key).to eq(post_params[:key])
expect(persisted.value).to eq(post_params[:value])
expect(persisted.scope).to eq('public')
expect(persisted.user_id).to eq(test_user.id)
end
it 'Update a label' do
patch "/api/v2/resource/labels/#{label.key}", params: post_params, headers: auth_header
expect(response.status).to eq(200)
persisted = Label.find_by(key: label.key)
expect(persisted.value).to eq(post_params[:value])
expect(persisted.scope).to eq('public')
end
it 'Delete a label' do
delete "/api/v2/resource/labels/#{label.key}", headers: auth_header
expect(response.status).to eq(204)
expect(Label.find_by(key: label.key)).to be_nil
end
end
context 'Errors.' do
let(:test_user) { create(:user, role: "admin") }
let!(:label) { create :label, user: test_user }
it 'Respond with errors on create if existing key is used for current user' do
post '/api/v2/resource/labels', params: post_params.merge(key: label.key), headers: auth_header
expect(response.status).to eq(422)
expect(response.body).to be_include('key.taken')
end
it 'Respond with error if attempted to update a private label' do
label.update(scope: 'private')
patch "/api/v2/resource/labels/#{label.key}", params: post_params, headers: auth_header
expect(response.status).to eq(400)
end
it 'Respond with error if key not found' do
get '/api/v2/resource/labels/blah', headers: auth_header
expect(response.status).to eq(404)
end
end
end

View File

@@ -0,0 +1,129 @@
# frozen_string_literal: true
describe 'Api::V2::Resource::Otp' do
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
let(:do_request) { post '/api/v2/resource/otp/enable', headers: auth_header }
let(:otp_code) { '111111' }
context 'valid request' do
before do
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, otp_code) { true }
end
it 'user enables 2fa successfully' do
post '/api/v2/resource/otp/enable', headers: auth_header, params: {
code: otp_code
}
expect(response.status).to eq 201
expect(test_user.reload.otp).to eq true
expect(test_user.reload.labels.find_by(key: :otp, scope: :private)).not_to eq nil
end
it 'user disables 2fa successfully' do
test_user.update(otp: true)
test_user.labels.create(value: 'verified', key: :otp, scope: :private)
post '/api/v2/resource/otp/disable', headers: auth_header, params: {
code: otp_code
}
expect(response.status).to eq 200
expect(test_user.reload.otp).to eq false
expect(test_user.reload.labels.find_by(key: :otp, scope: :private)).to eq nil
end
it 'user verify otp Code' do
test_user.update(otp: true)
test_user.labels.create(value: 'verified', key: :otp, scope: :private)
post '/api/v2/resource/otp/verify', headers: auth_header, params: {
code: otp_code
}
expect(response.status).to eq 201
expect(test_user.reload.otp).to eq true
expect(test_user.reload.labels.find_by(key: :otp, scope: :private)).not_to eq nil
end
end
context 'incomplete request' do
it 'user receives error in enabling' do
post '/api/v2/resource/otp/enable', headers: auth_header, params: {
code: otp_code
}
expect(response.status).to eq 422
expect(test_user.reload.otp).to eq false
expect(test_user.reload.labels.find_by(key: :otp, scope: :private)).to eq nil
end
it 'user receives error in disabling' do
test_user.update(otp: true)
test_user.labels.create(key: :otp, scope: :private)
post '/api/v2/resource/otp/disable', headers: auth_header, params: {
code: otp_code
}
expect(response.status).to eq 422
expect(test_user.reload.otp).to eq true
expect(test_user.reload.labels.find_by(key: :otp, scope: :private)).to eq nil
end
end
context 'already done' do
before do
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, otp_code) { true }
end
it 'enabling otp' do
test_user.update(otp: true)
test_user.labels.create(value: 'verified', key: :otp, scope: :private)
post '/api/v2/resource/otp/enable', headers: auth_header, params: {
code: otp_code
}
expect(response.status).to eq 400
expect(test_user.reload.otp).to eq true
expect(test_user.reload.labels.find_by(key: :otp, scope: :private)).not_to eq nil
end
it 'disabling otp' do
post '/api/v2/resource/otp/disable', headers: auth_header, params: {
code: otp_code
}
expect(response.status).to eq 400
expect(test_user.reload.otp).to eq false
expect(test_user.reload.labels.find_by(key: :otp, scope: :private)).to eq nil
end
it 'otp disabled' do
post '/api/v2/resource/otp/verify', headers: auth_header, params: {
code: otp_code
}
expect(response.status).to eq 400
expect(test_user.reload.otp).to eq false
expect(test_user.reload.labels.find_by(key: :otp, scope: :private)).to eq nil
end
it 'otp enabled' do
test_user.update(otp: true)
test_user.labels.create(value: 'verified', key: :otp, scope: :private)
post '/api/v2/resource/otp/generate_qrcode', headers: auth_header
expect(response.status).to eq 400
expect(test_user.reload.otp).to eq true
expect(test_user.reload.labels.find_by(key: :otp, scope: :private)).not_to eq nil
end
end
end

View File

@@ -0,0 +1,469 @@
# frozen_string_literal: true
describe 'Api::V2::Resources::Phones' do
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
context 'Twilio Verify Service' do
before do
allow(Barong::App.config).to receive(:twilio_provider).and_return(TwilioVerifyService)
end
describe 'GET /api/v2/resource/phones' do
let!(:phone1) { create(:phone, user: test_user) }
let!(:phone2) { create(:phone, user: test_user, number: 12345677711 ) }
let(:do_request) do
get '/api/v2/resource/phones', headers: auth_header
end
it 'returns list of user\'s phones' do
do_request
expect(json_body.length).to eq 2
expect(json_body.first[:number]).to eq phone1.sub_masked_number
expect(json_body.first[:country]).to eq phone1.country
expect(json_body.first[:validated_at]).to eq phone1.validated_at
expect(json_body.second[:number]).to eq phone2.sub_masked_number
expect(json_body.second[:country]).to eq phone2.country
expect(json_body.second[:validated_at]).to eq phone2.validated_at
end
context 'list of users phone without masking' do
before do
Barong::App.config.stub(:api_data_masking_enabled).and_return(false)
end
it 'returns list of user\'s phones' do
do_request
expect(json_body.length).to eq 2
expect(json_body.first[:number]).to eq phone1.number
expect(json_body.first[:country]).to eq phone1.country
expect(json_body.first[:validated_at]).to eq phone1.validated_at
expect(json_body.second[:number]).to eq phone2.number
expect(json_body.second[:country]).to eq phone2.country
expect(json_body.second[:validated_at]).to eq phone2.validated_at
end
end
end
describe 'POST /api/v2/resource/phones' do
let(:do_request) do
post '/api/v2/resource/phones', params: params, headers: auth_header
end
let(:phone_number) { nil }
let(:params) { { phone_number: phone_number, channel: 'sms' } }
describe 'errors: ' do
context 'when phone is missing' do
let(:phone_number) { nil }
it 'renders an error' do
do_request
expect_body.to eq(errors: ["resource.phone.empty_phone_number"])
expect_status.to eq 422
end
end
context 'when phone is invalid' do
let(:phone_number) { '123' }
it 'renders an error' do
do_request
expect_body.to eq(errors: ["resource.phone.invalid_num"])
expect_status.to eq 400
end
end
context 'when phone is already exists' do
let!(:phone) do
create(:phone, validated_at: validated_at)
end
let(:phone_number) { phone.number }
context 'when phone verified' do
let(:validated_at) { 1.minutes.ago }
it 'renders an error' do
do_request
expect_body.to eq(errors: ["resource.phone.number_exist"])
expect_status.to eq 400
end
end
context 'when phone is not verified' do
let(:validated_at) { 1.minutes.ago }
it 'renders an error' do
do_request
expect_body.to eq(errors: ["resource.phone.number_exist"])
expect_status.to eq 400
end
end
context 'when phone verified but number is not sanitized' do
let(:validated_at) { 1.minutes.ago }
let(:phone_number) { "++#{phone.number}" }
it 'renders an error' do
do_request
expect_body.to eq(errors: ["resource.phone.number_exist"])
expect_status.to eq 400
end
end
end
end
context 'valid story' do
before do
allow(Barong::App.config.twilio_provider).to receive(:send_code).and_return(false)
end
context 'when phone is not verified' do
let(:phone_number) { build(:phone).number }
it 'assigns a phone to account and send sms' do
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
end
end
context 'when phone is valid' do
let(:phone_number) { build(:phone).number }
it 'creates a phone and send code via sms channel' do
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
end
it 'creates a phone and send code via call channel' do
params['channel'] = 'call'
do_request
expect_body.to eq(message: 'Code was sent successfully via call')
expect_status.to eq 201
end
end
end
context 'when phone is on national format with zero' do
let(:phone_number) { '+44 07418084106' }
let(:international_phone) { '447418084106' }
it 'creates a phone and send sms' do
allow(Barong::App.config.twilio_provider).to receive(:send_code).and_return(false)
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
expect(Phone.last.number).to eq(international_phone)
end
end
context 'when phone exists on international format' do
let(:phone_number) { '+44 07418084106' }
let(:international_phone) { '447418084106' }
let!(:phone) do
create(:phone, validated_at: 1.minute.ago, number: international_phone)
end
it 'renders an error' do
do_request
expect_body.to eq errors: ["resource.phone.number_exist"]
expect_status.to eq 400
end
end
end
describe 'POST /api/v2/resource/phones/verify' do
let(:do_request) do
post '/api/v2/resource/phones/verify', params: params, headers: auth_header
end
let(:params) do
{
phone_number: phone_number,
verification_code: verification_code
}
end
let(:verification_code) { '12345' }
context 'when phone is missing and code is missing' do
let(:phone_number) { nil }
let(:verification_code) { '' }
it 'renders an error' do
do_request
expect_body.to eq(errors: ["resource.phone.empty_phone_number", "resource.phone.empty_verification_code"])
expect_status.to eq 422
end
end
context 'when phone is invalid' do
let(:phone_number) { '123' }
it 'renders an error' do
do_request
expect_body.to eq(errors: ["resource.phone.invalid_num"])
expect_status.to eq 400
end
end
context 'when phone is already exists and verified' do
let!(:phone) do
create(:phone, validated_at: 1.minutes.ago)
end
let(:phone_number) { phone.number }
it 'renders an error' do
do_request
expect_body.to eq(errors: ["resource.phone.number_exist"])
expect_status.to eq 400
end
end
context 'when phone exists in international format' do
let!(:phone) do
create(:phone, validated_at: 1.minutes.ago, number: international_phone)
end
let(:phone_number) { '+44 07418084106' }
let(:international_phone) { '447418084106' }
it 'renders an error' do
do_request
expect_body.to eq(errors: ["resource.phone.number_exist"])
expect_status.to eq 400
end
end
context 'when phone is not found in test_user' do
let!(:phone) { create(:phone) }
let(:phone_number) { phone.number }
it 'rendens an error' do
allow(Barong::App.config.twilio_provider).to receive(:verify_code?).and_return(false)
do_request
expect_body.to eq(errors: ["resource.phone.doesnt_exist"])
expect_status.to eq 404
end
end
context 'when phone is found in test_user but code is invalid' do
let!(:phone) { create(:phone, user: test_user) }
let(:phone_number) { phone.number }
it 'rendens an error' do
allow(Barong::App.config.twilio_provider).to receive(:verify_code?).and_return(false)
do_request
expect_body.to eq(errors: ["resource.phone.verification_invalid"])
expect_status.to eq 404
end
end
context 'when phone and code is valid' do
let(:phone) { create(:phone, user: test_user) }
let(:phone_number) { phone.number }
it 'responses with success' do
allow(Barong::App.config.twilio_provider).to receive(:verify_code?).and_return(true)
set_level(test_user, 1)
do_request
expect_status.to eq 201
expect(phone.reload.validated_at).to be
test_user.update_level
expect(test_user.reload.level).to eq 2
end
end
end
end
context 'With Twilio SMS Sender service' do
let(:phone_number) { phone.number }
let(:do_request) do
post '/api/v2/resource/phones', params: params, headers: auth_header
end
let(:params) { { phone_number: phone_number, channel: 'sms' } }
let(:verification_code) { '12345' }
context 'valid story sms sender service' do
let(:mock_sms) { Barong::MockSMS }
before do
allow(Barong::App.config).to receive(:twilio_provider).and_return(MockPhoneVerifyService)
end
context 'when phone is not verified' do
let(:phone_number) { build(:phone).number }
it 'assigns a phone to account and send sms' do
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
expect(mock_sms.messages.last.to).to eq "+#{phone_number}"
end
it 'sends a default sms content' do
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
expect(mock_sms.messages.last.body).to start_with('Your verification code for Barong: ')
end
it 'sends a custom message with content before code' do
allow(Barong::App.config).to receive(:sms_content_template).and_return('Please confirm your phone with the following code: {{code}}')
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
expect(mock_sms.messages.last.body).to start_with('Please confirm your phone with the following code: ')
end
it 'sends a custom message with content after code' do
allow(Barong::App.config).to receive(:sms_content_template).and_return('{{code}} - this is your confirmation code')
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
expect(mock_sms.messages.last.body).to end_with(' - this is your confirmation code')
end
it 'sends a custom message with code in the midle of the content' do
allow(Barong::App.config).to receive(:sms_content_template).and_return('Following code: {{code}} should be used for phone confirmation')
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
expect(mock_sms.messages.last.body).to start_with('Following code: ')
expect(mock_sms.messages.last.body).to end_with(' should be used for phone confirmation')
end
end
context 'when phone is valid' do
let(:phone_number) { build(:phone).number }
it 'creates a phone and send sms' do
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
expect(mock_sms.messages.last.to).to eq "+#{phone_number}"
end
it 'doesnt change code in DB on phone initialize' do
do_request
expect_body.to eq(message: 'Code was sent successfully via sms')
expect_status.to eq 201
code_after_create = Phone.last.code
# Phone.last initilazes phone
code_after_initialize = Phone.last.code
expect(code_after_create).to eq code_after_initialize
end
end
end
context 'POST /api/v2/resource/phones/verify' do
let(:do_request) do
post '/api/v2/resource/phones/verify', params: params, headers: auth_header
end
let(:params) do
{
phone_number: phone_number,
verification_code: verification_code
}
end
let(:verification_code) { '12345' }
context 'when phone is missing and code is missing' do
let(:phone_number) { nil }
let(:verification_code) { '' }
it 'renders an error' do
do_request
expect_body.to eq(errors: ['resource.phone.empty_phone_number', 'resource.phone.empty_verification_code'])
expect_status.to eq 422
end
end
context 'when phone is invalid' do
let(:phone_number) { '123' }
it 'renders an error' do
do_request
expect_body.to eq(errors: ['resource.phone.invalid_num'])
expect_status.to eq 400
end
end
context 'when phone is already exists and verified' do
let!(:phone) do
create(:phone, validated_at: 1.minutes.ago)
end
let(:phone_number) { phone.number }
it 'renders an error' do
do_request
expect_body.to eq(errors: ['resource.phone.number_exist'])
expect_status.to eq 400
end
end
context 'when phone exists in international format' do
let!(:phone) do
create(:phone, validated_at: 1.minutes.ago, number: international_phone)
end
let(:phone_number) { '+44 07418084106' }
let(:international_phone) { '447418084106' }
it 'renders an error' do
do_request
expect_body.to eq(errors: ['resource.phone.number_exist'])
expect_status.to eq 400
end
end
context 'when phone is not found in test_user' do
let!(:phone) { create(:phone) }
let(:phone_number) { phone.number }
it 'rendens an error' do
do_request
expect_body.to eq(errors: ['resource.phone.doesnt_exist'])
expect_status.to eq 404
end
end
context 'when phone is found in test_user but code is invalid still approves because of mock provider' do
let!(:phone) { create(:phone, user: test_user) }
let(:phone_number) { phone.number }
it 'approves phone' do
do_request
expect_status.to eq 201
expect(phone.reload.validated_at).to be
end
end
context 'when phone and code is valid' do
let(:phone) { create(:phone, user: test_user) }
let(:phone_number) { phone.number }
let(:verification_code) { phone.code }
it 'responses with success' do
set_level(test_user, 1)
do_request
expect_status.to eq 201
expect(phone.reload.validated_at).to be
test_user.update_level
expect(test_user.reload.level).to eq 2
end
end
end
end
end

View File

@@ -0,0 +1,572 @@
# frozen_string_literal: true
describe 'API::V2::Resource::Profiles' do
before { allow(Barong::App.config).to receive_messages(kyc_provider: 'local') }
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
let!(:optional_params) do
{
metadata: {
gender: Faker::Creature::Dog.gender,
place_of_birth: Faker::Address.city
}.to_json
}
end
describe 'POST /api/v2/resource/profiles' do
describe 'KYC verification' do
let!(:request_params) do
{
last_name: Faker::Name.last_name,
first_name: Faker::Name.first_name,
dob: Faker::Date.birthday,
country: Faker::Address.country_code,
city: Faker::Address.city,
address: Faker::Address.state,
postcode: Faker::Address.zip_code
}
end
let!(:url) { '/api/v2/resource/profiles' }
it 'triggers KycService' do
expect(KycService).to receive(:profile_step)
post url, params: request_params, headers: auth_header
expect(response.status).to eq(201)
end
context 'Local verification' do
before { allow(Barong::App.config).to receive_messages(kyc_provider: 'local') }
it 'adds a label for first verification' do
expect(test_user.labels).to eq([])
post url, params: request_params, headers: auth_header
expect(test_user.reload.labels.count).to eq(1)
expect(test_user.reload.labels.first.key).to eq('profile')
expect(test_user.reload.labels.first.value).to eq('drafted')
end
it 'doesnt trigger KYCAID worker' do
expect(KycService).to receive(:profile_step)
expect(KYC::Kycaid::ApplicantWorker).not_to receive(:perform_async)
post url, params: request_params, headers: auth_header
expect(response.status).to eq(201)
end
it 'updates label on re-submit' do
expect(test_user.labels).to eq([])
post url, params: request_params, headers: auth_header
expect(test_user.reload.labels.count).to eq(1)
expect(test_user.reload.labels.first.key).to eq('profile')
expect(test_user.reload.labels.first.value).to eq('drafted')
put url, params: request_params.merge(confirm: true), headers: auth_header
expect(test_user.reload.labels.count).to eq(1)
expect(test_user.reload.labels.first.key).to eq('profile')
expect(test_user.reload.labels.first.value).to eq('submitted')
end
end
context 'KYCAID verification' do
before { allow(Barong::App.config).to receive_messages(kyc_provider: 'kycaid') }
it 'adds a label for first verification' do
expect(test_user.labels).to eq([])
post url, params: request_params, headers: auth_header
expect(test_user.reload.labels.count).to eq(1)
expect(test_user.reload.labels.first.key).to eq('profile')
expect(test_user.reload.labels.first.value).to eq('drafted')
end
it 'updates label on re-submit' do
expect(test_user.labels).to eq([])
post url, params: request_params, headers: auth_header
expect(test_user.reload.labels.count).to eq(1)
expect(test_user.reload.labels.first.key).to eq('profile')
expect(test_user.reload.labels.first.value).to eq('drafted')
put url, params: request_params.merge(confirm: true), headers: auth_header
expect(test_user.reload.labels.count).to eq(1)
expect(test_user.reload.labels.first.key).to eq('profile')
expect(test_user.reload.labels.first.value).to eq('submitted')
end
it 'triggers KYCAID worker on submitted state' do
expect(KYC::Kycaid::ApplicantWorker).to receive(:perform_async)
post url, params: request_params.merge(confirm: true), headers: auth_header
expect(response.status).to eq(201)
end
it 'doesnt trigger KYCAID worker on drafted state' do
expect(KYC::Kycaid::ApplicantWorker).not_to receive(:perform_async)
post url, params: request_params, headers: auth_header
expect(response.status).to eq(201)
end
it 'doesnt trigger KYCAID worker on rejected state' do
post url, params: request_params.merge(confirm: true), headers: auth_header
expect(response.status).to eq(201)
expect(KYC::Kycaid::ApplicantWorker).not_to receive(:perform_async)
test_user.reload.profiles.last.update(state: 'rejected')
end
it 'doesnt trigger KYCAID worker on verified state' do
post url, params: request_params.merge(confirm: true), headers: auth_header
expect(response.status).to eq(201)
expect(KYC::Kycaid::ApplicantWorker).not_to receive(:perform_async)
test_user.reload.profiles.last.update(state: 'verified')
end
end
end
let!(:url) { '/api/v2/resource/profiles' }
let!(:user_info) { '/api/v2/resource/users/me' }
let!(:request_params) do
{
last_name: Faker::Name.last_name,
first_name: Faker::Name.first_name,
dob: Faker::Date.birthday,
country: Faker::Address.country_code_long,
city: Faker::Address.city,
address: Faker::Address.state,
postcode: Faker::Address.zip_code
}
end
let!(:asian_params) do
{
last_name: "",
first_name: "채원",
dob: Faker::Date.birthday,
country: Faker::Address.country_code_long,
city: "안산시",
address: "사직로3길 23",
postcode: Faker::Address.zip_code
}
end
it 'accept / , ; in address' do
request_params[:address] = '28/2 Kevin Brook; Miami, USA'
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:address]).to eq request_params[:address]
end
it 'accept . in address' do
request_params[:address] = 'Larkin Fork.South, New York/AP'
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:address]).to eq request_params[:address]
end
it 'accept # ~ \ : " & ( ) in address' do
request_params[:address] = '28~1/2 \"Kevin & Brook": (Miami, USA)'
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:address]).to eq request_params[:address]
end
it "accept ' in address" do
request_params[:address] = "'Larkin Fork' South New York"
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:address]).to eq request_params[:address]
end
it "accept in address" do
request_params[:address] = "'LarkinFork' South New York"
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:address]).to eq request_params[:address]
end
it "doesn't accept @ in address" do
request_params[:address] = "'LarkinFork' @South New York"
expect { post url, params: request_params, headers: auth_header }
.not_to change { Profile.count }
expect(response.status).to eq(422)
end
it 'accept . in city' do
request_params[:city] = 'St. Petersburg'
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:city]).to eq request_params[:city]
end
it 'accept dash in city' do
request_params[:city] = 'HubliDharwad'
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:city]).to eq request_params[:city]
end
it 'accept hyphen in city' do
request_params[:city] = 'Hubli-Dharwad'
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:city]).to eq request_params[:city]
end
it 'accept \' in city' do
request_params[:city] = 'Cava de\' Tirreni'
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:city]).to eq request_params[:city]
end
it "doesn't accept # in city" do
request_params[:city] = 'Cava de\' #Tirreni'
expect { post url, params: request_params, headers: auth_header }
.not_to change { Profile.count }
expect(response.status).to eq(422)
end
it "doesn't accept @ in city" do
request_params[:city] = 'Cava de\' @Tirreni'
expect { post url, params: request_params, headers: auth_header }
.not_to change { Profile.count }
expect(response.status).to eq(422)
end
it 'creates new profile with only required fields' do
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:last_name]).to eq request_params[:last_name].sub(/(?<=\A.{1})(.*)/) { |match| '*' * match.length }
expect(res[:first_name]).to eq request_params[:first_name]
expect(res[:dob]).to eq request_params[:dob].to_s.sub(/(?<=\A.{8})(.*)/) { |match| '*' * match.length }
expect(res[:country]).to eq request_params[:country]
expect(res[:city]).to eq request_params[:city]
expect(res[:address]).to eq request_params[:address]
expect(res[:postcode]).to eq request_params[:postcode]
expect(res[:metadata]).to be_blank
end
it 'creates new profile with only required fields without masking' do
Barong::App.config.stub(:api_data_masking_enabled).and_return(false)
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:last_name]).to eq request_params[:last_name]
expect(res[:first_name]).to eq request_params[:first_name]
expect(res[:dob]).to eq request_params[:dob].to_s
expect(res[:country]).to eq request_params[:country]
expect(res[:city]).to eq request_params[:city]
expect(res[:address]).to eq request_params[:address]
expect(res[:postcode]).to eq request_params[:postcode]
expect(res[:metadata]).to be_blank
end
it 'creates new profile with corean symbols fields' do
expect { post url, params: asian_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:last_name]).to eq asian_params[:last_name]
expect(res[:first_name]).to eq asian_params[:first_name]
expect(res[:dob]).to eq asian_params[:dob].to_s.sub(/(?<=\A.{8})(.*)/) { |match| '*' * match.length }
expect(res[:country]).to eq asian_params[:country]
expect(res[:city]).to eq asian_params[:city]
expect(res[:address]).to eq asian_params[:address]
expect(res[:postcode]).to eq asian_params[:postcode]
expect(res[:metadata]).to be_blank
end
it 'creates new profile with all metadata fields' do
expect { post url, params: request_params.merge(optional_params), headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
res = json_body
expect(res[:metadata]).to eq(optional_params[:metadata])
end
it 'renders an error if metadata is not json' do
expect { post url, params: request_params.merge({ metadata: '{ bar: baz }' }), headers: auth_header }
.not_to change { Profile.count }
expect_status_to_eq 422
expect_body.to eq(errors: ["metadata.invalid_format"])
end
context 'create another one profile with state drafted' do
before do
post url, params: request_params.merge(optional_params), headers: auth_header
end
it 'doesn\'t create new profile' do
post url, params: request_params.merge(optional_params), headers: auth_header
result = json_body
expect(*result[:errors]).to eq('state.exists')
end
end
context 'create another one profile with state submitted' do
before do
post url, params: request_params.merge(optional_params, confirm: true), headers: auth_header
end
it 'doesn\'t create new profile' do
post url, params: request_params.merge(optional_params, confirm: true), headers: auth_header
result = json_body
expect(*result[:errors]).to eq('state.exists')
end
end
context 'create another one profile with state submitted and drafted' do
before do
post url, params: request_params.merge(optional_params, confirm: true), headers: auth_header
end
it 'doesn\'t create new profile' do
post url, params: request_params.merge(optional_params), headers: auth_header
result = json_body
expect(*result[:errors]).to eq('state.exists')
end
end
context 'partial creating profile' do
context 'empty params' do
it 'returns profile' do
expect { post url, params: {}, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
expect(json_body[:state]).to eq('drafted')
expect(json_body[:metadata].blank?).to be_truthy
Profile::OPTIONAL_PARAMS.each { |p|
expect(json_body[p].blank?).to be_truthy
}
Profile::OPTIONAL_PARAMS.each { |p|
expect(json_body.with_indifferent_access[p].blank?).to be_truthy
}
expect(Profile.last.user.labels.find_by(key: 'profile').value).to eq('drafted')
end
end
context 'several params' do
let(:params) { { last_name: Faker::Name.last_name, first_name: Faker::Name.first_name } }
it 'returns profile' do
expect { post url, params: params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
expect(json_body[:first_name].nil?).to be_falsey
expect(json_body[:last_name].nil?).to be_falsey
expect(json_body[:state]).to eq('drafted')
expect(json_body[:metadata].blank?).to be_truthy
(Profile::OPTIONAL_PARAMS - params.stringify_keys.keys).each { |p|
expect(json_body.with_indifferent_access[p].blank?).to be_truthy
}
expect(Profile.last.user.labels.find_by(key: :profile).value).to eq('drafted')
end
end
context 'several params with profile confirmation' do
let(:params) { { last_name: Faker::Name.last_name, first_name: Faker::Name.first_name } }
it 'returns profile' do
expect { post url, params: params.merge(confirm: true), headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
expect(json_body[:first_name].nil?).to be_falsey
expect(json_body[:last_name].nil?).to be_falsey
expect(json_body[:state]).to eq('submitted')
expect(json_body[:metadata].blank?).to be_truthy
(Profile::OPTIONAL_PARAMS - params.stringify_keys.keys).each { |p|
expect(json_body.with_indifferent_access[p].blank?).to be_truthy
}
expect(Profile.last.user.labels.find_by(key: :profile).value).to eq('submitted')
end
end
context 'full profile params' do
it 'returns profile' do
expect { post url, params: request_params, headers: auth_header }
.to change { Profile.count }.by (1)
expect(response.status).to eq(201)
expect(json_body[:state]).to eq('drafted')
expect(json_body[:metadata].blank?).to be_truthy
request_params.keys.each { |p|
expect(json_body[p].present?).to be_truthy
}
expect(Profile.last.user.labels.find_by(key: 'profile').value).to eq('drafted')
end
end
end
end
describe 'GET /api/v2/resource/profiles/me' do
let!(:url) { '/api/v2/resource/profiles/me' }
let!(:request_params) do
{
first_name: Faker::Name.first_name,
last_name: Faker::Name.last_name,
dob: Faker::Date.birthday,
address: Faker::Address.state,
postcode: Faker::Address.zip_code,
city: Faker::Address.city,
country: Faker::Address.country_code_long
}
end
it 'returns user profile data with metadata' do
post '/api/v2/resource/profiles', params: request_params.merge(optional_params),
headers: auth_header
expect(response.status).to eq(201)
get url, headers: auth_header
expect(response.status).to eq(200)
last_name = request_params[:last_name].sub(/(?<=\A.{1})(.*)/) { |match| '*' * match.length }
dob = request_params[:dob].to_s.sub(/(?<=\A.{8})(.*)/) { |match| '*' * match.length }
expected_json = request_params.merge(state: 'drafted', last_name: last_name,dob: dob).merge(optional_params).to_json
expect(JSON.parse(response.body)[0].except('created_at', 'updated_at')).to eq(JSON.parse(expected_json))
end
end
context 'event API behavior' do
let!(:url) { '/api/v2/resource/profiles' }
let!(:request_params) do
{
last_name: Faker::Name.last_name,
first_name: Faker::Name.first_name,
dob: Faker::Date.birthday,
country: Faker::Address.country_code_long,
city: Faker::Address.city,
address: Faker::Address.state,
postcode: Faker::Address.zip_code
}
end
before do
allow(EventAPI).to receive(:notify)
end
it 'receive model.profile.created notify' do
expect(EventAPI).to receive(:notify).ordered.with('model.user.created', hash_including(:record))
expect(EventAPI).to receive(:notify).ordered.with('model.profile.created', hash_including(:record))
post url, params: request_params, headers: auth_header
end
it 'receive model.profile.created notify with user and profile params' do
expect(EventAPI).to receive(:notify).ordered.with('model.user.created', hash_including(:record))
expect(EventAPI).to receive(:notify).ordered.with(
'model.profile.created',
hash_including(
record: {
user: anything,
address: anything,
city: anything,
country: anything,
created_at: anything,
updated_at: anything,
dob: anything,
first_name: anything,
last_name: anything,
postcode: anything
}
)
)
post url, params: request_params, headers: auth_header
end
end
describe 'PUT /api/v2/resource/profiles' do
let!(:url) { '/api/v2/resource/profiles' }
let!(:request_params) do
{
last_name: Faker::Name.last_name,
first_name: Faker::Name.first_name,
dob: Faker::Date.birthday,
country: Faker::Address.country_code_long,
city: Faker::Address.city,
address: Faker::Address.street_address,
postcode: Faker::Address.zip_code
}
end
context 'user without profile' do
it 'renders an error when profile doesnt exist' do
put url, params: request_params, headers: auth_header
expect_status.to eq(404)
expect_body.to eq(errors: ['resource.profile.doesnt_exist_or_not_editable'])
end
end
context 'user with profile' do
let!(:profile) { create(:profile, user: test_user)}
it 'returns submitted profile' do
expect { put url, params: request_params.merge(confirm: true), headers: auth_header }
.not_to change { Profile.count }
expect(response.status).to eq(200)
expect(json_body[:state]).to eq('submitted')
expect(profile[:metadata]).to be_blank
end
end
context 'user with partial profile' do
let!(:profile) { create(:profile, user: test_user, last_name: nil, first_name: nil) }
it 'returns partial profile' do
expect { put url, params: request_params.except(:first_name), headers: auth_header }
.not_to change { Profile.count }
expect(response.status).to eq(200)
expect(json_body[:state]).to eq('drafted')
expect(json_body[:metadata]).to be_blank
end
it 'returns completed profile' do
expect { put url, params: request_params, headers: auth_header }
.not_to change { Profile.count }
expect(response.status).to eq(200)
expect(json_body[:state]).to eq('drafted')
expect(json_body[:metadata]).to be_blank
end
end
end
end

View File

@@ -0,0 +1,297 @@
# frozen_string_literal: true
describe 'Api::V2::Resource::ServiceAccounts' do
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
let!(:create_service_account_permission) do
create :permission,
role: 'service_account'
end
let!(:create_admin_permission) do
create :permission,
role: 'admin'
end
let!(:test_user) { create(:user, otp: otp_enabled, role: 'member') }
let!(:service_account) { create(:service_account, user: test_user) }
let(:otp_enabled) { true }
let!(:first_api_key) { create :api_key, key_holder_account: service_account }
let!(:second_api_key) { create :api_key, key_holder_account: service_account }
let(:valid_otp_code) { '1357' }
let(:invalid_otp_code) { '1234' }
let(:otp_code) { valid_otp_code }
before do
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, valid_otp_code) { true }
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, invalid_otp_code) { false }
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, nil) { false }
end
describe 'GET /api/v2/resource/service_accounts' do
let(:do_request) do
get '/api/v2/resource/service_accounts',
headers: auth_header
end
let(:expected_fields) do
{
uid: service_account.uid,
email: service_account.email,
owner_id: test_user.id,
role: service_account.role,
level: service_account.level,
state: service_account.state,
}
end
it 'Return service accounts for current user' do
do_request
expect(json_body.count).to eq 1
expect(response.status).to eq(200)
expect(json_body.first).to include(expected_fields)
end
end
describe 'GET /api/v2/resource/service_accounts/api_keys/' do
let(:get_params) do
{
service_account_uid: service_account.uid,
ordering: 'asc',
order_by: 'id'
}
end
let(:post_params) do
{
service_account_uid: service_account.uid,
scope: 'trade',
algorithm: 'HS256'
}
end
let(:do_request) do
post '/api/v2/resource/service_accounts/api_keys',
params: post_params.merge(totp_code: otp_code),
headers: auth_header
end
let(:do_get_request) { get "/api/v2/resource/service_accounts/api_keys", params: get_params, headers: auth_header }
let(:expected_fields) do
{
kid: first_api_key.kid,
state: first_api_key.state,
scope: %w[trade]
}
end
let(:totp_code) { valid_otp_code }
it 'Return api key for current account in ASC order' do
do_get_request
expect(json_body.count).to eq 2
expect(response.status).to eq(200)
expect(json_body.first).to include(expected_fields)
end
it 'Return api key for current account in DESC order' do
get_params.merge!(ordering: 'desc')
do_get_request
expect(json_body.count).to eq 2
expect(response.status).to eq(200)
expect(json_body.second).to include(expected_fields)
end
context 'when invalid ordering' do
it 'renders an error' do
get_params.merge!(ordering: 'resc')
do_get_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.service_accounts.invalid_ordering"])
end
end
context 'when invalid order_by' do
it 'renders an error' do
get_params.merge!(order_by: 'invalid')
do_get_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.service_accounts.invalid_attribute"])
end
end
context 'when otp is not enabled' do
let(:otp_enabled) { false }
it 'renders an error' do
do_request
expect(response.status).to eq(400)
expect_body.to eq(errors: ["resource.service_accounts.2fa_disabled"])
end
end
context 'when code is invalid' do
let(:otp_code) { invalid_otp_code }
it 'renders an error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.service_accounts.invalid_totp"])
end
end
end
describe 'POST /api/v2/resource/api_keys' do
let(:do_request) do
post '/api/v2/resource/api_keys',
params: params.merge(totp_code: otp_code),
headers: auth_header
end
let(:otp_code) { valid_otp_code }
context 'when fields are valid' do
let(:params) do
{
scope: 'trade',
algorithm: 'HS256'
}
end
let(:expected_fields) do
{
state: 'active',
scope: params[:scope].split(','),
algorithm: 'HS256'
}
end
it 'Create an api key' do
expect { do_request }.to change { APIKey.count }.by(1)
expect(response.status).to eq(201)
expect_body.to include(expected_fields)
end
it 'does not create api key if vault is down' do
allow(Vault::Rails).to receive(:encrypt).and_raise(Vault::VaultError)
expect { do_request }.not_to change { APIKey.count }
expect(response.status).to eq(422)
expect_body.to eq(errors: ["api_key.could_not_save_secret"])
end
context 'when otp is not enabled' do
let(:otp_enabled) { false }
it 'renders an error' do
do_request
expect(response.status).to eq(400)
expect_body.to eq(errors: ["resource.api_key.2fa_disabled"])
end
end
context 'when code is invalid' do
let(:otp_code) { invalid_otp_code }
it 'renders an error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.api_key.invalid_totp"])
end
end
context 'when algorithm is invalid' do
it 'renders an error' do
params[:algorithm] = 'kek'
do_request
expect_body.to eq(errors: ["kid.blank", "algorithm.inclusion"])
end
end
end
end
describe 'PUT /api/v2/resource/service_accounts/api_keys/:kid' do
let(:do_request) do
put "/api/v2/resource/service_accounts/api_keys/#{first_api_key.kid}", params: params.merge(totp_code: otp_code),
headers: auth_header
end
let(:otp_code) { valid_otp_code }
context 'when valid fields' do
let(:params) do
{
service_account_uid: service_account.uid,
state: 'inactive',
scope: 'sell',
algorithm: 'HS256'
}
end
it 'Updates a state' do
expect { do_request }.to change { first_api_key.reload.state }
.from('active').to('inactive')
expect(response.status).to eq(200)
end
it 'Updates a scope' do
expect { do_request }.to change { first_api_key.reload.scope }
.from(['trade']).to(['sell'])
expect(response.status).to eq(200)
end
context 'when otp is not enabled' do
let(:otp_enabled) { false }
it 'renders an error' do
do_request
expect(response.status).to eq(400)
expect_body.to eq(errors: ["resource.service_accounts.2fa_disabled"])
end
end
context 'when code is invalid' do
let(:otp_code) { invalid_otp_code }
it 'renders an error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.service_accounts.invalid_totp"])
end
end
end
end
describe 'DELETE /api/v2/resource/service_accounts/api_keys/:uid' do
let(:do_request) do
delete "/api/v2/resource/service_accounts/api_keys/#{first_api_key.kid}?totp_code=#{otp_code}&service_account_uid=#{service_account.uid}",
headers: auth_header
end
let(:otp_code) { valid_otp_code }
it 'Removes an api key' do
do_request
expect(response.status).to eq(204)
end
context 'when otp is not enabled' do
let(:otp_enabled) { false }
it 'renders an error' do
do_request
expect(response.status).to eq(400)
expect_body.to eq(errors: ["resource.service_accounts.2fa_disabled"])
end
end
context 'when code is invalid' do
let(:otp_code) { invalid_otp_code }
it 'renders an error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.service_accounts.invalid_totp"])
end
end
end
end

View File

@@ -0,0 +1,270 @@
# frozen_string_literal: true
describe 'Api::V1::Profiles' do
include_context 'bearer authentication'
let!(:create_member_permission) do
create :permission,
role: 'member'
end
describe 'GET /api/v2/resource/users/me' do
it 'should reply permissions denied' do
get '/api/v2/resource/users/me'
expect_body.to eq(errors: ["jwt.decode_and_verify"])
expect(response.status).to eq(401)
end
it 'should allow traffic with Authorization' do
get '/api/v2/resource/users/me', headers: auth_header
expect(json_body[:email]).to eq(test_user.email)
expect(response.status).to eq(200)
end
end
let(:valid_otp_code) { '1357' }
let(:invalid_otp_code) { '1234' }
before do
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, valid_otp_code) { true }
allow(TOTPService).to receive(:validate?)
.with(test_user.uid, invalid_otp_code) { false }
end
describe 'PUT /api/v2/resource/users/me' do
let(:correct_data) { { bar: 'baz' }.to_json }
let(:incorrect_data) { 'random string' }
it 'changes user data field' do
put '/api/v2/resource/users/me', headers: auth_header, params: {
data: correct_data
}
expect(test_user.reload.data).to eq(correct_data)
expect(response.status).to eq 200
end
it 'receives invalid data error' do
put '/api/v2/resource/users/me', headers: auth_header, params: {
data: incorrect_data
}
expect(response.status).to eq 422
expect_body.to eq errors: ['data.invalid_format']
end
end
describe 'DELETE /api/v2/resource/users/me' do
it 'receives invalid password error' do
delete '/api/v2/resource/users/me', headers: auth_header, params: {
password: 'WrongPassword'
}
expect(response.status).to eq 422
expect(test_user.reload.state).to eq 'active'
expect_body.to eq errors: ['resource.user.invalid_password']
end
it 'receives otp missing error if 2fa is enabled and param is missing' do
test_user.update(otp: true)
delete '/api/v2/resource/users/me', headers: auth_header, params: {
password: 'Tecohvi0'
}
expect(response.status).to eq 422
expect(test_user.reload.state).to eq 'active'
expect_body.to eq errors: ['resource.user.missing_otp_code']
end
it 'receives otp empty error if 2fa is enabled and param is empty' do
test_user.update(otp: true)
delete '/api/v2/resource/users/me', headers: auth_header, params: {
password: 'Tecohvi0',
otp_code: ''
}
expect(response.status).to eq 422
expect(test_user.reload.state).to eq 'active'
expect_body.to eq errors: ['resource.user.empty_otp_code']
end
it 'receives invalid otp error with wrong otp code' do
test_user.update(otp: true)
delete '/api/v2/resource/users/me', headers: auth_header, params: {
password: 'Tecohvi0',
otp_code: invalid_otp_code
}
expect(response.status).to eq 422
expect(test_user.reload.state).to eq 'active'
expect_body.to eq errors: ['resource.user.invalid_otp']
end
it 'marks user as deleted with turned on 2fa and valid otp' do
test_user.update(otp: true)
delete '/api/v2/resource/users/me', headers: auth_header, params: {
password: 'Tecohvi0',
otp_code: valid_otp_code
}
expect(response.status).to eq 200
expect(test_user.reload.state).to eq 'deleted'
end
it 'marks user as deleted with turned off 2fa' do
delete '/api/v2/resource/users/me', headers: auth_header, params: {
password: 'Tecohvi0'
}
expect(response.status).to eq 200
expect(test_user.reload.state).to eq 'deleted'
end
end
describe 'POST /api/v2/resource/otp/disable' do
it 'with dasbled 2fa' do
post '/api/v2/resource/otp/disable', headers: auth_header, params: { code: valid_otp_code }
expect_body.to eq errors: ['resource.otp.not_enabled']
end
it 'with invalid code' do
test_user.update(otp: true)
post '/api/v2/resource/otp/disable', headers: auth_header, params: { code: invalid_otp_code }
expect_body.to eq errors: ['resource.otp.invalid']
end
it 'disables 2fa' do
test_user.update(otp: true)
expect {
post '/api/v2/resource/otp/disable', headers: auth_header, params: { code: valid_otp_code }
}.to change { test_user.reload.otp }.from(true).to(false)
expect(response.status).to eq 200
end
end
describe 'POST /api/v2/resource/users/activity' do
it 'allows only [password, otp, session, all] as a topic parameter' do
get '/api/v2/resource/users/activity/invalid', headers: auth_header
expect(response.status).to eq(422)
expect_body.to eq(errors: ['resource.user.wrong_topic'])
get '/api/v2/resource/users/activity/session', headers: auth_header
expect(response.status).to eq(422)
expect_body.to eq(errors: ['resource.user.no_activity'])
end
it 'sorts user activities' do
4.times { create(:activity, user: test_user) }
get '/api/v2/resource/users/activity/all', headers: auth_header
activities = JSON.parse(response.body)
expect(activities.first['id']).to be >= activities.last['id']
end
it 'sorts user activities by result' do
4.times { create(:activity, user: test_user, result: 'succeed') }
get '/api/v2/resource/users/activity/all', params: { result: 'succeed' }, headers: auth_header
activities = JSON.parse(response.body)
expect(activities.length).to eq(4)
end
it 'sorts user activities by time range' do
4.times { create(:activity, user: test_user, result: 'succeed') }
get '/api/v2/resource/users/activity/all', params: { time_from: 5.hours.ago.to_i, time_to: 1.hours.ago.to_i }, headers: auth_header
activities = JSON.parse(response.body)
expect(activities.length).to eq(1)
end
it 'sorts user activities by time range' do
4.times { create(:activity, user: test_user, result: 'succeed') }
4.times { create(:activity, user: test_user, result: 'succeed', created_at: 10.hours.ago) }
get '/api/v2/resource/users/activity/all', params: { time_from: 5.hours.ago.to_i}, headers: auth_header
activities = JSON.parse(response.body)
expect(activities.length).to eq(4)
end
end
describe 'POST /api/v2/resource/users/password' do
let(:do_request) do
put '/api/v2/resource/users/password', params: params, headers: auth_header
end
let(:do_confirm_request) do
post '/api/v2/resource/users/confirm_password', params: { code: otp_code }, headers: auth_header
end
let(:params) do
{
old_password: old_password,
new_password: new_password,
confirm_password: confirm_password
}
end
let(:old_password) { '' }
let(:new_password) { '' }
let(:confirm_password) { '' }
context 'when params are blank' do
it 'renders 400 error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.user.empty_old_password", "resource.user.empty_new_password", "resource.user.empty_confirm_password"])
end
end
context 'when old password is not right' do
let(:old_password) { 'invalid' }
let(:new_password) { 'Gol4aid2' }
let(:confirm_password) { 'Gol4aid2' }
it 'renders 400 error' do
do_request
expect(response.status).to eq(400)
expect_body.to eq(errors: ["resource.password.prev_pass_not_correct"])
end
end
context 'when new pass and confirmation are different' do
let(:old_password) { 'Tecohvi0' } # 'Tecohvi0' - test_user password
let(:new_password) { 'Gol4aid1' }
let(:confirm_password) { 'Gol4aid2' }
it 'renders 422 error' do
do_request
expect(response.status).to eq(422)
expect_body.to eq(errors: ["resource.password.doesnt_match"])
end
end
context 'when params are valid, passwords are weak' do
let(:old_password) { 'Tecohvi0' } # 'Tecohvi0' - test_user password
let(:new_password) { 'Simple' }
let(:confirm_password) { 'Simple' }
it 'returns weak password error' do
do_request
expect_status_to_eq 422
expect_body.to eq(errors: ["temp_password.requirements"])
end
end
context 'when params are valid, confirm code not valid' do
let(:old_password) { 'Tecohvi0' } # 'Tecohvi0' - test_user password
let(:new_password) { 'Gol4aid1' }
let(:confirm_password) { 'Gol4aid1' }
let(:otp_code) { invalid_otp_code }
let(:log_in) { post '/api/v2/identity/sessions', params: { email: test_user.email, password: new_password } }
it 'changes a password' do
do_request
do_confirm_request
expect_status_to_eq 422
expect_body.to eq(errors: ["resource.password.confirm_code_not_match"])
end
end
context 'when params are valid' do
let(:old_password) { 'Tecohvi0' } # 'Tecohvi0' - test_user password
let(:new_password) { 'Gol4aid1' }
let(:confirm_password) { 'Gol4aid1' }
let(:otp_code) { valid_otp_code }
let(:log_in) { post '/api/v2/identity/sessions', params: { email: test_user.email, password: new_password } }
it 'changes a password' do
do_request
expect(response.status).to eq(201)
do_confirm_request
expect(response.status).to eq(201)
log_in
expect(response.status).to eq(200)
end
end
end
end