mbbx6spp-gitauth 0.0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +661 -0
- data/README.rdoc +141 -0
- data/USAGE +70 -0
- data/bin/gitauth +261 -0
- data/bin/gitauth-shell +30 -0
- data/config.ru +16 -0
- data/lib/gitauth/apache_authentication.rb +64 -0
- data/lib/gitauth/auth_setup_middleware.rb +53 -0
- data/lib/gitauth/client.rb +95 -0
- data/lib/gitauth/command.rb +101 -0
- data/lib/gitauth/group.rb +87 -0
- data/lib/gitauth/message.rb +69 -0
- data/lib/gitauth/repo.rb +155 -0
- data/lib/gitauth/saveable_class.rb +54 -0
- data/lib/gitauth/user.rb +135 -0
- data/lib/gitauth/web_app.rb +314 -0
- data/lib/gitauth.rb +101 -0
- data/public/gitauth.css +316 -0
- data/public/gitauth.js +17 -0
- data/public/jquery.js +19 -0
- data/resources/messages.yml +9 -0
- data/views/auth_setup.erb +27 -0
- data/views/clone_repo.erb +24 -0
- data/views/group.erb +24 -0
- data/views/index.erb +88 -0
- data/views/layout.erb +27 -0
- data/views/repo.erb +57 -0
- data/views/user.erb +51 -0
- metadata +196 -0
@@ -0,0 +1,314 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2009 Brown Beagle Software
|
3
|
+
# Copyright (C) 2009 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 'rack'
|
20
|
+
require 'sinatra'
|
21
|
+
require 'digest/sha2'
|
22
|
+
|
23
|
+
module GitAuth
|
24
|
+
class WebApp < Sinatra::Base
|
25
|
+
include GitAuth::Loggable
|
26
|
+
|
27
|
+
cattr_accessor :current_server
|
28
|
+
|
29
|
+
def self.has_auth?
|
30
|
+
username = GitAuth::Settings["web_username"]
|
31
|
+
password = GitAuth::Settings["web_password_hash"]
|
32
|
+
!(username.blank? || password.blank?)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.update_auth
|
36
|
+
raw_username = Readline.readline('GitAuth Username (default is \'gitauth\'): ')
|
37
|
+
raw_username = 'gitauth' if raw_username.blank?
|
38
|
+
raw_password = ''
|
39
|
+
while raw_password.blank?
|
40
|
+
system "stty -echo"
|
41
|
+
raw_password = Readline.readline('GitAuth Password: ')
|
42
|
+
system "stty echo"
|
43
|
+
print "\n"
|
44
|
+
puts "You need to provide a password, please try again" if raw_password.blank?
|
45
|
+
end
|
46
|
+
password_confirmation = nil
|
47
|
+
while password_confirmation != raw_password
|
48
|
+
system "stty -echo"
|
49
|
+
password_confirmation = Readline.readline('Confirm Password: ')
|
50
|
+
system "stty echo"
|
51
|
+
print "\n"
|
52
|
+
puts "The confirmation doesn't match your password, please try again" if raw_password != password_confirmation
|
53
|
+
end
|
54
|
+
GitAuth::Settings.update!({
|
55
|
+
:web_username => raw_username,
|
56
|
+
:web_password_hash => Digest::SHA256.hexdigest(raw_password)
|
57
|
+
})
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.check_auth
|
61
|
+
GitAuth.prepare
|
62
|
+
if !has_auth?
|
63
|
+
if $stderr.tty?
|
64
|
+
logger.verbose = true
|
65
|
+
puts "For gitauth to continue, you need to provide a username and password."
|
66
|
+
update_auth
|
67
|
+
else
|
68
|
+
logger.fatal "You need to provide a username and password for GitAuth to function; Please run 'gitauth webapp` once"
|
69
|
+
exit!
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.run(options = {})
|
75
|
+
check_auth
|
76
|
+
set options
|
77
|
+
handler = detect_rack_handler
|
78
|
+
handler_name = handler.name.gsub(/.*::/, '')
|
79
|
+
logger.info "Starting up web server on #{port}"
|
80
|
+
handler.run self, :Host => host, :Port => port do |server|
|
81
|
+
GitAuth::WebApp.current_server = server
|
82
|
+
set :running, true
|
83
|
+
end
|
84
|
+
rescue Errno::EADDRINUSE => e
|
85
|
+
logger.fatal "Server is already running on port #{port}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.stop
|
89
|
+
if current_server.present?
|
90
|
+
current_server.respond_to?(:stop!) ? current_server.stop! : current_server.stop
|
91
|
+
end
|
92
|
+
exit!
|
93
|
+
logger.debug "Stopped Server."
|
94
|
+
end
|
95
|
+
|
96
|
+
unless GitAuth::ApacheAuthentication.setup?
|
97
|
+
|
98
|
+
use GitAuth::AuthSetupMiddleware
|
99
|
+
|
100
|
+
use Rack::Auth::Basic do |username, password|
|
101
|
+
[username, Digest::SHA256.hexdigest(password)] == [GitAuth::Settings["web_username"], GitAuth::Settings["web_password_hash"]]
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
configure do
|
107
|
+
set :port, 8998
|
108
|
+
set :views, GitAuth::BASE_DIR.join("views")
|
109
|
+
set :public, GitAuth::BASE_DIR.join("public")
|
110
|
+
set :static, true
|
111
|
+
set :methodoverride, true
|
112
|
+
end
|
113
|
+
|
114
|
+
before { GitAuth.reload_models! }
|
115
|
+
|
116
|
+
helpers do
|
117
|
+
include Rack::Utils
|
118
|
+
alias_method :h, :escape_html
|
119
|
+
|
120
|
+
def link_to(text, link)
|
121
|
+
"<a href='#{u link}'>#{text}</a>"
|
122
|
+
end
|
123
|
+
|
124
|
+
def u(url)
|
125
|
+
"#{request.script_name}#{url}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def delete_link(text, url)
|
129
|
+
id = "deleteable-#{Digest::SHA256.hexdigest(url.to_s)[0, 6]}"
|
130
|
+
html = "<div class='deletable-container' style='display: none; margin: 0; padding: 0;'>"
|
131
|
+
html << "<form method='post' action='#{u url}' id='#{id}'>"
|
132
|
+
html << "<input name='_method' type='hidden' value='delete' />"
|
133
|
+
html << "</form></div>"
|
134
|
+
html << "<a href='#' onclick='if(confirm(\"Are you sure you want to do that? Deletion can not be reversed.\")) $(\"##{id}\").submit(); return false;'>#{text}</a>"
|
135
|
+
return html
|
136
|
+
end
|
137
|
+
|
138
|
+
def auto_link(member)
|
139
|
+
member = member.to_s
|
140
|
+
url = (member[0] == ?@ ? "/groups/#{URI.encode(member[1..-1])}" : "/users/#{URI.encode(member)}")
|
141
|
+
return link_to(member, url)
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
get '/' do
|
147
|
+
@repos = GitAuth::Repo.all
|
148
|
+
@users = GitAuth::User.all
|
149
|
+
@groups = GitAuth::Group.all
|
150
|
+
erb :index
|
151
|
+
end
|
152
|
+
|
153
|
+
# Listing / Index Page
|
154
|
+
|
155
|
+
get '/repos/:name' do
|
156
|
+
@repo = GitAuth::Repo.get(params[:name])
|
157
|
+
if @repo.nil?
|
158
|
+
redirect root_with_message("The given repository couldn't be found.")
|
159
|
+
else
|
160
|
+
read_perms, write_perms = (@repo.permissions[:read]||[]), (@repo.permissions[:write]||[])
|
161
|
+
@all_access = read_perms & write_perms
|
162
|
+
@read_only = read_perms - @all_access
|
163
|
+
@write_only = write_perms - @all_access
|
164
|
+
erb :repo
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
get '/users/:name' do
|
169
|
+
@user = GitAuth::User.get(params[:name])
|
170
|
+
if @user.nil?
|
171
|
+
redirect root_with_message("The given user couldn't be found.")
|
172
|
+
else
|
173
|
+
repos = GitAuth::Repo.all
|
174
|
+
read_perms = repos.select { |r| r.readable_by?(@user) }
|
175
|
+
write_perms = repos.select { |r| r.writeable_by?(@user) }
|
176
|
+
@all_access = read_perms & write_perms
|
177
|
+
@read_only = read_perms - @all_access
|
178
|
+
@write_only = write_perms - @all_access
|
179
|
+
@groups = GitAuth::Group.all.select { |g| g.member?(@user) }
|
180
|
+
erb :user
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
get '/groups/:name' do
|
185
|
+
@group = GitAuth::Group.get(params[:name])
|
186
|
+
if @group.nil?
|
187
|
+
redirect root_with_message("The given group could not be found.")
|
188
|
+
else
|
189
|
+
erb :group
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Create and update repos
|
194
|
+
|
195
|
+
post '/repos' do
|
196
|
+
name = params[:repo][:name]
|
197
|
+
path = params[:repo][:path]
|
198
|
+
path = name if path.to_s.strip.empty?
|
199
|
+
if repo = GitAuth::Repo.create(name, path)
|
200
|
+
make_empty = (params[:repo][:make_empty] == "1")
|
201
|
+
repo.make_empty! if make_empty
|
202
|
+
if repo.execute_post_create_hook!
|
203
|
+
redirect u("/?repo_name=#{URI.encode(name)}&made_empty=#{make_empty ? "yes" : "no"}")
|
204
|
+
else
|
205
|
+
redirect root_with_message("Repository added but the post-create hook exited unsuccessfully.")
|
206
|
+
end
|
207
|
+
else
|
208
|
+
redirect root_with_message("There was an error adding the repository.")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
post '/repos/:name' do
|
213
|
+
repo = GitAuth::Repo.get(params[:name])
|
214
|
+
if repo.nil?
|
215
|
+
redirect root_with_message("The given repository couldn't be found.")
|
216
|
+
else
|
217
|
+
new_permissions = Hash.new([])
|
218
|
+
[:all, :read, :write].each do |k|
|
219
|
+
if params[:repo][k]
|
220
|
+
perm_lines = params[:repo][k].to_s.split("\n")
|
221
|
+
new_permissions[k] = perm_lines.map do |l|
|
222
|
+
i = GitAuth.get_user_or_group(l.strip)
|
223
|
+
i.nil? ? nil : i.to_s
|
224
|
+
end.compact
|
225
|
+
end
|
226
|
+
end
|
227
|
+
all = new_permissions.delete(:all)
|
228
|
+
new_permissions[:read] |= all
|
229
|
+
new_permissions[:write] |= all
|
230
|
+
new_permissions.each_value { |v| v.uniq! }
|
231
|
+
repo.permissions = new_permissions
|
232
|
+
GitAuth::Repo.save!
|
233
|
+
redirect u("/repos/#{URI.encode(repo.name)}")
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
delete '/repos/:name' do
|
238
|
+
repo = GitAuth::Repo.get(params[:name])
|
239
|
+
if repo.nil?
|
240
|
+
redirect root_with_message("The given repository couldn't be found.")
|
241
|
+
else
|
242
|
+
repo.destroy!
|
243
|
+
redirect root_with_message("Repository removed.")
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# Create, delete and update users
|
248
|
+
|
249
|
+
post '/users' do
|
250
|
+
name = params[:user][:name]
|
251
|
+
admin = params[:user][:admin].to_s == "1"
|
252
|
+
key = params[:user][:key]
|
253
|
+
if GitAuth::User.create(name, admin, key)
|
254
|
+
redirect root_with_message("User Added")
|
255
|
+
else
|
256
|
+
redirect root_with_message("There was an error adding the requested user.")
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
delete '/users/:name' do
|
261
|
+
user = GitAuth::User.get(params[:name])
|
262
|
+
if user.nil?
|
263
|
+
redirect root_with_message("The specified user couldn't be found.")
|
264
|
+
else
|
265
|
+
user.destroy!
|
266
|
+
redirect root_with_message("User removed.")
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Create and Update Groups
|
271
|
+
|
272
|
+
post '/groups' do
|
273
|
+
if GitAuth::Group.create(params[:group][:name])
|
274
|
+
redirect root_with_message("Group added")
|
275
|
+
else
|
276
|
+
redirect root_with_message("There was an error adding the requested group.")
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
post '/groups/:name' do
|
281
|
+
group = GitAuth::Group.get(params[:name])
|
282
|
+
if group.nil?
|
283
|
+
redirect root_with_message("The specified group couldn't be found.")
|
284
|
+
else
|
285
|
+
if params[:group][:members]
|
286
|
+
member_lines = params[:group][:members].to_s.split("\n")
|
287
|
+
group.members = member_lines.map do |l|
|
288
|
+
i = GitAuth.get_user_or_group(l.strip)
|
289
|
+
i.nil? ? nil : i.to_s
|
290
|
+
end.compact - [group.to_s]
|
291
|
+
GitAuth::Group.save!
|
292
|
+
end
|
293
|
+
redirect u("/groups/#{URI.encode(group.name)}")
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
delete '/groups/:name' do
|
298
|
+
group = GitAuth::Group.get(params[:name])
|
299
|
+
if group.nil?
|
300
|
+
redirect root_with_message("The specified group couldn't be found.")
|
301
|
+
else
|
302
|
+
group.destroy!
|
303
|
+
redirect root_with_message("Group removed.")
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# Misc Helpers
|
308
|
+
|
309
|
+
def root_with_message(message)
|
310
|
+
u("/?message=#{URI.encode(message)}")
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|
314
|
+
end
|
data/lib/gitauth.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2009 Brown Beagle Software
|
3
|
+
# Copyright (C) 2009 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 'rubygems'
|
20
|
+
require 'pathname'
|
21
|
+
|
22
|
+
# Prepend lib dir + any vendored lib's to the front of the load
|
23
|
+
# path to ensure they're loaded first.
|
24
|
+
$LOAD_PATH.unshift(*Dir[Pathname(__FILE__).dirname.join("../{lib,vendor/*/lib}").expand_path.to_s])
|
25
|
+
|
26
|
+
require 'perennial'
|
27
|
+
|
28
|
+
module GitAuth
|
29
|
+
include Perennial
|
30
|
+
include Loggable
|
31
|
+
|
32
|
+
VERSION = [0, 0, 5, 2]
|
33
|
+
BASE_DIR = Pathname(__FILE__).dirname.join("..").expand_path
|
34
|
+
GITAUTH_DIR = Pathname("~/.gitauth/").expand_path
|
35
|
+
|
36
|
+
manifest do |m, l|
|
37
|
+
Settings.root = File.dirname(__FILE__)
|
38
|
+
Settings.default_settings_path = GITAUTH_DIR.join("settings.yml")
|
39
|
+
Settings.lookup_key_path = []
|
40
|
+
Logger.default_logger_path = GITAUTH_DIR.join("gitauth.log")
|
41
|
+
# Register stuff on the loader.
|
42
|
+
l.register_controller :web_app, 'GitAuth::WebApp'
|
43
|
+
l.before_run { GitAuth.prepare }
|
44
|
+
end
|
45
|
+
|
46
|
+
require 'gitauth/message' # Basic error messages etc (as of yet unushed)
|
47
|
+
require 'gitauth/saveable_class' # Simple YAML store for dumpables classes
|
48
|
+
require 'gitauth/repo' # The basic GitAuth repo object
|
49
|
+
require 'gitauth/user' # The basic GitAuth user object
|
50
|
+
require 'gitauth/group' # The basic GitAuth group object (collection of users)
|
51
|
+
require 'gitauth/command' # Processes / filters commands
|
52
|
+
require 'gitauth/client' # Handles the actual SSH interaction / bringing it together
|
53
|
+
|
54
|
+
autoload :AuthSetupMiddleware, 'gitauth/auth_setup_middleware'
|
55
|
+
autoload :ApacheAuthentication, 'gitauth/apache_authentication'
|
56
|
+
autoload :WebApp, 'gitauth/web_app'
|
57
|
+
|
58
|
+
class << self
|
59
|
+
|
60
|
+
def prepare
|
61
|
+
GitAuth::Settings.setup!
|
62
|
+
reload_models!
|
63
|
+
end
|
64
|
+
|
65
|
+
def version
|
66
|
+
VERSION.join(".")
|
67
|
+
end
|
68
|
+
|
69
|
+
def msg(type, message)
|
70
|
+
Message.new(type, message)
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_user_or_group(name)
|
74
|
+
name = name.to_s.strip
|
75
|
+
return if name.empty?
|
76
|
+
(name =~ /^@/ ? Group : User).get(name)
|
77
|
+
end
|
78
|
+
|
79
|
+
def has_git?
|
80
|
+
!`which git`.blank?
|
81
|
+
end
|
82
|
+
|
83
|
+
def each_model(method = nil, &blk)
|
84
|
+
[Repo, User, Group].each { |m| m.send(method) } if method.present?
|
85
|
+
[Repo, User, Group].each(&blk) unless blk.nil?
|
86
|
+
end
|
87
|
+
|
88
|
+
def reload_models!
|
89
|
+
each_model(:load!)
|
90
|
+
end
|
91
|
+
|
92
|
+
def run(command)
|
93
|
+
GitAuth::Logger.info "Running command: #{command}"
|
94
|
+
result = system "#{command} 2> /dev/null 1> /dev/null"
|
95
|
+
GitAuth::Logger.info "Command was #{"not " if !result}successful"
|
96
|
+
return result
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|