ruby-safenet 0.0.5 → 0.2.0
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 +4 -4
- data/README.md +35 -14
- data/lib/safenet/version.rb +1 -1
- data/lib/safenet.rb +509 -454
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3da1bbf0bd8ef4702c376d3a285b747da5ebe8d6
|
4
|
+
data.tar.gz: 0a2c39886bf3935eb36f7bcd11ddffeabcb4e223
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed01af92d3c24a9330a176339af88f1519da6dc4b5aa5be1fc84b23aaff6c558a329bee7ec2259f9132ffadfb1bff74deaf76935b117f5321a53cd20b09f1f0b
|
7
|
+
data.tar.gz: 5c672bfa76fec86cb219b619f0f315f259c99c47cd74d9386291963f45296fb1db72a07f22dabca81748d73019659708c30d03fb4ede0e0bef714b0242c9b980
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Ruby-Safenet
|
2
2
|
|
3
|
-
A
|
3
|
+
A simple SAFE API wrapper written in Ruby.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
```
|
@@ -12,37 +12,58 @@ A Ruby library for accessing the SAFE network
|
|
12
12
|
```ruby
|
13
13
|
require "safenet"
|
14
14
|
|
15
|
-
SafeNet.
|
15
|
+
my_client = SafeNet::Client.new
|
16
|
+
my_client.nfs.create_directory("/mydir", is_private: false)
|
17
|
+
my_client.nfs.file("/mydir/index.html", is_private: false)
|
18
|
+
my_client.nfs.update_file_content("/mydir/index.html", "Hello world!<br>I'm a webpage :D")
|
19
|
+
my_client.dns.register_service("my-wonderful-app", "www", "/mydir")
|
20
|
+
my_client.dns.get_file("/mydir/index.html")
|
21
|
+
|
22
|
+
# Then, open http://www.my-wonderful-app.safenet/
|
23
|
+
```
|
24
|
+
|
25
|
+
You can also set a more detailed App info:
|
26
|
+
```
|
27
|
+
my_client = SafeNet::Client.new({
|
16
28
|
name: "Ruby Demo App",
|
17
29
|
version: "0.0.1",
|
18
30
|
vendor: "Vendor's Name",
|
19
31
|
id: "org.thevendor.demo",
|
20
32
|
})
|
21
|
-
|
22
|
-
SafeNet.create_directory("/mydir", is_private: false)
|
23
|
-
SafeNet.file("/mydir/index.html", is_private: false)
|
24
|
-
SafeNet.update_file_content("/mydir/index.html", "Hello world!<br>I'm a webpage :D")
|
25
|
-
SafeNet.register_service("my-wonderful-app", "www", "/mydir")
|
26
|
-
SafeNet.get_file("/mydir/index.html")
|
27
|
-
|
28
|
-
# Then, open http://www.my-wonderful-app.safenet/
|
29
33
|
```
|
30
34
|
|
31
35
|
*File Upload / Download:*
|
32
36
|
```ruby
|
33
37
|
# upload
|
34
|
-
|
35
|
-
|
38
|
+
my_client.nfs.file("/mydir/dog.jpg")
|
39
|
+
my_client.nfs.update_file_content("/mydir/dog.jpg", File.read("/home/daniel/Pictures/dog.jpg"))
|
36
40
|
|
37
41
|
# download
|
38
42
|
File.open("/home/daniel/Pictures/dog-new.jpg", "w") do |file|
|
39
|
-
file.write(
|
43
|
+
file.write(my_client.nfs.get_file("/mydir/dog.jpg"))
|
40
44
|
end
|
41
45
|
```
|
42
46
|
|
43
47
|
*Directory's file list:*
|
44
48
|
```ruby
|
45
|
-
|
49
|
+
my_client.nfs.get_directory("/mydir")["files"].each do |file|
|
46
50
|
puts file["name"]
|
47
51
|
end
|
48
52
|
```
|
53
|
+
|
54
|
+
## Supported methods:
|
55
|
+
|Module|Method|Arguments|Optional|Doc|
|
56
|
+
|------|------|---------|--------|---|
|
57
|
+
|nfs|create_directory|dir_path|is_private, is_versioned, is_path_shared|Reference: https://maidsafe.readme.io/docs/nfs-create-directory|
|
58
|
+
|nfs|get_directory|dir_path|is_path_shared|https://maidsafe.readme.io/docs/nfs-get-directory|
|
59
|
+
|nfs|delete_directory|dir_path|is_path_shared|https://maidsafe.readme.io/docs/nfs-create-directory|
|
60
|
+
|nfs|file|file_path|is_private, is_versioned, is_path_shared|https://maidsafe.readme.io/docs/nfsfile|
|
61
|
+
|nfs|get_file|file_path|is_path_shared, offset, length|https://maidsafe.readme.io/docs/nfs-get-file|
|
62
|
+
|nfs|update_file_content|file_path, contents|is_path_shared, offset|https://maidsafe.readme.io/docs/nfs-update-file-content|
|
63
|
+
|nfs|delete_file|file_path|is_path_shared|https://maidsafe.readme.io/docs/nfs-delete-file|
|
64
|
+
|dns|create_long_name|long_name||https://maidsafe.readme.io/docs/dns-create-long-name|
|
65
|
+
|dns|register_service|long_name, service_name, service_home_dir_path|is_path_shared, metadata|https://maidsafe.readme.io/docs/dns-register-service|
|
66
|
+
|dns|list_long_names||is_path_shared, metadata|https://maidsafe.readme.io/docs/dns-list-long-names|
|
67
|
+
|dns|list_services|long_name||https://maidsafe.readme.io/docs/dns-list-services|
|
68
|
+
|dns|get_home_dir|long_name, service_name||https://maidsafe.readme.io/docs/dns-get-home-dir|
|
69
|
+
|dns|get_file_unauth|long_name, service_name, file_path|offset, length|https://maidsafe.readme.io/docs/dns-get-file-unauth|
|
data/lib/safenet/version.rb
CHANGED
data/lib/safenet.rb
CHANGED
@@ -1,514 +1,569 @@
|
|
1
1
|
require "safenet/version"
|
2
|
-
|
2
|
+
require "net/http"
|
3
|
+
require "rbnacl"
|
4
|
+
require "base64"
|
5
|
+
require "json"
|
6
|
+
require "cgi" # CGI.escape method
|
7
|
+
|
8
|
+
# usage:
|
9
|
+
# my_client = SafeNet::Client.new(name: 'My App')
|
10
|
+
# my_client.nfs.file('x.txt')
|
11
|
+
# my_client.nfs.update_file_content('x.txt', 'Hello World!')
|
12
|
+
# my_client.nfs.get_file('x.txt')
|
3
13
|
module SafeNet
|
4
|
-
require "net/http"
|
5
|
-
require "rbnacl"
|
6
|
-
require "base64"
|
7
|
-
require "json"
|
8
|
-
require "cgi" # CGI.escape method
|
9
|
-
|
10
|
-
# default values
|
11
|
-
@@NAME = "Ruby Demo App"
|
12
|
-
@@VERSION = "0.0.1"
|
13
|
-
@@VENDOR = "Vendor's Name"
|
14
|
-
@@ID = "org.thevendor.demo"
|
15
|
-
@@LAUNCHER_SERVER = "http://localhost:8100/"
|
16
|
-
@@CONF_PATH = File.join(File.expand_path('..', __FILE__), "conf.json")
|
17
|
-
|
18
|
-
def self.set_app_info(options)
|
19
|
-
@@NAME = options[:name] if options.has_key?(:name)
|
20
|
-
@@VERSION = options[:version] if options.has_key?(:version)
|
21
|
-
@@VENDOR = options[:vendor] if options.has_key?(:vendor)
|
22
|
-
@@ID = options[:id] if options.has_key?(:id)
|
23
|
-
@@LAUNCHER_SERVER = options[:server] if options.has_key?(:server)
|
24
|
-
@@CONF_PATH = options[:conf_file] if options.has_key?(:conf_file)
|
25
|
-
end
|
26
14
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
#
|
38
|
-
# The SAFE Launcher will prompt to the user with the application information
|
39
|
-
# along with the requested permissions. Once the user authorises the
|
40
|
-
# request, the symmetric keys for encryption are received. If the user
|
41
|
-
# denies the request then the SAFE Launcher sends an unauthorised error
|
42
|
-
# response.
|
43
|
-
#
|
44
|
-
# Usage: SafeNet.auth()
|
45
|
-
# Fail: nil
|
46
|
-
# Success: {token: "1222", encryptedKey: "232", "publicKey": "4323", "permissions": []}
|
47
|
-
#
|
48
|
-
# Reference: https://maidsafe.readme.io/docs/auth
|
49
|
-
#
|
50
|
-
def self.auth
|
51
|
-
# entry point
|
52
|
-
url = "#{@@LAUNCHER_SERVER}auth"
|
53
|
-
|
54
|
-
# new random key
|
55
|
-
private_key = RbNaCl::PrivateKey.generate
|
56
|
-
nonce = RbNaCl::Random.random_bytes(24)
|
57
|
-
|
58
|
-
# payload
|
59
|
-
payload = {
|
60
|
-
app: {
|
61
|
-
name: @@NAME,
|
62
|
-
version: @@VERSION,
|
63
|
-
vendor: @@VENDOR,
|
64
|
-
id: @@ID
|
65
|
-
},
|
66
|
-
publicKey: Base64.strict_encode64(private_key.public_key),
|
67
|
-
nonce: Base64.strict_encode64(nonce),
|
68
|
-
permissions: []
|
69
|
-
}
|
70
|
-
|
71
|
-
# api call
|
72
|
-
uri = URI(url)
|
73
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
74
|
-
req = Net::HTTP::Post.new(uri.path, {'Content-Type' => 'application/json'})
|
75
|
-
req.body = payload.to_json
|
76
|
-
res = http.request(req)
|
77
|
-
|
78
|
-
# return's parser
|
79
|
-
if res.code == "200"
|
80
|
-
response = JSON.parse(res.body)
|
81
|
-
|
82
|
-
# save it in conf.json
|
83
|
-
conf = response.dup
|
84
|
-
conf["nonce"] = Base64.strict_encode64(nonce)
|
85
|
-
conf["privateKey"] = Base64.strict_encode64(private_key)
|
86
|
-
File.open(@@CONF_PATH, "w") { |f| f << JSON.pretty_generate(conf) }
|
87
|
-
|
88
|
-
# invalidates @@keys
|
89
|
-
@@keys = {}
|
90
|
-
else
|
91
|
-
# puts "ERROR #{res.code}: #{res.message}"
|
92
|
-
response = nil
|
15
|
+
class Client
|
16
|
+
attr_reader :auth, :nfs, :dns, :app_info, :key_helper
|
17
|
+
|
18
|
+
def initialize(options = {})
|
19
|
+
@app_info = defaults()
|
20
|
+
set_app_info(options) if options.any?
|
21
|
+
@key_helper = SafeNet::KeyHelper.new(self)
|
22
|
+
@auth = SafeNet::Auth.new(self)
|
23
|
+
@nfs = SafeNet::NFS.new(self)
|
24
|
+
@dns = SafeNet::DNS.new(self)
|
93
25
|
end
|
94
26
|
|
95
|
-
|
96
|
-
|
97
|
-
|
27
|
+
def set_app_info(options = {})
|
28
|
+
@app_info[:name] = options[:name] if options.has_key?(:name)
|
29
|
+
@app_info[:version] = options[:version] if options.has_key?(:version)
|
30
|
+
@app_info[:vendor] = options[:vendor] if options.has_key?(:vendor)
|
31
|
+
@app_info[:id] = options[:id] if options.has_key?(:id)
|
32
|
+
@app_info[:launcher_server] = options[:server] if options.has_key?(:server)
|
33
|
+
@app_info[:conf_path] = options[:conf_file] if options.has_key?(:conf_file)
|
34
|
+
end
|
98
35
|
|
36
|
+
private
|
99
37
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
# entry point
|
112
|
-
url = "#{@@LAUNCHER_SERVER}auth"
|
113
|
-
|
114
|
-
# api call
|
115
|
-
uri = URI(url)
|
116
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
117
|
-
req = Net::HTTP::Get.new(uri.path, {
|
118
|
-
'Authorization' => "Bearer #{self.get_token()}"
|
119
|
-
})
|
120
|
-
res = http.request(req)
|
121
|
-
res.code == "200"
|
38
|
+
# default values
|
39
|
+
def defaults
|
40
|
+
{
|
41
|
+
name: "Ruby Demo App",
|
42
|
+
version: "0.0.1",
|
43
|
+
vendor: "Vendor's Name",
|
44
|
+
id: "org.thevendor.demo",
|
45
|
+
launcher_server: "http://localhost:8100/",
|
46
|
+
conf_path: File.join(File.expand_path('..', __FILE__), "conf.json")
|
47
|
+
}
|
48
|
+
end
|
122
49
|
end
|
123
50
|
|
51
|
+
class KeyHelper
|
124
52
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
# Success: true
|
131
|
-
#
|
132
|
-
# Reference: https://maidsafe.readme.io/docs/revoke-token
|
133
|
-
#
|
134
|
-
def self.revoke_token
|
135
|
-
# entry point
|
136
|
-
url = "#{@@LAUNCHER_SERVER}auth"
|
137
|
-
|
138
|
-
# api call
|
139
|
-
uri = URI(url)
|
140
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
141
|
-
req = Net::HTTP::Delete.new(uri.path, {
|
142
|
-
'Authorization' => "Bearer #{self.get_valid_token()}"
|
143
|
-
})
|
144
|
-
res = http.request(req)
|
145
|
-
res.code == "200"
|
146
|
-
end
|
53
|
+
def initialize(client_obj)
|
54
|
+
@client = client_obj
|
55
|
+
@keys = {}
|
56
|
+
@conf = {}
|
57
|
+
end
|
147
58
|
|
59
|
+
def get_token
|
60
|
+
@conf = File.exists?(@client.app_info[:conf_path]) ? JSON.parse(File.read(@client.app_info[:conf_path])) : (@client.auth.auth() || {})
|
61
|
+
@conf["token"]
|
62
|
+
end
|
148
63
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
# Success: {"info"=> {"name"=> "Ruby Demo App-Root-Dir", ...}, ...}
|
156
|
-
#
|
157
|
-
# Reference: https://maidsafe.readme.io/docs/nfs-create-directory
|
158
|
-
#
|
159
|
-
def self.get_directory(dir_path, options = {})
|
160
|
-
# default values
|
161
|
-
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
162
|
-
|
163
|
-
# entry point
|
164
|
-
url = "#{@@LAUNCHER_SERVER}nfs/directory/#{CGI.escape(dir_path)}/#{options[:is_path_shared]}"
|
165
|
-
|
166
|
-
# api call
|
167
|
-
uri = URI(url)
|
168
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
169
|
-
req = Net::HTTP::Get.new(uri.path, {
|
170
|
-
'Authorization' => "Bearer #{self.get_valid_token()}",
|
171
|
-
})
|
172
|
-
res = http.request(req)
|
173
|
-
JSON.parse(self.decrypt(res.body))
|
174
|
-
end
|
64
|
+
def get_valid_token
|
65
|
+
@last_conf = File.exists?(@client.app_info[:conf_path]) ? JSON.parse(File.read(@client.app_info[:conf_path])) : {}
|
66
|
+
@client.auth.auth() unless File.exists?(@client.app_info[:conf_path]) && @client.auth.is_token_valid()
|
67
|
+
@conf = JSON.parse(File.read(@client.app_info[:conf_path]))
|
68
|
+
@conf["token"]
|
69
|
+
end
|
175
70
|
|
71
|
+
def decrypt(message_base64)
|
72
|
+
keys = get_keys()
|
73
|
+
keys["secret_box"].decrypt(keys["symmetric_nonce"], Base64.strict_decode64(message_base64))
|
74
|
+
end
|
176
75
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
# Adv.Usage: SafeNet.file("/photos/cat.jpg", is_private: true, metadata: "some meta", is_path_shared: false, is_versioned: false)
|
183
|
-
# Fail: {"errorCode"=>-505, "description"=>"NfsError::FileAlreadyExistsWithSameName"}
|
184
|
-
# Success: true
|
185
|
-
#
|
186
|
-
# Reference: https://maidsafe.readme.io/docs/nfsfile
|
187
|
-
#
|
188
|
-
def self.file(file_path, options = {})
|
189
|
-
url = "#{@@LAUNCHER_SERVER}nfs/file"
|
76
|
+
def encrypt(message)
|
77
|
+
keys = get_keys()
|
78
|
+
res = keys["secret_box"].encrypt(keys["symmetric_nonce"], message)
|
79
|
+
Base64.strict_encode64(res)
|
80
|
+
end
|
190
81
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
195
|
-
|
196
|
-
# payload
|
197
|
-
payload = {
|
198
|
-
filePath: file_path,
|
199
|
-
isPrivate: options[:is_private],
|
200
|
-
isVersioned: options[:is_versioned],
|
201
|
-
isPathShared: options[:is_path_shared]
|
202
|
-
}
|
203
|
-
|
204
|
-
# optional
|
205
|
-
payload["metadata"] = Base64.strict_encode64(options[:metadata]) if options.has_key?(:metadata)
|
206
|
-
|
207
|
-
# api call
|
208
|
-
uri = URI(url)
|
209
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
210
|
-
req = Net::HTTP::Post.new(uri.path, {
|
211
|
-
'Authorization' => "Bearer #{self.get_valid_token()}",
|
212
|
-
'Content-Type' => 'text/plain'
|
213
|
-
})
|
214
|
-
req.body = self.encrypt(payload.to_json)
|
215
|
-
res = http.request(req)
|
216
|
-
res.code == "200" ? true : JSON.parse(self.decrypt(res.body))
|
217
|
-
end
|
82
|
+
def invalidate
|
83
|
+
@keys = {}
|
84
|
+
end
|
218
85
|
|
86
|
+
private
|
219
87
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
# Usage: SafeNet.create_directory("/photos")
|
225
|
-
# Adv.Usage: SafeNet.create_directory("/photos", is_private: true, metadata: "some meta", is_path_shared: false, is_versioned: false)
|
226
|
-
# Fail: {"errorCode"=>-505, "description"=>"NfsError::FileAlreadyExistsWithSameName"}
|
227
|
-
# Success: true
|
228
|
-
#
|
229
|
-
# Reference: https://maidsafe.readme.io/docs/nfs-create-directory
|
230
|
-
#
|
231
|
-
def self.create_directory(dir_path, options = {})
|
232
|
-
# entry point
|
233
|
-
url = "#{@@LAUNCHER_SERVER}nfs/directory"
|
88
|
+
def get_keys
|
89
|
+
# not loaded yet?
|
90
|
+
if @keys.empty?
|
91
|
+
get_valid_token() if @conf.empty?
|
234
92
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
# payload
|
241
|
-
payload = {
|
242
|
-
dirPath: dir_path,
|
243
|
-
isPrivate: options[:is_private],
|
244
|
-
isVersioned: options[:is_versioned],
|
245
|
-
isPathShared: options[:is_path_shared]
|
246
|
-
}
|
247
|
-
|
248
|
-
# optional
|
249
|
-
payload["metadata"] = Base64.strict_encode64(options[:metadata]) if options.has_key?(:metadata)
|
250
|
-
|
251
|
-
# api call
|
252
|
-
uri = URI(url)
|
253
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
254
|
-
req = Net::HTTP::Post.new(uri.path, {
|
255
|
-
'Authorization' => "Bearer #{self.get_valid_token()}",
|
256
|
-
'Content-Type' => 'text/plain'
|
257
|
-
})
|
258
|
-
req.body = self.encrypt(payload.to_json)
|
259
|
-
res = http.request(req)
|
260
|
-
res.code == "200" ? true : JSON.parse(self.decrypt(res.body))
|
261
|
-
end
|
93
|
+
# extract keys
|
94
|
+
cipher_text = Base64.strict_decode64(@conf["encryptedKey"])
|
95
|
+
nonce = Base64.strict_decode64(@conf["nonce"])
|
96
|
+
private_key = Base64.strict_decode64(@conf["privateKey"])
|
97
|
+
public_key = Base64.strict_decode64(@conf["publicKey"])
|
262
98
|
|
99
|
+
box = RbNaCl::Box.new(public_key, private_key)
|
100
|
+
data = box.decrypt(nonce, cipher_text)
|
263
101
|
|
264
|
-
|
265
|
-
|
266
|
-
# default values
|
267
|
-
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
268
|
-
|
269
|
-
# entry point
|
270
|
-
url = "#{@@LAUNCHER_SERVER}nfs/directory/#{CGI.escape(dir_path)}/#{options[:is_path_shared]}"
|
271
|
-
|
272
|
-
# api call
|
273
|
-
uri = URI(url)
|
274
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
275
|
-
req = Net::HTTP::Delete.new(uri.path, {
|
276
|
-
'Authorization' => "Bearer #{self.get_valid_token()}",
|
277
|
-
})
|
278
|
-
res = http.request(req)
|
279
|
-
res.code == "200" ? true : JSON.parse(self.decrypt(res.body))
|
280
|
-
end
|
102
|
+
# The first segment of the data will have the symmetric key
|
103
|
+
@keys["symmetric_key"] = data.slice(0, RbNaCl::SecretBox.key_bytes)
|
281
104
|
|
282
|
-
|
283
|
-
|
284
|
-
# default values
|
285
|
-
options[:offset] = 0 if ! options.has_key?(:offset)
|
286
|
-
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
287
|
-
|
288
|
-
# entry point
|
289
|
-
url = "#{@@LAUNCHER_SERVER}nfs/file/#{CGI.escape(file_path)}/#{options[:is_path_shared]}?"
|
290
|
-
|
291
|
-
# query params are encrypted
|
292
|
-
query = []
|
293
|
-
query << "offset=#{options[:offset]}"
|
294
|
-
query << "length=#{options[:length]}" if options.has_key?(:length) # length is optional
|
295
|
-
url = "#{url}#{self.encrypt(query.join('&'))}"
|
296
|
-
|
297
|
-
# api call
|
298
|
-
uri = URI(url)
|
299
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
300
|
-
req = Net::HTTP::Get.new(uri.path, {
|
301
|
-
'Authorization' => "Bearer #{self.get_valid_token()}",
|
302
|
-
})
|
303
|
-
res = http.request(req)
|
304
|
-
res.code == "200" ? self.decrypt(res.body) : JSON.parse(self.decrypt(res.body))
|
305
|
-
end
|
105
|
+
# The second segment of the data will have the nonce to be used
|
106
|
+
@keys["symmetric_nonce"] = data.slice(RbNaCl::SecretBox.key_bytes, RbNaCl::SecretBox.key_bytes)
|
306
107
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
url = "#{@@LAUNCHER_SERVER}nfs/file/#{CGI.escape(file_path)}/#{options[:is_path_shared]}?offset=#{options[:offset]}"
|
314
|
-
|
315
|
-
# api call
|
316
|
-
uri = URI(url)
|
317
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
318
|
-
req = Net::HTTP::Put.new(uri.path, {
|
319
|
-
'Authorization' => "Bearer #{self.get_valid_token()}",
|
320
|
-
'Content-Type' => 'text/plain'
|
321
|
-
})
|
322
|
-
req.body = self.encrypt(contents)
|
323
|
-
res = http.request(req)
|
324
|
-
res.code == "200" ? true : JSON.parse(self.decrypt(res.body))
|
325
|
-
end
|
108
|
+
# keep the box object in cache
|
109
|
+
@keys["secret_box"] = RbNaCl::SecretBox.new(@keys["symmetric_key"])
|
110
|
+
end
|
111
|
+
|
112
|
+
@keys
|
113
|
+
end
|
326
114
|
|
327
|
-
def self.delete_file(file_path, options = {})
|
328
|
-
# default values
|
329
|
-
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
330
|
-
|
331
|
-
# entry point
|
332
|
-
url = "#{@@LAUNCHER_SERVER}nfs/file/#{CGI.escape(file_path)}/#{options[:is_path_shared]}"
|
333
|
-
|
334
|
-
# api call
|
335
|
-
uri = URI(url)
|
336
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
337
|
-
req = Net::HTTP::Delete.new(uri.path, {
|
338
|
-
'Authorization' => "Bearer #{self.get_valid_token()}",
|
339
|
-
})
|
340
|
-
res = http.request(req)
|
341
|
-
res.code == "200" ? true : JSON.parse(self.decrypt(res.body))
|
342
115
|
end
|
343
116
|
|
117
|
+
class Auth
|
118
|
+
def initialize(client_obj)
|
119
|
+
@client = client_obj
|
120
|
+
end
|
344
121
|
|
345
|
-
|
346
|
-
#
|
347
|
-
|
122
|
+
#
|
123
|
+
# An application exchanges data with the SAFE Launcher using symmetric key
|
124
|
+
# encryption. The symmetric key is session based and is securely transferred
|
125
|
+
# from the SAFE Launcher to the application using ECDH Key Exchange.
|
126
|
+
# Applications will generate an asymmetric key pair and a nonce for ECDH Key
|
127
|
+
# Exchange with the SAFE Launcher.
|
128
|
+
#
|
129
|
+
# The application will initiate the authorisation request with the generated
|
130
|
+
# nonce and public key, along with information about the application and the
|
131
|
+
# required permissions.
|
132
|
+
#
|
133
|
+
# The SAFE Launcher will prompt to the user with the application information
|
134
|
+
# along with the requested permissions. Once the user authorises the
|
135
|
+
# request, the symmetric keys for encryption are received. If the user
|
136
|
+
# denies the request then the SAFE Launcher sends an unauthorised error
|
137
|
+
# response.
|
138
|
+
#
|
139
|
+
# Usage: my_client.auth()
|
140
|
+
# Fail: nil
|
141
|
+
# Success: {token: "1222", encryptedKey: "232", "publicKey": "4323", "permissions": []}
|
142
|
+
#
|
143
|
+
# Reference: https://maidsafe.readme.io/docs/auth
|
144
|
+
#
|
145
|
+
def auth
|
146
|
+
# entry point
|
147
|
+
url = "#{@client.app_info[:launcher_server]}auth"
|
148
|
+
|
149
|
+
# new random key
|
150
|
+
private_key = RbNaCl::PrivateKey.generate
|
151
|
+
nonce = RbNaCl::Random.random_bytes(24)
|
152
|
+
|
153
|
+
# payload
|
154
|
+
payload = {
|
155
|
+
app: {
|
156
|
+
name: @client.app_info[:name],
|
157
|
+
version: @client.app_info[:version],
|
158
|
+
vendor: @client.app_info[:vendor],
|
159
|
+
id: @client.app_info[:id]
|
160
|
+
},
|
161
|
+
publicKey: Base64.strict_encode64(private_key.public_key),
|
162
|
+
nonce: Base64.strict_encode64(nonce),
|
163
|
+
permissions: []
|
164
|
+
}
|
165
|
+
|
166
|
+
# api call
|
167
|
+
uri = URI(url)
|
168
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
169
|
+
req = Net::HTTP::Post.new(uri.path, {'Content-Type' => 'application/json'})
|
170
|
+
req.body = payload.to_json
|
171
|
+
res = http.request(req)
|
172
|
+
|
173
|
+
# return's parser
|
174
|
+
if res.code == "200"
|
175
|
+
response = JSON.parse(res.body)
|
176
|
+
|
177
|
+
# save it in conf.json
|
178
|
+
conf = response.dup
|
179
|
+
conf["nonce"] = Base64.strict_encode64(nonce)
|
180
|
+
conf["privateKey"] = Base64.strict_encode64(private_key)
|
181
|
+
File.open(@client.app_info[:conf_path], "w") { |f| f << JSON.pretty_generate(conf) }
|
182
|
+
|
183
|
+
# invalidates @keys
|
184
|
+
@client.key_helper.invalidate()
|
185
|
+
else
|
186
|
+
# puts "ERROR #{res.code}: #{res.message}"
|
187
|
+
response = nil
|
188
|
+
end
|
189
|
+
|
190
|
+
# return
|
191
|
+
response
|
192
|
+
end
|
348
193
|
|
349
|
-
# api call
|
350
|
-
uri = URI(url)
|
351
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
352
|
-
req = Net::HTTP::Post.new(uri.path, {
|
353
|
-
'Authorization' => "Bearer #{self.get_valid_token()}",
|
354
|
-
'Content-Type' => 'text/plain'
|
355
|
-
})
|
356
|
-
res = http.request(req)
|
357
|
-
res.code == "200" ? true : JSON.parse(self.decrypt(res.body))
|
358
|
-
end
|
359
194
|
|
195
|
+
#
|
196
|
+
# To check whether the authorisation token obtained is valid.
|
197
|
+
# The Authorization header must be present in the request.
|
198
|
+
#
|
199
|
+
# Usage: SafeNet.is_token_valid()
|
200
|
+
# Fail: false
|
201
|
+
# Success: true
|
202
|
+
#
|
203
|
+
# Reference: https://maidsafe.readme.io/docs/is-token-valid
|
204
|
+
#
|
205
|
+
def is_token_valid
|
206
|
+
# entry point
|
207
|
+
url = "#{@client.app_info[:launcher_server]}auth"
|
208
|
+
|
209
|
+
# api call
|
210
|
+
uri = URI(url)
|
211
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
212
|
+
req = Net::HTTP::Get.new(uri.path, {
|
213
|
+
'Authorization' => "Bearer #{@client.key_helper.get_token()}"
|
214
|
+
})
|
215
|
+
res = http.request(req)
|
216
|
+
res.code == "200"
|
217
|
+
end
|
360
218
|
|
361
|
-
# ex.: register_service("thegoogle", "www", "/www")
|
362
|
-
def self.register_service(long_name, service_name, service_home_dir_path, options = {})
|
363
|
-
# entry point
|
364
|
-
url = "#{@@LAUNCHER_SERVER}dns"
|
365
219
|
|
366
|
-
#
|
367
|
-
|
368
|
-
|
369
|
-
#
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
res = http.request(req)
|
389
|
-
res.code == "200" ? true : JSON.parse(self.decrypt(res.body))
|
220
|
+
#
|
221
|
+
# Removes the token from the SAFE Launcher.
|
222
|
+
#
|
223
|
+
# Usage: SafeNet.revoke_token()
|
224
|
+
# Fail: false
|
225
|
+
# Success: true
|
226
|
+
#
|
227
|
+
# Reference: https://maidsafe.readme.io/docs/revoke-token
|
228
|
+
#
|
229
|
+
def revoke_token
|
230
|
+
# entry point
|
231
|
+
url = "#{@client.app_info[:launcher_server]}auth"
|
232
|
+
|
233
|
+
# api call
|
234
|
+
uri = URI(url)
|
235
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
236
|
+
req = Net::HTTP::Delete.new(uri.path, {
|
237
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}"
|
238
|
+
})
|
239
|
+
res = http.request(req)
|
240
|
+
res.code == "200"
|
241
|
+
end
|
390
242
|
end
|
391
243
|
|
392
244
|
|
393
|
-
|
394
|
-
|
395
|
-
|
245
|
+
class NFS
|
246
|
+
def initialize(client_obj)
|
247
|
+
@client = client_obj
|
248
|
+
end
|
396
249
|
|
397
|
-
#
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
}
|
403
|
-
|
404
|
-
|
405
|
-
|
250
|
+
#
|
251
|
+
# Create a directory using the NFS API.
|
252
|
+
# Only authorised requests can create a directory.
|
253
|
+
#
|
254
|
+
# Usage: SafeNet.get_directory("/photos", is_path_shared: false)
|
255
|
+
# Fail: {"errorCode"=>-1502, "description"=>"FfiError::PathNotFound"}
|
256
|
+
# Success: {"info"=> {"name"=> "Ruby Demo App-Root-Dir", ...}, ...}
|
257
|
+
#
|
258
|
+
# Reference: https://maidsafe.readme.io/docs/nfs-get-directory
|
259
|
+
#
|
260
|
+
def get_directory(dir_path, options = {})
|
261
|
+
# default values
|
262
|
+
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
263
|
+
|
264
|
+
# entry point
|
265
|
+
url = "#{@client.app_info[:launcher_server]}nfs/directory/#{CGI.escape(dir_path)}/#{options[:is_path_shared]}"
|
266
|
+
|
267
|
+
# api call
|
268
|
+
uri = URI(url)
|
269
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
270
|
+
req = Net::HTTP::Get.new(uri.path, {
|
271
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
272
|
+
})
|
273
|
+
res = http.request(req)
|
274
|
+
JSON.parse(@client.key_helper.decrypt(res.body))
|
275
|
+
end
|
406
276
|
|
407
277
|
|
408
|
-
|
409
|
-
#
|
410
|
-
|
278
|
+
#
|
279
|
+
# Create a File using the NFS API.
|
280
|
+
# Only authorised requests can invoke the API.
|
281
|
+
#
|
282
|
+
# Usage: SafeNet.file("/photos/cat.jpg")
|
283
|
+
# Adv.Usage: SafeNet.file("/photos/cat.jpg", is_private: true, metadata: "some meta", is_path_shared: false, is_versioned: false)
|
284
|
+
# Fail: {"errorCode"=>-505, "description"=>"NfsError::FileAlreadyExistsWithSameName"}
|
285
|
+
# Success: true
|
286
|
+
#
|
287
|
+
# Reference: https://maidsafe.readme.io/docs/nfsfile
|
288
|
+
#
|
289
|
+
def file(file_path, options = {})
|
290
|
+
url = "#{@client.app_info[:launcher_server]}nfs/file"
|
291
|
+
|
292
|
+
# default values
|
293
|
+
options[:is_private] = true if ! options.has_key?(:is_private)
|
294
|
+
options[:is_versioned] = false if ! options.has_key?(:is_versioned)
|
295
|
+
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
296
|
+
|
297
|
+
# payload
|
298
|
+
payload = {
|
299
|
+
filePath: file_path,
|
300
|
+
isPrivate: options[:is_private],
|
301
|
+
isVersioned: options[:is_versioned],
|
302
|
+
isPathShared: options[:is_path_shared]
|
303
|
+
}
|
304
|
+
|
305
|
+
# optional
|
306
|
+
payload["metadata"] = Base64.strict_encode64(options[:metadata]) if options.has_key?(:metadata)
|
307
|
+
|
308
|
+
# api call
|
309
|
+
uri = URI(url)
|
310
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
311
|
+
req = Net::HTTP::Post.new(uri.path, {
|
312
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
313
|
+
'Content-Type' => 'text/plain'
|
314
|
+
})
|
315
|
+
req.body = @client.key_helper.encrypt(payload.to_json)
|
316
|
+
res = http.request(req)
|
317
|
+
res.code == "200" ? true : JSON.parse(@client.key_helper.decrypt(res.body))
|
318
|
+
end
|
411
319
|
|
412
|
-
# api call
|
413
|
-
uri = URI(url)
|
414
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
415
|
-
req = Net::HTTP::Get.new(uri.path, {
|
416
|
-
'Authorization' => "Bearer #{self.get_valid_token()}",
|
417
|
-
})
|
418
|
-
res = http.request(req)
|
419
|
-
JSON.parse(self.decrypt(res.body))
|
420
|
-
end
|
421
320
|
|
321
|
+
#
|
322
|
+
# Create a directory using the NFS API.
|
323
|
+
# Only authorised requests can create a directory.
|
324
|
+
#
|
325
|
+
# Usage: SafeNet.create_directory("/photos")
|
326
|
+
# Adv.Usage: SafeNet.create_directory("/photos", is_private: true, metadata: "some meta", is_path_shared: false, is_versioned: false)
|
327
|
+
# Fail: {"errorCode"=>-505, "description"=>"NfsError::FileAlreadyExistsWithSameName"}
|
328
|
+
# Success: true
|
329
|
+
#
|
330
|
+
# Reference: https://maidsafe.readme.io/docs/nfs-create-directory
|
331
|
+
#
|
332
|
+
def create_directory(dir_path, options = {})
|
333
|
+
# entry point
|
334
|
+
url = "#{@client.app_info[:launcher_server]}nfs/directory"
|
335
|
+
|
336
|
+
# default values
|
337
|
+
options[:is_private] = true if ! options.has_key?(:is_private)
|
338
|
+
options[:is_versioned] = false if ! options.has_key?(:is_versioned)
|
339
|
+
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
340
|
+
|
341
|
+
# payload
|
342
|
+
payload = {
|
343
|
+
dirPath: dir_path,
|
344
|
+
isPrivate: options[:is_private],
|
345
|
+
isVersioned: options[:is_versioned],
|
346
|
+
isPathShared: options[:is_path_shared]
|
347
|
+
}
|
348
|
+
|
349
|
+
# optional
|
350
|
+
payload["metadata"] = Base64.strict_encode64(options[:metadata]) if options.has_key?(:metadata)
|
351
|
+
|
352
|
+
# api call
|
353
|
+
uri = URI(url)
|
354
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
355
|
+
req = Net::HTTP::Post.new(uri.path, {
|
356
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
357
|
+
'Content-Type' => 'text/plain'
|
358
|
+
})
|
359
|
+
req.body = @client.key_helper.encrypt(payload.to_json)
|
360
|
+
res = http.request(req)
|
361
|
+
res.code == "200" ? true : JSON.parse(@client.key_helper.decrypt(res.body))
|
362
|
+
end
|
422
363
|
|
423
|
-
def self.get_home_dir(long_name, service_name)
|
424
|
-
# entry point
|
425
|
-
url = "#{@@LAUNCHER_SERVER}dns/#{CGI.escape(service_name)}/#{CGI.escape(long_name)}"
|
426
364
|
|
427
|
-
#
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
res = http.request(req)
|
432
|
-
JSON.parse(res.body)
|
433
|
-
end
|
365
|
+
# ex.: delete_directory("/photos")
|
366
|
+
def delete_directory(dir_path, options = {})
|
367
|
+
# default values
|
368
|
+
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
434
369
|
|
370
|
+
# entry point
|
371
|
+
url = "#{@client.app_info[:launcher_server]}nfs/directory/#{CGI.escape(dir_path)}/#{options[:is_path_shared]}"
|
435
372
|
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
query = []
|
446
|
-
query << "offset=#{options[:offset]}"
|
447
|
-
query << "length=#{options[:length]}" if options.has_key?(:length) # length is optional
|
448
|
-
url = "#{url}#{self.encrypt(query.join('&'))}"
|
449
|
-
|
450
|
-
# api call
|
451
|
-
uri = URI(url)
|
452
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
453
|
-
req = Net::HTTP::Get.new(uri.path)
|
454
|
-
res = http.request(req)
|
455
|
-
res.code == "200" ? res.body : JSON.parse(res.body)
|
456
|
-
end
|
373
|
+
# api call
|
374
|
+
uri = URI(url)
|
375
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
376
|
+
req = Net::HTTP::Delete.new(uri.path, {
|
377
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
378
|
+
})
|
379
|
+
res = http.request(req)
|
380
|
+
res.code == "200" ? true : JSON.parse(@client.key_helper.decrypt(res.body))
|
381
|
+
end
|
457
382
|
|
458
|
-
|
383
|
+
# options: offset, length, is_path_shared
|
384
|
+
def get_file(file_path, options = {})
|
385
|
+
# default values
|
386
|
+
options[:offset] = 0 if ! options.has_key?(:offset)
|
387
|
+
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
388
|
+
|
389
|
+
# entry point
|
390
|
+
url = "#{@client.app_info[:launcher_server]}nfs/file/#{CGI.escape(file_path)}/#{options[:is_path_shared]}?"
|
391
|
+
|
392
|
+
# query params are encrypted
|
393
|
+
query = []
|
394
|
+
query << "offset=#{options[:offset]}"
|
395
|
+
query << "length=#{options[:length]}" if options.has_key?(:length) # length is optional
|
396
|
+
url = "#{url}#{@client.key_helper.encrypt(query.join('&'))}"
|
397
|
+
|
398
|
+
# api call
|
399
|
+
uri = URI(url)
|
400
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
401
|
+
req = Net::HTTP::Get.new(uri.path, {
|
402
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
403
|
+
})
|
404
|
+
res = http.request(req)
|
405
|
+
res.code == "200" ? @client.key_helper.decrypt(res.body) : JSON.parse(@client.key_helper.decrypt(res.body))
|
406
|
+
end
|
459
407
|
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
408
|
+
def update_file_content(file_path, contents, options = {})
|
409
|
+
# default values
|
410
|
+
options[:offset] = 0 if ! options.has_key?(:offset)
|
411
|
+
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
412
|
+
|
413
|
+
# entry point
|
414
|
+
url = "#{@client.app_info[:launcher_server]}nfs/file/#{CGI.escape(file_path)}/#{options[:is_path_shared]}?offset=#{options[:offset]}"
|
415
|
+
|
416
|
+
# api call
|
417
|
+
uri = URI(url)
|
418
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
419
|
+
req = Net::HTTP::Put.new(uri.path, {
|
420
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
421
|
+
'Content-Type' => 'text/plain'
|
422
|
+
})
|
423
|
+
req.body = @client.key_helper.encrypt(contents)
|
424
|
+
res = http.request(req)
|
425
|
+
res.code == "200" ? true : JSON.parse(@client.key_helper.decrypt(res.body))
|
426
|
+
end
|
464
427
|
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
428
|
+
def delete_file(file_path, options = {})
|
429
|
+
# default values
|
430
|
+
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
431
|
+
|
432
|
+
# entry point
|
433
|
+
url = "#{@client.app_info[:launcher_server]}nfs/file/#{CGI.escape(file_path)}/#{options[:is_path_shared]}"
|
434
|
+
|
435
|
+
# api call
|
436
|
+
uri = URI(url)
|
437
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
438
|
+
req = Net::HTTP::Delete.new(uri.path, {
|
439
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
440
|
+
})
|
441
|
+
res = http.request(req)
|
442
|
+
res.code == "200" ? true : JSON.parse(@client.key_helper.decrypt(res.body))
|
443
|
+
end
|
470
444
|
end
|
471
445
|
|
472
446
|
|
473
|
-
|
474
|
-
|
447
|
+
class DNS
|
448
|
+
def initialize(client_obj)
|
449
|
+
@client = client_obj
|
450
|
+
end
|
451
|
+
|
452
|
+
# https://maidsafe.readme.io/docs/dns-create-long-name
|
453
|
+
def create_long_name(long_name)
|
454
|
+
# entry point
|
455
|
+
url = "#{@client.app_info[:launcher_server]}dns/#{CGI.escape(long_name)}"
|
456
|
+
|
457
|
+
# api call
|
458
|
+
uri = URI(url)
|
459
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
460
|
+
req = Net::HTTP::Post.new(uri.path, {
|
461
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
462
|
+
'Content-Type' => 'text/plain'
|
463
|
+
})
|
464
|
+
res = http.request(req)
|
465
|
+
res.code == "200" ? true : JSON.parse(@client.key_helper.decrypt(res.body))
|
466
|
+
end
|
475
467
|
|
476
|
-
# not loaded yet?
|
477
|
-
if @@keys.empty?
|
478
|
-
@@conf ||= {}
|
479
|
-
self.get_valid_token if @@conf.empty?
|
480
468
|
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
469
|
+
# ex.: register_service("thegoogle", "www", "/www")
|
470
|
+
# https://maidsafe.readme.io/docs/dns-register-service
|
471
|
+
def register_service(long_name, service_name, service_home_dir_path, options = {})
|
472
|
+
# entry point
|
473
|
+
url = "#{@client.app_info[:launcher_server]}dns"
|
474
|
+
|
475
|
+
# default values
|
476
|
+
options[:is_path_shared] = false if ! options.has_key?(:is_path_shared)
|
477
|
+
|
478
|
+
# payload
|
479
|
+
payload = {
|
480
|
+
longName: long_name,
|
481
|
+
serviceName: service_name,
|
482
|
+
serviceHomeDirPath: service_home_dir_path,
|
483
|
+
isPathShared: options[:is_path_shared]
|
484
|
+
}
|
485
|
+
|
486
|
+
# optional
|
487
|
+
payload["metadata"] = options[:metadata] if options.has_key?(:metadata)
|
488
|
+
|
489
|
+
# api call
|
490
|
+
uri = URI(url)
|
491
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
492
|
+
req = Net::HTTP::Post.new(uri.path, {
|
493
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
494
|
+
'Content-Type' => 'text/plain'
|
495
|
+
})
|
496
|
+
req.body = @client.key_helper.encrypt(payload.to_json)
|
497
|
+
res = http.request(req)
|
498
|
+
res.code == "200" ? true : JSON.parse(@client.key_helper.decrypt(res.body))
|
499
|
+
end
|
486
500
|
|
487
|
-
|
488
|
-
|
501
|
+
# https://maidsafe.readme.io/docs/dns-list-long-names
|
502
|
+
def list_long_names
|
503
|
+
# entry point
|
504
|
+
url = "#{@client.app_info[:launcher_server]}dns"
|
505
|
+
|
506
|
+
# api call
|
507
|
+
uri = URI(url)
|
508
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
509
|
+
req = Net::HTTP::Get.new(uri.path, {
|
510
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
511
|
+
})
|
512
|
+
res = http.request(req)
|
513
|
+
JSON.parse(@client.key_helper.decrypt(res.body))
|
514
|
+
end
|
489
515
|
|
490
|
-
|
491
|
-
|
516
|
+
# https://maidsafe.readme.io/docs/dns-list-services
|
517
|
+
def list_services(long_name)
|
518
|
+
# entry point
|
519
|
+
url = "#{@client.app_info[:launcher_server]}dns/#{CGI.escape(long_name)}"
|
520
|
+
|
521
|
+
# api call
|
522
|
+
uri = URI(url)
|
523
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
524
|
+
req = Net::HTTP::Get.new(uri.path, {
|
525
|
+
'Authorization' => "Bearer #{@client.key_helper.get_valid_token()}",
|
526
|
+
})
|
527
|
+
res = http.request(req)
|
528
|
+
JSON.parse(@client.key_helper.decrypt(res.body))
|
529
|
+
end
|
492
530
|
|
493
|
-
# The second segment of the data will have the nonce to be used
|
494
|
-
@@keys["symmetric_nonce"] = data.slice(RbNaCl::SecretBox.key_bytes, RbNaCl::SecretBox.key_bytes)
|
495
531
|
|
496
|
-
|
497
|
-
|
532
|
+
# https://maidsafe.readme.io/docs/dns-get-home-dir
|
533
|
+
def get_home_dir(long_name, service_name)
|
534
|
+
# entry point
|
535
|
+
url = "#{@client.app_info[:launcher_server]}dns/#{CGI.escape(service_name)}/#{CGI.escape(long_name)}"
|
536
|
+
|
537
|
+
# api call
|
538
|
+
uri = URI(url)
|
539
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
540
|
+
req = Net::HTTP::Get.new(uri.path)
|
541
|
+
res = http.request(req)
|
542
|
+
JSON.parse(res.body)
|
498
543
|
end
|
499
544
|
|
500
|
-
@@keys
|
501
|
-
end
|
502
545
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
546
|
+
# https://maidsafe.readme.io/docs/dns-get-file-unauth
|
547
|
+
# get_file_unauth("thegoogle", "www", "index.html", offset: 3, length: 5)
|
548
|
+
def self.get_file_unauth(long_name, service_name, file_path, options = {})
|
549
|
+
# default values
|
550
|
+
options[:offset] = 0 if ! options.has_key?(:offset)
|
507
551
|
|
508
|
-
|
509
|
-
|
510
|
-
res = keys["secret_box"].encrypt(keys["symmetric_nonce"], message)
|
511
|
-
Base64.strict_encode64(res)
|
512
|
-
end
|
552
|
+
# entry point
|
553
|
+
url = "#{@client.app_info[:launcher_server]}dns/#{CGI.escape(service_name)}/#{CGI.escape(long_name)}/#{CGI.escape(file_path)}?"
|
513
554
|
|
555
|
+
# query params are encrypted
|
556
|
+
query = []
|
557
|
+
query << "offset=#{options[:offset]}"
|
558
|
+
query << "length=#{options[:length]}" if options.has_key?(:length) # length is optional
|
559
|
+
url = "#{url}#{@client.key_helper.encrypt(query.join('&'))}"
|
560
|
+
|
561
|
+
# api call
|
562
|
+
uri = URI(url)
|
563
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
564
|
+
req = Net::HTTP::Get.new(uri.path)
|
565
|
+
res = http.request(req)
|
566
|
+
res.code == "200" ? res.body : JSON.parse(res.body)
|
567
|
+
end
|
568
|
+
end
|
514
569
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-safenet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Loureiro
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|