lastpass-api 0.2.3 → 0.3.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 +4 -0
- data/lib/lastpass-api.rb +10 -0
- data/lib/lastpass-api/account.rb +44 -2
- data/lib/lastpass-api/accounts.rb +47 -0
- data/lib/lastpass-api/cli.rb +40 -11
- data/lib/lastpass-api/client.rb +43 -0
- data/lib/lastpass-api/collection.rb +15 -0
- data/lib/lastpass-api/group.rb +30 -0
- data/lib/lastpass-api/groups.rb +36 -0
- data/lib/lastpass-api/parser.rb +15 -0
- data/lib/lastpass-api/utils.rb +9 -0
- data/lib/lastpass-api/version.rb +2 -1
- 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: f26e4e827da19cccd9805e2100cac712895fc826
|
4
|
+
data.tar.gz: df65a26f0e0f16101129defd81581b846a3a3cf6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d7852b0df17ccd15b70154e6b74336dc9a44f9efad5a2e2f2dcbbfa9d19e6aebe53189594ac0d880185fc061435648dd0658bc471fe534f4cfd429883727b94
|
7
|
+
data.tar.gz: 3e34687404317f013e4fcdc72da1866fee36c899b32658b0b4da6c0d8f73d17075d9759576c6b41cf7dc59f57a468c08b8e865e35f40c1f903f8839029f87f70
|
data/README.md
CHANGED
@@ -180,6 +180,10 @@ puts groups.first.to_h
|
|
180
180
|
|
181
181
|
#### Update group (rename a group)
|
182
182
|
|
183
|
+
Note that although this does rename the group, any accounts that were inside the group
|
184
|
+
will still remain under the original group name. Any new accounts that are created
|
185
|
+
will be placed under the new group name.
|
186
|
+
|
183
187
|
```ruby
|
184
188
|
# Update using instance variables
|
185
189
|
group = @lastpass.groups.find( 'Group1' )
|
data/lib/lastpass-api.rb
CHANGED
@@ -17,14 +17,24 @@ require 'lastpass-api/parser'
|
|
17
17
|
module Lastpass
|
18
18
|
@@verbose = false
|
19
19
|
|
20
|
+
# Verbose mode flag
|
20
21
|
def self.verbose
|
21
22
|
@@verbose
|
22
23
|
end
|
23
24
|
|
25
|
+
# Set if you want to turn on verbose mode. Turning on verbose will show much more output.
|
26
|
+
# This is good for debugging. It will output any commands that are executed with "lpass".
|
27
|
+
#
|
28
|
+
# @return [Boolean]
|
29
|
+
# @example
|
30
|
+
# Lastpass.verbose = true
|
24
31
|
def self.verbose=( verbose )
|
25
32
|
@@verbose = verbose
|
26
33
|
end
|
27
34
|
|
35
|
+
private
|
36
|
+
|
37
|
+
# Make sure "lpass" is installed with the correct version.
|
28
38
|
def self.check_lpass_in_path
|
29
39
|
error_message = 'Cannot find the "lpass" executable in the path!'
|
30
40
|
begin
|
data/lib/lastpass-api/account.rb
CHANGED
@@ -1,12 +1,29 @@
|
|
1
1
|
module Lastpass
|
2
|
+
|
3
|
+
# Interact with a Lastpass account
|
2
4
|
class Account
|
3
|
-
attr_reader :id
|
5
|
+
attr_reader :id
|
6
|
+
# @todo Make group editable eventually
|
7
|
+
attr_reader :group
|
4
8
|
attr_accessor :name, :username, :password, :url, :notes
|
5
9
|
|
10
|
+
# @param params [Hash]
|
6
11
|
def initialize( params )
|
7
12
|
params_to_account( params )
|
8
13
|
end
|
9
14
|
|
15
|
+
# Update the account details
|
16
|
+
#
|
17
|
+
# @param params [Hash]
|
18
|
+
# @example
|
19
|
+
# account = @lastpass.accounts.find( 'MyAccount' )
|
20
|
+
# account.update(
|
21
|
+
# name: 'MyAccount EDIT',
|
22
|
+
# username: 'root EDIT',
|
23
|
+
# password: 'pass EDIT',
|
24
|
+
# url: 'http://www.exampleEDIT.com',
|
25
|
+
# notes: 'This is my note. EDIT'
|
26
|
+
# )
|
10
27
|
def update( params )
|
11
28
|
deleted! if @deleted
|
12
29
|
params.delete( :id ) # Prevent overwriting ID
|
@@ -15,7 +32,19 @@ module Lastpass
|
|
15
32
|
save
|
16
33
|
end
|
17
34
|
|
18
|
-
#
|
35
|
+
# Either create or update an account, depending on what
|
36
|
+
# was changed on the account object before this method was called.
|
37
|
+
#
|
38
|
+
# @todo This does not support changing groups yet!
|
39
|
+
# @example
|
40
|
+
# # Update using instance variables
|
41
|
+
# account = @lastpass.accounts.find( 'MyAccount' )
|
42
|
+
# account.name = 'MyAccount EDIT'
|
43
|
+
# account.username = 'root EDIT'
|
44
|
+
# account.password = 'pass EDIT'
|
45
|
+
# account.url = 'http://www.exampleEDIT.com'
|
46
|
+
# account.notes = 'This is my notes. EDIT'
|
47
|
+
# account.save
|
19
48
|
def save
|
20
49
|
deleted! if @deleted
|
21
50
|
# If there is an ID, update that entry
|
@@ -41,11 +70,22 @@ module Lastpass
|
|
41
70
|
self
|
42
71
|
end
|
43
72
|
|
73
|
+
# Delete the account
|
74
|
+
#
|
75
|
+
# @example
|
76
|
+
# account = @lastpass.accounts.find( 1234 )
|
77
|
+
# account.delete
|
44
78
|
def delete
|
45
79
|
Cli.rm( @id )
|
46
80
|
@deleted = true
|
47
81
|
end
|
48
82
|
|
83
|
+
# Hash representation of the account object
|
84
|
+
#
|
85
|
+
# @return [Hash]
|
86
|
+
# @example
|
87
|
+
# puts account.to_h
|
88
|
+
# # => { id: '1234', name: 'MyAccount', username: 'root', password: 'pass', url: 'http://www.example.com', notes: 'This is my note.', group: 'MyGroup' }
|
49
89
|
def to_hash
|
50
90
|
params = {}
|
51
91
|
params[:id] = @id if @id
|
@@ -61,6 +101,8 @@ module Lastpass
|
|
61
101
|
alias_method :to_h, :to_hash
|
62
102
|
|
63
103
|
# Hide instance variables and values
|
104
|
+
#
|
105
|
+
# @api private
|
64
106
|
def inspect
|
65
107
|
original_inspect = super
|
66
108
|
original_inspect.split( ' ' ).first << '>'
|
@@ -1,6 +1,19 @@
|
|
1
1
|
module Lastpass
|
2
|
+
|
3
|
+
# Interact with Lastpass accounts
|
2
4
|
class Accounts < Collection
|
3
5
|
|
6
|
+
# Find a specific account by name or by ID
|
7
|
+
#
|
8
|
+
# @param search_text [String] Account name or ID
|
9
|
+
# @param with_password [Boolean] Fetch the password along with the account details (default: false)
|
10
|
+
# @return [Lastpass::Account, NilClass]
|
11
|
+
# @example
|
12
|
+
# # Find a specific account by name
|
13
|
+
# account = @lastpass.accounts.find( 'MyAccount', with_password: true )
|
14
|
+
#
|
15
|
+
# # Find a specific account by ID
|
16
|
+
# account = @lastpass.accounts.find( 1234, with_password: true )
|
4
17
|
def find( search_text, with_password: false )
|
5
18
|
params = super
|
6
19
|
if params.is_a?( Hash ) && !params[:name]&.end_with?( '/' )
|
@@ -8,6 +21,20 @@ module Lastpass
|
|
8
21
|
end
|
9
22
|
end
|
10
23
|
|
24
|
+
# Find all accounts by name or by ID
|
25
|
+
#
|
26
|
+
# @note By default, with no params specified, all accounts will be returned.
|
27
|
+
# @param search_text [String] Account name or ID (can pass in regex like '.*')
|
28
|
+
# @param with_passwords [Boolean] Fetch the password along with the account details (default: false)
|
29
|
+
# @return [Array<Lastpass::Account>]
|
30
|
+
# @example
|
31
|
+
# # Find all accounts that match string (or regex)
|
32
|
+
# accounts = @lastpass.accounts.find_all( 'MyAcc' )
|
33
|
+
# puts accounts.count
|
34
|
+
# puts accounts.first.to_h
|
35
|
+
#
|
36
|
+
# # Fetch all accounts - same as find_all( '.*' )
|
37
|
+
# @lastpass.accounts.find_all
|
11
38
|
def find_all( search_text = '.*', with_passwords: false )
|
12
39
|
accounts = super.select { |params| !params[:name]&.end_with? '/' }
|
13
40
|
accounts.map do |params|
|
@@ -15,12 +42,32 @@ module Lastpass
|
|
15
42
|
end
|
16
43
|
end
|
17
44
|
|
45
|
+
# Create a new account
|
46
|
+
#
|
47
|
+
# @param params [Hash]
|
48
|
+
# @return [Lastpass::Account]
|
49
|
+
# @example
|
50
|
+
# # Create an optional group to place account into
|
51
|
+
# @lastpass.groups.create( name: 'MyGroup' )
|
52
|
+
#
|
53
|
+
# # Create account
|
54
|
+
# account = @lastpass.accounts.create(
|
55
|
+
# name: 'MyAccount',
|
56
|
+
# username: 'root',
|
57
|
+
# password: 'pass',
|
58
|
+
# url: 'http://www.example.com',
|
59
|
+
# notes: 'This is my note.',
|
60
|
+
# group: 'MyGroup'
|
61
|
+
# )
|
62
|
+
# puts account.id
|
18
63
|
def create( params )
|
19
64
|
params.delete( :id ) # Prevent overwriting ID
|
20
65
|
Account.new( params ).save
|
21
66
|
end
|
22
67
|
|
23
68
|
# Hide instance variables and values
|
69
|
+
#
|
70
|
+
# @api private
|
24
71
|
def inspect
|
25
72
|
original_inspect = super
|
26
73
|
original_inspect.split( ' ' ).first << '>'
|
data/lib/lastpass-api/cli.rb
CHANGED
@@ -3,8 +3,26 @@ require 'timeout'
|
|
3
3
|
module Lastpass
|
4
4
|
|
5
5
|
# Low-level interaction with LastPass CLI
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
# @example
|
9
|
+
# Lastpass::Cli.login( username, password:, trust: false, plaintext_key: false, force: false )
|
10
|
+
# Lastpass::Cli.logout( force: false )
|
11
|
+
# Lastpass::Cli.show( account, clip: false, expand_multi: false, all: false, basic_regexp: false, id: false )
|
12
|
+
# Lastpass::Cli.ls( group = nil, long: false, m: false, u: false )
|
13
|
+
# Lastpass::Cli.add( name, username: nil, password: nil, url: nil, notes: nil, group: nil )
|
14
|
+
# Lastpass::Cli.add_group( name )
|
15
|
+
# Lastpass::Cli.edit( id, name: nil, username: nil, password: nil, url: nil, notes: nil, group: nil )
|
16
|
+
# Lastpass::Cli.edit_group( id, name: )
|
17
|
+
# Lastpass::Cli.rm( id )
|
18
|
+
# Lastpass::Cli.status( quiet: false )
|
19
|
+
# Lastpass::Cli.sync
|
20
|
+
# Lastpass::Cli.export
|
21
|
+
# Lastpass::Cli.import( csv_filename )
|
22
|
+
# Lastpass::Cli.version
|
6
23
|
class Cli
|
7
|
-
|
24
|
+
# @todo Make this configurable? Or at least smarter?
|
25
|
+
UPLOAD_QUEUE_PATH = '~/.lpass/upload-queue'
|
8
26
|
|
9
27
|
# Login to LastPass, opening up a global session
|
10
28
|
#
|
@@ -26,11 +44,12 @@ module Lastpass
|
|
26
44
|
end
|
27
45
|
|
28
46
|
# @note lpass passwd
|
47
|
+
# @todo Not yet implemented
|
29
48
|
def self.passwd
|
30
49
|
not_implemented!
|
31
50
|
end
|
32
51
|
|
33
|
-
# @note lpass show [--sync=auto|now|no] [--clip, -c] [--expand-multi, -x] [--all|--username|--password|--url|--notes|--field=FIELD|--id|--name|--attach=ATTACHID] [--basic-regexp, -G|--fixed-strings, -F] [--color=auto|never|always] {UNIQUENAME|UNIQUEID}
|
52
|
+
# @note lpass show [--sync=auto|now|no] [--clip, -c] [--expand-multi, -x] [--all|--username|--password|--url|--notes|--field=FIELD|--id|--name|--attach=ATTACHID] [--basic-regexp, -G|--fixed-strings, -F] [--color=auto|never|always] \\{UNIQUENAME|UNIQUEID}
|
34
53
|
def self.show( account, clip: false, expand_multi: false, all: false, basic_regexp: false, id: false )
|
35
54
|
sync # Ensure everything is synced up before running!
|
36
55
|
command = 'lpass show'
|
@@ -62,12 +81,13 @@ module Lastpass
|
|
62
81
|
response
|
63
82
|
end
|
64
83
|
|
65
|
-
# @note lpass mv [--color=auto|never|always] {UNIQUENAME|UNIQUEID} GROUP
|
84
|
+
# @note lpass mv [--color=auto|never|always] \\{UNIQUENAME|UNIQUEID} GROUP
|
85
|
+
# @todo Not yet implemented
|
66
86
|
def self.mv
|
67
87
|
not_implemented!
|
68
88
|
end
|
69
89
|
|
70
|
-
# @note lpass add [--sync=auto|now|no] [--non-interactive] [--color=auto|never|always] {--username|--password|--url|--notes|--field=FIELD|--note-type=NOTETYPE} NAME
|
90
|
+
# @note lpass add [--sync=auto|now|no] [--non-interactive] [--color=auto|never|always] \\{--username|--password|--url|--notes|--field=FIELD|--note-type=NOTETYPE} NAME
|
71
91
|
def self.add( name, username: nil, password: nil, url: nil, notes: nil, group: nil )
|
72
92
|
data = {}
|
73
93
|
data[:Username] = escape( username, double: true ) if username
|
@@ -85,14 +105,14 @@ module Lastpass
|
|
85
105
|
response
|
86
106
|
end
|
87
107
|
|
88
|
-
# @note lpass add [--sync=auto|now|no] [--non-interactive] [--color=auto|never|always] {--username|--password|--url|--notes|--field=FIELD|--note-type=NOTETYPE} NAME
|
108
|
+
# @note lpass add [--sync=auto|now|no] [--non-interactive] [--color=auto|never|always] \\{--username|--password|--url|--notes|--field=FIELD|--note-type=NOTETYPE} NAME
|
89
109
|
def self.add_group( name )
|
90
110
|
response = Utils.cmd "printf 'URL: http://group' | lpass add --non-interactive --sync=no '#{escape( name )}/'"
|
91
111
|
sync
|
92
112
|
response
|
93
113
|
end
|
94
114
|
|
95
|
-
# @note lpass edit [--sync=auto|now|no] [--non-interactive] [--color=auto|never|always] {--name|--username|--password|--url|--notes|--field=FIELD} {NAME|UNIQUEID}
|
115
|
+
# @note lpass edit [--sync=auto|now|no] [--non-interactive] [--color=auto|never|always] \\{--name|--username|--password|--url|--notes|--field=FIELD} \\{NAME|UNIQUEID}
|
96
116
|
def self.edit( id, name: nil, username: nil, password: nil, url: nil, notes: nil, group: nil )
|
97
117
|
data = {}
|
98
118
|
name_with_group = ''
|
@@ -114,7 +134,13 @@ module Lastpass
|
|
114
134
|
response
|
115
135
|
end
|
116
136
|
|
117
|
-
# @note lpass edit [--sync=auto|now|no] [--non-interactive] [--color=auto|never|always] {--name|--username|--password|--url|--notes|--field=FIELD} {NAME|UNIQUEID}
|
137
|
+
# @note lpass edit [--sync=auto|now|no] [--non-interactive] [--color=auto|never|always] \\{--name|--username|--password|--url|--notes|--field=FIELD} \\{NAME|UNIQUEID}
|
138
|
+
# @note This does actually rename the project even though it looks like it
|
139
|
+
# creates a new group in Lastpass. This is because the original creds that
|
140
|
+
# were under this project have the group name in the name of the creds
|
141
|
+
# (yay for Lastpass awesomeness). So, after a project rename, newly created
|
142
|
+
# creds will go under the new group name. Old creds will rename in the
|
143
|
+
# old pseudo name.
|
118
144
|
def self.edit_group( id, name: )
|
119
145
|
command = 'printf "'
|
120
146
|
command << "Name: #{escape( name, double: true )}/"
|
@@ -125,17 +151,19 @@ module Lastpass
|
|
125
151
|
response
|
126
152
|
end
|
127
153
|
|
128
|
-
# @note lpass generate [--sync=auto|now|no] [--clip, -c] [--username=USERNAME] [--url=URL] [--no-symbols] {NAME|UNIQUEID} LENGTH
|
154
|
+
# @note lpass generate [--sync=auto|now|no] [--clip, -c] [--username=USERNAME] [--url=URL] [--no-symbols] \\{NAME|UNIQUEID} LENGTH
|
155
|
+
# @todo Not yet implemented
|
129
156
|
def self.generate
|
130
|
-
not_implemented!
|
157
|
+
not_implemented!
|
131
158
|
end
|
132
159
|
|
133
|
-
# @note lpass duplicate [--sync=auto|now|no] [--color=auto|never|always] {UNIQUENAME|UNIQUEID}
|
160
|
+
# @note lpass duplicate [--sync=auto|now|no] [--color=auto|never|always] \\{UNIQUENAME|UNIQUEID}
|
161
|
+
# @todo Not yet implemented
|
134
162
|
def self.duplicate
|
135
163
|
not_implemented!
|
136
164
|
end
|
137
165
|
|
138
|
-
# @note lpass rm [--sync=auto|now|no] [--color=auto|never|always] {UNIQUENAME|UNIQUEID}
|
166
|
+
# @note lpass rm [--sync=auto|now|no] [--color=auto|never|always] \\{UNIQUENAME|UNIQUEID}
|
139
167
|
def self.rm( id )
|
140
168
|
response = Utils.cmd "lpass rm --sync=no #{id}"
|
141
169
|
sync
|
@@ -168,6 +196,7 @@ module Lastpass
|
|
168
196
|
end
|
169
197
|
|
170
198
|
# @note lpass share subcommand sharename ...
|
199
|
+
# @todo Not yet implemented
|
171
200
|
def self.share
|
172
201
|
not_implemented!
|
173
202
|
end
|
data/lib/lastpass-api/client.rb
CHANGED
@@ -1,10 +1,33 @@
|
|
1
1
|
module Lastpass
|
2
|
+
|
3
|
+
# Main class to interact with Lastpass API
|
2
4
|
class Client
|
3
5
|
|
6
|
+
# @param verbose [Boolean] Set if you want to turn on verbose mode. Turning on
|
7
|
+
# verbose will show much more output. This is good for debugging. It will
|
8
|
+
# output any commands that are executed with "lpass". (default: false)
|
9
|
+
# @example Without verbose
|
10
|
+
# require 'lastpass-api'
|
11
|
+
# @lastpass = Lastpass::Client.new
|
12
|
+
# @example With verbose mode on
|
13
|
+
# require 'lastpass-api'
|
14
|
+
# @lastpass = Lastpass::Client.new( verbose: true )
|
4
15
|
def initialize( verbose: false )
|
5
16
|
Lastpass.verbose = verbose
|
6
17
|
end
|
7
18
|
|
19
|
+
# Login to Lastpass
|
20
|
+
#
|
21
|
+
# @note This is not thread safe. Only one login session can be active at a time.
|
22
|
+
# @note If there is a valid active login session already when this is called, it
|
23
|
+
# will use that session rather than create a new one.
|
24
|
+
# @param email [String] Lastpass master email
|
25
|
+
# @param password [String] Lastpass master password
|
26
|
+
# @raise [RuntimeError] if login failed
|
27
|
+
# @return [Boolean] if login was successful
|
28
|
+
# @example
|
29
|
+
# @lastpass.login( email: 'user@example.com', password: 'secret' )
|
30
|
+
# puts @lastpass.logged_in?
|
8
31
|
def login( email:, password: )
|
9
32
|
if logged_in?
|
10
33
|
Cli.sync
|
@@ -17,6 +40,12 @@ module Lastpass
|
|
17
40
|
true
|
18
41
|
end
|
19
42
|
|
43
|
+
# Logout of Lastpass
|
44
|
+
#
|
45
|
+
# @return [Boolean] if logout was successful
|
46
|
+
# @example
|
47
|
+
# @lastpass.logout
|
48
|
+
# puts @lastpass.logged_out?
|
20
49
|
def logout
|
21
50
|
return true if logged_out?
|
22
51
|
Cli.logout
|
@@ -25,25 +54,39 @@ module Lastpass
|
|
25
54
|
false
|
26
55
|
end
|
27
56
|
|
57
|
+
# Check to see if currently logged into Lastpass
|
58
|
+
#
|
59
|
+
# @return [Boolean]
|
28
60
|
def logged_in?
|
29
61
|
Cli.status.include? 'Logged in'
|
30
62
|
rescue
|
31
63
|
false
|
32
64
|
end
|
33
65
|
|
66
|
+
# Check to see if logged out of Lastpass
|
67
|
+
#
|
68
|
+
# @return [Boolean]
|
34
69
|
def logged_out?
|
35
70
|
!logged_in?
|
36
71
|
end
|
37
72
|
|
73
|
+
# Interface to interacting with Lastpass accounts
|
74
|
+
#
|
75
|
+
# @return [Lastpass::Accounts]
|
38
76
|
def accounts
|
39
77
|
Accounts.new
|
40
78
|
end
|
41
79
|
|
80
|
+
# Interface to interacting with Lastpass groups
|
81
|
+
#
|
82
|
+
# @return [Lastpass::Groups]
|
42
83
|
def groups
|
43
84
|
Groups.new
|
44
85
|
end
|
45
86
|
|
46
87
|
# Hide instance variables and values
|
88
|
+
#
|
89
|
+
# @api private
|
47
90
|
def inspect
|
48
91
|
original_inspect = super
|
49
92
|
original_inspect.split( ' ' ).first << '>'
|
@@ -1,10 +1,25 @@
|
|
1
1
|
module Lastpass
|
2
|
+
|
3
|
+
# Represents a collection of Lastpass objects (whether that be accounts or groups)
|
4
|
+
#
|
5
|
+
# @api private
|
2
6
|
class Collection
|
3
7
|
|
8
|
+
# Find a specific object by name or by ID
|
9
|
+
#
|
10
|
+
# @param search_text [String] Object name or ID
|
11
|
+
# @param with_password [Boolean] Fetch the password along with the object details (default: false)
|
12
|
+
# @return [Hash, NilClass]
|
4
13
|
def find( search_text, with_password: false )
|
5
14
|
show( search_text, with_passwords: with_password )&.first
|
6
15
|
end
|
7
16
|
|
17
|
+
# Find all objects by name or by ID
|
18
|
+
#
|
19
|
+
# @note By default, with no params specified, all objects will be returned.
|
20
|
+
# @param search_text [String] Object name or ID (can pass in regex like '.*')
|
21
|
+
# @param with_passwords [Boolean] Fetch the password along with the object details (default: false)
|
22
|
+
# @return [Array<Hash>]
|
8
23
|
def find_all( search_text = '.*', with_passwords: false )
|
9
24
|
show( search_text, with_passwords: with_passwords, regex: true ) || []
|
10
25
|
end
|
data/lib/lastpass-api/group.rb
CHANGED
@@ -1,13 +1,22 @@
|
|
1
1
|
module Lastpass
|
2
|
+
|
3
|
+
# Interact with a Lastpass group/folder
|
2
4
|
class Group
|
3
5
|
attr_reader :id
|
4
6
|
attr_accessor :name
|
5
7
|
|
8
|
+
# @param params [Hash]
|
6
9
|
def initialize( params )
|
7
10
|
params[:name].chomp!( '/' ) if params[:name]&.end_with? '/'
|
8
11
|
params_to_group( params )
|
9
12
|
end
|
10
13
|
|
14
|
+
# Update the group details
|
15
|
+
#
|
16
|
+
# @param params [Hash]
|
17
|
+
# @example
|
18
|
+
# group = @lastpass.groups.find( 'Group1' )
|
19
|
+
# group.update( name: 'Group1 EDIT' )
|
11
20
|
def update( params )
|
12
21
|
deleted! if @deleted
|
13
22
|
params.delete( :id ) # Prevent overwriting ID
|
@@ -15,6 +24,14 @@ module Lastpass
|
|
15
24
|
save
|
16
25
|
end
|
17
26
|
|
27
|
+
# Either create or update a group, depending on what
|
28
|
+
# was changed on the group object before this method was called.
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# # Update using instance variables
|
32
|
+
# group = @lastpass.groups.find( 'Group1' )
|
33
|
+
# group.name = 'Group1 EDIT'
|
34
|
+
# group.save
|
18
35
|
def save
|
19
36
|
deleted! if @deleted
|
20
37
|
# If there is an ID, update that entry
|
@@ -27,11 +44,22 @@ module Lastpass
|
|
27
44
|
self
|
28
45
|
end
|
29
46
|
|
47
|
+
# Delete the group
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# group = @lastpass.groups.find( 1234 )
|
51
|
+
# group.delete
|
30
52
|
def delete
|
31
53
|
Cli.rm( @id )
|
32
54
|
@deleted = true
|
33
55
|
end
|
34
56
|
|
57
|
+
# Hash representation of the account object
|
58
|
+
#
|
59
|
+
# @return [Hash]
|
60
|
+
# @example
|
61
|
+
# puts group.to_h
|
62
|
+
# # => { id: '1234', name: 'Group1' }
|
35
63
|
def to_hash
|
36
64
|
params = {}
|
37
65
|
params[:id] = @id if @id
|
@@ -42,6 +70,8 @@ module Lastpass
|
|
42
70
|
alias_method :to_h, :to_hash
|
43
71
|
|
44
72
|
# Hide instance variables and values
|
73
|
+
#
|
74
|
+
# @api private
|
45
75
|
def inspect
|
46
76
|
original_inspect = super
|
47
77
|
original_inspect.split( ' ' ).first << '>'
|
data/lib/lastpass-api/groups.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
module Lastpass
|
2
|
+
|
3
|
+
# Interact with Lastpass groups/folders
|
2
4
|
class Groups < Collection
|
3
5
|
|
6
|
+
# Find a specific group by name or by ID
|
7
|
+
#
|
8
|
+
# @param search_text [String] Group name or ID
|
9
|
+
# @param with_password [Boolean] Fetch the account passwords along with the group details (default: false)
|
10
|
+
# @return [Lastpass::Group, NilClass]
|
11
|
+
# @example
|
12
|
+
# # Find a specific group by name
|
13
|
+
# group = @lastpass.groups.find( 'Group1' )
|
14
|
+
#
|
15
|
+
# # Find a specific group by ID
|
16
|
+
# group = @lastpass.groups.find( '1234' )
|
4
17
|
def find( search_text, with_password: false )
|
5
18
|
search_text.to_s.gsub!( '/', '' )
|
6
19
|
search_text << '/' unless is_number?( search_text )
|
@@ -10,6 +23,20 @@ module Lastpass
|
|
10
23
|
end
|
11
24
|
end
|
12
25
|
|
26
|
+
# Find all groups by name or by ID
|
27
|
+
#
|
28
|
+
# @note By default, with no params specified, all groups will be returned.
|
29
|
+
# @param search_text [String] Group name or ID (can pass in regex like '.*')
|
30
|
+
# @param with_passwords [Boolean] Fetch the account passwords along with the group details (default: false)
|
31
|
+
# @return [Array<Lastpass::Group>]
|
32
|
+
# @example
|
33
|
+
# # Find all groups that match string (or regex)
|
34
|
+
# groups = @lastpass.groups.find_all( 'Gro' )
|
35
|
+
# puts groups.count
|
36
|
+
# puts groups.first.to_h
|
37
|
+
#
|
38
|
+
# # Fetch all groups - same as find_all( '.*' )
|
39
|
+
# @lastpass.groups.find_all
|
13
40
|
def find_all( search_text = '.*', with_passwords: false )
|
14
41
|
groups = super.select { |params| params[:name]&.end_with? '/' }
|
15
42
|
groups.map do |params|
|
@@ -17,12 +44,21 @@ module Lastpass
|
|
17
44
|
end
|
18
45
|
end
|
19
46
|
|
47
|
+
# Create a new group
|
48
|
+
#
|
49
|
+
# @param params [Hash]
|
50
|
+
# @return [Lastpass::Group]
|
51
|
+
# @example
|
52
|
+
# group = @lastpass.groups.create( name: 'Group1' )
|
53
|
+
# puts group.id
|
20
54
|
def create( params )
|
21
55
|
params.delete( :id ) # Prevent overwriting ID
|
22
56
|
Group.new( params ).save
|
23
57
|
end
|
24
58
|
|
25
59
|
# Hide instance variables and values
|
60
|
+
#
|
61
|
+
# @api private
|
26
62
|
def inspect
|
27
63
|
original_inspect = super
|
28
64
|
original_inspect.split( ' ' ).first << '>'
|
data/lib/lastpass-api/parser.rb
CHANGED
@@ -1,16 +1,29 @@
|
|
1
1
|
module Lastpass
|
2
|
+
|
3
|
+
# Internal class for parsing through Lastpass raw output
|
4
|
+
#
|
5
|
+
# @api private
|
2
6
|
class Parser
|
3
7
|
|
8
|
+
# Method to interact directly with parser
|
9
|
+
#
|
10
|
+
# @param raw_string [String] Lastpass CLI response string
|
11
|
+
# @param with_passwords [Boolean] Whether or not to return passwords
|
12
|
+
# @return [Array<Hash>]
|
4
13
|
def self.parse( raw_string, with_passwords: false )
|
5
14
|
new( raw_string, with_passwords: with_passwords ).parse_all
|
6
15
|
end
|
7
16
|
|
17
|
+
# @param (see parse)
|
8
18
|
def initialize( raw_string, with_passwords: false )
|
9
19
|
@raw_string = raw_string
|
10
20
|
@with_passwords = with_passwords
|
11
21
|
@all = {}
|
12
22
|
end
|
13
23
|
|
24
|
+
# Parse through all lines in raw output
|
25
|
+
#
|
26
|
+
# @return [Array<Hash>]
|
14
27
|
def parse_all
|
15
28
|
@raw_string.split( "\n" ).each do |line|
|
16
29
|
parse_line( line )
|
@@ -19,6 +32,8 @@ module Lastpass
|
|
19
32
|
end
|
20
33
|
|
21
34
|
# Hide instance variables and values
|
35
|
+
#
|
36
|
+
# @api private
|
22
37
|
def inspect
|
23
38
|
original_inspect = super
|
24
39
|
original_inspect.split( ' ' ).first << '>'
|
data/lib/lastpass-api/utils.rb
CHANGED
@@ -2,9 +2,18 @@ require 'colorize'
|
|
2
2
|
require 'open3'
|
3
3
|
|
4
4
|
module Lastpass
|
5
|
+
|
6
|
+
# Internal utility class
|
7
|
+
#
|
8
|
+
# @api private
|
5
9
|
class Utils
|
6
10
|
|
7
11
|
# Run a command
|
12
|
+
#
|
13
|
+
# @param command [String]
|
14
|
+
# @param output [Boolean] Print command output on stdout (default: false)
|
15
|
+
# @raise [StandardError] if execution of command has errors
|
16
|
+
# @return [String] Command output
|
8
17
|
def self.cmd( command, output: false )
|
9
18
|
puts "RUN COMMAND: #{command}".green if Lastpass.verbose
|
10
19
|
@stdout = ''
|
data/lib/lastpass-api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lastpass-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Terry
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|