lokal 0.0.1

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.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +6 -0
  3. data/lib/lokal/version.rb +3 -0
  4. data/lib/lokal.rb +239 -0
  5. metadata +131 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e4f1a0752a0149c66ed465f85d01ae149696e37342401d06562dc3e751f3268c
4
+ data.tar.gz: f76d75a2c1be8907b3088220c92730d3a2de1c8ab526c3791fdbf2ccaeee466c
5
+ SHA512:
6
+ metadata.gz: 985f2e4e34f05c87971f291cd3da88ae650a989836d96f2b2d4052972812682544bae2c2f2ca1d161f34617f5d895f773c626ba8215abd784b0b5fdb0775f6b7
7
+ data.tar.gz: 1642bebdf111f422b7abef364aff754cb0e5cb15abb0cf16f51553688a0849dd187c49524ae07dfc45aaaca5f1e21aac75f3c2789aa48beb02bd12f36f767749
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,3 @@
1
+ module Lokal
2
+ VERSION = "0.0.1"
3
+ end
data/lib/lokal.rb ADDED
@@ -0,0 +1,239 @@
1
+ # File: lib/lokal.rb
2
+
3
+ require 'json'
4
+ require 'faraday'
5
+ require 'semantic'
6
+ require 'colorize'
7
+
8
+ module Lokal
9
+ class Client
10
+ SERVER_MIN_VERSION = '0.6.0'
11
+
12
+ attr_reader :base_url, :rest
13
+
14
+ def initialize(options = {})
15
+ @base_url = options[:base_url] || 'http://127.0.0.1:6174'
16
+ @rest = Faraday.new(url: @base_url) do |faraday|
17
+ faraday.request :url_encoded
18
+ faraday.adapter Faraday.default_adapter
19
+ faraday.headers['User-Agent'] = 'Lokal Ruby - github.com/lokal-so/lokal-ruby'
20
+ end
21
+
22
+ set_basic_auth(options[:username], options[:password]) if options[:username] && options[:password]
23
+ set_api_token(options[:api_token]) if options[:api_token]
24
+
25
+ @rest.response :raise_error
26
+ end
27
+
28
+ def set_base_url(url)
29
+ @base_url = url
30
+ @rest.url_prefix = url
31
+ self
32
+ end
33
+
34
+ def set_basic_auth(username, password)
35
+ @rest.basic_auth(username, password)
36
+ self
37
+ end
38
+
39
+ def set_api_token(token)
40
+ @rest.headers['X-Auth-Token'] = token
41
+ self
42
+ end
43
+
44
+ def new_tunnel
45
+ Tunnel.new(self)
46
+ end
47
+
48
+ private
49
+
50
+ def check_server_version(response)
51
+ server_version = response.headers['Lokal-Server-Version']
52
+ return unless server_version
53
+
54
+ if Semantic::Version.new(server_version) < Semantic::Version.new(SERVER_MIN_VERSION)
55
+ raise "Your local client is outdated, please update to minimum version #{SERVER_MIN_VERSION}"
56
+ end
57
+ end
58
+ end
59
+
60
+ class Tunnel
61
+ attr_accessor :lokal, :id, :name, :tunnel_type, :local_address, :server_id, :address_tunnel,
62
+ :address_tunnel_port, :address_public, :address_mdns, :inspect, :options,
63
+ :ignore_duplicate, :startup_banner
64
+
65
+ def initialize(lokal)
66
+ @lokal = lokal
67
+ @options = Options.new
68
+ @ignore_duplicate = false
69
+ @startup_banner = false
70
+ end
71
+
72
+ def set_local_address(local_address)
73
+ @local_address = local_address
74
+ self
75
+ end
76
+
77
+ def set_tunnel_type(tunnel_type)
78
+ @tunnel_type = tunnel_type
79
+ self
80
+ end
81
+
82
+ def set_inspection(inspect)
83
+ @inspect = inspect
84
+ self
85
+ end
86
+
87
+ def set_lan_address(lan_address)
88
+ @address_mdns = lan_address.chomp('.local')
89
+ self
90
+ end
91
+
92
+ def set_public_address(public_address)
93
+ @address_public = public_address
94
+ self
95
+ end
96
+
97
+ def set_name(name)
98
+ @name = name
99
+ self
100
+ end
101
+
102
+ def ignore_duplicate
103
+ @ignore_duplicate = true
104
+ self
105
+ end
106
+
107
+ def show_startup_banner
108
+ @startup_banner = true
109
+ self
110
+ end
111
+
112
+ def create
113
+ raise "Please enable either LAN address or random/custom public URL" if @address_mdns.empty? && @address_public.empty?
114
+
115
+ response = @lokal.rest.post('/api/tunnel/start') do |req|
116
+ req.headers['Content-Type'] = 'application/json'
117
+ req.body = to_json
118
+ end
119
+
120
+ @lokal.send(:check_server_version, response)
121
+
122
+ data = JSON.parse(response.body)
123
+ raise data['message'] unless data['success']
124
+
125
+ tunnel_data = data['data'].first
126
+ update_attributes(tunnel_data)
127
+
128
+ print_startup_banner if @startup_banner
129
+
130
+ self
131
+ rescue Faraday::ClientError => e
132
+ handle_duplicate_error(e) if @ignore_duplicate
133
+ raise
134
+ end
135
+
136
+ def get_lan_address
137
+ raise "LAN address is not being set" if @address_mdns.empty?
138
+ @address_mdns.end_with?('.local') ? @address_mdns : "#{@address_mdns}.local"
139
+ end
140
+
141
+ def get_public_address
142
+ raise "Public address is not requested by client" if @address_public.empty?
143
+ raise "Unable to assign public address" if @address_public.empty?
144
+
145
+ if @tunnel_type != 'HTTP' && !@address_public.include?(':')
146
+ update_public_url_port
147
+ raise "Tunnel is using a random port, but it has not been assigned yet. Please try again later"
148
+ end
149
+
150
+ @address_public
151
+ end
152
+
153
+ private
154
+
155
+ def to_json
156
+ {
157
+ name: @name,
158
+ tunnel_type: @tunnel_type,
159
+ local_address: @local_address,
160
+ server_id: @server_id,
161
+ address_tunnel: @address_tunnel,
162
+ address_tunnel_port: @address_tunnel_port,
163
+ address_public: @address_public,
164
+ address_mdns: @address_mdns,
165
+ inspect: @inspect,
166
+ options: @options.to_h
167
+ }.to_json
168
+ end
169
+
170
+ def update_attributes(data)
171
+ data.each do |key, value|
172
+ instance_variable_set("@#{key}", value) if respond_to?("#{key}=")
173
+ end
174
+ end
175
+
176
+ def update_public_url_port
177
+ response = @lokal.rest.get("/api/tunnel/info/#{@id}")
178
+ @lokal.send(:check_server_version, response)
179
+
180
+ data = JSON.parse(response.body)
181
+ raise data['message'] unless data['success']
182
+
183
+ tunnel_data = data['data'].first
184
+ @address_public = tunnel_data['address_public'] if tunnel_data['address_public'].include?(':')
185
+ end
186
+
187
+ def handle_duplicate_error(error)
188
+ return unless error.response.status == 409 # Assuming 409 is used for conflicts/duplicates
189
+
190
+ data = JSON.parse(error.response.body)
191
+ tunnel_data = data['data'].first
192
+ update_attributes(tunnel_data)
193
+ show_startup_banner if @startup_banner
194
+ end
195
+
196
+ def print_startup_banner
197
+ banner = <<-BANNER
198
+ __ _ _
199
+ / / ___ | | ____ _| | ___ ___
200
+ / / / _ \\| |/ / _ | | / __|/ _ \\
201
+ / /__| (_) | < (_| | |_\\__ \\ (_) |
202
+ \\____/\\___/|_|\\_\\__,_|_(_)___/\\___/
203
+ BANNER
204
+
205
+ colors = [:magenta, :blue, :cyan, :green, :red]
206
+ random_color = colors.sample
207
+
208
+ puts banner.colorize(random_color)
209
+
210
+ puts
211
+ puts "Minimum Lokal Client".colorize(:red) + "\t" + Lokal::Client::SERVER_MIN_VERSION
212
+ puts "Public Address".colorize(:cyan) + "\t\thttps://#{@address_public}" if @address_public.length > 0
213
+ puts "LAN Address".colorize(:green) + "\t\thttps://#{get_lan_address}" if @address_mdns.length > 0
214
+ puts
215
+ end
216
+ end
217
+
218
+ class Options
219
+ attr_accessor :basic_auth, :cidr_allow, :cidr_deny, :request_header_add, :request_header_remove,
220
+ :response_header_add, :response_header_remove, :header_key
221
+
222
+ def initialize
223
+ @basic_auth = []
224
+ @cidr_allow = []
225
+ @cidr_deny = []
226
+ @request_header_add = []
227
+ @request_header_remove = []
228
+ @response_header_add = []
229
+ @response_header_remove = []
230
+ @header_key = []
231
+ end
232
+
233
+ def to_h
234
+ instance_variables.each_with_object({}) do |var, hash|
235
+ hash[var.to_s.delete('@')] = instance_variable_get(var)
236
+ end
237
+ end
238
+ end
239
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lokal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rubi Jihantoro
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-07-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.7.11
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.7.11
27
+ - !ruby/object:Gem::Dependency
28
+ name: semantic
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.6.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.6.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: colorize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '13.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '13.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description: Ruby Gem for interacting with Lokal Client REST API, Lokal Client installation
98
+ area required in order to use this gem
99
+ email:
100
+ - ceo@lokal.so
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - Rakefile
106
+ - lib/lokal.rb
107
+ - lib/lokal/version.rb
108
+ homepage: http://rubygems.org/gems/lokal-rb
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 3.0.3.1
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Ruby Gem for interacting with Lokal Client REST API
131
+ test_files: []