pmng/src/pmng.cr

212 lines
5.9 KiB
Crystal
Raw Normal View History

2022-01-03 23:32:49 +03:00
require "option_parser"
2022-01-03 21:21:30 +03:00
require "yaml"
require "colorize"
2022-03-15 01:42:17 +03:00
# password serializer
2022-01-03 21:21:30 +03:00
class Password
include YAML::Serializable
@[YAML::Field(key: "url")]
property url : String
@[YAML::Field(key: "email")]
property email : String
@[YAML::Field(key: "login")]
property login : String
@[YAML::Field(key: "password")]
property password : String
@[YAML::Field(key: "desc")]
property desc : String
@[YAML::Field(key: "profile_url")]
property profile_url : String
@[YAML::Field(key: "update")]
property update : Int32
end
2022-07-26 19:16:42 +03:00
VERSION = "0.2.4"
2022-05-02 11:34:18 +03:00
PASSWORD_FILE_PATH = "#{ENV["HOME"]}/.pwd.yml"
ASCII_LOGO = "
2022-05-02 10:41:31 +03:00
"
2022-01-03 21:21:30 +03:00
2022-03-15 01:42:17 +03:00
# program options
2022-01-03 23:47:06 +03:00
begin
OptionParser.parse do |parser|
2022-03-15 01:56:01 +03:00
parser.banner = "The very simple password manager for humans\n"
2022-01-03 23:32:49 +03:00
2022-01-03 23:47:06 +03:00
parser.on "-v", "--version", "Show version" do
2022-05-02 11:04:29 +03:00
puts ASCII_LOGO.colorize(:yellow)
puts "The very simple password manager for humans.".colorize(:yellow)
print "Version ".colorize(:yellow)
puts VERSION.colorize(:red).mode(:bold)
print "\nURL to full change log: ".colorize(:yellow)
puts "https://git.a2s.su/iiiypuk/pmng/raw/branch/master/HISTORY.md".colorize(:green).mode(:bold)
2022-01-04 00:52:31 +03:00
exit(0)
2022-01-03 23:47:06 +03:00
end
parser.on "-h", "--help", "Show help" do
puts parser
2022-05-02 11:04:29 +03:00
2022-01-04 00:52:31 +03:00
exit(0)
2022-01-03 23:47:06 +03:00
end
parser.on "-g", "--generate-password", "Generate password" do
puts Random::Secure.urlsafe_base64(16, padding: false).colorize(:black).back(:white)
puts Random::Secure.urlsafe_base64(16, padding: false).colorize(:white).back(:blue)
2022-03-13 13:46:29 +03:00
puts Random::Secure.urlsafe_base64(16, padding: false).colorize(:white).back(:red)
2022-05-02 11:04:29 +03:00
2022-01-04 00:52:31 +03:00
exit(0)
2022-01-03 23:47:06 +03:00
end
parser.on "-t", "--unixtime", "Return local timestamp" do
puts Time.local.to_unix.colorize(:yellow).mode(:bold)
2022-05-02 11:04:29 +03:00
2022-01-04 00:52:31 +03:00
exit(0)
2022-01-03 23:47:06 +03:00
end
2022-01-03 23:32:49 +03:00
end
2022-01-03 23:47:06 +03:00
rescue ex
puts ex.message, ""
2022-01-03 23:32:49 +03:00
end
2022-03-15 01:42:17 +03:00
# check password file exists
2022-05-02 10:51:25 +03:00
if File.exists?(PASSWORD_FILE_PATH)
yaml = File.open(PASSWORD_FILE_PATH) do |file|
2022-01-04 22:31:02 +03:00
YAML.parse(file)
end
else
2022-06-26 23:54:21 +03:00
print "~/.pwd.yml".colorize(:red).mode(:bold)
puts ": No such file"
2022-01-03 21:21:30 +03:00
exit(1)
end
2022-04-08 17:35:56 +03:00
# check file ppermissions
2022-05-02 10:51:25 +03:00
password_file_permissions = File.info(PASSWORD_FILE_PATH).permissions.to_s
2022-04-08 17:35:56 +03:00
if /\d{3}/.match(password_file_permissions).try &.[0] != "600"
puts "Password file permissions is not RW for you.".colorize(:red)
2022-07-26 19:16:42 +03:00
print "Execute: ".colorize(:yellow)
print "(chmod 600 ~/.pwd.yml) ".colorize(:green).mode(:bold)
puts "for fix.".colorize(:yellow)
2022-04-08 17:35:56 +03:00
exit(1)
end
2022-05-02 11:34:18 +03:00
# fill passwords array
passwords_array = [] of Password
count = 0
while count < yaml.size
passwords_array << Password.from_yaml(yaml[count].to_yaml)
count += 1
end
2022-04-08 16:38:03 +03:00
# pmng title
system "clear"
2022-05-02 10:41:31 +03:00
puts ASCII_LOGO.colorize(:yellow)
2022-04-08 16:38:03 +03:00
puts "The very simple password manager for humans".colorize(:yellow).mode(:bold)
puts "-------------------------------------------".colorize(:yellow).mode(:bold)
2022-03-15 01:42:17 +03:00
# main loop
2022-01-04 00:30:41 +03:00
loop = true
while loop
2022-03-15 01:42:17 +03:00
# shell prompt
2022-04-08 16:11:44 +03:00
print "Enter URL (".colorize(:white).mode(:bold)
print ":h".colorize(:red).mode(:bold)
print " for help or ".colorize(:white).mode(:bold)
print ":q".colorize(:red).mode(:bold)
print " for exit)\n".colorize(:white).mode(:bold)
2022-04-08 15:59:24 +03:00
print "> ".colorize(:green).mode(:bold)
2022-04-08 16:11:44 +03:00
2022-01-03 21:21:30 +03:00
password_string = gets
if password_string.to_s == ":q"
2022-04-08 17:49:26 +03:00
# if ':q' to close program
2022-05-02 11:34:18 +03:00
loop = false
2022-03-13 13:46:29 +03:00
elsif password_string.to_s.size == 0
2022-04-08 17:49:26 +03:00
# if puts empty, retry prompt
2022-03-13 13:46:29 +03:00
puts
2022-01-03 21:21:30 +03:00
elsif password_string.to_s == ":h"
2022-04-08 17:49:26 +03:00
# if ':h' to view help
system "clear"
puts "Help\n----".colorize(:yellow).mode(:bold)
print ":s".colorize(:red).mode(:bold)
puts " - Return stats"
2022-01-03 21:21:30 +03:00
elsif password_string.to_s == ":s"
2022-04-08 17:49:26 +03:00
# if ':s' to view Statistics
system "clear"
puts "Statistics\n----------".colorize(:yellow).mode(:bold)
print "All elements: ".colorize(:yellow).mode(:bold)
2022-03-15 01:56:01 +03:00
puts passwords_array.size
2022-01-03 21:21:30 +03:00
2022-04-08 17:49:26 +03:00
print "Passwords outdated: ".colorize(:red).mode(:bold)
2022-01-03 23:25:07 +03:00
outdated_count = 0
current_time = Time.local.to_unix
a = [] of String
2022-03-15 01:56:01 +03:00
passwords_array.each do |item|
2022-04-09 22:06:40 +03:00
if item.update + (2629743 * 3) < current_time # 2629743 * 3 -- 3 month
2022-01-03 23:25:07 +03:00
outdated_count += 1
a << item.url
end
end
puts outdated_count
2022-03-13 13:46:29 +03:00
else
2022-04-08 17:49:26 +03:00
# list search password
2022-04-08 16:38:03 +03:00
system "clear"
2022-05-02 10:51:25 +03:00
passwords_finded_array = 0
2022-03-15 01:56:01 +03:00
passwords_array.each do |item|
2022-03-13 13:46:29 +03:00
if item.url.includes?(password_string.to_s)
2022-04-08 16:05:11 +03:00
print "🌐 "
2022-04-08 15:59:24 +03:00
puts item.url.colorize(:magenta).mode(:bold).mode(:underline)
2022-03-13 13:46:29 +03:00
if !item.email.blank?
2022-04-08 16:05:11 +03:00
print "📧 "
2022-03-13 13:46:29 +03:00
puts item.email.colorize(:red)
end
2022-04-08 17:49:26 +03:00
2022-03-13 13:46:29 +03:00
if !item.login.blank?
2022-04-08 17:35:56 +03:00
print "🗿 "
2022-03-13 13:46:29 +03:00
puts item.login.colorize(:yellow)
end
2022-04-08 17:49:26 +03:00
2022-03-13 13:46:29 +03:00
if !item.password.blank?
2022-04-08 16:05:11 +03:00
print "🔐 "
2022-03-13 13:46:29 +03:00
puts item.password.colorize(:red).back(:red)
end
2022-04-08 17:49:26 +03:00
2022-03-13 13:46:29 +03:00
if !item.desc.blank?
2022-04-08 16:05:11 +03:00
print "📄 "
2022-03-13 13:46:29 +03:00
puts item.desc.colorize(:cyan)
end
2022-04-08 17:49:26 +03:00
2022-03-13 13:46:29 +03:00
if !item.profile_url.blank?
2022-04-08 16:05:11 +03:00
print "👦 "
2022-03-13 13:46:29 +03:00
puts item.profile_url.colorize(:green)
end
2022-04-08 15:59:24 +03:00
puts "-----".colorize(:dark_gray).mode(:bold)
2022-05-02 10:51:25 +03:00
passwords_finded_array += 1
2022-01-03 21:21:30 +03:00
end
end
2022-05-21 00:07:33 +03:00
puts
print "Finded ".colorize(:yellow).mode(:bold)
print passwords_finded_array.colorize(:red).mode(:bold)
puts " records".colorize(:yellow).mode(:bold)
puts "-----".colorize(:dark_gray).mode(:bold)
2022-01-03 21:21:30 +03:00
end
puts
end
2022-05-02 11:34:18 +03:00
system "clear"
puts "Bye! 👋"