# frozen_string_literal: true require_relative "../base" module Neetob class CLI module Users class Audit < Base attr_accessor :sandbox def initialize(sandbox = false) super() @sandbox = sandbox end def run users_data = users_for_all_available_apps users = extract_values_from_user_data(users_data) email_repos_map = create_email_repos_map(users) unique_users = users.uniq { |user| [user[0], user[1]] }.sort ui.info("\nUsers with multiple emails:") find_users_with_multiple_emails(unique_users.transpose, email_repos_map) ui.info("Users with emails having 3rd party domains:") find_users_with_invalid_emails(unique_users.transpose, email_repos_map) end private def users_for_all_available_apps find_all_matching_apps(["*"], :github, sandbox, true).map do |app| clone_repo_and_get_users(app).split("\n").map { |user| "#{user} #{app}" } end end def extract_values_from_user_data(users) users.flatten.map do |user| values = user.strip.split(" ")[1..-1] [values[0..-3].join(" "), clean_email(values[-2]), clean_repo_name(values[-1])] end end def clone_repo_and_get_users(app) app_name_without_org_suffix = app.split("/")[1] `git -C ./#{app_name_without_org_suffix} shortlog -sne` end def create_email_repos_map(users) map = {} users.each do |user| email = user[1] repo = user[2] map[email] = [] unless map.key?(email) map[email].push(repo) end map end def find_users_with_multiple_emails(users, email_repos_map) user_emails = {} users[0].each_with_index do |name, index| email = users[1][index] user_emails[name] = [] unless user_emails.key?(name) user_emails[name].push(email) end user_with_multiple_emails = user_emails.filter { |_, val| val.length > 1 } table_rows = create_rows_and_add_repos(user_with_multiple_emails, email_repos_map) create_and_show_table(table_rows, table_columns) end def find_users_with_invalid_emails(users, email_repos_map) user_with_invalid_emails = {} users[1].each_with_index do |email, index| name = users[0][index] if invalid_email?(email) user_with_invalid_emails[name] = [] unless user_with_invalid_emails.key?(name) user_with_invalid_emails[name].push(email) end end table_rows = create_rows_and_add_repos(user_with_invalid_emails, email_repos_map) create_and_show_table(table_rows, table_columns) end def table_columns [:Name, :Email, :Repo] end def create_rows_and_add_repos(users, email_repos_map) users.map do |name, emails| repos = emails.map { |email| email_repos_map[email] } [name, emails.join(", "), join_and_truncate_repos(repos)] end end def create_and_show_table(data, column_names) table = Terminal::Table.new headings: column_names, rows: data ui.error(table) end def join_and_truncate_repos(repos) repos.flatten.uniq.join(",").truncate(35) end def clean_email(email) email.gsub(/<|>/, "") end def clean_repo_name(repo) repo.gsub("bigbinary/", "") end def invalid_email?(email) !allowed_email_domains.any? { |domain| email.downcase.include?(domain) } end def allowed_email_domains ["github", "gmail", "bigbinary"] end end end end end