mbbx6spp-gitauth 0.0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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