#!/usr/bin/env ruby #-- # Copyright (C) 2009 Brown Beagle Software # Copyright (C) 2008 Darcy Laycock # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . #++ require 'rubygems' require 'readline' require 'thor' require File.join(File.dirname(__FILE__), "..", "lib", "gitauth") class GitAuthRunner < Thor # Adding users, groups and repos desc "addrepo REPO-NAME [PATH-PART]", "Adds a new repository" def addrepo(name, path = name) GitAuth.setup! if GitAuth::Repo.create(name, path) $stdout.puts "Repo was successfully created" else $stderr.puts "There was an error creating the repo" exit! 1 end end desc "adduser NAME PATH-TO-PUBLIC-KEY [--admin]", "Adds a user" method_options :admin => :boolean def adduser(name, key_path) GitAuth.setup! admin = !!(options && options[:admin]) if GitAuth::User.create(name, admin, File.read(key_path).strip) $stdout.puts "User added" else $stderr.puts "There was an error adding the given user" exit! end end desc "addgroup NAME", "Adds a group with the specified name" def addgroup(name) GitAuth.setup! if GitAuth::Group.create(name) $stdout.puts "The group was added" else $stderr.puts "There was an error creating the aforementioned group" exit! 1 end end # Misc. operations desc "permissions REPO USERORGROUP [PERMISION=all,read,write]", "Adds Permissions for a user or group to a repository" def permissions(repo, user_or_group, permissions = "all") GitAuth.setup! unless %w(read write all).include?(permissions) $stderr.puts "Invalid permissions: #{permissions}" exit! 1 end repo = GitAuth::Repo.get(repo) uog = GitAuth.get_user_or_group(user_or_group) if repo.nil? || uog.nil? $stderr.puts "Invalid repository or user, please check the name" exit! 1 end repo.writeable_by(uog) if %w(all write).include?(permissions) repo.readable_by(uog) if %w(all read).include?(permissions) GitAuth::Repo.save! $stdout.puts "Permissions Added" end desc "install [ADMIN-PUBLIC-KEY]", "creates and sets the permissions for .ssh and .ssh/authorized keys" method_options :force_config => :boolean def install(public_key_path = nil) $stdout.print "Are you logged in as the correct user? (y/n) " answer = Readline.readline if answer !~ /^y/i $stderr.puts "Please log in as the correct user and re-run" exit! 1 end if !GitAuth::Repo.has_git? $stderr.puts "'git' was not found in your path - please install it before continuing." exit! 1 end require 'fileutils' folder = File.expand_path("~/.ssh") if !File.exist?(folder) || !File.directory?(folder) FileUtils.mkdir(folder) FileUtils.chmod(0700, folder) end authorized_keys = File.join(folder, "authorized_keys") if !File.exist?(authorized_keys) File.open(authorized_keys, "w+") do |f| f.puts "## GitAuth - DO NO EDIT BELOW THIS LINE ##" end FileUtils.chmod(0600, authorized_keys) end gitauth_folder = File.expand_path("~/.gitauth/") FileUtils.mkdir(gitauth_folder) if !File.exist?(gitauth_folder) || !File.directory?(gitauth_folder) gitauth_settings_path = File.join(gitauth_folder, "settings.yml") unless File.exist?(gitauth_settings_path) || (options && options[:force_config]) print "Where did you want repositories to be stored? (default: ~/repositories/): " path = Readline.readline.strip path = File.expand_path("~/repositories") if path.empty? begin FileUtils.mkdir_p(path) rescue $stderr.puts "There was an error making the repository folder: #{path}" $stderr.puts "Please check again" exit! 1 end current_gitauth_shell_path = File.join(GitAuth::BASE_DIR, "bin", "gitauth-shell") $stdout.print "What is the path to your gitauth-shell (default: '#{current_gitauth_shell_path}'): " gitauth_shell_path = Readline.readline gitauth_shell_path = current_gitauth_shell_path if gitauth_shell_path.empty? File.open(gitauth_settings_path, "w+") do |f| f.write({ "base_path" => path, "authorized_keys_file" => authorized_keys, "shell_executable" => gitauth_shell_path }.to_yaml) end if !public_key_path.nil? && File.exist?(public_key_path) GitAuth.setup! created = GitAuth::User.create("admin", true, File.read(public_key_path).strip) if created $stdout.puts "Admin User Created." else $stderr.puts "An admin user couldn't be created." exit! 1 end end end rescue Errno::EACCES $stderr.puts "Hey, it looks you don't have access to that - sorry!" exit! 1 end # Viewing Users etc desc "repos", "Lists all the current repos handled by gitauth" def repos GitAuth.setup! $stdout.puts "Repositories:" GitAuth::Repo.all.each do |repo| line = " - #{repo.name}" line << " (#{repo.path})" if repo.path != repo.name $stdout.puts line end end desc "users", "Lists all users handled by gitauth" def users GitAuth.setup! $stdout.puts "Users:" GitAuth::User.all.each do |user| line = "- #{user}" line << " (admin)" if user.admin? $stdout.puts line end end desc "groups", "Lists all groups handled by gitauth" def groups GitAuth.setup! $stdout.puts "Groups:" GitAuth::Group.all.each do |group| $stdout.puts "- #{group} - #{group.members.empty? ? "no members" : group.members.join(", ")}" end end desc "webapp", "starts serving the GitAuth web-app on Port 8998" def webapp s = GitAuth.settings if s.web_username.to_s.empty? || s.web_password_hash.to_s.empty? $stdout.puts "To use the web interface you must first setup some credentials:" $stdout.print "What username would you like to use? (default is 'gitauth'): " username = Readline.readline.strip username = "gitauth" if username.empty? $stdout.print "What password would you like to use?: " password = read_password while password.empty? $stdout.print "Please try again, What password would you like to use?: " password = read_password end print "Please enter your password again: " confirmation = read_password while confirmation != password print "Wrong password, please confirm again: " confirmation = read_password end require 'digest/sha2' settings = YAML.load_file(File.join(GitAuth::GITAUTH_DIR, "settings.yml")) settings.merge!({ "web_username" => username, "web_password_hash" => Digest::SHA256.hexdigest(password) }) File.open(File.join(GitAuth::GITAUTH_DIR, "settings.yml"), "w+") { |f| f.write settings.to_yaml } puts "Username and Password saved." GitAuth.reload_settings! end GitAuth.serve_web! rescue Interrupt exit! 1 end protected def read_password system "stty -echo" line = Readline.readline.strip system "stty echo" print "\n" return line end end if ARGV.empty? GitAuthRunner.new.help else GitAuthRunner.start end