securevpn-xyz-http-hooks 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +39 -0
- data/LICENSE +19 -0
- data/README.md +22 -0
- data/bin/openvpn-activate +6 -0
- data/bin/openvpn-authenticate +8 -0
- data/bin/openvpn-connect +6 -0
- data/bin/openvpn-disconnect +7 -0
- data/lib/api/activation.rb +37 -0
- data/lib/api/authentication.rb +23 -0
- data/lib/api/billing.rb +55 -0
- data/lib/api/connect.rb +21 -0
- data/lib/api/connection.rb +70 -0
- data/lib/api/disconnect.rb +21 -0
- data/lib/exceptions/option_not_found.rb +2 -0
- data/lib/openvpn-http-hooks.rb +19 -0
- data/lib/openvpn_password_authenticator.rb +18 -0
- data/lib/option/base.rb +30 -0
- data/lib/option/i2p.rb +28 -0
- data/lib/option/proxy.rb +66 -0
- data/lib/option/repository.rb +18 -0
- data/lib/signer.rb +7 -0
- data/lib/system/openvpn_status.rb +19 -0
- data/lib/system/openvpn_status_log_parser.rb +30 -0
- data/lib/system/openvpn_status_log_reader.rb +29 -0
- data/openvpn-http-hooks.gemspec +16 -0
- data/spec/fixtures/active_connections.txt +10 -0
- data/spec/fixtures/multiple_connections.txt +11 -0
- data/spec/lib/api/activation_spec.rb +30 -0
- data/spec/lib/api/authentication_spec.rb +29 -0
- data/spec/lib/api/billing_spec.rb +71 -0
- data/spec/lib/api/connect_spec.rb +40 -0
- data/spec/lib/api/connection_spec.rb +59 -0
- data/spec/lib/api/disconnect_spec.rb +40 -0
- data/spec/lib/openvpn_password_authenticator_spec.rb +52 -0
- data/spec/lib/option/base_spec.rb +26 -0
- data/spec/lib/option/i2p_spec.rb +19 -0
- data/spec/lib/option/proxy_spec.rb +32 -0
- data/spec/lib/option/repository_spec.rb +25 -0
- data/spec/lib/signer_spec.rb +21 -0
- data/spec/lib/system/openvpn_status_log_parser_spec.rb +25 -0
- data/spec/lib/system/openvpn_status_log_reader_spec.rb +33 -0
- data/spec/lib/system/openvpn_status_spec.rb +22 -0
- data/spec/spec_helper.rb +9 -0
- metadata +133 -0
    
        data/lib/option/i2p.rb
    ADDED
    
    | @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            module Option
         | 
| 2 | 
            +
              class I2p < Base
         | 
| 3 | 
            +
                def activate!
         | 
| 4 | 
            +
                  add_firewall_routes
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def deactivate!
         | 
| 8 | 
            +
                  remove_firewall_routes
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                private
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def add_firewall_routes
         | 
| 14 | 
            +
                  system "/sbin/iptables -t filter -D INPUT -p tcp -m tcp --dport 8118 -j DROP"
         | 
| 15 | 
            +
                  system "/sbin/iptables -t filter -A INPUT -s #{virtual_ip} -p tcp -m tcp --dport 8118 -j ACCEPT"
         | 
| 16 | 
            +
                  system "/sbin/iptables -t filter -A INPUT -p tcp -m tcp --dport 8118 -j DROP"
         | 
| 17 | 
            +
                  system "/sbin/iptables -t nat -A PREROUTING -p udp -m udp -s #{virtual_ip} --dport 53 -j DNAT --to-destination #{server_virtual_ip}:53"
         | 
| 18 | 
            +
                  system "/sbin/iptables -t nat -A PREROUTING -p tcp -m tcp -s #{virtual_ip} --dport 53 -j DNAT --to-destination #{server_virtual_ip}:53"
         | 
| 19 | 
            +
                  true
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def remove_firewall_routes
         | 
| 23 | 
            +
                  system "/sbin/iptables -D INPUT -s #{virtual_ip} -p tcp -m tcp --dport 8118 -j ACCEPT"
         | 
| 24 | 
            +
                  system "/sbin/iptables -t nat -D PREROUTING -p udp -m udp -s #{virtual_ip} --dport 53 -j DNAT --to-destination #{server_virtual_ip}:53"
         | 
| 25 | 
            +
                  system "/sbin/iptables -t nat -D PREROUTING -p tcp -m tcp -s #{virtual_ip} --dport 53 -j DNAT --to-destination #{server_virtual_ip}:53"
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
    
        data/lib/option/proxy.rb
    ADDED
    
    | @@ -0,0 +1,66 @@ | |
| 1 | 
            +
            module Option
         | 
| 2 | 
            +
              class Proxy < Base
         | 
| 3 | 
            +
                def activate!
         | 
| 4 | 
            +
                  relay_port = start_proxy_daemon
         | 
| 5 | 
            +
                  add_firewall_rules(relay_port)
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def deactivate!
         | 
| 9 | 
            +
                  relay_port = relay_manager.free(virtual_ip)
         | 
| 10 | 
            +
                  remove_firewall_rules(relay_port)
         | 
| 11 | 
            +
                  kill_proxy_daemon(relay_port)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                private
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def start_proxy_daemon
         | 
| 17 | 
            +
                    relay_port = relay_manager.next_available_port
         | 
| 18 | 
            +
                    relay_manager.lock(virtual_ip, relay_port)
         | 
| 19 | 
            +
                    system "/etc/openvpn/any_proxy -l :#{relay_port} -p '#{attributes['host']}:#{attributes['port']}' &"
         | 
| 20 | 
            +
                    relay_port
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def add_firewall_rules(relay_port)
         | 
| 24 | 
            +
                    system "iptables -A PREROUTING -t nat -s #{virtual_ip}/32 -p tcp --dport 80 -j REDIRECT --to-port #{relay_port}"
         | 
| 25 | 
            +
                    true
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  def kill_proxy_daemon(relay_port)
         | 
| 29 | 
            +
                    pids = `ps -ef | grep #{relay_port} | awk '{ print $2 }'`
         | 
| 30 | 
            +
                    relay_pid = pids.split( /\r?\n/ ).first
         | 
| 31 | 
            +
                    `kill #{relay_pid} &`
         | 
| 32 | 
            +
                    true
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def remove_firewall_rules(relay_port)
         | 
| 36 | 
            +
                    system "iptables -D PREROUTING -t nat -s #{virtual_ip}/32 -p tcp --dport 80 -j REDIRECT --to-port #{relay_port}"
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def relay_manager
         | 
| 40 | 
            +
                    RelayManager.new
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  class RelayManager
         | 
| 44 | 
            +
                    RELAY_PORTS = [8090, 8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, 8099, 8010]
         | 
| 45 | 
            +
                    STATUS_FILE = '/etc/openvpn/relays.txt'
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    def lock(host, port)
         | 
| 48 | 
            +
                      File.open(STATUS_FILE, 'a') { |f| f.puts("#{host} #{port} ") }
         | 
| 49 | 
            +
                    end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    def free(host)
         | 
| 52 | 
            +
                      list = File.readlines(STATUS_FILE).map { |l| l.split(' ') }
         | 
| 53 | 
            +
                      port = list.find { |e| e[0] == host }[1]
         | 
| 54 | 
            +
                      updated_list = list.reject { |e| e[0] == host }.join()
         | 
| 55 | 
            +
                      File.open(STATUS_FILE, 'w') { |file| file.write(updated_list) }
         | 
| 56 | 
            +
                      port
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    def next_available_port
         | 
| 60 | 
            +
                      used_ports = File.readlines(STATUS_FILE).map { |l| l.split(' ')[1] }
         | 
| 61 | 
            +
                      available_ports = RELAY_PORTS - used_ports
         | 
| 62 | 
            +
                      available_ports.sample
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            module Option
         | 
| 2 | 
            +
              class Repository
         | 
| 3 | 
            +
                class << self
         | 
| 4 | 
            +
                  def find_by_code(code)
         | 
| 5 | 
            +
                    index[code.to_s] || raise(OptionNotFound)
         | 
| 6 | 
            +
                  end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  private
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def index
         | 
| 11 | 
            +
                    @index ||= {
         | 
| 12 | 
            +
                      'i2p'   => Option::I2p,
         | 
| 13 | 
            +
                      'proxy' => Option::Proxy
         | 
| 14 | 
            +
                    }
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
    
        data/lib/signer.rb
    ADDED
    
    
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            module System
         | 
| 2 | 
            +
              class OpenvpnStatus
         | 
| 3 | 
            +
                attr_accessor :clients_list
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                class << self
         | 
| 6 | 
            +
                  def current_virtual_address
         | 
| 7 | 
            +
                    ENV['ifconfig_pool_remote_ip']
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def server_virtual_address
         | 
| 11 | 
            +
                    ENV['ifconfig_local']
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def initialize
         | 
| 16 | 
            +
                  @clients_list = {}
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            module System
         | 
| 2 | 
            +
              class OpenvpnStatusLogParser
         | 
| 3 | 
            +
                attr_accessor :status, :clients_block, :text
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(text)
         | 
| 6 | 
            +
                  @status = System::OpenvpnStatus.new
         | 
| 7 | 
            +
                  @clients_block = false
         | 
| 8 | 
            +
                  @text = text
         | 
| 9 | 
            +
                  parse
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def parse
         | 
| 13 | 
            +
                  @text.lines.each do |line|
         | 
| 14 | 
            +
                    line_tokens = line.strip.split(',')
         | 
| 15 | 
            +
                    parse_client_virtual_ips(line_tokens)
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                private
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def parse_client_virtual_ips(tokens)
         | 
| 22 | 
            +
                  @clients_block = false if tokens[0] == 'GLOBAL STATS'
         | 
| 23 | 
            +
                  if clients_block
         | 
| 24 | 
            +
                    common_name, ip_address = tokens[1], tokens[0]
         | 
| 25 | 
            +
                    @status.clients_list[common_name] = ip_address
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                  @clients_block = true if tokens[0] == 'Virtual Address'
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            module System
         | 
| 2 | 
            +
              class OpenvpnStatusLogReader
         | 
| 3 | 
            +
                LOGFILE_PATH = '/etc/openvpn/openvpn-status.log'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                attr_accessor :log_content
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                class << self
         | 
| 8 | 
            +
                  def vpn_ip(common_name)
         | 
| 9 | 
            +
                    reader = new
         | 
| 10 | 
            +
                    reader.vpn_ip_for common_name
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def initialize
         | 
| 15 | 
            +
                  read_logfile
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def vpn_ip_for(common_name)
         | 
| 19 | 
            +
                  status = System::OpenvpnStatusLogParser.new(log_content).status
         | 
| 20 | 
            +
                  status.clients_list[common_name]
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                private
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def read_logfile
         | 
| 26 | 
            +
                  @log_content = File.read(LOGFILE_PATH)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            Gem::Specification.new do |s|
         | 
| 2 | 
            +
              s.name        = 'securevpn-xyz-http-hooks'
         | 
| 3 | 
            +
              s.version     = '1.3.3'
         | 
| 4 | 
            +
              s.date        = '2014-04-27'
         | 
| 5 | 
            +
              s.summary     = "HTTP hooks for OpenVPN server on securevpn.xyz"
         | 
| 6 | 
            +
              s.description = "Trigger on openvpn events and notify HTTP API for securevpn.xyz"
         | 
| 7 | 
            +
              s.authors     = ["Victor Ivanov at securevpn.xyz"]
         | 
| 8 | 
            +
              s.email       = 'admin@securevpn.xyz'
         | 
| 9 | 
            +
              s.files       = `git ls-files`.split($/)
         | 
| 10 | 
            +
              s.homepage    = 'https://securevpn.xyz'
         | 
| 11 | 
            +
              s.executables = ['openvpn-activate', 'openvpn-authenticate', 'openvpn-connect', 'openvpn-disconnect']
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              s.add_development_dependency 'rspec', ['>= 0']
         | 
| 14 | 
            +
              s.add_development_dependency 'mocha'
         | 
| 15 | 
            +
              s.add_development_dependency 'webmock'
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            OpenVPN CLIENT LIST
         | 
| 2 | 
            +
            Updated,Fri Jun  6 16:42:48 2014
         | 
| 3 | 
            +
            Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
         | 
| 4 | 
            +
            e0c187715fa9e1bb9fd96882dfa7af22,5.57.222.68:52248,294554,526171,Fri Jun  6 16:42:02 2014
         | 
| 5 | 
            +
            ROUTING TABLE
         | 
| 6 | 
            +
            Virtual Address,Common Name,Real Address,Last Ref
         | 
| 7 | 
            +
            10.77.2.6,e0c187715fa9e1bb9fd96882dfa7af22,5.57.222.68:52248,Fri Jun  6 16:42:47 2014
         | 
| 8 | 
            +
            GLOBAL STATS
         | 
| 9 | 
            +
            Max bcast/mcast queue length,0
         | 
| 10 | 
            +
            END
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            OpenVPN CLIENT LIST
         | 
| 2 | 
            +
            Updated,Fri Jun  6 16:42:48 2014
         | 
| 3 | 
            +
            Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
         | 
| 4 | 
            +
            e0c187715fa9e1bb9fd96882dfa7af22,5.57.222.68:52248,294554,526171,Fri Jun  6 16:42:02 2014
         | 
| 5 | 
            +
            ROUTING TABLE
         | 
| 6 | 
            +
            Virtual Address,Common Name,Real Address,Last Ref
         | 
| 7 | 
            +
            10.77.2.6,login1,5.57.222.68:52248,Fri Jun  6 16:42:47 2014
         | 
| 8 | 
            +
            10.77.2.5,login2,5.57.222.68:52248,Fri Jun  6 16:42:47 2014
         | 
| 9 | 
            +
            GLOBAL STATS
         | 
| 10 | 
            +
            Max bcast/mcast queue length,0
         | 
| 11 | 
            +
            END
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Api::Activation do
         | 
| 4 | 
            +
              subject { described_class.new }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              describe '.activate' do
         | 
| 7 | 
            +
                context 'successful activation' do
         | 
| 8 | 
            +
                  before do
         | 
| 9 | 
            +
                    stub_request(:post, 'api.securevpn.xyz/api/activate')
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  it 'saves key' do
         | 
| 13 | 
            +
                    subject.expects(:save_auth_key)
         | 
| 14 | 
            +
                    subject.activate
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                context 'not successful activation' do
         | 
| 19 | 
            +
                  before do
         | 
| 20 | 
            +
                    stub_request(:post, 'api.securevpn.xyz/api/activate').to_return(status: '404')
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  it 'raises error' do
         | 
| 24 | 
            +
                    expect {
         | 
| 25 | 
            +
                      subject.activate
         | 
| 26 | 
            +
                    }.to raise_error
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Api::Authentication do
         | 
| 4 | 
            +
              subject { described_class.new('login', 'password') }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              describe '.valid_credentials?' do
         | 
| 7 | 
            +
                before do
         | 
| 8 | 
            +
                  subject.stubs(:auth_key).returns('key')
         | 
| 9 | 
            +
                  stub_request(:post, 'api.securevpn.xyz/api/auth').
         | 
| 10 | 
            +
                    to_return(status: status)
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                context 'status 200' do
         | 
| 14 | 
            +
                  let(:status) { 200 }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  it 'returns true' do
         | 
| 17 | 
            +
                    expect(subject.valid_credentials?).to be_true
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                context 'status 404' do
         | 
| 22 | 
            +
                  let(:status) { 404 }
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  it 'returns false' do
         | 
| 25 | 
            +
                    expect(subject.valid_credentials?).to be_false
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Api::Billing do
         | 
| 4 | 
            +
              subject { described_class.new }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              it "returns api url" do
         | 
| 7 | 
            +
                expect(subject.host_with_port).to include "http://"
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              it "reads file with auth key" do
         | 
| 11 | 
            +
                File.stubs(:read).with(described_class::KEY_PATH).returns("key")
         | 
| 12 | 
            +
                expect(subject.auth_key).to eq "key"
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              it "returns machine hostname" do
         | 
| 16 | 
            +
                Socket.stubs(:gethostname).returns("hostname.dev")
         | 
| 17 | 
            +
                expect(subject.hostname).to eq "hostname.dev"
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              describe ".success_api_call?" do
         | 
| 21 | 
            +
                let(:api_call_result) { mock() }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                before do
         | 
| 24 | 
            +
                  api_call_result.stubs(:code).returns(code)
         | 
| 25 | 
            +
                  subject.stubs(:api_call_result).returns(api_call_result)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                context "result is 404" do
         | 
| 29 | 
            +
                  let(:code) { "404" }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  it "api call is not successful" do
         | 
| 32 | 
            +
                    expect(subject.success_api_call?).to be_false
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                context "result is 200" do
         | 
| 37 | 
            +
                  let(:code) { "200" }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  it "api call is successful" do
         | 
| 40 | 
            +
                    expect(subject.success_api_call?).to be_true
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              describe ".api_call_result" do
         | 
| 46 | 
            +
                before do
         | 
| 47 | 
            +
                  stub_request(:post, 'api.securevpn.xyz/api/auth')
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                it "fetches HTTP response" do
         | 
| 51 | 
            +
                  subject.stubs(:action).returns("auth")
         | 
| 52 | 
            +
                  subject.stubs(:data).returns({})
         | 
| 53 | 
            +
                  subject.stubs(:auth_key).returns("key")
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  subject.api_call_result
         | 
| 56 | 
            +
                  expect(subject.success_api_call?).to be_true
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              it "returns URI for api call" do
         | 
| 61 | 
            +
                action = "auth"
         | 
| 62 | 
            +
                subject.stubs(:action).returns(action)
         | 
| 63 | 
            +
                expect(subject.uri).to eq URI("http://#{described_class::API_HOST}/api/#{action}")
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              it "adds signature to params hash" do
         | 
| 67 | 
            +
                subject.stubs(:auth_key).returns("key")
         | 
| 68 | 
            +
                subject.stubs(:data).returns({})
         | 
| 69 | 
            +
                expect(subject.signed_data).not_to be_empty
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Api::Connect do
         | 
| 4 | 
            +
              subject { described_class.new }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              describe '#invoke' do
         | 
| 7 | 
            +
                before do
         | 
| 8 | 
            +
                  subject.stubs(:response).returns(
         | 
| 9 | 
            +
                    JSON.parse(
         | 
| 10 | 
            +
                      '{"id":101,"common_name":"login","options":["i2p", "proxy"],"option_attributes":{"i2p":{"attr1": "value1"},"proxy":{"attr2": "value2"}}}'
         | 
| 11 | 
            +
                    )
         | 
| 12 | 
            +
                  )
         | 
| 13 | 
            +
                  subject.stubs(:trigger_script_return)
         | 
| 14 | 
            +
                  subject.stubs(:success_api_call?).returns(api_call_validation_result)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                context 'successfull script call' do
         | 
| 18 | 
            +
                  let(:api_call_validation_result) { true }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  it 'activates options' do
         | 
| 21 | 
            +
                    Option::I2p.any_instance.expects(:activate!)
         | 
| 22 | 
            +
                    Option::Proxy.any_instance.expects(:activate!)
         | 
| 23 | 
            +
                    subject.invoke
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                context 'unsuccessfull call' do
         | 
| 28 | 
            +
                  let(:api_call_validation_result) { false }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  it 'does not activate options' do
         | 
| 31 | 
            +
                    Option::I2p.any_instance.expects(:activate!).never
         | 
| 32 | 
            +
                    subject.invoke
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              it 'represents connect action' do
         | 
| 38 | 
            +
                expect(subject.action).to eq 'connect'
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Api::Connection do
         | 
| 4 | 
            +
              subject { described_class.new }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              describe '.invoke_if_valid_api_call' do
         | 
| 7 | 
            +
                before do
         | 
| 8 | 
            +
                  subject.stubs(:success_api_call?).returns(success_status)
         | 
| 9 | 
            +
                  subject.expects(:exit).with(exit_status)
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                context 'success' do
         | 
| 13 | 
            +
                  let(:success_status) { true }
         | 
| 14 | 
            +
                  let(:exit_status) { 0 }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  it 'exits with zero status' do
         | 
| 17 | 
            +
                    subject.invoke_if_valid_api_call { "empty block" }
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                context 'failure' do
         | 
| 22 | 
            +
                  let(:success_status) { false }
         | 
| 23 | 
            +
                  let(:exit_status) { 1 }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  it 'exits with non zero status' do
         | 
| 26 | 
            +
                    subject.invoke_if_valid_api_call
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              describe 'attributes' do
         | 
| 32 | 
            +
                let(:option_name) { "i2p" }
         | 
| 33 | 
            +
                let(:common_name) { "login" }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                before do
         | 
| 36 | 
            +
                  subject.stubs(:response).returns(
         | 
| 37 | 
            +
                    JSON.parse(
         | 
| 38 | 
            +
                      "{\"id\":101,\"common_name\":\"#{common_name}\",\"options\":[\"#{option_name}\", \"proxy\"],\"option_attributes\":{\"i2p\":{\"attr1\": \"value1\"},\"proxy\":{\"attr2\": \"value2\"}}}"
         | 
| 39 | 
            +
                    )
         | 
| 40 | 
            +
                  )
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                describe '.options' do
         | 
| 44 | 
            +
                  it 'returns options array' do
         | 
| 45 | 
            +
                    expect(subject.options.class).to eq Hash
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  it 'includes option name' do
         | 
| 49 | 
            +
                    expect(subject.options['i2p'][:option_class]).to eq Option::I2p
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                describe '.common_name' do
         | 
| 54 | 
            +
                  it 'returns common name' do
         | 
| 55 | 
            +
                    expect(subject.common_name).to eq common_name
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         |