adamantite 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/adamantite.rb +99 -70
- data/lib/base/adamantite.rb +43 -3
- data/lib/file_utils/adamantite_file_utils.rb +12 -1
- data/lib/gui/form/license_form.rb +49 -0
- data/lib/gui/request/set_master_license_key_request.rb +21 -0
- data/lib/gui/screen/login_screen.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c3fa0d2056a2b58771a3d36c7e7a93d6d1ef280778d55b27aa6d43662746e50
|
4
|
+
data.tar.gz: 631ccf39897ad7f96fa4ffec126a9cf2a1f7c50e30e7cd74fb772a3de6662473
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1c46782cd2252a23a3b1017683c1202ce7ba551f71425a93d7901440da1413eeb89c48bd116507edc46be6d147d6d3ab47ba2be0af1adb334d40a1ba97d4950
|
7
|
+
data.tar.gz: 5a5d5b8a5b3e7e89c3c3a59b69e21d4ac5bed6899da9ff572b5940b8353cedfdea6354192201469e31355dee3059f6a5643128a68b96626b9a0c5a42d5a1ed26
|
data/lib/adamantite.rb
CHANGED
@@ -1,25 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'glimmer-dsl-libui'
|
4
|
-
require 'bcrypt'
|
5
|
-
require 'openssl'
|
6
|
-
require 'base64'
|
7
|
-
require 'json'
|
8
|
-
require 'io/console'
|
9
4
|
|
10
5
|
require 'fileutils'
|
11
6
|
require 'file_utils/adamantite_file_utils'
|
12
7
|
require 'base/adamantite'
|
13
8
|
require 'base/password_object'
|
14
|
-
require 'gui/screen/login_screen'
|
15
9
|
require 'gui/screen/copy_screen'
|
16
|
-
require 'gui/screen/
|
10
|
+
require 'gui/screen/login_screen'
|
17
11
|
require 'gui/screen/set_master_password_screen'
|
12
|
+
require 'gui/screen/show_screen'
|
18
13
|
require 'gui/screen/update_master_password_screen'
|
19
14
|
require 'gui/request/login_request'
|
20
15
|
require 'gui/request/add_password_request'
|
21
16
|
require 'gui/request/update_master_password_request'
|
17
|
+
require 'gui/request/set_master_license_key_request'
|
22
18
|
require 'gui/request/set_master_password_request'
|
19
|
+
require 'gui/form/license_form'
|
23
20
|
require 'gui/form/password_object_form_window'
|
24
21
|
|
25
22
|
module Adamantite
|
@@ -51,83 +48,115 @@ module Adamantite
|
|
51
48
|
@add_password_request = GUI::Request::AddPasswordRequest.new(@master_password, @master_password_salt)
|
52
49
|
end
|
53
50
|
|
51
|
+
menu('About') do
|
52
|
+
menu_item('Software Information') do
|
53
|
+
on_clicked do
|
54
|
+
msg_box('For more information please visit adamantitehomepage.com')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
menu_item('Author') do
|
58
|
+
on_clicked do
|
59
|
+
msg_box('Jake Bruemmer - https://x.com/jakebruemmer')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
54
64
|
body do
|
55
|
-
window('Adamantite', 800, 400) do
|
65
|
+
window('Adamantite', 800, 400, true) do
|
56
66
|
margined true
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
67
|
+
if @adamantite.licensed?
|
68
|
+
vertical_box do
|
69
|
+
table do
|
70
|
+
text_column('Title')
|
71
|
+
text_column('Username')
|
72
|
+
button_column('Edit') do
|
73
|
+
on_clicked do |row|
|
74
|
+
on_save = lambda do |password_object|
|
75
|
+
stored_password = []
|
76
|
+
stored_password << password_object.website_title
|
77
|
+
stored_password << password_object.username
|
78
|
+
stored_password << 'Edit'
|
79
|
+
stored_password << 'Copy'
|
80
|
+
stored_password << 'Show'
|
81
|
+
stored_password << 'Delete'
|
82
|
+
@stored_passwords[password_object.row_index] = stored_password
|
83
|
+
adamantite_stored_password = {
|
84
|
+
'dir_name': password_object.dir_name,
|
85
|
+
'website_title': password_object.website_title,
|
86
|
+
'username': @adamantite.retrieve_password_info(password_object.dir_name, 'username')
|
87
|
+
}
|
88
|
+
@adamantite.stored_passwords[password_object.row_index] = adamantite_stored_password
|
89
|
+
end
|
90
|
+
website_title = @stored_passwords[row][0]
|
91
|
+
username = @stored_passwords[row][1]
|
92
|
+
dir_name = @adamantite.stored_passwords[row][:dir_name]
|
93
|
+
password = @adamantite.retrieve_password_info(dir_name, 'password')
|
94
|
+
password_object = Base::PasswordObject.new(website_title, username, password, password, row, dir_name)
|
95
|
+
password_object_form_window(adamantite: @adamantite, on_save: on_save, password_object: password_object).show
|
79
96
|
end
|
80
|
-
website_title = @stored_passwords[row][0]
|
81
|
-
username = @stored_passwords[row][1]
|
82
|
-
dir_name = @adamantite.stored_passwords[row][:dir_name]
|
83
|
-
password = @adamantite.retrieve_password_info(dir_name, 'password')
|
84
|
-
password_object = Base::PasswordObject.new(website_title, username, password, password, row, dir_name)
|
85
|
-
password_object_form_window(adamantite: @adamantite, on_save: on_save, password_object: password_object).show
|
86
97
|
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
98
|
+
button_column('Copy') do
|
99
|
+
on_clicked do |row|
|
100
|
+
IO.popen('pbcopy', 'w') do |f|
|
101
|
+
dir_name = @adamantite.stored_passwords[row][:dir_name]
|
102
|
+
f << @adamantite.retrieve_password_info(dir_name, 'password')
|
103
|
+
end
|
104
|
+
copy_screen(password_title: @stored_passwords[row].first).show
|
105
|
+
end
|
106
|
+
end
|
107
|
+
button_column('Show') do
|
108
|
+
on_clicked do |row|
|
91
109
|
dir_name = @adamantite.stored_passwords[row][:dir_name]
|
92
|
-
|
110
|
+
show_screen(password: @adamantite.retrieve_password_info(dir_name, 'password')).show
|
93
111
|
end
|
94
|
-
copy_screen(password_title: @stored_passwords[row].first).show
|
95
112
|
end
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
113
|
+
button_column('Delete') do
|
114
|
+
on_clicked do |row|
|
115
|
+
@adamantite.delete_password(@adamantite.stored_passwords[row][:dir_name])
|
116
|
+
@stored_passwords.delete_at(row)
|
117
|
+
end
|
101
118
|
end
|
119
|
+
cell_rows <=> [self, :stored_passwords]
|
102
120
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
121
|
+
horizontal_box do
|
122
|
+
button('Add Password') do
|
123
|
+
on_clicked do
|
124
|
+
on_save = lambda do |password_object|
|
125
|
+
stored_password = []
|
126
|
+
stored_password << password_object.website_title
|
127
|
+
stored_password << password_object.username
|
128
|
+
stored_password << 'Edit'
|
129
|
+
stored_password << 'Copy'
|
130
|
+
stored_password << 'Show'
|
131
|
+
stored_password << 'Delete'
|
132
|
+
@stored_passwords << stored_password
|
133
|
+
end
|
134
|
+
password_object_form_window(adamantite: @adamantite, on_save: on_save).show
|
135
|
+
end
|
107
136
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
button('Add Password') do
|
113
|
-
on_clicked do
|
114
|
-
on_save = lambda do |password_object|
|
115
|
-
stored_password = []
|
116
|
-
stored_password << password_object.website_title
|
117
|
-
stored_password << password_object.username
|
118
|
-
stored_password << 'Edit'
|
119
|
-
stored_password << 'Copy'
|
120
|
-
stored_password << 'Show'
|
121
|
-
stored_password << 'Delete'
|
122
|
-
@stored_passwords << stored_password
|
137
|
+
button('Update Master Password') do
|
138
|
+
on_clicked do
|
139
|
+
update_master_password_request = GUI::Request::UpdateMasterPasswordRequest.new(@adamantite)
|
140
|
+
update_master_password_screen(update_master_password_request: update_master_password_request).show
|
123
141
|
end
|
124
|
-
password_object_form_window(adamantite: @adamantite, on_save: on_save).show
|
125
142
|
end
|
126
143
|
end
|
127
|
-
|
144
|
+
horizontal_box do
|
145
|
+
label('This is valid Adamantite installation.')
|
146
|
+
end
|
147
|
+
end
|
148
|
+
else
|
149
|
+
vertical_box do
|
150
|
+
license_label = <<-TEXT
|
151
|
+
No license detected. Please add one to start using Adamantite.
|
152
|
+
If you need one, visit https://jakebruemmer.github.io/adamantite-info/
|
153
|
+
for more information.
|
154
|
+
TEXT
|
155
|
+
label(license_label)
|
156
|
+
button('Add License Info') do
|
128
157
|
on_clicked do
|
129
|
-
|
130
|
-
|
158
|
+
set_master_license_key_request = GUI::Request::SetMasterLicenseKeyRequest.new(@adamantite)
|
159
|
+
license_form(set_master_license_key_request: set_master_license_key_request).show
|
131
160
|
end
|
132
161
|
end
|
133
162
|
end
|
data/lib/base/adamantite.rb
CHANGED
@@ -1,19 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'file_utils/adamantite_file_utils'
|
4
|
-
require 'rbnacl'
|
5
3
|
require 'base64'
|
4
|
+
require 'httparty'
|
5
|
+
require 'rbnacl'
|
6
|
+
|
7
|
+
require 'file_utils/adamantite_file_utils'
|
6
8
|
|
7
9
|
module Adamantite
|
8
10
|
module Base
|
9
11
|
class Adamantite
|
10
12
|
include AdamantiteFileUtils
|
11
13
|
|
12
|
-
attr_reader :authenticated, :master_password, :master_password_salt, :stored_passwords
|
14
|
+
attr_reader :authenticated, :master_password, :master_password_salt, :stored_passwords,
|
15
|
+
:master_license_key
|
13
16
|
|
14
17
|
OPSLIMIT = 2**20
|
15
18
|
MEMLIMIT = 2**24
|
16
19
|
DIGEST_SIZE = 32
|
20
|
+
LICENSE_ACTIVATION_URL = 'https://api.keygen.sh/v1/accounts/c8f50eb9-eb87-4431-a680-d8f181441ef8/licenses/actions/validate-key'
|
17
21
|
|
18
22
|
def initialize(master_password)
|
19
23
|
@master_password = master_password
|
@@ -33,6 +37,7 @@ module Adamantite
|
|
33
37
|
@master_password_salt = master_password_salt
|
34
38
|
@vault = rbnacl_box(@master_vault_key)
|
35
39
|
update_stored_passwords!
|
40
|
+
read_license_key! if has_license_key?
|
36
41
|
true
|
37
42
|
rescue RbNaCl::CryptoError
|
38
43
|
false
|
@@ -42,6 +47,31 @@ module Adamantite
|
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
50
|
+
def activate_license!(master_license_key)
|
51
|
+
return unless authenticated?
|
52
|
+
|
53
|
+
headers = {
|
54
|
+
'Content-Type': 'application/vnd.api+json',
|
55
|
+
'Accept': 'application/vnd.api+json'
|
56
|
+
}
|
57
|
+
body = {
|
58
|
+
'meta': {
|
59
|
+
'key': master_license_key,
|
60
|
+
'scope': {
|
61
|
+
'product': 'bb6542ab-7d74-44d0-b4f5-1fbc39cdeb99'
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
res = HTTParty.post(LICENSE_ACTIVATION_URL, headers: headers, body: body.to_json)
|
66
|
+
|
67
|
+
if res['meta']['valid']
|
68
|
+
@master_license_key = master_license_key
|
69
|
+
write_to_file(password_file('master_license_key'), @vault.encrypt(@master_license_key), true)
|
70
|
+
true
|
71
|
+
end
|
72
|
+
licensed?
|
73
|
+
end
|
74
|
+
|
45
75
|
def save_password(website_title, username, password, password_confirmation)
|
46
76
|
return unless password == password_confirmation && authenticated?
|
47
77
|
|
@@ -130,6 +160,10 @@ module Adamantite
|
|
130
160
|
end
|
131
161
|
end
|
132
162
|
|
163
|
+
def licensed?
|
164
|
+
!@master_license_key.nil?
|
165
|
+
end
|
166
|
+
|
133
167
|
private
|
134
168
|
|
135
169
|
def rbnacl_box(key)
|
@@ -153,6 +187,12 @@ module Adamantite
|
|
153
187
|
write_to_file(password_file('master_password_salt'), master_password_salt, true)
|
154
188
|
write_to_file(password_file('master_encrypted_vault_key'), master_vault_key, true)
|
155
189
|
end
|
190
|
+
|
191
|
+
def read_license_key!
|
192
|
+
return unless authenticated?
|
193
|
+
|
194
|
+
@master_license_key = @vault.decrypt(get_license_key)
|
195
|
+
end
|
156
196
|
end
|
157
197
|
end
|
158
198
|
end
|
@@ -92,13 +92,24 @@ module Adamantite
|
|
92
92
|
File.open(pw_file('master_encrypted_vault_key'), 'rb', &:read)
|
93
93
|
end
|
94
94
|
|
95
|
+
def get_license_key
|
96
|
+
File.open(pw_file('master_license_key'), 'rb', &:read)
|
97
|
+
end
|
98
|
+
|
95
99
|
def get_stored_pws
|
96
|
-
excluded_filenames = [
|
100
|
+
excluded_filenames = [
|
101
|
+
'.', '..', 'master_password_hash', 'master_password_salt', 'master_encrypted_vault_key',
|
102
|
+
'master_license_key'
|
103
|
+
]
|
97
104
|
Dir.entries(pwmanager_dir).filter { |f| !excluded_filenames.include?(f) }
|
98
105
|
end
|
99
106
|
|
100
107
|
def master_password_exists?
|
101
108
|
pw_file_exists?('master_encrypted_vault_key') && pw_file_exists?('master_password_salt')
|
102
109
|
end
|
110
|
+
|
111
|
+
def has_license_key?
|
112
|
+
pw_file_exists?('master_license_key')
|
113
|
+
end
|
103
114
|
end
|
104
115
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Adamantite
|
4
|
+
module GUI
|
5
|
+
module Screen
|
6
|
+
class LicenseForm
|
7
|
+
include Glimmer::LibUI::CustomWindow
|
8
|
+
|
9
|
+
option :set_master_license_key_request
|
10
|
+
|
11
|
+
body do
|
12
|
+
window('Adamantite - Set License', 600, 150) do
|
13
|
+
margined true
|
14
|
+
vertical_box do
|
15
|
+
horizontal_box do
|
16
|
+
form do
|
17
|
+
entry do
|
18
|
+
label 'License - please include hyphens'
|
19
|
+
text <=> [set_master_license_key_request, :master_license_key]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
horizontal_box do
|
24
|
+
button('Set License') do
|
25
|
+
on_clicked do
|
26
|
+
set_master_license_key_request.activate_license!
|
27
|
+
if set_master_license_key_request.master_license_key_activated
|
28
|
+
body_root.destroy
|
29
|
+
::LibUI.quit
|
30
|
+
else
|
31
|
+
set_master_license_key_request.master_license_key = ''
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
horizontal_box do
|
37
|
+
info = <<-TEXT
|
38
|
+
This window will close if your license is entered successfully. Restart
|
39
|
+
Adamantite to begin using it.
|
40
|
+
TEXT
|
41
|
+
label(info)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Adamantite
|
4
|
+
module GUI
|
5
|
+
module Request
|
6
|
+
class SetMasterLicenseKeyRequest
|
7
|
+
attr_accessor :adamantite, :master_license_key, :master_license_key_activated
|
8
|
+
|
9
|
+
def initialize(adamantite)
|
10
|
+
@adamantite = adamantite
|
11
|
+
@master_license_key_activated = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def activate_license!
|
15
|
+
@adamantite.activate_license!(master_license_key)
|
16
|
+
@master_license_key_activated = true if @adamantite.licensed?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adamantite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jake Bruemmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11-
|
11
|
+
date: 2023-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A local password manager written in Ruby.
|
14
14
|
email: jakebruemmer@gmail.com
|
@@ -23,9 +23,11 @@ files:
|
|
23
23
|
- lib/base/editor/password_object_editor.rb
|
24
24
|
- lib/base/password_object.rb
|
25
25
|
- lib/file_utils/adamantite_file_utils.rb
|
26
|
+
- lib/gui/form/license_form.rb
|
26
27
|
- lib/gui/form/password_object_form_window.rb
|
27
28
|
- lib/gui/request/add_password_request.rb
|
28
29
|
- lib/gui/request/login_request.rb
|
30
|
+
- lib/gui/request/set_master_license_key_request.rb
|
29
31
|
- lib/gui/request/set_master_password_request.rb
|
30
32
|
- lib/gui/request/update_master_password_request.rb
|
31
33
|
- lib/gui/screen/copy_screen.rb
|