lib/postfix_admin/cli.rb in postfix_admin-0.3.0 vs lib/postfix_admin/cli.rb in postfix_admin-0.3.1
- old
+ new
@@ -55,13 +55,13 @@
if name
# domain name
show_domain_details(name)
else
# no argument: show all domains and admins
- show_domain
+ show_domains
puts
- show_admin
+ show_admins
end
end
def show_summary(domain_name = nil)
if domain_name
@@ -71,28 +71,36 @@
end
end
# Set up a domain
# Add a domain, add an admin, and grant the admin access to the domain
- def setup_domain(domain_name, password)
+ def setup_domain(domain_name, password, scheme: nil, rounds: nil)
admin = "admin@#{domain_name}"
add_domain(domain_name)
- add_admin(admin, password)
+ add_admin(admin, password, scheme: scheme, rounds: rounds)
add_admin_domain(admin, domain_name)
end
+ # Tear down a domain
+ # Delete a domain and delete an admin user for it
+ def teardown_domain(domain_name)
+ admin = "admin@#{domain_name}"
+ delete_domain(domain_name)
+ delete_admin(admin)
+ end
+
def show_account_details(user_name, display_password: false)
account_check(user_name)
mailbox = Mailbox.find(user_name)
mail_alias = Alias.find(user_name)
rows = []
puts_title("Mailbox")
rows << ["Address", mailbox.username]
rows << ["Name", mailbox.name]
rows << ["Password", mailbox.password] if display_password
- rows << ["Quota (MB)", mailbox.quota_mb_str]
+ rows << ["Quota (MB)", mailbox.quota_display_str(format: "%.1f")]
rows << ["Go to", mail_alias.goto]
rows << ["Active", mailbox.active_str]
puts_table(rows: rows)
end
@@ -123,11 +131,11 @@
rows << ["Active", mail_alias.active_str]
puts_table(rows: rows)
end
- def show_domain
+ def show_domains
rows = []
headings = ["No.", "Domain", "Aliases", "Mailboxes","Max Quota (MB)",
"Active", "Description"]
puts_title("Domains")
@@ -150,16 +158,16 @@
def add_domain(domain_name, description: nil)
@base.add_domain(domain_name, description: description)
puts_registered(domain_name, "a domain")
end
- def change_admin_password(user_name, password)
- change_password(Admin, user_name, password)
+ def change_admin_password(user_name, password, scheme: nil, rounds: nil)
+ change_password(Admin, user_name, password, scheme: scheme, rounds: rounds)
end
- def change_account_password(user_name, password)
- change_password(Mailbox, user_name, password)
+ def change_account_password(user_name, password, scheme: nil, rounds: nil)
+ change_password(Mailbox, user_name, password, scheme: scheme, rounds: rounds)
end
def edit_admin(admin_name, options)
admin_check(admin_name)
admin = Admin.find(admin_name)
@@ -169,11 +177,11 @@
end
admin.active = options[:active] unless options[:active].nil?
admin.save!
- puts "Successfully updated #{admin_name}"
+ puts "successfully updated #{admin_name}"
show_admin_details(admin_name)
end
def edit_domain(domain_name, options)
domain_check(domain_name)
@@ -183,22 +191,22 @@
domain.maxquota = options[:maxquota] if options[:maxquota]
domain.active = options[:active] unless options[:active].nil?
domain.description = options[:description] if options[:description]
domain.save!
- puts "Successfully updated #{domain_name}"
+ puts "successfully updated #{domain_name}"
show_summary(domain_name)
end
def delete_domain(domain_name)
@base.delete_domain(domain_name)
puts_deleted(domain_name)
end
- def show_admin(domain_name = nil)
+ def show_admins(domain_name = nil)
admins = domain_name ? Admin.select { |a| a.rel_domains.exists?(domain_name) } : Admin.all
- headings = %w[No. Admin Domains Active]
+ headings = ["No.", "Admin", "Domains", "Active", "Scheme Prefix"]
puts_title("Admins")
if admins.empty?
puts "No admins"
return
@@ -206,49 +214,64 @@
rows = []
admins.each_with_index do |a, i|
no = i + 1
domains = a.super_admin? ? 'Super Admin' : a.rel_domains.count
- rows << [no.to_s, a.username, domains.to_s, a.active_str]
+ rows << [no.to_s, a.username, domains.to_s, a.active_str, a.scheme_prefix]
end
puts_table(headings: headings, rows: rows)
end
- def show_address(domain_name)
- domain_check(domain_name)
+ def show_accounts(domain_name=nil)
+ domain_check(domain_name) if domain_name
rows = []
- mailboxes = Domain.find(domain_name).rel_mailboxes
- headings = ["No.", "Email", "Name", "Quota (MB)", "Active", "Maildir"]
+ mailboxes = if domain_name
+ Domain.find(domain_name).rel_mailboxes
+ else
+ Mailbox.all
+ end
+ headings = ["No.", "Email", "Name", "Quota (MB)", "Active",
+ "Scheme Prefix", "Maildir"]
- puts_title("Addresses")
+ puts_title("Accounts")
if mailboxes.empty?
- puts "No addresses"
+ puts "No accounts"
return
end
mailboxes.each_with_index do |m, i|
no = i + 1
- rows << [no.to_s, m.username, m.name, m.quota_mb_str,
- m.active_str, m.maildir]
+ rows << [no.to_s, m.username, m.name, m.quota_display_str,
+ m.active_str, m.scheme_prefix, m.maildir]
end
puts_table(headings: headings, rows: rows)
end
- def show_alias(domain_name)
- domain_check(domain_name)
+ def show_forwards(domain_name=nil)
+ domain_check(domain_name) if domain_name
- forwards, aliases = Domain.find(domain_name).rel_aliases.partition { |a| a.mailbox? }
+ forwards = if domain_name
+ Domain.find(domain_name).rel_aliases.forward
+ else
+ Alias.forward
+ end
- forwards.delete_if do |f|
- f.address == f.goto
- end
-
show_alias_base("Forwards", forwards)
- puts
+ end
+
+ def show_aliases(domain_name=nil)
+ domain_check(domain_name) if domain_name
+
+ aliases = if domain_name
+ Domain.find(domain_name).rel_aliases.pure
+ else
+ db_aliases = Alias.pure
+ end
+
show_alias_base("Aliases", aliases)
end
def show_admin_domain(user_name)
admin = Admin.find(user_name)
@@ -264,14 +287,18 @@
rows << [no.to_s, d.domain]
end
puts_table(rows: rows, headings: %w[No. Domain])
end
- def add_admin(user_name, password, super_admin = false, scheme = nil)
+ def add_admin(user_name, password, super_admin: false,
+ scheme: nil, rounds: nil)
validate_password(password)
- @base.add_admin(user_name, hashed_password(password, scheme))
+ h_password = hashed_password(password, user_name: user_name,
+ scheme: scheme, rounds: rounds)
+ @base.add_admin(user_name, h_password)
+
if super_admin
Admin.find(user_name).super_admin = true
puts_registered(user_name, "a super admin")
else
puts_registered(user_name, "an admin")
@@ -286,48 +313,53 @@
def delete_admin_domain(user_name, domain_name)
@base.delete_admin_domain(user_name, domain_name)
puts "#{domain_name} was successfully deleted from #{user_name}"
end
- def add_account(address, password, scheme = nil, name = nil)
+ def add_account(address, password, name: nil, scheme: nil, rounds: nil)
validate_password(password)
- @base.add_account(address, hashed_password(password, scheme), name: name)
+ h_password = hashed_password(password, user_name: address,
+ scheme: scheme, rounds: rounds)
+ @base.add_account(address, h_password, name: name)
puts_registered(address, "an account")
end
def add_alias(address, goto)
@base.add_alias(address, goto)
puts_registered("#{address}: #{goto}", "an alias")
end
def edit_account(address, options)
+ quota = options[:quota]
+ raise "Invalid Quota value: #{quota}" if quota && quota <= 0
+
mailbox_check(address)
mailbox = Mailbox.find(address)
mailbox.name = options[:name] if options[:name]
- mailbox.quota = options[:quota] * KB_TO_MB if options[:quota]
+ mailbox.quota_mb = quota if quota
mailbox.active = options[:active] unless options[:active].nil?
mailbox.save!
if options[:goto]
mail_alias = Alias.find(address)
mail_alias.goto = options[:goto]
mail_alias.save!
end
- puts "Successfully updated #{address}"
+ puts "successfully updated #{address}"
show_account_details(address)
end
def edit_alias(address, options)
alias_check(address)
mail_alias = Alias.find(address)
mail_alias.goto = options[:goto] if options[:goto]
mail_alias.active = options[:active] unless options[:active].nil?
mail_alias.save or raise "Could not save Alias"
- puts "Successfully updated #{address}"
+ puts "successfully updated #{address}"
show_alias_details(address)
end
def delete_alias(address)
@base.delete_alias(address)
@@ -426,15 +458,17 @@
puts_title(domain_name)
puts_table(rows: rows)
end
def show_domain_details(domain_name)
- show_admin(domain_name)
+ show_admins(domain_name)
puts
- show_address(domain_name)
+ show_accounts(domain_name)
puts
- show_alias(domain_name)
+ show_forwards(domain_name)
+ puts
+ show_aliases(domain_name)
end
def show_alias_base(title, addresses)
rows = []
puts_title(title)
@@ -522,26 +556,46 @@
if password.size < MIN_NUM_PASSWORD_CHARACTER
raise ArgumentError, "Password is too short. It should be larger than #{MIN_NUM_PASSWORD_CHARACTER}"
end
end
- def change_password(klass, user_name, password)
+ def change_password(klass, user_name, password, scheme: nil, rounds: nil)
raise Error, "Could not find #{user_name}" unless klass.exists?(user_name)
validate_password(password)
obj = klass.find(user_name)
+ h_password = hashed_password(password, scheme: scheme, rounds: rounds,
+ user_name: user_name)
- if obj.update(password: hashed_password(password))
- puts "the password of #{user_name} was successfully changed."
+ if obj.update(password: h_password)
+ puts "the password of #{user_name} was successfully updated."
else
raise "Could not change password of #{klass.name}"
end
end
- def hashed_password(password, in_scheme = nil)
+ # The default number of rounds for BLF-CRYPT in `doveadm pw` is 5.
+ # However, this method uses 10 rounds by default, similar to
+ # the password_hash() function in PHP.
+ #
+ # https://www.php.net/manual/en/function.password-hash.php
+ # <?php
+ # echo password_hash("password", PASSWORD_BCRYPT);
+ #
+ # $2y$10$qzRgjWZWfH4VsNQGvp/DNObFSaMiZxXJSzgXqOOS/qtF68qIhhwFe
+ DEFAULT_BLF_CRYPT_ROUNDS = 10
+
+ # Generate a hashed password
+ def hashed_password(password, scheme: nil, rounds: nil, user_name: nil)
prefix = @base.config[:passwordhash_prefix]
- scheme = in_scheme || @base.config[:scheme]
- PostfixAdmin::Doveadm.password(password, scheme, prefix)
+ new_scheme = scheme || @base.config[:scheme]
+ new_rounds = if rounds
+ rounds
+ elsif new_scheme == "BLF-CRYPT"
+ DEFAULT_BLF_CRYPT_ROUNDS
+ end
+ PostfixAdmin::Doveadm.password(password, new_scheme, rounds: new_rounds,
+ user_name: user_name, prefix: prefix)
end
end
end