omnigollum 0.1.1

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,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: []