#!/usr/bin/env ruby require File.join(File.dirname(__FILE__), "..", "lib", "gitauth") GitAuth::Application.processing(ARGV) do |a| a.banner = "GitAuth v#{GitAuth.version}" a.generator! a.option(:force, "force the creation of the settings file") a.option(:admin, "pass the path to a ssh public key and it adds a default admin user") a.add("install", "Sets up GitAuth for the current user") do |options| setup_generator ".", :silent => true # Check for a valid admin key if options.has_key?(:admin) && (!options[:admin].is_a?(String) || !file?(options[:admin])) puts "You provided the admin option but didn't provide it with a path to public key." die! "Please re-run again with a path to a key, e.g. --admin=~/id_rsa.pub" end if !yes?("Are you logged in as the correct user?") die!("Please log in as the correct user and re-run") end if !GitAuth.has_git? die!("'git' was not found in your path - please install it / add it to your path before continuing.") end ssh_folder = "~/.ssh" if !folder?(ssh_folder) folders ssh_folder chmod 0700, ssh_folder end authorized_keys = ssh_folder / "authorized_keys" if !file?(authorized_keys) file authorized_keys, "\n\n## GitAuth - DO NO EDIT BELOW THIS LINE ##\n" chmod 0600, authorized_keys end gitauth_folder = "~/.gitauth/" folders gitauth_folder settings_file = gitauth_folder / "settings.yml" if !file?(settings_file) || options[:force] repo_path = ask("Where did you want repositories to be stored?", "~/repositories") repo_path = File.expand_path(repo_path) folders repo_path default_shell_path = GitAuth::BASE_DIR.join("bin", "gitauth-shell").to_s gitauth_shell_path = "" gitauth_shell_set = false while gitauth_shell_path.blank? || !(file?(gitauth_shell_path) && executable?(gitauth_shell_path)) # A Give the user a message if the path doesn't exist. if gitauth_shell_set puts "The shell you provided, #{gitauth_shell_path}, isn't executable" else gitauth_shell_set = true end gitauth_shell_path = ask("What is the path to your gitauth-shell?", default_shell_path) gitauth_shell_path = File.expand_path(gitauth_shell_path) end GitAuth::Settings.update!({ :base_path => File.expand_path(repo_path), :authorized_keys_file => File.expand_path(authorized_keys), :shell_executable => File.expand_path(gitauth_shell_path) }) end if options[:admin] key_contents = File.read(options[:admin]).strip if GitAuth::User.create("admin", true, key_contents) puts "Default admin user added with key '#{options[:admin]}'" else die! "Error adding default admin user with key at '#{options[:admin]}'" end end end a.controller!(:web_app, "Starts the gitauth frontend using the default sintra runner", :skip_path => true) a.option(:force, "Skip the verification / confirmation part of adding the permissions") a.option(:type, "The type of permissions - one of all, read, write or none. Defaults to all") full_desc = "Gives a specific user or group the specified permissions to a given repository" a.add("permissions REPOSITORY USER-OR-GROUP", full_desc) do |repo, target, options| GitAuth.prepare permissions = options[:type] || 'all' if !%w(all read write none).include? permissions die! "'#{permissions}' is not a valid permission type. It must be all, read, write or none" end real_permissions = ({"all" => ["read", "write"], "none" => []}[permissions] || [permissions]) repository = GitAuth::Repo.get(repo) real_target = GitAuth.get_user_or_group(target) die! "Unknown repository '#{repo}'" if repository.blank? die! "Unknown user or group '#{target}'" if real_target.blank? if options[:force] || yes?("Adding '#{permissions}' permissions for #{real_target} to #{repository.name}") repository.update_permissions!(real_target, real_permissions) puts "Permissions updated." else puts "Permissions not added, exiting." end end a.option(:admin, "Makes a user an admin user") a.add("add-user NAME PATH-TO-PUBLIC-KEY", "Creates a user with a given public key") do |name, ssh_key, options| GitAuth.prepare die! "'#{ssh_key}' is not a valid path to a public key" if !File.file?(ssh_key) admin = !!options[:admin] contents = File.read(ssh_key).strip if GitAuth::User.create(name, admin, contents) puts "Successfully added user '#{name}' (user #{admin ? 'is' : 'is not'} an admin)" else die! "There was an unknown error attempting to add a user called '#{name}'" end end a.option(:make_empty, "Initializes the repository to be empty / have an initial blank commit") a.add("add-repo NAME [PATH=NAME]", "Creates a named repository, with an optional path on the file system") do |name, *args| GitAuth.prepare options = args.extract_options! path = (args.shift || name) if (repo = GitAuth::Repo.create(name, path)) puts "Successfully created repository '#{name}' located at '#{path}'" if options[:make_empty] puts "Attempting to make empty repository" repo.make_empty! end else die! "Unable to create repository '#{name}' in location '#{path}'" end end a.add("add-group NAME", "Creates a group with a given name") do |name, options| GitAuth.prepare if GitAuth::Group.create(name) puts "Successfully created group '#{name}'" else die! "Unable to create group '#{name}'" end end a.add("ls-users", "Lists all users currently managed by gitauth") do |options| GitAuth.prepare puts "Users:" (GitAuth::User.all || []).each do |user| line = "- #{user}" line << " (admin)" if user.admin? puts line end end a.add("ls-repos", "Lists all repositories currently managed by gitauth") do |options| GitAuth.prepare puts "Repositories:" (GitAuth::Repo.all || []).each do |repo| line = " - #{repo.name}" line << " (#{repo.path})" if repo.path != repo.name puts line end end a.add("ls-groups", "Lists all groups currently managed by gitauth") do |options| GitAuth.prepare puts "Groups:" (GitAuth::Group.all || []).each do |group| puts "- #{group} (#{group.members.empty? ? "no members" : group.members.join(", ")})" end end a.add("rm-user NAME", "Removes the specified user") do |name, options| GitAuth.prepare user = GitAuth::User.get(name) die! "Unknown user '#{name}'" if user.blank? user.destroy! puts "Removed user '#{name}' - Please note you will manually need to remove this users line from authorized_keys" end a.add("rm-repo NAME", "Removes the specified repo") do |name, options| GitAuth.prepare repo = GitAuth::Repo.get(name) die! "Unknown repo '#{name}'" if repo.blank? repo.destroy! puts "Removed repo '#{name}'" end a.add("rm-group NAME", "Removes the specified group") do |name, options| GitAuth.prepare group = GitAuth::Group.get(name) die! "Unknown group '#{name}'" if group.blank? group.destroy! puts "Removed group '#{name}'" end a.add("usage", "Prints out the sample usage instructions") do |options| File.open(GitAuth::BASE_DIR.join("USAGE")) do |f| f.each_line { |line| puts line } end end a.add("show-repo NAME", "Shows information for a repository with a given name") do |name, options| GitAuth.prepare repo = GitAuth::Repo.get(name) die! "Unknown repository '#{repo}'" if repo.blank? puts "Repository Name: #{repo.name}" puts "Repository Path: #{repo.path}" puts "Actual Path: #{repo.real_path}" puts "\nRead Permissions:" read_perms = repo.permissions.fetch(:read, []) read_perms.each { |item| puts " - #{item}" } puts " - No read permissions" if read_perms.blank? puts "\nWrite Permissions:" write_perms = repo.permissions.fetch(:write, []) write_perms.each { |item| puts " - #{item}" } puts " - No write permissions" if write_perms.blank? end a.add("show-group NAME", "Shows information for a group with a given name") do |name, options| GitAuth.prepare group = GitAuth::Group.get(name) die! "Unable to find a group named '#{name}'" if group.blank? puts "Group Name: #{group.name}" puts "Reference Name: #{group.to_s}" puts "\nGroup Members:" group.members.each { |member| puts " - #{member}" } puts " - This group has no members" if group.members.blank? end a.add("show-user NAME", "Shows details for a user with a specific name") do |name, options| GitAuth.prepare user = GitAuth::User.get(name) die! "Unable to find a user named '#{name}'" if user.blank? puts "User Name: #{user.name}" groups = user.groups puts "\nGroups:" puts " - This user isn't a member of any groups" if groups.blank? groups.each { |g| puts " - #{g.to_s}" } end end