brownbeagle-gitauth 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +11 -1
- data/bin/gitauth +100 -24
- data/bin/gitauth-shell +2 -32
- data/lib/gitauth/client.rb +17 -19
- data/lib/gitauth/command.rb +2 -2
- data/lib/gitauth/group.rb +86 -0
- data/lib/gitauth/repo.rb +43 -40
- data/lib/gitauth/saveable_class.rb +60 -0
- data/lib/gitauth/{users.rb → user.rb} +35 -31
- data/lib/gitauth/web_app.rb +230 -0
- data/lib/gitauth.rb +29 -5
- data/public/gitauth.css +264 -0
- data/public/gitauth.js +17 -0
- data/public/jquery.js +19 -0
- data/views/group.erb +24 -0
- data/views/index.erb +80 -0
- data/views/layout.erb +27 -0
- data/views/repo.erb +56 -0
- data/views/user.erb +51 -0
- metadata +26 -5
data/README.rdoc
CHANGED
@@ -48,9 +48,19 @@ Would initialize an admin user with the given public key.
|
|
48
48
|
Note that from now on, all gitauth keys should be run either logged in as
|
49
49
|
git (via the admin user and ssh) or by being prefixed with asgit or "sudo -H -u git"
|
50
50
|
|
51
|
+
=== Web Interface
|
52
|
+
|
53
|
+
To start the web interface, just run:
|
54
|
+
|
55
|
+
gitauth webapp
|
56
|
+
|
57
|
+
The first time you boot the web app, you will be prompted
|
58
|
+
to enter a username and a password. Please do so
|
59
|
+
and then surf to http://your-server-ip:8998/
|
60
|
+
|
51
61
|
=== Adding Users
|
52
62
|
|
53
|
-
Whenever you want to add a user, it's
|
63
|
+
Whenever you want to add a user, it's as simple as:
|
54
64
|
|
55
65
|
gitauth adduser user-name path-to-public-key
|
56
66
|
|
data/bin/gitauth
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (C) 2009
|
4
|
+
# Copyright (C) 2009 Brown Beagle Software
|
5
5
|
# Copyright (C) 2008 Darcy Laycock <sutto@sutto.net>
|
6
6
|
#
|
7
7
|
# This program is free software: you can redistribute it and/or modify
|
@@ -26,6 +26,7 @@ require File.join(File.dirname(__FILE__), "..", "lib", "gitauth")
|
|
26
26
|
|
27
27
|
class GitAuthRunner < Thor
|
28
28
|
|
29
|
+
# Adding users, groups and repos
|
29
30
|
|
30
31
|
desc "addrepo REPO-NAME [PATH-PART]", "Adds a new repository"
|
31
32
|
def addrepo(name, path = name)
|
@@ -43,7 +44,7 @@ class GitAuthRunner < Thor
|
|
43
44
|
def adduser(name, key_path)
|
44
45
|
GitAuth.setup!
|
45
46
|
admin = !!(options && options[:admin])
|
46
|
-
if GitAuth::
|
47
|
+
if GitAuth::User.create(name, admin, File.read(key_path).strip)
|
47
48
|
$stdout.puts "User added"
|
48
49
|
else
|
49
50
|
$stderr.puts "There was an error adding the given user"
|
@@ -51,41 +52,34 @@ class GitAuthRunner < Thor
|
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
|
-
desc "
|
55
|
-
def
|
55
|
+
desc "addgroup NAME", "Adds a group with the specified name"
|
56
|
+
def addgroup(name)
|
56
57
|
GitAuth.setup!
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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}"
|
58
|
+
if GitAuth::Group.create(name)
|
59
|
+
$stdout.puts "The group was added"
|
60
|
+
else
|
61
|
+
$stderr.puts "There was an error creating the aforementioned group"
|
62
|
+
exit! 1
|
69
63
|
end
|
70
64
|
end
|
71
65
|
|
66
|
+
# Misc. operations
|
72
67
|
|
73
|
-
desc "permissions REPO
|
74
|
-
def permissions(repo,
|
68
|
+
desc "permissions REPO USERORGROUP [PERMISION=all,read,write]", "Adds Permissions for a user or group to a repository"
|
69
|
+
def permissions(repo, user_or_group, permissions = "all")
|
75
70
|
GitAuth.setup!
|
76
71
|
unless %w(read write all).include?(permissions)
|
77
72
|
$stderr.puts "Invalid permissions: #{permissions}"
|
78
73
|
exit! 1
|
79
74
|
end
|
80
75
|
repo = GitAuth::Repo.get(repo)
|
81
|
-
|
82
|
-
if repo.nil? ||
|
76
|
+
uog = GitAuth.get_user_or_group(user_or_group)
|
77
|
+
if repo.nil? || uog.nil?
|
83
78
|
$stderr.puts "Invalid repository or user, please check the name"
|
84
79
|
exit! 1
|
85
80
|
end
|
86
|
-
repo.writeable_by(
|
87
|
-
repo.readable_by(
|
88
|
-
GitAuth::Users.save!
|
81
|
+
repo.writeable_by(uog) if %w(all write).include?(permissions)
|
82
|
+
repo.readable_by(uog) if %w(all read).include?(permissions)
|
89
83
|
GitAuth::Repo.save!
|
90
84
|
$stdout.puts "Permissions Added"
|
91
85
|
end
|
@@ -99,6 +93,10 @@ class GitAuthRunner < Thor
|
|
99
93
|
$stderr.puts "Please log in as the correct user and re-run"
|
100
94
|
exit! 1
|
101
95
|
end
|
96
|
+
if !GitAuth::Repo.has_git?
|
97
|
+
$stderr.puts "'git' was not found in your path - please install it before continuing."
|
98
|
+
exit! 1
|
99
|
+
end
|
102
100
|
require 'fileutils'
|
103
101
|
folder = File.expand_path("~/.ssh")
|
104
102
|
if !File.exist?(folder) || !File.directory?(folder)
|
@@ -139,7 +137,7 @@ class GitAuthRunner < Thor
|
|
139
137
|
end
|
140
138
|
if !public_key_path.nil? && File.exist?(public_key_path)
|
141
139
|
GitAuth.setup!
|
142
|
-
created = GitAuth::
|
140
|
+
created = GitAuth::User.create("admin", true, File.read(public_key_path).strip)
|
143
141
|
if created
|
144
142
|
$stdout.puts "Admin User Created."
|
145
143
|
else
|
@@ -153,6 +151,84 @@ class GitAuthRunner < Thor
|
|
153
151
|
exit! 1
|
154
152
|
end
|
155
153
|
|
154
|
+
# Viewing Users etc
|
155
|
+
|
156
|
+
desc "repos", "Lists all the current repos handled by gitauth"
|
157
|
+
def repos
|
158
|
+
GitAuth.setup!
|
159
|
+
$stdout.puts "Repositories:"
|
160
|
+
GitAuth::Repo.all.each do |repo|
|
161
|
+
line = " - #{repo.name}"
|
162
|
+
line << " (#{repo.path})" if repo.path != repo.name
|
163
|
+
$stdout.puts line
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
desc "users", "Lists all users handled by gitauth"
|
168
|
+
def users
|
169
|
+
GitAuth.setup!
|
170
|
+
$stdout.puts "Users:"
|
171
|
+
GitAuth::User.all.each do |user|
|
172
|
+
line = "- #{user}"
|
173
|
+
line << " (admin)" if user.admin?
|
174
|
+
$stdout.puts line
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
desc "groups", "Lists all groups handled by gitauth"
|
179
|
+
def groups
|
180
|
+
GitAuth.setup!
|
181
|
+
$stdout.puts "Groups:"
|
182
|
+
GitAuth::Group.all.each do |group|
|
183
|
+
$stdout.puts "- #{group} - #{group.members.empty? ? "no members" : group.members.join(", ")}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
desc "webapp", "starts serving the GitAuth web-app on Port 8998"
|
188
|
+
def webapp
|
189
|
+
s = GitAuth.settings
|
190
|
+
if s.web_username.to_s.empty? || s.web_password_hash.to_s.empty?
|
191
|
+
$stdout.puts "To use the web interface you must first setup some credentials:"
|
192
|
+
$stdout.print "What username would you like to use? (default is 'gitauth'): "
|
193
|
+
username = Readline.readline.strip
|
194
|
+
username = "gitauth" if username.empty?
|
195
|
+
$stdout.print "What password would you like to use?: "
|
196
|
+
password = read_password
|
197
|
+
while password.empty?
|
198
|
+
$stdout.print "Please try again, What password would you like to use?: "
|
199
|
+
password = read_password
|
200
|
+
end
|
201
|
+
print "Please enter your password again: "
|
202
|
+
confirmation = read_password
|
203
|
+
while confirmation != password
|
204
|
+
print "Wrong password, please confirm again: "
|
205
|
+
confirmation = read_password
|
206
|
+
end
|
207
|
+
require 'digest/sha2'
|
208
|
+
settings = YAML.load_file(File.join(GitAuth::GITAUTH_DIR, "settings.yml"))
|
209
|
+
settings.merge!({
|
210
|
+
"web_username" => username,
|
211
|
+
"web_password_hash" => Digest::SHA256.hexdigest(password)
|
212
|
+
})
|
213
|
+
File.open(File.join(GitAuth::GITAUTH_DIR, "settings.yml"), "w+") { |f| f.write settings.to_yaml }
|
214
|
+
puts "Username and Password saved."
|
215
|
+
GitAuth.reload_settings!
|
216
|
+
end
|
217
|
+
GitAuth.serve_web!
|
218
|
+
rescue Interrupt
|
219
|
+
exit! 1
|
220
|
+
end
|
221
|
+
|
222
|
+
protected
|
223
|
+
|
224
|
+
def read_password
|
225
|
+
system "stty -echo"
|
226
|
+
line = Readline.readline.strip
|
227
|
+
system "stty echo"
|
228
|
+
print "\n"
|
229
|
+
return line
|
230
|
+
end
|
231
|
+
|
156
232
|
end
|
157
233
|
|
158
234
|
if ARGV.empty?
|
data/bin/gitauth-shell
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
#--
|
4
|
-
# Copyright (C) 2009
|
4
|
+
# Copyright (C) 2009 Brown Beagle Software
|
5
5
|
# Copyright (C) 2008 Darcy Laycock <sutto@sutto.net>
|
6
6
|
#
|
7
7
|
# This program is free software: you can redistribute it and/or modify
|
@@ -32,35 +32,5 @@ File.umask(0022)
|
|
32
32
|
user_name = ARGV[0]
|
33
33
|
command = ENV["SSH_ORIGINAL_COMMAND"]
|
34
34
|
|
35
|
-
GitAuth::Client.start!(user_name, command)
|
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
|
35
|
+
GitAuth::Client.start!(user_name, command)
|
66
36
|
|
data/lib/gitauth/client.rb
CHANGED
@@ -25,20 +25,12 @@ module GitAuth
|
|
25
25
|
attr_accessor :user, :command
|
26
26
|
|
27
27
|
def initialize(user_name, command)
|
28
|
-
GitAuth.logger.debug "Initializing client with command:
|
28
|
+
GitAuth.logger.debug "Initializing client with command: #{command.inspect} and user name #{user_name.inspect}"
|
29
29
|
@callbacks = Hash.new { |h,k| h[k] = [] }
|
30
|
-
@user = GitAuth::
|
30
|
+
@user = GitAuth::User.get(user_name.to_s.strip)
|
31
31
|
@command = command
|
32
32
|
end
|
33
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
34
|
def exit_with_error(error)
|
43
35
|
GitAuth.logger.warn "Exiting with error: #{error}"
|
44
36
|
$stderr.puts error
|
@@ -47,24 +39,30 @@ module GitAuth
|
|
47
39
|
|
48
40
|
def run!
|
49
41
|
if @user.nil?
|
50
|
-
|
42
|
+
exit_with_error "An invalid user / key was used. Please ensure it is setup with GitAuth"
|
51
43
|
elsif @command.to_s.strip.empty?
|
52
|
-
|
44
|
+
if user.shell_accessible?
|
45
|
+
exec(ENV["SHELL"])
|
46
|
+
else
|
47
|
+
exit_with_error "SSH_ORIGINAL_COMMAND is needed, mmmkay?"
|
48
|
+
end
|
53
49
|
else
|
54
50
|
command = Command.parse!(@command)
|
55
|
-
repo = Repo.get(extract_repo_name(command))
|
51
|
+
repo = command.bad? ? nil : Repo.get(extract_repo_name(command))
|
56
52
|
if command.bad?
|
57
|
-
|
53
|
+
if user.shell_accessible?
|
54
|
+
exec(@command)
|
55
|
+
else
|
56
|
+
exit_with_error "A Bad Command Has Failed Ye, Thou Shalt Not Continue."
|
57
|
+
end
|
58
58
|
elsif repo.nil?
|
59
|
-
|
59
|
+
exit_with_error "Ze repository you specified does not exist."
|
60
60
|
elsif user.can_execute?(command, repo)
|
61
|
-
# We can go ahead.
|
62
61
|
git_shell_argument = "#{command.verb} '#{repo.real_path}'"
|
63
|
-
# And execute that soab.
|
64
62
|
GitAuth.logger.info "Running command: #{git_shell_argument} for user: #{@user.name}"
|
65
63
|
exec("git-shell", "-c", git_shell_argument)
|
66
64
|
else
|
67
|
-
|
65
|
+
exit_with_error "These are not the droids you are looking for"
|
68
66
|
end
|
69
67
|
end
|
70
68
|
rescue Exception => e
|
@@ -72,7 +70,7 @@ module GitAuth
|
|
72
70
|
e.backtrace.each do |l|
|
73
71
|
GitAuth.logger.fatal " => #{l}"
|
74
72
|
end
|
75
|
-
|
73
|
+
exit_with_error "Holy crap, we've imploded cap'n!"
|
76
74
|
end
|
77
75
|
|
78
76
|
def self.start!(user, command)
|
data/lib/gitauth/command.rb
CHANGED
@@ -34,7 +34,7 @@ module GitAuth
|
|
34
34
|
# Standard Commands
|
35
35
|
READ_COMMANDS = ["git-upload-pack", "git upload-pack"]
|
36
36
|
WRITE_COMMANDS = ["git-receive-pack", "git receive-pack"]
|
37
|
-
PATH_REGEXP = /^'([
|
37
|
+
PATH_REGEXP = /^'([\w\_\-\.\+]+(\.git)?)'$/i.freeze
|
38
38
|
|
39
39
|
attr_reader :path, :verb, :command
|
40
40
|
|
@@ -61,7 +61,7 @@ module GitAuth
|
|
61
61
|
# These exceptions are FUGLY.
|
62
62
|
# Clean up, mmkay?
|
63
63
|
def process!
|
64
|
-
raise BadCommandError if @command.include?("\n")
|
64
|
+
raise BadCommandError if @command.include?("\n") || @command !~ /^git/i
|
65
65
|
@verb, @argument = split_command
|
66
66
|
raise BadCommandError if @argument.nil? || @argument.is_a?(Array)
|
67
67
|
# Check if it's read / write
|
@@ -0,0 +1,86 @@
|
|
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
|
+
|
20
|
+
module GitAuth
|
21
|
+
class Group < SaveableClass(:groups)
|
22
|
+
|
23
|
+
attr_accessor :name, :members
|
24
|
+
|
25
|
+
def initialize(name)
|
26
|
+
@name = name
|
27
|
+
@members = []
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy!
|
31
|
+
GitAuth::Repo.all.each { |r| r.remove_permissions_for(self) }
|
32
|
+
self.class.all.each { |r| r.remove_member(self) }
|
33
|
+
self.class.all.reject! { |g| g == self }
|
34
|
+
GitAuth::Repo.save!
|
35
|
+
self.class.save!
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_member(member)
|
39
|
+
return if member == self
|
40
|
+
@members << member.to_s
|
41
|
+
@members.uniq!
|
42
|
+
end
|
43
|
+
|
44
|
+
def remove_member(member)
|
45
|
+
@members.reject! { |m| m == member.to_s }
|
46
|
+
end
|
47
|
+
|
48
|
+
def ==(group)
|
49
|
+
group.is_a?(Group) && group.name == self.name
|
50
|
+
end
|
51
|
+
|
52
|
+
def member?(user_or_group, recurse = false, level = 0)
|
53
|
+
member = @members.include?(user_or_group.to_s)
|
54
|
+
Thread.current[:checked_groups] = [] if level == 0
|
55
|
+
if !member
|
56
|
+
return false if level > 0 && Thread.current[:checked_groups].include?(self)
|
57
|
+
Thread.current[:checked_groups] << self
|
58
|
+
member = recurse && @members.map { |m| Group.get(m) }.compact.any? { |g| g.member?(user_or_group, true, level + 1) }
|
59
|
+
end
|
60
|
+
Thread.current[:checked_groups] = nil if level == 0
|
61
|
+
return member
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_s
|
65
|
+
"@#{name}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.create(name)
|
69
|
+
name = name.to_s.strip.gsub(/^@/, "")
|
70
|
+
return false if name.empty? || name !~ /^([\w\_\-\.]+)$/
|
71
|
+
self.add_item self.new(name)
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.get(name)
|
76
|
+
GitAuth.logger.debug "Getting group named #{name.inspect}"
|
77
|
+
real_name = name.to_s.gsub(/^@/, "")
|
78
|
+
self.all.detect { |g| g.name == real_name }
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.group?(name)
|
82
|
+
name.to_s =~ /^@/ && !get(name).nil?
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
data/lib/gitauth/repo.rb
CHANGED
@@ -18,28 +18,8 @@
|
|
18
18
|
|
19
19
|
require 'fileutils'
|
20
20
|
module GitAuth
|
21
|
-
class Repo
|
22
|
-
|
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
|
21
|
+
class Repo < SaveableClass(:repositories)
|
22
|
+
NAME_RE = /^([\w\_\-\.\+]+(\.git)?)$/i
|
43
23
|
|
44
24
|
def self.get(name)
|
45
25
|
GitAuth.logger.debug "Getting Repo w/ name: '#{name}'"
|
@@ -47,43 +27,55 @@ module GitAuth
|
|
47
27
|
end
|
48
28
|
|
49
29
|
def self.create(name, path = name)
|
50
|
-
return false
|
30
|
+
return false if name.nil? || path.nil?
|
31
|
+
return false if self.get(name) || self.all.any? { |r| r.path == path } || name !~ NAME_RE || path !~ NAME_RE
|
51
32
|
repository = self.new(name, path)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
self.save!
|
56
|
-
return true
|
57
|
-
else
|
58
|
-
return false
|
59
|
-
end
|
33
|
+
return false unless repository.create_repo!
|
34
|
+
self.add_item(repository)
|
35
|
+
return true
|
60
36
|
end
|
61
37
|
|
62
|
-
attr_accessor :name, :path
|
38
|
+
attr_accessor :name, :path, :permissions
|
63
39
|
|
64
40
|
def initialize(name, path, auto_create = false)
|
65
41
|
@name, @path = name, path
|
66
42
|
@permissions = {}
|
67
43
|
end
|
68
44
|
|
69
|
-
def
|
45
|
+
def ==(other)
|
46
|
+
other.is_a?(Repo) && other.name == name && other.path == path
|
47
|
+
end
|
48
|
+
|
49
|
+
def writeable_by(user_or_group)
|
70
50
|
@permissions[:write] ||= []
|
71
|
-
@permissions[:write] <<
|
51
|
+
@permissions[:write] << user_or_group.to_s
|
72
52
|
@permissions[:write].uniq!
|
73
53
|
end
|
74
54
|
|
75
|
-
def readable_by(
|
55
|
+
def readable_by(user_or_group)
|
76
56
|
@permissions[:read] ||= []
|
77
|
-
@permissions[:read] <<
|
57
|
+
@permissions[:read] << user_or_group.to_s
|
78
58
|
@permissions[:read].uniq!
|
79
59
|
end
|
80
60
|
|
81
|
-
def writeable_by?(
|
82
|
-
(@permissions[:write] || []).
|
61
|
+
def writeable_by?(user_or_group)
|
62
|
+
!(@permissions[:write] || []).detect do |writer|
|
63
|
+
writer = GitAuth.get_user_or_group(writer)
|
64
|
+
writer == user_or_group || (writer.is_a?(Group) && writer.member?(user_or_group, true))
|
65
|
+
end.nil?
|
83
66
|
end
|
84
67
|
|
85
|
-
def readable_by?(
|
86
|
-
(@permissions[:read] || []).
|
68
|
+
def readable_by?(user_or_group)
|
69
|
+
!(@permissions[:read] || []).detect do |reader|
|
70
|
+
reader = GitAuth.get_user_or_group(reader)
|
71
|
+
reader == user_or_group || (reader.is_a?(Group) && reader.member?(user_or_group, true))
|
72
|
+
end.nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
def remove_permissions_for(user_or_group)
|
76
|
+
@permissions.each_value do |val|
|
77
|
+
val.reject! { |m| m == user_or_group.to_s }
|
78
|
+
end
|
87
79
|
end
|
88
80
|
|
89
81
|
def real_path
|
@@ -91,6 +83,7 @@ module GitAuth
|
|
91
83
|
end
|
92
84
|
|
93
85
|
def create_repo!
|
86
|
+
return false if !self.class.has_git?
|
94
87
|
path = self.real_path
|
95
88
|
unless File.exist?(path) && File.directory?(path)
|
96
89
|
FileUtils.mkdir_p(path)
|
@@ -102,5 +95,15 @@ module GitAuth
|
|
102
95
|
end
|
103
96
|
end
|
104
97
|
|
98
|
+
def destroy!
|
99
|
+
FileUtils.rm_rf(self.real_path) if File.exist?(self.real_path)
|
100
|
+
self.class.all.reject! { |r| r == self }
|
101
|
+
self.class.save!
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.has_git?
|
105
|
+
!`which git`.strip.empty?
|
106
|
+
end
|
107
|
+
|
105
108
|
end
|
106
109
|
end
|
@@ -0,0 +1,60 @@
|
|
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
|
+
|
20
|
+
module GitAuth
|
21
|
+
def self.SaveableClass(kind)
|
22
|
+
klass = Class.new
|
23
|
+
path_name = "#{kind.to_s.upcase}_PATH"
|
24
|
+
yaml_file_name = "#{kind}.yml"
|
25
|
+
|
26
|
+
saveable_class_def = <<-END
|
27
|
+
|
28
|
+
#{path_name} = File.join(GitAuth::GITAUTH_DIR, #{yaml_file_name.inspect})
|
29
|
+
|
30
|
+
def self.all
|
31
|
+
@@all_#{kind} ||= nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.all=(value)
|
35
|
+
@@all_#{kind} = value
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.load!
|
39
|
+
self.all = YAML.load_file(#{path_name}) rescue nil if File.exist?(#{path_name})
|
40
|
+
self.all = [] unless self.all.is_a?(Array)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.save!
|
44
|
+
load! if self.all.nil?
|
45
|
+
File.open(#{path_name}, "w+") do |f|
|
46
|
+
f.write self.all.to_yaml
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.add_item(item)
|
51
|
+
self.load! if self.all.nil?
|
52
|
+
self.all << item
|
53
|
+
self.save!
|
54
|
+
end
|
55
|
+
|
56
|
+
END
|
57
|
+
klass.class_eval(saveable_class_def)
|
58
|
+
return klass
|
59
|
+
end
|
60
|
+
end
|