brownbeagle-gitauth 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +661 -0
- data/README.rdoc +92 -0
- data/bin/gitauth +162 -0
- data/bin/gitauth-shell +66 -0
- data/lib/gitauth/client.rb +91 -0
- data/lib/gitauth/command.rb +105 -0
- data/lib/gitauth/repo.rb +106 -0
- data/lib/gitauth/users.rb +119 -0
- data/lib/gitauth.rb +51 -0
- metadata +74 -0
data/README.rdoc
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
== GitAuth - SSH-based authentication for Shared Git Repositories.
|
2
|
+
|
3
|
+
If you've heard of Gitosis before, GitAuth is like Gitosis but A) in Ruby, B) slightly simpler to get going and C) doesn't use a git repository to manage users.
|
4
|
+
|
5
|
+
At the moment configuration / adding users is done via a single command - +gitauth+. For usage, see below.
|
6
|
+
|
7
|
+
=== License
|
8
|
+
|
9
|
+
GitAuth is licensed under AGPL, with parts of the code being derived
|
10
|
+
from Gitorius - http://gitorious.org/
|
11
|
+
|
12
|
+
=== Installing GitAuth
|
13
|
+
|
14
|
+
Getting started is relatively simple. First of, you'll need to log onto the remote server / your git host. Next, you'll need to install the gem:
|
15
|
+
|
16
|
+
sudo gem install brownbeagle-gitauth --source=https://gems.github.com/
|
17
|
+
|
18
|
+
Once that's done, the +gitauth+ and +gitauth-shell+ commands should be in your path.
|
19
|
+
Next, you'll want to (in most cases anyway) use a specific +git+ user to host repositories.
|
20
|
+
|
21
|
+
Using the example of ubuntu, we'll add a git user under which all actions will now take place (note, this is essentially the same as gitosis):
|
22
|
+
|
23
|
+
sudo adduser --disabled-password --shell /bin/bash --group --home /home/git --system --gecos 'gitauth user for version control' git
|
24
|
+
|
25
|
+
Now, whenever you run the +gitauth+ executable, you'll do so as the user you just created
|
26
|
+
above. For simplicity purposes, I added the the following to my zsh profile so I always
|
27
|
+
had it available. If you don't wish to, just use as you would without the alias:
|
28
|
+
|
29
|
+
alias asgit='sudo -H -u git'
|
30
|
+
|
31
|
+
And finally, to create a settings file and initialize .ssh and authorized_keys, perform the
|
32
|
+
following:
|
33
|
+
|
34
|
+
asgit gitauth install
|
35
|
+
|
36
|
+
Note that when it asks you for the gitauth shell path, the default will lock
|
37
|
+
it to the current gitauth version SO if you want it to stay up to date between gem versions
|
38
|
+
point it to the path for always-current executable (e.g. on Ubuntu 9.04 w/ apt-get ruby + gems,
|
39
|
+
+/var/lib/gems/1.8/bin/gitauth-shell+)
|
40
|
+
|
41
|
+
Also, Note that if you append a path to a public key to the end of the install command,
|
42
|
+
it will initialize a new +admin+ user who can also login via SSH. e.g.
|
43
|
+
|
44
|
+
asgit gitauth install id_rsa.pub
|
45
|
+
|
46
|
+
Would initialize an admin user with the given public key.
|
47
|
+
|
48
|
+
Note that from now on, all gitauth keys should be run either logged in as
|
49
|
+
git (via the admin user and ssh) or by being prefixed with asgit or "sudo -H -u git"
|
50
|
+
|
51
|
+
=== Adding Users
|
52
|
+
|
53
|
+
Whenever you want to add a user, it's ass imple as:
|
54
|
+
|
55
|
+
gitauth adduser user-name path-to-public-key
|
56
|
+
|
57
|
+
Note that if the --admin option is specified, the user will
|
58
|
+
be able to log in to the shell via SSH and will also be able
|
59
|
+
to access any repository.
|
60
|
+
|
61
|
+
=== Adding Repositories
|
62
|
+
|
63
|
+
Adding a repository is a two step process. First, you create it:
|
64
|
+
|
65
|
+
gitauth addrepo repo-name
|
66
|
+
|
67
|
+
Then, for every user who needs access, you do:
|
68
|
+
|
69
|
+
gitauth permissions repo-name user-name permission-type
|
70
|
+
|
71
|
+
Where permission type is read, write or all. If permission
|
72
|
+
type isn't specified, it will default to all.
|
73
|
+
|
74
|
+
=== Accessing repos:
|
75
|
+
|
76
|
+
Finally, once you've added users / repos, using them is as simple
|
77
|
+
as doing the following on each users computer:
|
78
|
+
|
79
|
+
git clone git@your-remote-host:repo-name
|
80
|
+
|
81
|
+
Or
|
82
|
+
|
83
|
+
git clone git@your-remote-host:repo-name.git
|
84
|
+
|
85
|
+
Either form working just as well.
|
86
|
+
|
87
|
+
Note that for the first time you push, you will need
|
88
|
+
to use the full form:
|
89
|
+
|
90
|
+
git push origin master
|
91
|
+
|
92
|
+
As it starts as an empty repo.
|
data/bin/gitauth
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009 BrownBeagle
|
5
|
+
# Copyright (C) 2008 Darcy Laycock <sutto@sutto.net>
|
6
|
+
#
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Affero General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#++
|
20
|
+
|
21
|
+
require 'rubygems'
|
22
|
+
require 'readline'
|
23
|
+
require 'thor'
|
24
|
+
require File.join(File.dirname(__FILE__), "..", "lib", "gitauth")
|
25
|
+
|
26
|
+
|
27
|
+
class GitAuthRunner < Thor
|
28
|
+
|
29
|
+
|
30
|
+
desc "addrepo REPO-NAME [PATH-PART]", "Adds a new repository"
|
31
|
+
def addrepo(name, path = name)
|
32
|
+
GitAuth.setup!
|
33
|
+
if GitAuth::Repo.create(name, path)
|
34
|
+
$stdout.puts "Repo was successfully created"
|
35
|
+
else
|
36
|
+
$stderr.puts "There was an error creating the repo"
|
37
|
+
exit! 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "adduser NAME PATH-TO-PUBLIC-KEY [--admin]", "Adds a user"
|
42
|
+
method_options :admin => :boolean
|
43
|
+
def adduser(name, key_path)
|
44
|
+
GitAuth.setup!
|
45
|
+
admin = !!(options && options[:admin])
|
46
|
+
if GitAuth::Users.create(name, admin, File.read(key_path).strip)
|
47
|
+
$stdout.puts "User added"
|
48
|
+
else
|
49
|
+
$stderr.puts "There was an error adding the given user"
|
50
|
+
exit!
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "repos", "Lists all the current repos"
|
55
|
+
def repos
|
56
|
+
GitAuth.setup!
|
57
|
+
$stdout.puts "repositories:"
|
58
|
+
GitAuth::Repo.all.each do |repo|
|
59
|
+
$stdout.puts " - #{repo.name}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "users", "Lists all users in the system"
|
64
|
+
def users
|
65
|
+
GitAuth.setup!
|
66
|
+
$stdout.puts "users:"
|
67
|
+
GitAuth::Users.all.each do |user|
|
68
|
+
$stdout.puts "- #{user.name}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
desc "permissions REPO USER [PERMISION=all,read,write]", "Adds Permissions for a user to a repository"
|
74
|
+
def permissions(repo, user, permissions = "all")
|
75
|
+
GitAuth.setup!
|
76
|
+
unless %w(read write all).include?(permissions)
|
77
|
+
$stderr.puts "Invalid permissions: #{permissions}"
|
78
|
+
exit! 1
|
79
|
+
end
|
80
|
+
repo = GitAuth::Repo.get(repo)
|
81
|
+
user = GitAuth::Users.get(user)
|
82
|
+
if repo.nil? || user.nil?
|
83
|
+
$stderr.puts "Invalid repository or user, please check the name"
|
84
|
+
exit! 1
|
85
|
+
end
|
86
|
+
repo.writeable_by(user) if %w(all write).include?(permissions)
|
87
|
+
repo.readable_by(user) if %w(all read).include?(permissions)
|
88
|
+
GitAuth::Users.save!
|
89
|
+
GitAuth::Repo.save!
|
90
|
+
$stdout.puts "Permissions Added"
|
91
|
+
end
|
92
|
+
|
93
|
+
desc "install [ADMIN-PUBLIC-KEY]", "creates and sets the permissions for .ssh and .ssh/authorized keys"
|
94
|
+
method_options :force_config => :boolean
|
95
|
+
def install(public_key_path = nil)
|
96
|
+
$stdout.print "Are you logged in as the correct user? (y/n) "
|
97
|
+
answer = Readline.readline
|
98
|
+
if answer !~ /^y/i
|
99
|
+
$stderr.puts "Please log in as the correct user and re-run"
|
100
|
+
exit! 1
|
101
|
+
end
|
102
|
+
require 'fileutils'
|
103
|
+
folder = File.expand_path("~/.ssh")
|
104
|
+
if !File.exist?(folder) || !File.directory?(folder)
|
105
|
+
FileUtils.mkdir(folder)
|
106
|
+
FileUtils.chmod(0700, folder)
|
107
|
+
end
|
108
|
+
authorized_keys = File.join(folder, "authorized_keys")
|
109
|
+
if !File.exist?(authorized_keys)
|
110
|
+
File.open(authorized_keys, "w+") do |f|
|
111
|
+
f.puts "## GitAuth - DO NO EDIT BELOW THIS LINE ##"
|
112
|
+
end
|
113
|
+
FileUtils.chmod(0600, authorized_keys)
|
114
|
+
end
|
115
|
+
gitauth_folder = File.expand_path("~/.gitauth/")
|
116
|
+
FileUtils.mkdir(gitauth_folder) if !File.exist?(gitauth_folder) || !File.directory?(gitauth_folder)
|
117
|
+
gitauth_settings_path = File.join(gitauth_folder, "settings.yml")
|
118
|
+
unless File.exist?(gitauth_settings_path) || (options && options[:force_config])
|
119
|
+
print "Where did you want repositories to be stored? (default: ~/repositories/): "
|
120
|
+
path = Readline.readline.strip
|
121
|
+
path = File.expand_path("~/repositories") if path.empty?
|
122
|
+
begin
|
123
|
+
FileUtils.mkdir_p(path)
|
124
|
+
rescue
|
125
|
+
$stderr.puts "There was an error making the repository folder: #{path}"
|
126
|
+
$stderr.puts "Please check again"
|
127
|
+
exit! 1
|
128
|
+
end
|
129
|
+
current_gitauth_shell_path = File.join(GitAuth::BASE_DIR, "bin", "gitauth-shell")
|
130
|
+
$stdout.print "What is the path to your gitauth-shell (default: '#{current_gitauth_shell_path}'): "
|
131
|
+
gitauth_shell_path = Readline.readline
|
132
|
+
gitauth_shell_path = current_gitauth_shell_path if gitauth_shell_path.empty?
|
133
|
+
File.open(gitauth_settings_path, "w+") do |f|
|
134
|
+
f.write({
|
135
|
+
"base_path" => path,
|
136
|
+
"authorized_keys_file" => authorized_keys,
|
137
|
+
"shell_executable" => gitauth_shell_path
|
138
|
+
}.to_yaml)
|
139
|
+
end
|
140
|
+
if !public_key_path.nil? && File.exist?(public_key_path)
|
141
|
+
GitAuth.setup!
|
142
|
+
created = GitAuth::Users.create("admin", true, File.read(public_key_path).strip)
|
143
|
+
if created
|
144
|
+
$stdout.puts "Admin User Created."
|
145
|
+
else
|
146
|
+
$stderr.puts "An admin user couldn't be created."
|
147
|
+
exit! 1
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
rescue Errno::EACCES
|
152
|
+
$stderr.puts "Hey, it looks you don't have access to that - sorry!"
|
153
|
+
exit! 1
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
if ARGV.empty?
|
159
|
+
GitAuthRunner.new.help
|
160
|
+
else
|
161
|
+
GitAuthRunner.start
|
162
|
+
end
|
data/bin/gitauth-shell
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009 BrownBeagle
|
5
|
+
# Copyright (C) 2008 Darcy Laycock <sutto@sutto.net>
|
6
|
+
#
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Affero General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#++
|
20
|
+
|
21
|
+
|
22
|
+
REAL_FILE = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
|
23
|
+
|
24
|
+
# Require the proper gitauth file.
|
25
|
+
require File.expand_path(File.join(File.dirname(REAL_FILE), "..", "lib", "gitauth"))
|
26
|
+
|
27
|
+
GitAuth.setup!
|
28
|
+
|
29
|
+
# Gitorious does it so I should too!
|
30
|
+
File.umask(0022)
|
31
|
+
|
32
|
+
user_name = ARGV[0]
|
33
|
+
command = ENV["SSH_ORIGINAL_COMMAND"]
|
34
|
+
|
35
|
+
GitAuth::Client.start!(user_name, command) do |c|
|
36
|
+
|
37
|
+
c.on(:invalid_user) do |c|
|
38
|
+
c.exit_with_error "An invalid user / key was used. Please ensure it is setup with GitAuth"
|
39
|
+
end
|
40
|
+
|
41
|
+
c.on(:invalid_command) do |c|
|
42
|
+
if c.user.shell_accessible?
|
43
|
+
exec(ENV["SHELL"])
|
44
|
+
else
|
45
|
+
c.exit_with_error "SSH_ORIGINAL_COMMAND is needed, mmmkay?"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
c.on(:invalid_repository) do |c|
|
50
|
+
c.exit_with_error "Ze repository you specified does not exist."
|
51
|
+
end
|
52
|
+
|
53
|
+
c.on(:bad_command) do |c|
|
54
|
+
c.exit_with_error "A Bad Command Has Failed Ye, Thou Shalt Not Continue."
|
55
|
+
end
|
56
|
+
|
57
|
+
c.on(:access_denied) do |c|
|
58
|
+
c.exit_with_error "These are not the droids you are looking for"
|
59
|
+
end
|
60
|
+
|
61
|
+
c.on(:fatal_error) do |c|
|
62
|
+
c.exit_with_error "Holy crap, we've imploded cap'n!"
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2009 Brown Beagle Software
|
3
|
+
# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
|
4
|
+
# Copyright (C) 2007, 2008 Johan Sørensen <johan@johansorensen.com>
|
5
|
+
# Copyright (C) 2008 Tor Arne Vestbø <tavestbo@trolltech.com>
|
6
|
+
# Copyright (C) 2008 Darcy Laycock <sutto@sutto.net>
|
7
|
+
#
|
8
|
+
# This program is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU Affero General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU Affero General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU Affero General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
|
22
|
+
module GitAuth
|
23
|
+
class Client
|
24
|
+
|
25
|
+
attr_accessor :user, :command
|
26
|
+
|
27
|
+
def initialize(user_name, command)
|
28
|
+
GitAuth.logger.debug "Initializing client with command: '#{command}' and user name '#{user_name}'"
|
29
|
+
@callbacks = Hash.new { |h,k| h[k] = [] }
|
30
|
+
@user = GitAuth::Users.get(user_name.to_s.strip)
|
31
|
+
@command = command
|
32
|
+
end
|
33
|
+
|
34
|
+
def on(command, &blk)
|
35
|
+
@callbacks[command.to_sym] << blk
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute_callback!(command)
|
39
|
+
@callbacks[command.to_sym].each { |c| c.call(self) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def exit_with_error(error)
|
43
|
+
GitAuth.logger.warn "Exiting with error: #{error}"
|
44
|
+
$stderr.puts error
|
45
|
+
exit! 1
|
46
|
+
end
|
47
|
+
|
48
|
+
def run!
|
49
|
+
if @user.nil?
|
50
|
+
execute_callback! :invalid_user
|
51
|
+
elsif @command.to_s.strip.empty?
|
52
|
+
execute_callback! :invalid_command
|
53
|
+
else
|
54
|
+
command = Command.parse!(@command)
|
55
|
+
repo = Repo.get(extract_repo_name(command))
|
56
|
+
if command.bad?
|
57
|
+
execute_callback! :bad_command
|
58
|
+
elsif repo.nil?
|
59
|
+
execute_callback! :invalid_repository
|
60
|
+
elsif user.can_execute?(command, repo)
|
61
|
+
# We can go ahead.
|
62
|
+
git_shell_argument = "#{command.verb} '#{repo.real_path}'"
|
63
|
+
# And execute that soab.
|
64
|
+
GitAuth.logger.info "Running command: #{git_shell_argument} for user: #{@user.name}"
|
65
|
+
exec("git-shell", "-c", git_shell_argument)
|
66
|
+
else
|
67
|
+
execute_callback! :access_denied
|
68
|
+
end
|
69
|
+
end
|
70
|
+
rescue Exception => e
|
71
|
+
GitAuth.logger.fatal "Exception: #{e.class.name}: #{e.message}"
|
72
|
+
e.backtrace.each do |l|
|
73
|
+
GitAuth.logger.fatal " => #{l}"
|
74
|
+
end
|
75
|
+
execute_callback! :fatal_error
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.start!(user, command)
|
79
|
+
client = self.new(user, command)
|
80
|
+
yield client if block_given?
|
81
|
+
client.run!
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
def extract_repo_name(command)
|
87
|
+
command.path.gsub(/\.git$/, "")
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2009 Brown Beagle Software
|
3
|
+
# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
|
4
|
+
# Copyright (C) 2007, 2008 Johan Sørensen <johan@johansorensen.com>
|
5
|
+
# Copyright (C) 2008 Tim Dysinger <tim@dysinger.net>
|
6
|
+
# Copyright (C) 2008 Tor Arne Vestbø <tavestbo@trolltech.com>
|
7
|
+
# Copyright (C) 2008 Darcy Laycock <sutto@sutto.net>
|
8
|
+
#
|
9
|
+
# This program is free software: you can redistribute it and/or modify
|
10
|
+
# it under the terms of the GNU Affero General Public License as published by
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
12
|
+
# (at your option) any later version.
|
13
|
+
#
|
14
|
+
# This program is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
# GNU Affero General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU Affero General Public License
|
20
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
#++
|
22
|
+
|
23
|
+
# This along with the associated gitauth-shell command are inspired by
|
24
|
+
# (and essentially, derived from) gitosis (http://eagain.net/gitweb/?p=gitosis.git)
|
25
|
+
# and gitorius (http://gitorius.org)
|
26
|
+
# Gitosis is of this writing licensed under the GPLv2 and is copyright (c) Tommi Virtanen
|
27
|
+
# and can be found at http://eagain.net/gitweb/?p=gitosis.git
|
28
|
+
# GitAuth::Command is licensed under the same license
|
29
|
+
|
30
|
+
module GitAuth
|
31
|
+
class Command
|
32
|
+
class BadCommandError < StandardError; end
|
33
|
+
|
34
|
+
# Standard Commands
|
35
|
+
READ_COMMANDS = ["git-upload-pack", "git upload-pack"]
|
36
|
+
WRITE_COMMANDS = ["git-receive-pack", "git receive-pack"]
|
37
|
+
PATH_REGEXP = /^'([a-z0-9\-\+]+(\.git)?)'$/i.freeze
|
38
|
+
|
39
|
+
attr_reader :path, :verb, :command
|
40
|
+
|
41
|
+
def initialize(command)
|
42
|
+
@command = command
|
43
|
+
@verb = nil
|
44
|
+
@argument = nil
|
45
|
+
@path = nil
|
46
|
+
@bad_command = true
|
47
|
+
end
|
48
|
+
|
49
|
+
def bad?
|
50
|
+
!!@bad_command
|
51
|
+
end
|
52
|
+
|
53
|
+
def write?
|
54
|
+
!bad? && @verb_type == :write
|
55
|
+
end
|
56
|
+
|
57
|
+
def read?
|
58
|
+
!bad? && !write?
|
59
|
+
end
|
60
|
+
|
61
|
+
# These exceptions are FUGLY.
|
62
|
+
# Clean up, mmkay?
|
63
|
+
def process!
|
64
|
+
raise BadCommandError if @command.include?("\n")
|
65
|
+
@verb, @argument = split_command
|
66
|
+
raise BadCommandError if @argument.nil? || @argument.is_a?(Array)
|
67
|
+
# Check if it's read / write
|
68
|
+
if READ_COMMANDS.include?(@verb)
|
69
|
+
@verb_type = :read
|
70
|
+
elsif WRITE_COMMANDS.include?(@verb)
|
71
|
+
@verb_type = :write
|
72
|
+
else
|
73
|
+
raise BadCommandError
|
74
|
+
end
|
75
|
+
if PATH_REGEXP =~ @argument
|
76
|
+
@path = $1
|
77
|
+
raise BadCommandError unless @path
|
78
|
+
else
|
79
|
+
raise BadCommandError
|
80
|
+
end
|
81
|
+
@bad_command = false
|
82
|
+
rescue BadCommandError
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.parse!(command)
|
86
|
+
command = self.new(command)
|
87
|
+
command.process!
|
88
|
+
command
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def split_command
|
94
|
+
parts = @command.split(" ")
|
95
|
+
if parts.size == 3
|
96
|
+
["#{parts[0]} #{parts[1]}", parts[2]]
|
97
|
+
elsif parts.size == 2
|
98
|
+
parts
|
99
|
+
else
|
100
|
+
raise BadCommandError
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
data/lib/gitauth/repo.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2009 Brown Beagle Software
|
3
|
+
# Copyright (C) 2008 Darcy Laycock <sutto@sutto.net>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Affero General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#++
|
18
|
+
|
19
|
+
require 'fileutils'
|
20
|
+
module GitAuth
|
21
|
+
class Repo
|
22
|
+
REPOS_PATH = File.join(GitAuth::GITAUTH_DIR, "repositories.yml")
|
23
|
+
|
24
|
+
def self.all
|
25
|
+
@@all_repositories ||= nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.load!
|
29
|
+
self.all = YAML.load_file(REPOS_PATH) rescue nil if File.exist?(REPOS_PATH)
|
30
|
+
self.all = [] unless self.all.is_a?(Array)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.save!
|
34
|
+
load! if self.all.nil?
|
35
|
+
File.open(REPOS_PATH, "w+") do |f|
|
36
|
+
f.write self.all.to_yaml
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.all=(value)
|
41
|
+
@@all_repositories = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.get(name)
|
45
|
+
GitAuth.logger.debug "Getting Repo w/ name: '#{name}'"
|
46
|
+
self.all.detect { |r| r.name == name }
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.create(name, path = name)
|
50
|
+
return false unless self.get(name).nil?
|
51
|
+
repository = self.new(name, path)
|
52
|
+
if repository.create_repo!
|
53
|
+
self.load!
|
54
|
+
self.all << repository
|
55
|
+
self.save!
|
56
|
+
return true
|
57
|
+
else
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_accessor :name, :path
|
63
|
+
|
64
|
+
def initialize(name, path, auto_create = false)
|
65
|
+
@name, @path = name, path
|
66
|
+
@permissions = {}
|
67
|
+
end
|
68
|
+
|
69
|
+
def writeable_by(user)
|
70
|
+
@permissions[:write] ||= []
|
71
|
+
@permissions[:write] << user.name
|
72
|
+
@permissions[:write].uniq!
|
73
|
+
end
|
74
|
+
|
75
|
+
def readable_by(user)
|
76
|
+
@permissions[:read] ||= []
|
77
|
+
@permissions[:read] << user.name
|
78
|
+
@permissions[:read].uniq!
|
79
|
+
end
|
80
|
+
|
81
|
+
def writeable_by?(user)
|
82
|
+
(@permissions[:write] || []).include? user.name
|
83
|
+
end
|
84
|
+
|
85
|
+
def readable_by?(user)
|
86
|
+
(@permissions[:read] || []).include? user.name
|
87
|
+
end
|
88
|
+
|
89
|
+
def real_path
|
90
|
+
File.join(GitAuth.settings.base_path, @path)
|
91
|
+
end
|
92
|
+
|
93
|
+
def create_repo!
|
94
|
+
path = self.real_path
|
95
|
+
unless File.exist?(path) && File.directory?(path)
|
96
|
+
FileUtils.mkdir_p(path)
|
97
|
+
output = ""
|
98
|
+
Dir.chdir(path) do
|
99
|
+
IO.popen("git init --bare") { |f| output << f.read }
|
100
|
+
end
|
101
|
+
return !!(output =~ /Initialized empty Git repository/)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|