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,154 @@
# frozen_string_literal: true
describe EncryptionService do
context 'current_salt' do
before(:each) do
EncryptionService.instance_variable_set(:@cache, {})
end
it { expect(EncryptionService.current_salt).to eq Time.now.strftime('%Y%W') }
it do
allow(Time).to receive(:now).and_return(1.week.ago)
expect(EncryptionService.current_salt).to eq Time.now.strftime('%Y%W')
end
end
context 'pack' do
before(:each) do
EncryptionService.instance_variable_set(:@cache, {})
end
it { expect(EncryptionService.pack('salt', 'value')).to eq 'salt.value' }
it { expect(EncryptionService.pack('salt', nil)).to eq 'salt.' }
it { expect(EncryptionService.pack('salt', '')).to eq 'salt.' }
end
context 'unpack' do
before(:each) do
EncryptionService.instance_variable_set(:@cache, {})
end
it { expect(EncryptionService.unpack('salt.value')).to eq ['salt', 'value'] }
it { expect(EncryptionService.unpack('salt.value.value')).to eq ['salt', 'value.value'] }
it { expect(EncryptionService.unpack(' salt.value')).to eq ['salt', 'value'] }
it { expect(EncryptionService.unpack(' salt_underscore.value')).to eq ['salt_underscore', 'value'] }
it { expect(EncryptionService.unpack('salt.')).to eq ['salt', ''] }
it { expect { EncryptionService.unpack('salt') }.to raise_error('Invalid encrypted value: salt') }
end
context 'encrypt' do
before(:each) do
EncryptionService.instance_variable_set(:@cache, {})
end
let(:time) { Time.now.strftime('%Y%W') }
it { expect(EncryptionService.encrypt('value')).to match(/#{time}/) }
end
context 'decrypt' do
before(:each) do
EncryptionService.instance_variable_set(:@cache, {})
end
let(:encrypted_key) { EncryptionService.encrypt('value') }
it { expect(EncryptionService.decrypt(encrypted_key)).to eq 'value' }
end
context 'private methods' do
context 'delete_expired_keys' do
context 'ivalid cases' do
context 'cache as number' do
it 'shouldnt delete expired hash when hash is invalid' do
EncryptionService.instance_variable_set(:@cache, 5)
EncryptionService.send(:delete_expired_keys)
expect(EncryptionService.instance_variable_get(:@cache)).to eq 5
end
end
context 'empty hash' do
it 'shouldnt delete expired hash when hash is invalid' do
EncryptionService.instance_variable_set(:@cache, {})
EncryptionService.send(:delete_expired_keys)
expect(EncryptionService.instance_variable_get(:@cache)).to eq ({})
end
end
context 'invalid hash' do
it 'shouldnt delete expired hash when hash is invalid' do
EncryptionService.instance_variable_set(:@cache, {'test': 'value'})
EncryptionService.send(:delete_expired_keys)
expect(EncryptionService.instance_variable_get(:@cache)).to eq ({'test': 'value'})
end
end
context 'hash without expire date' do
it 'shouldnt delete expired hash when hash is invalid' do
EncryptionService.instance_variable_set(:@cache, {'test': {'key': 'generated_key'}})
EncryptionService.send(:delete_expired_keys)
expect(EncryptionService.instance_variable_get(:@cache)).to eq ({'test': {'key': 'generated_key'}})
end
end
end
context 'valid cases' do
context 'should not delete keys' do
it 'shouldnt delete hash keys' do
EncryptionService.instance_variable_set(:@cache,
{
'test1': {key: 'generated_key', expire_date: Time.now + 3.hours },
'test2': {key: 'generated_key', expire_date: Time.now + 2.hours },
'test3': {key: 'generated_key', expire_date: Time.now + 1.hours },
}.with_indifferent_access
)
EncryptionService.send(:delete_expired_keys)
expect(EncryptionService.instance_variable_get(:@cache).keys).to match_array %w[test1 test2 test3]
end
end
context 'should delete keys' do
it 'should delete hash keys' do
EncryptionService.instance_variable_set(:@cache,
{
'test1': {key: 'generated_key', expire_date: Time.now - 3.hours },
'test2': {key: 'generated_key', expire_date: Time.now - 2.hours },
'test3': {key: 'generated_key', expire_date: Time.now - 1.hours },
}.with_indifferent_access
)
EncryptionService.send(:delete_expired_keys)
expect(EncryptionService.instance_variable_get(:@cache)).to eq({})
end
end
end
end
context 'get_master_key' do
context 'empty cache' do
it 'should generate key by salt' do
EncryptionService.instance_variable_set(:@cache, {})
key = EncryptionService.send(:get_master_key, 'salt')
expect(EncryptionService.instance_variable_get(:@cache)['salt']['key']).to eq key
expect(EncryptionService.instance_variable_get(:@cache)['salt']['expire_date'].to_date).to eq 1.week.from_now.to_date
end
end
context 'non empty hash' do
let(:values) {
{
"salt":{
"key": "\xD5\xD8e\\N{1}\xEB\x9DP\x033)\x10{X\x91\xA1V\xB7\xCC\xE1L2\xDF\xC5,\f\x1Fh\xC6",
"expire_date": 1.week.from_now
}
}
}
it 'should get key from hash' do
EncryptionService.instance_variable_set(:@cache, values)
allow(Time).to receive(:now).and_return(1.week.ago)
key = EncryptionService.send(:get_master_key, 'salt')
expect(key).to eq values['salt']['key']
end
end
end
end
end

View File

@@ -0,0 +1,97 @@
# frozen_string_literal: true
describe EventMailer do
let(:event_mailer) { EventMailer.new('', '', '')}
let(:event) {
{:record=>
{:user=>
{:uid=>"ID8434CD6E8E",
:email=>"admin@barong.io",
:role=>"admin",
:level=>1,
:otp=>false,
:state=>"active",
:referral_uid=>nil,
:created_at=>"2020-05-26T07:01:04Z",
:updated_at=>"2020-05-26T08:30:54Z"},
:user_ip=>"::1",
:user_agent=>"PostmanRuntime/7.25.0"},
:name=>"system.session.create",
:state=>"sdasd"
}
}
describe "#nested_hash_value" do
it 'return event value' do
expect(event_mailer.send(:safe_dig, event, %i[name])).to eq event[:name]
expect(event_mailer.send(:safe_dig, event, %i[record user state])).to eq event[:record][:user][:state]
expect(event_mailer.send(:safe_dig, event, %i[record user uid])).to eq event[:record][:user][:uid]
expect(event_mailer.send(:safe_dig, event, %i[record user_agent])).to eq event[:record][:user_agent]
expect(event_mailer.send(:safe_dig, event, %i[record user_ip])).to eq event[:record][:user_ip]
expect(event_mailer.send(:safe_dig, event, %i[record name])).to eq nil
end
end
describe "#skip_event" do
context 'AND expression' do
let(:expression) { {
:and=>
{:"record.user_ip"=>"::1", :"record.user.role"=>"member"}
}
}
it 'should skip event' do
expect(event_mailer.send(:skip_event, event, expression)).to eq true
end
it 'shouldnt skip event' do
expression[:and][:"record.user.role"] = 'admin'
expect(event_mailer.send(:skip_event, event, expression)).to eq false
end
end
context 'OR expression' do
let(:expression) { {
:or=>
{:"record.user_ip"=>"::1", :"record.user.role"=>"member"}
}
}
it 'shouldnt skip event' do
expect(event_mailer.send(:skip_event, event, expression)).to eq false
end
it 'should skip event' do
expression[:or][:"record.user_ip"] = 'test'
expect(event_mailer.send(:skip_event, event, expression)).to eq true
end
end
context 'NOT expression' do
let(:expression) { {
:not=>
{:"record.user_ip"=>"::1"}
}
}
it 'shoul skip event' do
expect(event_mailer.send(:skip_event, event, expression)).to eq true
end
it 'shouldnt skip event' do
expression[:not][:"record.user_ip"] = 'test'
expect(event_mailer.send(:skip_event, event, expression)).to eq false
end
it 'should skip event' do
expression[:not][:'record.user.email'] = 'admin@barong.io'
expect(event_mailer.send(:skip_event, event, expression)).to eq true
end
it 'shouldnt skip event' do
expression[:not][:'record.user.email'] = 'admin1@barong.io'
expect(event_mailer.send(:skip_event, event, expression)).to eq false
end
end
end
end

View File

@@ -0,0 +1,148 @@
# frozen_string_literal: true
describe TOTPService do
let(:uid) { 'uid' }
let(:email) { 'email' }
let(:period) { '60' }
describe '.with_human_error' do
it 'renders human error when vault is down' do
expect do
described_class.with_human_error do
raise Vault::VaultError, 'Message connection refused message'
end
end.to raise_error(described_class::Error, '2FA server is under maintenance')
end
it 'renders human error when code was used twice' do
expect do
described_class.with_human_error do
raise Vault::VaultError, 'Message code already used message'
end
end.to raise_error(described_class::Error,
'This code was already used. Wait until the next time period')
end
it 'renders error when called without block' do
expect do
described_class.with_human_error
end.to raise_error(ArgumentError, 'Block is required')
end
end
describe '.server_available?' do
subject { described_class.server_available? }
context 'when server is available' do
before { expect(described_class).to receive(:read_data) { ['data'] } }
it { is_expected.to eq true }
end
context 'when server is not available' do
before { expect(described_class).to receive(:read_data) { [] } }
it { is_expected.to eq false }
end
context 'when exception raised' do
before do
expect(described_class).to receive(:read_data).and_raise(StandardError, 'vault error')
end
it { is_expected.to eq false }
end
end
describe '.otp_secret' do
let(:otp_url) { 'otpauth://totp/Alvand:admin@barong.io?secret=code' }
let(:otp) { double(data: { url: otp_url }) }
it { expect(described_class.otp_secret(otp)).to eq 'code' }
end
describe '.safe_create' do
it 'does not create secret when it exists' do
expect(described_class).to receive(:exist?).with(uid) { true }
expect(described_class).to_not receive(:create)
described_class.safe_create(uid, email, period)
end
it 'creates secret when it does not exist' do
expect(described_class).to receive(:exist?).with(uid) { false }
expect(described_class).to receive(:create).with(uid, email, period)
described_class.safe_create(uid, email, period)
end
end
describe '.create' do
let(:create_params) do
{
generate: true,
issuer: 'Alvand',
account_name: 'email',
period: period,
qr_size: 300
}
end
it 'creates secret' do
expect(described_class).to receive(:write_data)
.with('totp/keys/alvand_uid', create_params)
described_class.create(uid, email, period)
end
end
describe '.exist?' do
it 'creates secret' do
expect(described_class).to receive(:read_data)
.with('totp/keys/alvand_uid') { ['data'] }
described_class.exist?(uid)
end
end
describe '.validate?' do
before do
allow(described_class).to receive(:write_data) { double(data: data) }
allow(described_class).to receive(:read_data) { double(data: data) }
end
let(:data) { { valid: true } }
subject { described_class.validate?(uid, 'code') }
context 'when not exist' do
before { expect(described_class).to receive(:exist?) { false } }
it { is_expected.to eq false }
end
context 'when valid' do
before { expect(described_class).to receive(:exist?) { true } }
it { is_expected.to eq true }
end
context 'when invalid' do
before { expect(described_class).to receive(:exist?) { true } }
let(:data) { { valid: false } }
it { is_expected.to eq false }
end
end
describe '.delete' do
before { expect(described_class).to receive(:delete_data) }
it { expect(described_class.delete(uid)) }
end
describe 'private methods' do
let(:fake_vault) { double(read: 'read', write: 'writed', delete: 'deleted') }
before { stub_const('Vault', double(logical: fake_vault)) }
it 'read_data reads from vault storage' do
expect(described_class.send(:read_data, 'key')).to eq 'read'
end
it 'write_data writes to vault storage' do
expect(described_class.send(:write_data, 'key', {})).to eq 'writed'
end
it 'delete_data deletes from vault storage' do
expect(described_class.send(:delete_data, 'key')).to eq 'deleted'
end
end
end