add-to-org 1.0.0 → 2.0.0
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.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +3 -0
- data/LICENSE.md +21 -0
- data/README.md +70 -0
- data/Rakefile +12 -0
- data/add-to-org.gemspec +29 -0
- data/lib/add-to-org/helpers.rb +42 -0
- data/lib/add-to-org/version.rb +1 -1
- data/lib/add-to-org/views/success.erb +1 -1
- data/lib/add-to-org.rb +39 -32
- data/script/bootstrap +3 -0
- data/script/cibuild +7 -0
- data/script/release +38 -0
- data/script/server +3 -0
- data/spec/add-to-org-helpers_spec.rb +80 -0
- data/spec/add-to-org_spec.rb +106 -0
- data/spec/fixtures/emails.json +12 -0
- data/spec/fixtures/invalid_emails.json +12 -0
- data/spec/spec_helper.rb +48 -0
- metadata +112 -20
- data/lib/add-to-org/server.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2780fa01cfb6f6cf5bf218c6c015d98ecbc2e045
|
4
|
+
data.tar.gz: ada99c96ee50a764e09ccbe33738fe0d6a47bb52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b61f4a36252610297738ff296d7e95bdb2f056a751378eeb882f19d31f56faa43ace43efe385b84b9ba02246ddf63000c31fb184a677884d452637f73567e939
|
7
|
+
data.tar.gz: d7603d3c1c37d09b497cdfba1283b086b6cf27ab0f8fbf1b84e12485e9a84b17946acd66521e4677e36748b20d7efb5d296c1050c058a686c0e5c8bb4c36796e
|
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.0
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Ben Balter
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Add to Org
|
2
|
+
|
3
|
+
*A simple Oauth App to automatically add users to an organization*
|
4
|
+
|
5
|
+
[](http://badge.fury.io/rb/add-to-org) [](https://travis-ci.org/benbalter/add-to-org)
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
Once set up, simply swap out your app's domain for any GitHub URL. E.g., `github.com/government/best-practices/issues/1` becomes `government-community.githubapp.com/government/best-practices/1`. The user will be authenticated, added to the organization, and redirected to the requested GitHub URL.
|
10
|
+
|
11
|
+
## Setup
|
12
|
+
|
13
|
+
1. Create [an oauth app](github.com/settings/applications/new)
|
14
|
+
2. Create a personal access token for a user with admin rights to the organization
|
15
|
+
3. Add `gem 'add-to-org' to your project's Gemfile
|
16
|
+
4. Add the following to a `config.ru` file:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
require 'add-to-org'
|
20
|
+
run AddToOrg::App
|
21
|
+
```
|
22
|
+
|
23
|
+
## Configuration
|
24
|
+
|
25
|
+
The following environmental values should be set:
|
26
|
+
|
27
|
+
* `GITHUB_ORG_ID` - The name of the org to add users to
|
28
|
+
* `GITHUB_TEAM_ID` - The ID of the team to add users to. Get this from the team page's URL
|
29
|
+
* `GITHUB_CLIENT_ID` - Your OAuth app's client ID
|
30
|
+
* `GITHUB_CLIENT_SECRET` - Your Oauth app's client secret
|
31
|
+
* `GITHUB_TOKEN` - A personal access token for a user with admin rights to the organization
|
32
|
+
* `CONTACT_EMAIL` - Point of contact to point users to if something goes wrong
|
33
|
+
|
34
|
+
You'll also need to monkey patch a validation method to determine if a user should be added, e.g.:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'add-to-org'
|
38
|
+
|
39
|
+
module AddToOrg
|
40
|
+
class App < Sinatra::Base
|
41
|
+
def valid?
|
42
|
+
verified_emails.any? { |email| email[:email] =~ /@github\.com$/}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
## Customizing Views
|
49
|
+
|
50
|
+
There are three views, `success`, `forbidden`, and `error`. They're pretty boring by default, so you may want to swap them out for something a bit my snazzy. There are two ways to do that:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
module AddToOrg
|
54
|
+
class App < Sinatra::Base
|
55
|
+
set :views, "path/to/your/views"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
or by overwriting the `success`, `forbidden`, and `error` methods entirely:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
module AddToOrg
|
64
|
+
class App < Sinatra::Base
|
65
|
+
def success(locals={})
|
66
|
+
halt erb :some_template, :locals => locals
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubygems/package_task'
|
2
|
+
require 'rubygems/specification'
|
3
|
+
require 'bundler'
|
4
|
+
|
5
|
+
task :default => [:spec]
|
6
|
+
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
desc "Run specs"
|
9
|
+
RSpec::Core::RakeTask.new do |t|
|
10
|
+
t.pattern = 'spec/**/*_spec.rb'
|
11
|
+
t.rspec_opts = ["--order", "rand", "--color"]
|
12
|
+
end
|
data/add-to-org.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path('../lib/add-to-org/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "add-to-org"
|
5
|
+
s.summary = "A simple Oauth App to automatically add users to an organization"
|
6
|
+
s.description = "A simple Oauth App to automatically add users to an organization."
|
7
|
+
s.version = AddToOrg::VERSION
|
8
|
+
s.authors = ["Ben Balter"]
|
9
|
+
s.email = "ben.balter@github.com"
|
10
|
+
s.homepage = "https://github.com/benbalter/add-to-org"
|
11
|
+
s.licenses = ["MIT"]
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.add_dependency "warden-github", "~> 1.1"
|
20
|
+
s.add_dependency "sinatra_auth_github", "~> 1.1"
|
21
|
+
s.add_dependency "octokit", "~> 3.3"
|
22
|
+
s.add_dependency "rack-ssl-enforcer", "~> 0.2"
|
23
|
+
s.add_dependency "dotenv", "~> 1.0"
|
24
|
+
s.add_dependency "rake", "~> 10.3"
|
25
|
+
s.add_development_dependency "rspec", "~> 3.1"
|
26
|
+
s.add_development_dependency "rack-test", "~> 0.6"
|
27
|
+
s.add_development_dependency "webmock", "~> 1.2 "
|
28
|
+
s.add_development_dependency "pry", "~> 0.10"
|
29
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module AddToOrg
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
# user client
|
5
|
+
def client
|
6
|
+
@client ||= Octokit::Client.new :access_token => github_user.token
|
7
|
+
end
|
8
|
+
|
9
|
+
# new org admin client
|
10
|
+
def sudo_client
|
11
|
+
@sudo_client ||= Octokit::Client.new :access_token => ENV['GITHUB_TOKEN']
|
12
|
+
end
|
13
|
+
|
14
|
+
# query api for the user's verified emails
|
15
|
+
def verified_emails
|
16
|
+
emails = client.emails :accept => 'application/vnd.github.v3'
|
17
|
+
emails.select { |email| email.verified }
|
18
|
+
end
|
19
|
+
|
20
|
+
# true if user is already a member of the org
|
21
|
+
def member?
|
22
|
+
client.organization_member? org_id, github_user.login
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid?
|
26
|
+
raise "You must define a custom valid? method to determine eligibility"
|
27
|
+
end
|
28
|
+
|
29
|
+
def team_id
|
30
|
+
ENV['GITHUB_TEAM_ID']
|
31
|
+
end
|
32
|
+
|
33
|
+
def org_id
|
34
|
+
ENV['GITHUB_ORG_ID']
|
35
|
+
end
|
36
|
+
|
37
|
+
# the main event...
|
38
|
+
def add
|
39
|
+
sudo_client.add_team_membership team_id, github_user.login
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/add-to-org/version.rb
CHANGED
@@ -7,6 +7,6 @@
|
|
7
7
|
<body>
|
8
8
|
<h1>You're all set</h1>
|
9
9
|
<p>You should have recieved an email inviting you to join the organization.</p>
|
10
|
-
<p>Once confirmed, you will have access to <a href="<%= ERB::Util.html_escape(redirect) %>"
|
10
|
+
<p>Once confirmed, you will have access to <a href="<%= ERB::Util.html_escape(redirect) %>"><%= ERB::Util.html_escape(redirect) %></a>, the requested URL.</h1>
|
11
11
|
</body>
|
12
12
|
</html>
|
data/lib/add-to-org.rb
CHANGED
@@ -1,60 +1,67 @@
|
|
1
1
|
require 'octokit'
|
2
2
|
require 'sinatra_auth_github'
|
3
3
|
require 'dotenv'
|
4
|
-
require_relative 'add-to-org/
|
4
|
+
require_relative 'add-to-org/helpers'
|
5
5
|
|
6
6
|
Dotenv.load
|
7
7
|
|
8
8
|
module AddToOrg
|
9
9
|
class App < Sinatra::Base
|
10
10
|
|
11
|
+
include AddToOrg::Helpers
|
12
|
+
|
11
13
|
set :github_options, {
|
12
|
-
:scopes
|
13
|
-
:secret => ENV['GITHUB_CLIENT_SECRET'],
|
14
|
-
:client_id => ENV['GITHUB_CLIENT_ID']
|
14
|
+
:scopes => "user,user:email"
|
15
15
|
}
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
use Rack::Session::Cookie, {
|
18
|
+
:http_only => true,
|
19
|
+
:secret => ENV['SESSION_SECRET'] || SecureRandom.hex
|
20
|
+
}
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
@client ||= Octokit::Client.new :access_token => user.token
|
24
|
-
end
|
22
|
+
ENV['WARDEN_GITHUB_VERIFIER_SECRET'] ||= SecureRandom.hex
|
23
|
+
register Sinatra::Auth::Github
|
25
24
|
|
26
|
-
|
27
|
-
def sudo_client
|
28
|
-
@sudo_client ||= Octokit::Client.new :access_token => ENV['GITHUB_TOKEN']
|
29
|
-
end
|
25
|
+
set :views, File.expand_path("add-to-org/views", File.dirname(__FILE__))
|
30
26
|
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
27
|
+
# require ssl
|
28
|
+
configure :production do
|
29
|
+
require 'rack-ssl-enforcer'
|
30
|
+
use Rack::SslEnforcer
|
35
31
|
end
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
# dat auth
|
34
|
+
before do
|
35
|
+
session[:return_to] = request.url #store requested URL for post-auth redirect
|
36
|
+
authenticate!
|
40
37
|
end
|
41
38
|
|
42
|
-
def
|
43
|
-
|
39
|
+
def success(locals={})
|
40
|
+
halt erb :success, :locals => locals
|
44
41
|
end
|
45
42
|
|
46
|
-
def
|
47
|
-
|
43
|
+
def forbidden
|
44
|
+
status 403
|
45
|
+
halt erb :forbidden
|
48
46
|
end
|
49
47
|
|
50
|
-
def
|
51
|
-
|
48
|
+
def error
|
49
|
+
status 500
|
50
|
+
halt erb :error
|
52
51
|
end
|
53
52
|
|
54
|
-
#
|
55
|
-
|
56
|
-
sudo_client.add_team_membership team_id, user.login
|
57
|
-
end
|
53
|
+
# request a GitHub (authenticated) URL
|
54
|
+
get "/*" do
|
58
55
|
|
56
|
+
path = request.path || "/#{team_id}"
|
57
|
+
halt redirect "https://github.com#{path}", 302 if member?
|
58
|
+
forbidden unless valid?
|
59
|
+
|
60
|
+
if add
|
61
|
+
success({ :redirect => "https://github.com#{path}" })
|
62
|
+
else
|
63
|
+
error
|
64
|
+
end
|
65
|
+
end
|
59
66
|
end
|
60
67
|
end
|
data/script/bootstrap
ADDED
data/script/cibuild
ADDED
data/script/release
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# Tag and push a release.
|
3
|
+
|
4
|
+
set -e
|
5
|
+
|
6
|
+
# Make sure we're in the project root.
|
7
|
+
|
8
|
+
cd $(dirname "$0")/..
|
9
|
+
|
10
|
+
# Build a new gem archive.
|
11
|
+
|
12
|
+
rm -rf add-to-org-*.gem
|
13
|
+
gem build -q add-to-org.gemspec
|
14
|
+
|
15
|
+
# Make sure we're on the master branch.
|
16
|
+
|
17
|
+
(git branch | grep -q '* master') || {
|
18
|
+
echo "Only release from the master branch."
|
19
|
+
exit 1
|
20
|
+
}
|
21
|
+
|
22
|
+
# Figure out what version we're releasing.
|
23
|
+
|
24
|
+
tag=v`ls add-to-org-*.gem | sed 's/^add-to-org-\(.*\)\.gem$/\1/'`
|
25
|
+
|
26
|
+
# Make sure we haven't released this version before.
|
27
|
+
|
28
|
+
git fetch -t origin
|
29
|
+
|
30
|
+
(git tag -l | grep -q "$tag") && {
|
31
|
+
echo "Whoops, there's already a '${tag}' tag."
|
32
|
+
exit 1
|
33
|
+
}
|
34
|
+
|
35
|
+
# Tag it and bag it.
|
36
|
+
|
37
|
+
gem push add-to-org-*.gem && git tag "$tag" &&
|
38
|
+
git push origin master && git push origin "$tag"
|
data/script/server
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "AddToOrgHelpers" do
|
4
|
+
|
5
|
+
class TestHelper
|
6
|
+
include AddToOrg::Helpers
|
7
|
+
|
8
|
+
def github_user
|
9
|
+
User.make({"login" => "benbaltertest"}, "asdf1234")
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(path=nil)
|
13
|
+
@path = path
|
14
|
+
end
|
15
|
+
|
16
|
+
def request
|
17
|
+
Rack::Request.new("PATH_INFO" => @path)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
before(:each) do
|
22
|
+
@helper = TestHelper.new
|
23
|
+
end
|
24
|
+
|
25
|
+
it "initializes the client" do
|
26
|
+
expect(@helper.client.class).to eql(Octokit::Client)
|
27
|
+
expect(@helper.client.instance_variable_get("@access_token")).to eql("asdf1234")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "initializes the sudo client" do
|
31
|
+
with_env "GITHUB_TOKEN", "SUDO_TOKEN" do
|
32
|
+
expect(@helper.sudo_client.class).to eql(Octokit::Client)
|
33
|
+
expect(@helper.sudo_client.instance_variable_get("@access_token")).to eql("SUDO_TOKEN")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "retrieves a users verified emails" do
|
38
|
+
stub_request(:get, "https://api.github.com/user/emails").
|
39
|
+
to_return(:status => 200, :body => fixture("emails.json"), :headers => { 'Content-Type'=>'application/json' })
|
40
|
+
expect(@helper.verified_emails.count).to eql(1)
|
41
|
+
expect(@helper.verified_emails.first[:email]).to eql("octocat@github.com")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "retrieves the org id" do
|
45
|
+
with_env "GITHUB_ORG_ID", "some_org" do
|
46
|
+
expect(@helper.org_id).to eql("some_org")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "retrieves the team id" do
|
51
|
+
with_env "GITHUB_TEAM_ID", "1234" do
|
52
|
+
expect(@helper.team_id).to eql("1234")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "knows if a user is an org member" do
|
57
|
+
with_env "GITHUB_ORG_ID", "some_org" do
|
58
|
+
stub_request(:get, "https://api.github.com/orgs/some_org/members/benbaltertest").
|
59
|
+
to_return(:status => 204)
|
60
|
+
expect(@helper.member?).to eql(true)
|
61
|
+
|
62
|
+
stub_request(:get, "https://api.github.com/orgs/some_org/members/benbaltertest").
|
63
|
+
to_return(:status => 404)
|
64
|
+
expect(@helper.member?).to eql(false)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "knows how to add a mebmer to an org" do
|
69
|
+
with_env "GITHUB_ORG_ID", "some_org" do
|
70
|
+
stub = stub_request(:put, "https://api.github.com/teams/memberships/benbaltertest").
|
71
|
+
to_return(:status => 204)
|
72
|
+
@helper.add
|
73
|
+
expect(stub).to have_been_requested
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "throws an error if valid? is not defined" do
|
78
|
+
expect { @helper.valid? }.to raise_error("You must define a custom valid? method to determine eligibility")
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "logged out user" do
|
4
|
+
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
def app
|
8
|
+
AddToOrg::App
|
9
|
+
end
|
10
|
+
|
11
|
+
it "asks you to log in" do
|
12
|
+
get "/"
|
13
|
+
expect(last_response.status).to eql(302)
|
14
|
+
expect(last_response.headers['Location']).to match(%r{^https://github\.com/login/oauth/authorize})
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "logged in user" do
|
19
|
+
|
20
|
+
include Rack::Test::Methods
|
21
|
+
|
22
|
+
module AddToOrg
|
23
|
+
class App < Sinatra::Base
|
24
|
+
def valid?
|
25
|
+
verified_emails.any? { |email| email[:email] =~ /@github\.com$/}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def app
|
31
|
+
AddToOrg::App
|
32
|
+
end
|
33
|
+
|
34
|
+
before do
|
35
|
+
@user = make_user('login' => 'benbaltertest')
|
36
|
+
login_as @user
|
37
|
+
end
|
38
|
+
|
39
|
+
it "redirects if the user is a member" do
|
40
|
+
with_env "GITHUB_ORG_ID", "some_org" do
|
41
|
+
stub_request(:get, "https://api.github.com/orgs/some_org/members/benbaltertest").
|
42
|
+
to_return(:status => 204)
|
43
|
+
get "/"
|
44
|
+
expect(last_response.status).to eql(302)
|
45
|
+
expect(last_response.headers['Location']).to eql("https://github.com/")
|
46
|
+
|
47
|
+
get "/foo"
|
48
|
+
expect(last_response.status).to eql(302)
|
49
|
+
expect(last_response.headers['Location']).to eql("https://github.com/foo")
|
50
|
+
|
51
|
+
get "/foo/bar"
|
52
|
+
expect(last_response.status).to eql(302)
|
53
|
+
expect(last_response.headers['Location']).to eql("https://github.com/foo/bar")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "denies acccess to invalid users" do
|
58
|
+
with_env "GITHUB_ORG_ID", "some_org" do
|
59
|
+
stub_request(:get, "https://api.github.com/orgs/some_org/members/benbaltertest").
|
60
|
+
to_return(:status => 404)
|
61
|
+
|
62
|
+
stub_request(:get, "https://api.github.com/user/emails").
|
63
|
+
to_return(:status => 200, :body => fixture("invalid_emails.json"), :headers => { 'Content-Type'=>'application/json' })
|
64
|
+
|
65
|
+
get "/"
|
66
|
+
expect(last_response.status).to eql(403)
|
67
|
+
expect(last_response.body).to match(/We're unable to verify your eligibility at this time/)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "tries to add valid users" do
|
72
|
+
with_env "GITHUB_ORG_ID", "some_org" do
|
73
|
+
stub_request(:get, "https://api.github.com/orgs/some_org/members/benbaltertest").
|
74
|
+
to_return(:status => 404)
|
75
|
+
|
76
|
+
stub_request(:get, "https://api.github.com/user/emails").
|
77
|
+
to_return(:status => 200, :body => fixture("emails.json"), :headers => { 'Content-Type'=>'application/json' })
|
78
|
+
|
79
|
+
stub = stub_request(:put, "https://api.github.com/teams/memberships/benbaltertest").
|
80
|
+
to_return(:status => 204)
|
81
|
+
|
82
|
+
get "/"
|
83
|
+
expect(stub).to have_been_requested
|
84
|
+
expect(last_response.status).to eql(200)
|
85
|
+
expect(last_response.body).to match(/You should have recieved an email inviting you to join the organization/)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it "includes the requested URL" do
|
90
|
+
with_env "GITHUB_ORG_ID", "some_org" do
|
91
|
+
stub_request(:get, "https://api.github.com/orgs/some_org/members/benbaltertest").
|
92
|
+
to_return(:status => 404)
|
93
|
+
|
94
|
+
stub_request(:get, "https://api.github.com/user/emails").
|
95
|
+
to_return(:status => 200, :body => fixture("emails.json"), :headers => { 'Content-Type'=>'application/json' })
|
96
|
+
|
97
|
+
stub = stub_request(:put, "https://api.github.com/teams/memberships/benbaltertest").
|
98
|
+
to_return(:status => 204)
|
99
|
+
|
100
|
+
get "/foo/bar"
|
101
|
+
expect(stub).to have_been_requested
|
102
|
+
expect(last_response.status).to eql(200)
|
103
|
+
expect(last_response.body).to match(Regexp.new('<a href="https://github.com/foo/bar">https://github.com/foo/bar</a>'))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
ENV['RACK_ENV'] = 'test'
|
5
|
+
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
|
6
|
+
|
7
|
+
require 'rack/test'
|
8
|
+
require 'sinatra/auth/github'
|
9
|
+
require 'sinatra/auth/github/test/test_helper'
|
10
|
+
require 'webmock/rspec'
|
11
|
+
|
12
|
+
require_relative "../lib/add-to-org"
|
13
|
+
WebMock.disable_net_connect!
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.include(Sinatra::Auth::Github::Test::Helper)
|
17
|
+
end
|
18
|
+
|
19
|
+
def fixture_path(fixture)
|
20
|
+
File.expand_path "./fixtures/#{fixture}", File.dirname(__FILE__)
|
21
|
+
end
|
22
|
+
|
23
|
+
def fixture(fixture)
|
24
|
+
File.open(fixture_path(fixture)).read
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def with_env(key, value)
|
29
|
+
old_env = ENV[key]
|
30
|
+
ENV[key] = value
|
31
|
+
yield
|
32
|
+
ENV[key] = old_env
|
33
|
+
end
|
34
|
+
|
35
|
+
class User < Warden::GitHub::User
|
36
|
+
def self.make(attrs = {}, token=nil)
|
37
|
+
default_attrs = {
|
38
|
+
'login' => "test_user",
|
39
|
+
'name' => "Test User",
|
40
|
+
'email' => "test@example.com",
|
41
|
+
'company' => "GitHub",
|
42
|
+
'gravatar_id' => 'a'*32,
|
43
|
+
'avatar_url' => 'https://a249.e.akamai.net/assets.github.com/images/gravatars/gravatar-140.png?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png'
|
44
|
+
}
|
45
|
+
default_attrs.merge! attrs
|
46
|
+
User.new(default_attrs,token)
|
47
|
+
end
|
48
|
+
end
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: add-to-org
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Balter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: warden-github
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: sinatra_auth_github
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.1'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: octokit
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,42 +56,129 @@ dependencies:
|
|
56
56
|
name: rack-ssl-enforcer
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
61
|
+
version: '0.2'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
68
|
+
version: '0.2'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: dotenv
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
89
|
+
version: '10.3'
|
76
90
|
type: :runtime
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- - "
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.1'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.1'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rack-test
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.6'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.6'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: webmock
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.2'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.2'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: pry
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.10'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
81
151
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
152
|
+
version: '0.10'
|
83
153
|
description: A simple Oauth App to automatically add users to an organization.
|
84
154
|
email: ben.balter@github.com
|
85
155
|
executables: []
|
86
156
|
extensions: []
|
87
157
|
extra_rdoc_files: []
|
88
158
|
files:
|
159
|
+
- ".gitignore"
|
160
|
+
- ".ruby-version"
|
161
|
+
- ".travis.yml"
|
162
|
+
- Gemfile
|
163
|
+
- LICENSE.md
|
164
|
+
- README.md
|
165
|
+
- Rakefile
|
166
|
+
- add-to-org.gemspec
|
89
167
|
- lib/add-to-org.rb
|
90
|
-
- lib/add-to-org/
|
168
|
+
- lib/add-to-org/helpers.rb
|
91
169
|
- lib/add-to-org/version.rb
|
92
170
|
- lib/add-to-org/views/error.erb
|
93
171
|
- lib/add-to-org/views/forbidden.erb
|
94
172
|
- lib/add-to-org/views/success.erb
|
173
|
+
- script/bootstrap
|
174
|
+
- script/cibuild
|
175
|
+
- script/release
|
176
|
+
- script/server
|
177
|
+
- spec/add-to-org-helpers_spec.rb
|
178
|
+
- spec/add-to-org_spec.rb
|
179
|
+
- spec/fixtures/emails.json
|
180
|
+
- spec/fixtures/invalid_emails.json
|
181
|
+
- spec/spec_helper.rb
|
95
182
|
homepage: https://github.com/benbalter/add-to-org
|
96
183
|
licenses:
|
97
184
|
- MIT
|
@@ -116,4 +203,9 @@ rubygems_version: 2.2.0
|
|
116
203
|
signing_key:
|
117
204
|
specification_version: 4
|
118
205
|
summary: A simple Oauth App to automatically add users to an organization
|
119
|
-
test_files:
|
206
|
+
test_files:
|
207
|
+
- spec/add-to-org-helpers_spec.rb
|
208
|
+
- spec/add-to-org_spec.rb
|
209
|
+
- spec/fixtures/emails.json
|
210
|
+
- spec/fixtures/invalid_emails.json
|
211
|
+
- spec/spec_helper.rb
|
data/lib/add-to-org/server.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
module AddToOrg
|
2
|
-
class App < Sinatra::Base
|
3
|
-
|
4
|
-
use Rack::Session::Cookie, {
|
5
|
-
:http_only => true,
|
6
|
-
:secret => ENV['SESSION_SECRET'] || SecureRandom.hex
|
7
|
-
}
|
8
|
-
|
9
|
-
register Sinatra::Auth::Github
|
10
|
-
|
11
|
-
set :views, File.expand_path("views", File.dirname(__FILE__))
|
12
|
-
|
13
|
-
# require ssl
|
14
|
-
configure :production do
|
15
|
-
require 'rack-ssl-enforcer'
|
16
|
-
use Rack::SslEnforcer
|
17
|
-
end
|
18
|
-
|
19
|
-
# dat auth
|
20
|
-
before do
|
21
|
-
session[:return_to] = request.url #store requested URL for post-auth redirect
|
22
|
-
authenticate!
|
23
|
-
end
|
24
|
-
|
25
|
-
def success(locals={})
|
26
|
-
erb :success, locals
|
27
|
-
end
|
28
|
-
|
29
|
-
def forbidden
|
30
|
-
status 403
|
31
|
-
erb :forbidden
|
32
|
-
end
|
33
|
-
|
34
|
-
def error
|
35
|
-
status 500
|
36
|
-
erb :error
|
37
|
-
end
|
38
|
-
|
39
|
-
# request a GitHub (authenticated) URL
|
40
|
-
get "/*" do
|
41
|
-
|
42
|
-
path = request.path || "/#{team_id}"
|
43
|
-
halt redirect "https://github.com#{path}", 302 if member?
|
44
|
-
forbidden unless valid?
|
45
|
-
|
46
|
-
if add
|
47
|
-
success({ :redirect => "https://github.com#{path}" })
|
48
|
-
else
|
49
|
-
error
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|