pmng/src/pmng.cr

148 lines
3.6 KiB
Crystal

require "option_parser"
require "yaml"
require "colorize"
# password serializer
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
VERSION = "0.2.1"
# program options
begin
OptionParser.parse do |parser|
parser.banner = "The very simple password manager for humans\n"
parser.on "-v", "--version", "Show version" do
puts "Version #{VERSION}"
exit(0)
end
parser.on "-h", "--help", "Show help" do
puts parser
exit(0)
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)
puts Random::Secure.urlsafe_base64(16, padding: false).colorize(:white).back(:red)
exit(0)
end
parser.on "-t", "--unixtime", "Return local timestamp" do
puts Time.local.to_unix.colorize(:yellow)
exit(0)
end
end
rescue ex
puts ex.message, ""
end
# password_file_path = PROGRAM_NAME.split("/")
# password_file_path.pop
# password_file_path.insert(-1, "pwd.yml")
# password_file_path = password_file_path.join("/")
# TODO: Fix later
password_file_path = "#{ENV["HOME"]}/.pwd.yml"
# check password file exists
if File.exists?(password_file_path)
yaml = File.open(password_file_path) do |file|
YAML.parse(file)
end
else
puts "No password.yml file exists."
exit(1)
end
# 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
# main loop
loop = true
while loop
# shell prompt
print "Enter URL (or :q for exit)\n"
print "> ".colorize(:green)
password_string = gets
# if ':q' to close program
if password_string.to_s == ":q"
puts "Bye! 👋🏻"
exit(0)
# if puts empty, retry prompt
elsif password_string.to_s.size == 0
puts
# if ':h' to view help
elsif password_string.to_s == ":h"
puts "Help:\n-----"
puts ":s - Return stats"
# if ':s' to view Statistics
elsif password_string.to_s == ":s"
puts "Statistics:\n----------"
print "Elements: ".colorize(:yellow)
puts passwords_array.size
print "Outdated: ".colorize(:red)
outdated_count = 0
current_time = Time.local.to_unix
a = [] of String
passwords_array.each do |item|
if item.update + (2629743 * 2) < current_time # 2629743 * 2 -- 2 month
outdated_count += 1
a << item.url
end
end
puts outdated_count
# list search password
else
passwords_array.each do |item|
if item.url.includes?(password_string.to_s)
puts item.url.colorize(:magenta).mode(:blink)
if !item.email.blank?
puts item.email.colorize(:red)
end
if !item.login.blank?
puts item.login.colorize(:yellow)
end
if !item.password.blank?
puts item.password.colorize(:red).back(:red)
end
if !item.desc.blank?
puts item.desc.colorize(:cyan)
end
if !item.profile_url.blank?
puts item.profile_url.colorize(:green)
end
puts "---".colorize(:dark_gray)
end
end
end
puts
end