omnigollum 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6433e6d7b91b97428df0d818edad425d84b13e12
4
+ data.tar.gz: 54e215475b725c404151388c7179666019d61dbe
5
+ SHA512:
6
+ metadata.gz: f62358d2eb2bfc45fb6d4ebedc223c82f538d49a8801a1caaab8637f810853ae8597c0cfe4d7529ad338583f628a9dbb16e334d606f0b4132d0c1a371898dee8
7
+ data.tar.gz: 1ef15b097f7833ff8f987b730e62dceb9d2ade100681183e7fc9e3d0559fd60bf596489372967220a06abfe6a36c6acdd797a15e1c1139021a6c108c699352eb
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2012-2013 Arran Cudbard-Bell
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the 'Software'), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,103 @@
1
+ # omnigollum - omniauth meets gollum
2
+
3
+ ## Quick Installation/Configuration
4
+
5
+ ```
6
+ $ git clone https://github.com/arr2036/omnigollum.git
7
+ $ cd omnigollum
8
+ $ gem build omnigollum.gemspec
9
+ $ gem install omnigollum*.gem
10
+ ```
11
+
12
+ ```sh
13
+ $ cp config.rb.example config.rb
14
+ ```
15
+ Customize config.rb to use your preferred omniauth strategy.
16
+
17
+ Execute via Gollum
18
+ ```sh
19
+ $ gollum --config config.rb
20
+ ```
21
+
22
+ ## Installation
23
+
24
+ ### Manual
25
+
26
+ Clone into your ruby library path.
27
+
28
+ git clone git://github.com/arr2036/omnigollum.git
29
+
30
+ ## Configuration
31
+
32
+ Omnigollum executes an OmniAuth::Builder proc/block to figure out which providers you've configured,
33
+ then passes it on to omniauth to create the actual omniauth configuration.
34
+
35
+ To configure both omniauth and omnigollum you should add the following to your config.ru file.
36
+
37
+ ### Load omnigollum library
38
+ ```ruby
39
+ require 'omnigollum'
40
+ ```
41
+
42
+ ### Load individual provider libraries
43
+ ```ruby
44
+ require 'omniauth/strategies/twitter'
45
+ require 'omniauth/strategies/open_id'
46
+ ```
47
+
48
+ ### Set configuration
49
+ ```ruby
50
+ options = {
51
+ # OmniAuth::Builder block is passed as a proc
52
+ :providers => Proc.new do
53
+ provider :twitter, 'CONSUMER_KEY', 'CONSUMER_SECRET'
54
+ provider :open_id, OpenID::Store::Filesystem.new('/tmp')
55
+ end,
56
+ :dummy_auth => false
57
+ }
58
+
59
+ # :omnigollum options *must* be set before the Omnigollum extension is registered
60
+ Precious::App.set(:omnigollum, options)
61
+ ```
62
+
63
+ ### Access control
64
+
65
+ By default, any authenticated user will be able to access the protected routes. Restrict this by setting the `authorized_users` option.
66
+
67
+ `authorized_users` accepts an array of emails. Users must authenticate with one of these authorized emails in order to be allowed access.
68
+
69
+ ```ruby
70
+ options[:authorized_users] = ["example0@example.org", "example1@example.org", "example2@example.org"]
71
+ ```
72
+
73
+ Instead of setting these directly, you can use an [env var](http://www.12factor.net/config), maybe like this:
74
+
75
+ ```ruby
76
+ # in .env, or other
77
+ # OMNIGOLLUM_AUTHORIZED_USERS=example0@example.org,example1@example.org,example2@example.org
78
+
79
+ options[:authorized_users] = ENV["OMNIGOLLUM_AUTHORIZED_USERS"].split(",")
80
+ ```
81
+
82
+ ### Register omnigollum extension with sinatra
83
+ ```ruby
84
+ Precious::App.register Omnigollum::Sinatra
85
+ ```
86
+
87
+ ## Required patches
88
+
89
+ ### mustache
90
+
91
+ https://github.com/defunkt/mustache
92
+
93
+ Must be at v0.99.5 (currently unreleased), replace the gem version with 6c4e12d58844d99909df or
94
+ the current HEAD.
95
+
96
+ Feel free to complain loudly that the maintainer should roll a new gem.
97
+
98
+ ### Gollum
99
+ You can also (optionally) apply the patches here, to get a neat little auth
100
+ status widget in the top right corner of the page https://github.com/arr2036/gollum/commit/32de2cad920ccc6e955b8e19f6e23c2b3b4c8964
101
+
102
+
103
+
@@ -0,0 +1,297 @@
1
+ require 'cgi'
2
+ require 'omniauth'
3
+ require 'mustache/sinatra'
4
+ require 'sinatra/base'
5
+
6
+ module Omnigollum
7
+ module Views; class Layout < Mustache; end; end
8
+ module Models
9
+ class OmniauthUserInitError < StandardError; end
10
+
11
+ class User
12
+ attr_reader :uid, :name, :email, :nickname, :provider
13
+ end
14
+
15
+ class OmniauthUser < User
16
+ def initialize (hash, options)
17
+ # Validity checks, don't trust providers
18
+ @uid = hash['uid'].to_s.strip
19
+ raise OmniauthUserInitError, "Insufficient data from authentication provider, uid not provided or empty" if @uid.empty?
20
+
21
+ @name = hash['info']['name'].to_s.strip if hash['info'].has_key?('name')
22
+ @name = options[:default_name] if !@name || @name.empty?
23
+
24
+ raise OmniauthUserInitError, "Insufficient data from authentication provider, name not provided or empty" if !@name || @name.empty?
25
+
26
+ @email = hash['info']['email'].to_s.strip if hash['info'].has_key?('email')
27
+ @email = options[:default_email] if !@email || @email.empty?
28
+
29
+ raise OmniauthUserInitError, "Insufficient data from authentication provider, email not provided or empty" if !@email || @email.empty?
30
+
31
+ @nickname = hash['info']['nickname'].to_s.strip if hash['info'].has_key?('nickname')
32
+
33
+ @provider = hash['provider']
34
+
35
+ self
36
+ end
37
+ end
38
+ end
39
+
40
+ module Helpers
41
+ def user_authed?
42
+ session.has_key? :omniauth_user
43
+ end
44
+
45
+ def user_auth
46
+ @title = 'Authentication is required'
47
+ @subtext = 'Please choose a login service'
48
+ show_login
49
+ end
50
+
51
+ def kick_back
52
+ redirect !request.referrer.nil? && request.referrer !~ /#{Regexp.escape(settings.send(:omnigollum)[:route_prefix])}\/.*/ ?
53
+ request.referrer:
54
+ '/'
55
+ halt
56
+ end
57
+
58
+ def get_user
59
+ session[:omniauth_user]
60
+ end
61
+
62
+ def user_deauth
63
+ session.delete :omniauth_user
64
+ end
65
+
66
+ def auth_config
67
+ options = settings.send(:omnigollum)
68
+
69
+ @auth = {
70
+ :route_prefix => options[:route_prefix],
71
+ :providers => options[:provider_names],
72
+ :path_images => options[:path_images],
73
+ :logo_suffix => options[:logo_suffix],
74
+ :logo_missing => options[:logo_missing]
75
+ }
76
+ end
77
+
78
+ def show_login
79
+ options = settings.send(:omnigollum)
80
+
81
+ # Don't bother showing the login screen, just redirect
82
+ if options[:provider_names].count == 1
83
+ if !request.params['origin'].nil?
84
+ origin = request.params['origin']
85
+ elsif !request.path.nil?
86
+ origin = request.path
87
+ else
88
+ origin = '/'
89
+ end
90
+
91
+ redirect options[:route_prefix] + '/auth/' + options[:provider_names].first.to_s + "?origin=" +
92
+ CGI.escape(origin)
93
+ else
94
+ auth_config
95
+ require options[:path_views] + '/login'
96
+ halt mustache Omnigollum::Views::Login
97
+ end
98
+ end
99
+
100
+ def commit_message
101
+ if user_authed?
102
+ user = get_user
103
+ return { :message => params[:message], :name => user.name, :email => user.email}
104
+ else
105
+ return { :message => params[:message]}
106
+ end
107
+ end
108
+ end
109
+
110
+ # Config class provides default values for omnigollum configuration, and an array
111
+ # of all providers which have been enabled if a omniauth config block is passed to
112
+ # eval_omniauth_config.
113
+ class Config
114
+ attr_accessor :default_options
115
+ class << self; attr_accessor :default_options; end
116
+
117
+ @default_options = {
118
+ :protected_routes => [
119
+ '/revert/*',
120
+ '/revert',
121
+ '/create/*',
122
+ '/create',
123
+ '/edit/*',
124
+ '/edit',
125
+ '/delete/*',
126
+ '/delete'],
127
+
128
+ :route_prefix => '/__omnigollum__',
129
+ :dummy_auth => true,
130
+ :providers => Proc.new { provider :github, '', '' },
131
+ :path_base => dir = File.expand_path(File.dirname(__FILE__) + '/..'),
132
+ :logo_suffix => "_logo.png",
133
+ :logo_missing => "omniauth", # Set to false to disable missing logos
134
+ :path_images => "#{dir}/public/images",
135
+ :path_views => "#{dir}/views",
136
+ :path_templates => "#{dir}/templates",
137
+ :default_name => nil,
138
+ :default_email => nil,
139
+ :provider_names => [],
140
+ :authorized_users => [],
141
+ :author_format => Proc.new { |user| user.nickname ? user.name + ' (' + user.nickname + ')' : user.name },
142
+ }
143
+
144
+ def initialize
145
+ @default_options = self.class.default_options
146
+ end
147
+
148
+ # Register provider name
149
+ #
150
+ # name - Provider symbol
151
+ # args - Arbitrary arguments
152
+ def provider(name, *args)
153
+ @default_options[:provider_names].push name
154
+ end
155
+
156
+ # Evaluate procedure calls in an omniauth config block/proc in the context
157
+ # of this class.
158
+ #
159
+ # This allows us to learn about omniauth config items that would otherwise be inaccessible.
160
+ #
161
+ # block - Omniauth proc or block
162
+ def eval_omniauth_config(&block)
163
+ self.instance_eval(&block)
164
+ end
165
+
166
+ # Catches missing methods we haven't implemented, but which omniauth accepts
167
+ # in its config block.
168
+ #
169
+ # args - Arbitrary list of arguments
170
+ def method_missing(*args); end
171
+ end
172
+
173
+ module Sinatra
174
+ def self.registered(app)
175
+ # As options determine which routes are created, they must be set before registering omniauth
176
+ config = Omnigollum::Config.new
177
+
178
+ options = app.settings.respond_to?(:omnigollum) ?
179
+ config.default_options.merge(app.settings.send(:omnigollum)) :
180
+ config.default_options
181
+
182
+ # Set omniauth path prefix based on options
183
+ OmniAuth.config.path_prefix = options[:route_prefix] + OmniAuth.config.path_prefix
184
+
185
+ # Setup test_mode options
186
+ if options[:dummy_auth]
187
+ OmniAuth.config.test_mode = true
188
+ OmniAuth.config.mock_auth[:default] = {
189
+ 'uid' => '12345',
190
+ "info" => {
191
+ "email" => "user@example.com",
192
+ "name" => "example user"
193
+ },
194
+ 'provider' => 'local'
195
+ }
196
+ end
197
+ # Register helpers
198
+ app.helpers Helpers
199
+
200
+ # Enable sinatra session support
201
+ app.set :sessions, true
202
+
203
+ # Setup omniauth providers
204
+ if !options[:providers].nil?
205
+ app.use OmniAuth::Builder, &options[:providers]
206
+
207
+ # You told omniauth, now tell us!
208
+ config.eval_omniauth_config &options[:providers] if options[:provider_names].count == 0
209
+ end
210
+
211
+ # Populates instance variables used to display currently logged in user
212
+ app.before '/*' do
213
+ @user_authed = user_authed?
214
+ @user = get_user
215
+ end
216
+
217
+ # Stop browsers from screwing up our referrer information
218
+ # FIXME: This is hacky...
219
+ app.before '/favicon.ico' do
220
+ halt 403 unless user_authed?
221
+ end
222
+
223
+ # Explicit login (user followed login link) clears previous redirect info
224
+ app.before options[:route_prefix] + '/login' do
225
+ kick_back if user_authed?
226
+ @auth_params = "?origin=#{CGI.escape(request.referrer)}" unless request.referrer.nil?
227
+ user_auth
228
+ end
229
+
230
+ app.before options[:route_prefix] + '/logout' do
231
+ user_deauth
232
+ kick_back
233
+ end
234
+
235
+ app.before options[:route_prefix] + '/auth/failure' do
236
+ user_deauth
237
+ @title = 'Authentication failed'
238
+ @subtext = "Provider did not validate your credentials (#{params[:message]}) - please retry or choose another login service"
239
+ @auth_params = "?origin=#{CGI.escape(request.env['omniauth.origin'])}" unless request.env['omniauth.origin'].nil?
240
+ show_login
241
+ end
242
+
243
+ app.before options[:route_prefix] + '/auth/:name/callback' do
244
+ begin
245
+ if !request.env['omniauth.auth'].nil?
246
+ user = Omnigollum::Models::OmniauthUser.new(request.env['omniauth.auth'], options)
247
+
248
+ # Check authorized users
249
+ if !options[:authorized_users].empty? && !options[:authorized_users].include?(user.email) &&
250
+ !options[:authorized_users].include?(user.nickname)
251
+ @title = 'Authorization failed'
252
+ @subtext = 'User was not found in the authorized users list'
253
+ @auth_params = "?origin=#{CGI.escape(request.env['omniauth.origin'])}" unless request.env['omniauth.origin'].nil?
254
+ show_login
255
+ end
256
+
257
+ session[:omniauth_user] = user
258
+
259
+ # Update gollum's author hash, so commits are recorded correctly
260
+ session['gollum.author'] = {
261
+ :name => options[:author_format].call(user),
262
+ :email => user.email
263
+ }
264
+
265
+ redirect request.env['omniauth.origin']
266
+ elsif !user_authed?
267
+ @title = 'Authentication failed'
268
+ @subtext = 'Omniauth experienced an error processing your request'
269
+ @auth_params = "?origin=#{CGI.escape(request.env['omniauth.origin'])}" unless request.env['omniauth.origin'].nil?
270
+ show_login
271
+ end
272
+ rescue StandardError => fail_reason
273
+ @title = 'Authentication failed'
274
+ @subtext = fail_reason
275
+ @auth_params = "?origin=#{CGI.escape(request.env['omniauth.origin'])}" unless request.env['omniauth.origin'].nil?
276
+ show_login
277
+ end
278
+ end
279
+
280
+ app.before options[:route_prefix] + '/images/:image.png' do
281
+ content_type :png
282
+ send_file options[:path_images] + '/' + params[:image] + '.png'
283
+ end
284
+
285
+ # Stop sinatra processing and hand off to omniauth
286
+ app.before options[:route_prefix] + '/auth/:provider' do
287
+ halt 404
288
+ end
289
+
290
+ # Pre-empt protected routes
291
+ options[:protected_routes].each {|route| app.before(route) {user_auth unless user_authed?}}
292
+
293
+ # Write the actual config back to the app instance
294
+ app.set(:omnigollum, options)
295
+ end
296
+ end
297
+ end
@@ -0,0 +1,18 @@
1
+ <div id="wiki-wrapper" class="markdown-body">
2
+ <h2>{{title}}</h2>
3
+ <div id="login" class="login_form">
4
+ <h3>{{subtext}}</h3>
5
+ <ul class="actions">
6
+ {{#providers_active}}
7
+ <li class="minibutton">
8
+ <a style="height:auto" href="{{{provider_url}}}">
9
+ {{#image}}
10
+ <img src="{{{image}}}" alt="{{image_alt}}" title="{{image_title}}"/>
11
+ {{/image}}
12
+ <div style="text-align: center">{{{name}}}</div>
13
+ </a>
14
+ </li>
15
+ {{/providers_active}}
16
+ </ul>
17
+ </div>
18
+ </div>
@@ -0,0 +1,42 @@
1
+ module Omnigollum
2
+ module Views
3
+ class Login < Mustache
4
+ self.template_path = File.expand_path("../../templates", __FILE__)
5
+ self.template_name = 'Login'
6
+
7
+ def title
8
+ @title
9
+ end
10
+
11
+ def subtext
12
+ @subtext
13
+ end
14
+
15
+ def providers_active
16
+ providers = []
17
+ @auth[:providers].each do |name|
18
+ provider_attr = {
19
+ :name => OmniAuth::Utils.camelize(name),
20
+ :provider_url => @auth[:route_prefix] + "/auth/#{name}" + (defined?(@auth_params) ? @auth_params : '')
21
+ }
22
+ name = name.to_s
23
+ if has_logo?(logo_name = name) || (logo_name = @auth[:logo_missing])
24
+ provider_attr[:image] = get_logo logo_name
25
+ provider_attr[:image_alt] = "#{provider_attr[:name]} logo"
26
+ provider_attr[:image_title] = "Connect with #{provider_attr[:name]}"
27
+ end
28
+ providers.push provider_attr
29
+ end
30
+ providers
31
+ end
32
+
33
+ def has_logo?(name)
34
+ File.exists?(@auth[:path_images] + '/' + name + @auth[:logo_suffix])
35
+ end
36
+
37
+ def get_logo(name)
38
+ @auth[:route_prefix] + "/images/#{name}" + @auth[:logo_suffix]
39
+ end
40
+ end
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omnigollum
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Arran Cudbard-Bell
8
+ - Tenshi Hinanawi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-09-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: gollum
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: omniauth
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: mustache
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: |
57
+ Omnigollum adds support for OmniAuth in Gollum. It executes an OmniAuth::Builder proc/block to figure out which providers you've configured, then passes it on to omniauth to create the actual omniauth configuration.
58
+
59
+ See https://github.com/arr2036/omnigollum for usage instructions.
60
+ email: a.cudbardb@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files:
64
+ - Readme.md
65
+ - LICENSE
66
+ files:
67
+ - Readme.md
68
+ - LICENSE
69
+ - lib/omnigollum.rb
70
+ - public/images/bitly_logo.png
71
+ - public/images/blogger_logo.png
72
+ - public/images/facebook_logo.png
73
+ - public/images/github_logo.png
74
+ - public/images/google_logo.png
75
+ - public/images/omniauth_logo.png
76
+ - public/images/open_id_logo.png
77
+ - public/images/twitter_logo.png
78
+ - public/images/youtube_logo.png
79
+ - templates/Login.mustache
80
+ - views/login.rb
81
+ homepage: https://github.com/arr2036/omnigollum
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options:
87
+ - --charset=UTF-8
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 2.1.5
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: Omnigollum makes it easy to use OmniAuth with Gollum
106
+ test_files: []