acm 0.7.0 → 0.8.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/.gitignore +11 -10
- data/.travis.yml +4 -4
- data/Gemfile +6 -6
- data/LICENSE.txt +22 -22
- data/README.md +129 -108
- data/Rakefile +1 -1
- data/acm.gemspec +34 -34
- data/bin/console +14 -14
- data/bin/setup +7 -7
- data/exe/acm +284 -211
- data/lib/acm/version.rb +3 -3
- data/lib/acm.rb +5 -5
- metadata +10 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b8a6ae6c1c5af67e6343fd6c25e0cddbd9d1d2038f57d961e7c681d7edf7ffda
|
|
4
|
+
data.tar.gz: 2144945bb16411304ee5018d56410f07c7fdde7c0ce5ba406fd07b2cee1f451e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b4bcf239d333fc8beaca52ff8091fae3461b4b2c1b43e1d9fba96ecca20cb2d553a40299a0055a8c0a184753e223ef933a1a0c3efe5acad138df8bc019090784
|
|
7
|
+
data.tar.gz: ed121534dc47e3ce0e4b918841687e57b33ca5e3d5e4d16056fce3f9ec6fe452d46844704f461d458c97e0a8944f61bae5ca06612bbcf9e5d844cc0e014045dc
|
data/.gitignore
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
/.bundle/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/
|
|
5
|
-
/
|
|
6
|
-
/
|
|
7
|
-
/
|
|
8
|
-
/
|
|
9
|
-
/
|
|
10
|
-
|
|
1
|
+
/.bundle/
|
|
2
|
+
/vendor/
|
|
3
|
+
/.yardoc
|
|
4
|
+
/Gemfile.lock
|
|
5
|
+
/_yardoc/
|
|
6
|
+
/coverage/
|
|
7
|
+
/doc/
|
|
8
|
+
/pkg/
|
|
9
|
+
/spec/reports/
|
|
10
|
+
/tmp/
|
|
11
|
+
.ruby-version
|
data/.travis.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
language: ruby
|
|
2
|
-
rvm:
|
|
3
|
-
- 2.1.7
|
|
4
|
-
before_install: gem install bundler -v 1.10.6
|
|
1
|
+
language: ruby
|
|
2
|
+
rvm:
|
|
3
|
+
- 2.1.7
|
|
4
|
+
before_install: gem install bundler -v 1.10.6
|
data/Gemfile
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
source 'https://rubygems.org'
|
|
2
|
-
|
|
3
|
-
# Specify your gem's dependencies in acm.gemspec
|
|
4
|
-
gemspec
|
|
5
|
-
|
|
6
|
-
gem "ffi", :platforms => [:mswin, :mingw, :x64_mingw]
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
# Specify your gem's dependencies in acm.gemspec
|
|
4
|
+
gemspec
|
|
5
|
+
|
|
6
|
+
gem "ffi", :platforms => [:mswin, :mingw, :x64_mingw]
|
data/LICENSE.txt
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
Copyright (c) 2015-2020 takatoh
|
|
2
|
-
|
|
3
|
-
MIT License
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
-
a copy of this software and associated documentation files (the
|
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
-
the following conditions:
|
|
12
|
-
|
|
13
|
-
The above copyright notice and this permission notice shall be
|
|
14
|
-
included in all copies or substantial portions of the Software.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
Copyright (c) 2015-2020 takatoh
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,108 +1,129 @@
|
|
|
1
|
-
# acm
|
|
2
|
-
|
|
3
|
-
A simple account manager. This is NOT secure, excuse me ;p.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## Installation
|
|
7
|
-
|
|
8
|
-
Install it yourself as:
|
|
9
|
-
|
|
10
|
-
> gem install acm
|
|
11
|
-
|
|
12
|
-
If you are using Windows, please install ffi gem:
|
|
13
|
-
|
|
14
|
-
> gem install ffi
|
|
15
|
-
|
|
16
|
-
## Usage
|
|
17
|
-
|
|
18
|
-
At first, init database:
|
|
19
|
-
|
|
20
|
-
> acm init
|
|
21
|
-
|
|
22
|
-
The database file is saved as "ENV['ACMDB']" or "ENV['HOME']/.accounts", in YAML.
|
|
23
|
-
Set location of database file to environment variable 'ACMDB', if you
|
|
24
|
-
|
|
25
|
-
Add account:
|
|
26
|
-
|
|
27
|
-
> acm add takatoh.m@gmail.com
|
|
28
|
-
(acm) Key? email
|
|
29
|
-
(acm) Value? takatoh.m@gmail.com
|
|
30
|
-
(acm) Key? password
|
|
31
|
-
(acm) Value? xxxxxxxx
|
|
32
|
-
(acm) Key? # Enter to exit.
|
|
33
|
-
|
|
34
|
-
Then added account to database.
|
|
35
|
-
|
|
36
|
-
List account(s):
|
|
37
|
-
|
|
38
|
-
> acm list
|
|
39
|
-
takatoh.m@gmail.com
|
|
40
|
-
|
|
41
|
-
Search account(s):
|
|
42
|
-
|
|
43
|
-
> acm search gmail
|
|
44
|
-
takatoh.m@gmail.com
|
|
45
|
-
|
|
46
|
-
Show details:
|
|
47
|
-
|
|
48
|
-
> acm show takatoh.m@gmail.com
|
|
49
|
-
Account: takatoh.m@gmail.com
|
|
50
|
-
email: takatoh.m@gmail.com
|
|
51
|
-
password: ******
|
|
52
|
-
|
|
53
|
-
In default, value of password is masked. If you see the password, give
|
|
54
|
-
Or
|
|
55
|
-
|
|
56
|
-
Update value of key:
|
|
57
|
-
|
|
58
|
-
> acm update takatoh.m@gmail.com password yyyyyyyy
|
|
59
|
-
|
|
60
|
-
> acm show --pass takatoh.m@gmail.com
|
|
61
|
-
Account: takatoh.m@gmail.com
|
|
62
|
-
email: takatoh.m@gmail.com
|
|
63
|
-
password: yyyyyyyy
|
|
64
|
-
|
|
65
|
-
Remove key and value:
|
|
66
|
-
|
|
67
|
-
> acm remove-key takatoh.m@gmail.com password
|
|
68
|
-
|
|
69
|
-
> acm show takatoh.m@gmail.com
|
|
70
|
-
Account: takatoh.m@gmail.com
|
|
71
|
-
email: takatoh.m@gmail.com
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
> acm
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
1
|
+
# acm
|
|
2
|
+
|
|
3
|
+
A simple account manager. This is NOT secure, excuse me ;p.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Install it yourself as:
|
|
9
|
+
|
|
10
|
+
> gem install acm
|
|
11
|
+
|
|
12
|
+
If you are using Windows, please install ffi gem:
|
|
13
|
+
|
|
14
|
+
> gem install ffi
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
At first, init database:
|
|
19
|
+
|
|
20
|
+
> acm init
|
|
21
|
+
|
|
22
|
+
The database file is saved as "ENV['ACMDB']" or "ENV['HOME']/.accounts", in YAML.
|
|
23
|
+
Set location of database file to environment variable 'ACMDB', if you need.
|
|
24
|
+
|
|
25
|
+
Add account:
|
|
26
|
+
|
|
27
|
+
> acm add takatoh.m@gmail.com
|
|
28
|
+
(acm) Key? email
|
|
29
|
+
(acm) Value? takatoh.m@gmail.com
|
|
30
|
+
(acm) Key? password
|
|
31
|
+
(acm) Value? xxxxxxxx
|
|
32
|
+
(acm) Key? # Enter to exit.
|
|
33
|
+
|
|
34
|
+
Then added account to database.
|
|
35
|
+
|
|
36
|
+
List account(s):
|
|
37
|
+
|
|
38
|
+
> acm list
|
|
39
|
+
takatoh.m@gmail.com
|
|
40
|
+
|
|
41
|
+
Search account(s):
|
|
42
|
+
|
|
43
|
+
> acm search gmail
|
|
44
|
+
takatoh.m@gmail.com
|
|
45
|
+
|
|
46
|
+
Show details:
|
|
47
|
+
|
|
48
|
+
> acm show takatoh.m@gmail.com
|
|
49
|
+
Account: takatoh.m@gmail.com
|
|
50
|
+
email: takatoh.m@gmail.com
|
|
51
|
+
password: ******
|
|
52
|
+
|
|
53
|
+
In default, value of `password` is masked. If you need to see the password, give `--pass` option.
|
|
54
|
+
Or `--clip` option copies the password to clipboard.
|
|
55
|
+
|
|
56
|
+
Update value of key:
|
|
57
|
+
|
|
58
|
+
> acm update takatoh.m@gmail.com password yyyyyyyy
|
|
59
|
+
|
|
60
|
+
> acm show --pass takatoh.m@gmail.com
|
|
61
|
+
Account: takatoh.m@gmail.com
|
|
62
|
+
email: takatoh.m@gmail.com
|
|
63
|
+
password: yyyyyyyy
|
|
64
|
+
|
|
65
|
+
Remove key and value:
|
|
66
|
+
|
|
67
|
+
> acm remove-key takatoh.m@gmail.com password
|
|
68
|
+
|
|
69
|
+
> acm show takatoh.m@gmail.com
|
|
70
|
+
Account: takatoh.m@gmail.com
|
|
71
|
+
email: takatoh.m@gmail.com
|
|
72
|
+
|
|
73
|
+
Create alias for account:
|
|
74
|
+
|
|
75
|
+
> acm alias google takatoh.m@gmail.com
|
|
76
|
+
Create alias: google for takatoh.m@gmail.com
|
|
77
|
+
|
|
78
|
+
> acm show google
|
|
79
|
+
NOTE: 'google' is alias for 'takatoh.m@gmail.com'.
|
|
80
|
+
Account: takatoh.m@gmail.com
|
|
81
|
+
email: takatoh.m@gmail.com
|
|
82
|
+
|
|
83
|
+
Rename account:
|
|
84
|
+
|
|
85
|
+
> acm rename-account takatoh.m@gmail.com Gmail
|
|
86
|
+
|
|
87
|
+
> acm show Gmail
|
|
88
|
+
Account: Gmail
|
|
89
|
+
email: takatoh.m@gmail.com
|
|
90
|
+
|
|
91
|
+
The alias tracks account name changes.
|
|
92
|
+
|
|
93
|
+
> acm show google
|
|
94
|
+
NOTE: 'google' is alias for 'Gmail'.
|
|
95
|
+
Account: Ggmail
|
|
96
|
+
email: takatoh.m@gmail.com
|
|
97
|
+
|
|
98
|
+
And remove account:
|
|
99
|
+
|
|
100
|
+
> acm remove-account Gmail
|
|
101
|
+
Account: Gmail
|
|
102
|
+
email: takatoh.m@gmail.com
|
|
103
|
+
|
|
104
|
+
Are you sure?(y/n) y # Enter 'y' to remove.
|
|
105
|
+
|
|
106
|
+
> acm show Gmail
|
|
107
|
+
No such account: Gmail
|
|
108
|
+
|
|
109
|
+
The alias is also removed.
|
|
110
|
+
|
|
111
|
+
> acm show google
|
|
112
|
+
No such account: google
|
|
113
|
+
|
|
114
|
+
## Special key: login-with
|
|
115
|
+
|
|
116
|
+
Special key `login-with` is reference to other account.
|
|
117
|
+
|
|
118
|
+
> acm add SomeWebService
|
|
119
|
+
(acm) Key? login-with
|
|
120
|
+
(acm) Value? GitHub
|
|
121
|
+
(acm) Key? # Enter to exit.
|
|
122
|
+
|
|
123
|
+
To track reference, use `acm show` command with `--track` option.
|
|
124
|
+
|
|
125
|
+
> acm show --track SomeWebService
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT License
|
data/Rakefile
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
require "bundler/gem_tasks"
|
|
1
|
+
require "bundler/gem_tasks"
|
data/acm.gemspec
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require 'acm/version'
|
|
5
|
-
|
|
6
|
-
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name = "acm"
|
|
8
|
-
spec.version = Acm::VERSION
|
|
9
|
-
spec.authors = ["takatoh"]
|
|
10
|
-
spec.email = ["takatoh.m@gmail.com"]
|
|
11
|
-
|
|
12
|
-
spec.summary = %q{A simple account manager (NOT SECURE ;p).}
|
|
13
|
-
spec.description = %q{}
|
|
14
|
-
spec.homepage = "https://github.com/takatoh/acm"
|
|
15
|
-
spec.license = "MIT"
|
|
16
|
-
|
|
17
|
-
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
|
18
|
-
# delete this section to allow pushing this gem to any host.
|
|
19
|
-
# if spec.respond_to?(:metadata)
|
|
20
|
-
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
|
21
|
-
# else
|
|
22
|
-
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
|
23
|
-
# end
|
|
24
|
-
|
|
25
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
-
spec.bindir = "exe"
|
|
27
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
28
|
-
spec.require_paths = ["lib"]
|
|
29
|
-
|
|
30
|
-
spec.add_development_dependency "bundler", "~> 2.
|
|
31
|
-
spec.add_development_dependency "rake", ">=
|
|
32
|
-
spec.add_runtime_dependency "thor"
|
|
33
|
-
spec.add_runtime_dependency "clipboard"
|
|
34
|
-
end
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'acm/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "acm"
|
|
8
|
+
spec.version = Acm::VERSION
|
|
9
|
+
spec.authors = ["takatoh"]
|
|
10
|
+
spec.email = ["takatoh.m@gmail.com"]
|
|
11
|
+
|
|
12
|
+
spec.summary = %q{A simple account manager (NOT SECURE ;p).}
|
|
13
|
+
spec.description = %q{}
|
|
14
|
+
spec.homepage = "https://github.com/takatoh/acm"
|
|
15
|
+
spec.license = "MIT"
|
|
16
|
+
|
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
|
19
|
+
# if spec.respond_to?(:metadata)
|
|
20
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
|
21
|
+
# else
|
|
22
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
|
23
|
+
# end
|
|
24
|
+
|
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
+
spec.bindir = "exe"
|
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
28
|
+
spec.require_paths = ["lib"]
|
|
29
|
+
|
|
30
|
+
spec.add_development_dependency "bundler", "~> 2.2"
|
|
31
|
+
spec.add_development_dependency "rake", ">= 13.0"
|
|
32
|
+
spec.add_runtime_dependency "thor"
|
|
33
|
+
spec.add_runtime_dependency "clipboard"
|
|
34
|
+
end
|
data/bin/console
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require "bundler/setup"
|
|
4
|
-
require "acm"
|
|
5
|
-
|
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
-
|
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
-
# require "pry"
|
|
11
|
-
# Pry.start
|
|
12
|
-
|
|
13
|
-
require "irb"
|
|
14
|
-
IRB.start
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "acm"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start
|
data/bin/setup
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
IFS=$'\n\t'
|
|
4
|
-
|
|
5
|
-
bundle install
|
|
6
|
-
|
|
7
|
-
# Do any other automated setup that you need to do here
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
IFS=$'\n\t'
|
|
4
|
+
|
|
5
|
+
bundle install
|
|
6
|
+
|
|
7
|
+
# Do any other automated setup that you need to do here
|
data/exe/acm
CHANGED
|
@@ -1,211 +1,284 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# -*- encoding: utf-8 -*-
|
|
3
|
-
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if key
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
db
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
puts "
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
puts "
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def
|
|
179
|
-
db
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# -*- encoding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
require "acm"
|
|
5
|
+
require "thor"
|
|
6
|
+
require "yaml"
|
|
7
|
+
require "clipboard"
|
|
8
|
+
require "fileutils"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AcmCLI < Thor
|
|
12
|
+
|
|
13
|
+
DB_FILE = ENV['ACMDB'] || "#{ENV['HOME']}/.accounts"
|
|
14
|
+
REFERENCE_KEY = "login-with"
|
|
15
|
+
|
|
16
|
+
desc "init", "Init database"
|
|
17
|
+
def init
|
|
18
|
+
if File.exist?(DB_FILE)
|
|
19
|
+
puts "Database file is already exist."
|
|
20
|
+
else
|
|
21
|
+
init_db
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
desc "add ACCOUNT", "Add ACCOUNT"
|
|
26
|
+
def add(account)
|
|
27
|
+
db = load_db
|
|
28
|
+
ac = lookup(account, db)
|
|
29
|
+
if ac
|
|
30
|
+
puts "Account #{account} is already exist."
|
|
31
|
+
exit 0
|
|
32
|
+
end
|
|
33
|
+
details = {}
|
|
34
|
+
ac = {
|
|
35
|
+
"account" => account,
|
|
36
|
+
"details" => details
|
|
37
|
+
}
|
|
38
|
+
while true
|
|
39
|
+
print "(acm) Key? "
|
|
40
|
+
key = STDIN.gets.chomp.strip
|
|
41
|
+
break if key.empty?
|
|
42
|
+
if key == "login-with"
|
|
43
|
+
while true
|
|
44
|
+
print "(acm) Value? "
|
|
45
|
+
value = STDIN.gets.chomp.strip
|
|
46
|
+
ref_account = lookup(value, db)
|
|
47
|
+
if ref_account
|
|
48
|
+
break
|
|
49
|
+
else
|
|
50
|
+
puts "#{value} not exist."
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
else
|
|
54
|
+
print "(acm) Value? "
|
|
55
|
+
value = STDIN.gets.chomp.strip
|
|
56
|
+
end
|
|
57
|
+
details[key] = value
|
|
58
|
+
end
|
|
59
|
+
db << ac
|
|
60
|
+
save_db(db)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
desc "list", "List accounts"
|
|
64
|
+
def list
|
|
65
|
+
db = load_db
|
|
66
|
+
db.sort_by{|a| a['account'] }.each do |a|
|
|
67
|
+
if a['alias_for']
|
|
68
|
+
puts "#{a['account']} -> #{a['alias_for']}"
|
|
69
|
+
else
|
|
70
|
+
puts a['account']
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
desc "search PATTERN", "Search accounts by PATTERN"
|
|
76
|
+
def search(target)
|
|
77
|
+
db = load_db
|
|
78
|
+
accounts = search_accounts(target, db)
|
|
79
|
+
if accounts.empty?
|
|
80
|
+
puts "Not found: #{target}"
|
|
81
|
+
else
|
|
82
|
+
accounts.each do |a|
|
|
83
|
+
if a['alias_for']
|
|
84
|
+
puts "#{a['account']} -> #{a['alias_for']}"
|
|
85
|
+
else
|
|
86
|
+
puts a['account']
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
desc "show [options] ACCOUNT", "Show details of ACCOUNT"
|
|
93
|
+
option :pass, :type => :boolean, :aliases => "-p", :desc => "Show password"
|
|
94
|
+
option :clip, :type => :boolean, :aliases => "-c", :desc => "Copy password to clipboard"
|
|
95
|
+
option :track, :type => :boolean, :aliases => "-t", :desc => "Track referred account"
|
|
96
|
+
def show(target)
|
|
97
|
+
db = load_db
|
|
98
|
+
account = lookup(target.encode("utf-8"), db)
|
|
99
|
+
if account && account['alias_for']
|
|
100
|
+
account = lookup(account['alias_for'], db)
|
|
101
|
+
puts "NOTE: '#{target}' is alias for '#{account['account']}'."
|
|
102
|
+
end
|
|
103
|
+
if account
|
|
104
|
+
puts "Account: #{account['account']}"
|
|
105
|
+
print_details(account['details'], options[:pass])
|
|
106
|
+
copy_password(account['details'], options[:clip])
|
|
107
|
+
if options[:track] && account['details'][REFERENCE_KEY]
|
|
108
|
+
ref_account = lookup(account['details'][REFERENCE_KEY], db)
|
|
109
|
+
if ref_account
|
|
110
|
+
puts "\nReference: #{ref_account['account']}"
|
|
111
|
+
print_details(ref_account['details'], options[:pass])
|
|
112
|
+
copy_password(ref_account['details'], options[:clip])
|
|
113
|
+
else
|
|
114
|
+
puts "\nReference not found: #{account['details'][REFERENCE_KEY]}"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
else
|
|
118
|
+
puts "No such account: #{target}"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
desc "update ACCOUNT KEY VALUE", "Update value of KEY in ACCOUNT"
|
|
123
|
+
def update(target, key, value)
|
|
124
|
+
db = load_db
|
|
125
|
+
account = lookup(target.encode("utf-8"), db)
|
|
126
|
+
if account
|
|
127
|
+
account['details'][key] = value
|
|
128
|
+
save_db(db)
|
|
129
|
+
else
|
|
130
|
+
puts "No such account: #{target}"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
desc "remove-key ACCOUNT KEY", "Remove KEY and value in ACCOUNT"
|
|
135
|
+
def remove_key(target, key)
|
|
136
|
+
db = load_db
|
|
137
|
+
account = lookup(target.encode("utf-8"), db)
|
|
138
|
+
if account
|
|
139
|
+
account['details'].delete(key)
|
|
140
|
+
save_db(db)
|
|
141
|
+
else
|
|
142
|
+
puts "No such account: #{target}"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
desc "remove-account ACCOUNT", "Remove ACCOUNT"
|
|
147
|
+
def remove_account(target)
|
|
148
|
+
db = load_db
|
|
149
|
+
account = lookup(target.encode("utf-8"), db)
|
|
150
|
+
if account
|
|
151
|
+
if account['alias_for']
|
|
152
|
+
puts "INFO: '#{target}' is alias for '#{account['alias_for']}'."
|
|
153
|
+
puts "Please run 'acm remove-account #{account['alias_for']}' to remove."
|
|
154
|
+
exit(0)
|
|
155
|
+
end
|
|
156
|
+
puts "Account: #{target}"
|
|
157
|
+
account['details'].each do |k, v|
|
|
158
|
+
puts " #{k}: #{v}"
|
|
159
|
+
end
|
|
160
|
+
aliases = search_alias(target.encode("utf-8"), db)
|
|
161
|
+
if aliases.size > 0
|
|
162
|
+
puts "Aliases: " + aliases.map{|al| al['account'] }.join(", ")
|
|
163
|
+
end
|
|
164
|
+
print "\nAre you sure?(y/n) "
|
|
165
|
+
if STDIN.gets.chomp.downcase == "y"
|
|
166
|
+
db.reject!{|ac| ac['account'] == target.encode("utf-8") }
|
|
167
|
+
aliases.each do |al|
|
|
168
|
+
db.reject!{|ac| ac['account'] == al['account'] }
|
|
169
|
+
end
|
|
170
|
+
save_db(db)
|
|
171
|
+
end
|
|
172
|
+
else
|
|
173
|
+
puts "No such account: #{target}"
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
desc "rename-account OLD NEW", "Rename ACCOUNT"
|
|
178
|
+
def rename_account(old, new)
|
|
179
|
+
db = load_db
|
|
180
|
+
account = lookup(old.encode("utf-8"), db)
|
|
181
|
+
if account
|
|
182
|
+
puts "Account: #{old} -> #{new}"
|
|
183
|
+
aliases = search_alias(old.encode("utf-8"), db)
|
|
184
|
+
account['account'] = new.encode("utf-8")
|
|
185
|
+
aliases.each{|al| al['alias_for'] = new.encode("utf-8") }
|
|
186
|
+
save_db(db)
|
|
187
|
+
else
|
|
188
|
+
puts "No such account: #{old}"
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
desc "env", "Display Environments"
|
|
193
|
+
def env
|
|
194
|
+
puts "Database file: #{DB_FILE}"
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
desc "alias ALIAS ACCOUNT", "Create an ALIAS for ACCOUNT"
|
|
198
|
+
def alias(from, dest)
|
|
199
|
+
db = load_db
|
|
200
|
+
ac = lookup(dest.encode("utf-8"), db)
|
|
201
|
+
if ac
|
|
202
|
+
puts "Create alias: #{from} for #{dest}"
|
|
203
|
+
al = {
|
|
204
|
+
"account" => from,
|
|
205
|
+
"alias_for" => ac['account']
|
|
206
|
+
}
|
|
207
|
+
db << al
|
|
208
|
+
save_db(db)
|
|
209
|
+
else
|
|
210
|
+
puts "No such account: #{dest}"
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
desc "remove-alias ALIAS", "Remove ALIAS"
|
|
215
|
+
def remove_alias(target)
|
|
216
|
+
db = load_db
|
|
217
|
+
ac = lookup(target.encode("utf-8"), db)
|
|
218
|
+
if ac
|
|
219
|
+
puts "Remove alias: #{target}"
|
|
220
|
+
db.reject!{|a| a['account'] == target.encode("utf-8") }
|
|
221
|
+
save_db(db)
|
|
222
|
+
else
|
|
223
|
+
puts "No such alias: #{target}"
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
desc "version", "Show version and exit"
|
|
228
|
+
def version
|
|
229
|
+
puts "v#{Acm::VERSION}"
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
private
|
|
234
|
+
|
|
235
|
+
def init_db
|
|
236
|
+
File.open(DB_FILE, "w"){|f| f.puts [].to_yaml }
|
|
237
|
+
FileUtils.chmod(0600, DB_FILE)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def load_db
|
|
241
|
+
YAML.load_file(DB_FILE)
|
|
242
|
+
rescue
|
|
243
|
+
puts "Error: Not found database file."
|
|
244
|
+
exit(1)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def lookup(target, db)
|
|
248
|
+
db.find{|a| a['account'] == target }
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def save_db(db)
|
|
252
|
+
File.open(DB_FILE, "w"){|f| f.puts db.to_yaml }
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def search_accounts(target, db)
|
|
256
|
+
pattern = /#{target.encode("utf-8")}/i
|
|
257
|
+
db.select{|a| pattern =~ a['account'].tr(" ", "") }
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def search_alias(target, db)
|
|
261
|
+
db.select{|a| target == a['alias_for'] }
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def print_details(details, pass = false)
|
|
265
|
+
details.each do |key, val|
|
|
266
|
+
if /pass/ =~ key && !pass
|
|
267
|
+
puts " #{key}: ******"
|
|
268
|
+
else
|
|
269
|
+
puts " #{key}: #{val}"
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def copy_password(details, clip = false)
|
|
275
|
+
if clip
|
|
276
|
+
password_key = details.keys.select{|k| /pass/ =~ k}.first
|
|
277
|
+
Clipboard.copy(details[password_key])
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
end # of class AcmCLI
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
AcmCLI.start(ARGV)
|
data/lib/acm/version.rb
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
module Acm
|
|
2
|
-
VERSION = "0.
|
|
3
|
-
end
|
|
1
|
+
module Acm
|
|
2
|
+
VERSION = "0.8.0"
|
|
3
|
+
end
|
data/lib/acm.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require "acm/version"
|
|
2
|
-
|
|
3
|
-
module Acm
|
|
4
|
-
# Your code goes here...
|
|
5
|
-
end
|
|
1
|
+
require "acm/version"
|
|
2
|
+
|
|
3
|
+
module Acm
|
|
4
|
+
# Your code goes here...
|
|
5
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: acm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- takatoh
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-02-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -16,28 +16,28 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '2.
|
|
19
|
+
version: '2.2'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '2.
|
|
26
|
+
version: '2.2'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
33
|
+
version: '13.0'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
40
|
+
version: '13.0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: thor
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -90,7 +90,7 @@ homepage: https://github.com/takatoh/acm
|
|
|
90
90
|
licenses:
|
|
91
91
|
- MIT
|
|
92
92
|
metadata: {}
|
|
93
|
-
post_install_message:
|
|
93
|
+
post_install_message:
|
|
94
94
|
rdoc_options: []
|
|
95
95
|
require_paths:
|
|
96
96
|
- lib
|
|
@@ -105,8 +105,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
105
105
|
- !ruby/object:Gem::Version
|
|
106
106
|
version: '0'
|
|
107
107
|
requirements: []
|
|
108
|
-
rubygems_version: 3.
|
|
109
|
-
signing_key:
|
|
108
|
+
rubygems_version: 3.2.33
|
|
109
|
+
signing_key:
|
|
110
110
|
specification_version: 4
|
|
111
111
|
summary: A simple account manager (NOT SECURE ;p).
|
|
112
112
|
test_files: []
|