diff --git a/Gemfile b/Gemfile
index 38c955195..f49be1f49 100644
--- a/Gemfile
+++ b/Gemfile
@@ -35,6 +35,7 @@ gem "omniauth-openid"
gem "openid-redis-store"
gem "omniauth-facebook"
gem "omniauth-twitter"
+gem "omniauth-github"
gem 'oj'
gem 'pbkdf2'
gem 'pg'
diff --git a/Gemfile.lock b/Gemfile.lock
index 78575bdcb..67dbdcf14 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -279,6 +279,9 @@ GEM
rack
omniauth-facebook (1.4.1)
omniauth-oauth2 (~> 1.1.0)
+ omniauth-github (1.1.0)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.1)
omniauth-oauth (1.0.1)
oauth
omniauth (~> 1.0)
@@ -489,6 +492,7 @@ DEPENDENCIES
oj
omniauth
omniauth-facebook
+ omniauth-github
omniauth-openid
omniauth-twitter
openid-redis-store
diff --git a/app/assets/javascripts/discourse/templates/modal/login.js.handlebars b/app/assets/javascripts/discourse/templates/modal/login.js.handlebars
index b605373bd..2c0d7cff0 100644
--- a/app/assets/javascripts/discourse/templates/modal/login.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/modal/login.js.handlebars
@@ -5,6 +5,9 @@
+ {{#if Discourse.SiteSettings.enable_github_logins}}
+
+ {{/if}}
{{i18n login.or}}
diff --git a/app/assets/javascripts/discourse/views/modal/login_view.js b/app/assets/javascripts/discourse/views/modal/login_view.js
index da08b0196..f11712ab3 100644
--- a/app/assets/javascripts/discourse/views/modal/login_view.js
+++ b/app/assets/javascripts/discourse/views/modal/login_view.js
@@ -101,6 +101,14 @@ Discourse.LoginView = Discourse.ModalBodyView.extend({
}
},
+ githubLogin: function() {
+ var left, top;
+ this.set('authenticate', 'github');
+ left = this.get('lastX') - 400;
+ top = this.get('lastY') - 200;
+ return window.open("/auth/github", "_blank", "menubar=no,status=no,height=400,width=800,left=" + left + ",top=" + top);
+ },
+
authenticationComplete: function(options) {
if (options.awaiting_approval) {
this.flash(Em.String.i18n('login.awaiting_approval'), 'success');
diff --git a/app/assets/stylesheets/components/buttons.css.scss b/app/assets/stylesheets/components/buttons.css.scss
index 80e8756ba..74fdda739 100755
--- a/app/assets/stylesheets/components/buttons.css.scss
+++ b/app/assets/stylesheets/components/buttons.css.scss
@@ -162,6 +162,12 @@
content: "Y";
}
}
+ &.github {
+ background: $github;
+ &:before {
+ content: "g";
+ }
+ }
}
// Button Sizes
diff --git a/app/assets/stylesheets/foundation/variables.scss b/app/assets/stylesheets/foundation/variables.scss
index 39eea5716..4407937c8 100644
--- a/app/assets/stylesheets/foundation/variables.scss
+++ b/app/assets/stylesheets/foundation/variables.scss
@@ -123,6 +123,7 @@ $google: #5b76f7 !default;
$facebook: #3b5998 !default;
$twitter: #00bced !default;
$yahoo: #810293 !default;
+$github: #6d6d6d !default;
// Layout dimensions
diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb
index a719a14ae..f876fcdde 100644
--- a/app/controllers/users/omniauth_callbacks_controller.rb
+++ b/app/controllers/users/omniauth_callbacks_controller.rb
@@ -19,6 +19,8 @@ class Users::OmniauthCallbacksController < ApplicationController
create_or_sign_on_user_using_twitter(auth_token)
when "google", "yahoo"
create_or_sign_on_user_using_openid(auth_token)
+ when "github"
+ create_or_sign_on_user_using_github(auth_token)
end
end
@@ -169,4 +171,35 @@ class Users::OmniauthCallbacksController < ApplicationController
end
end
+ def create_or_sign_on_user_using_github(auth_token)
+
+ data = auth_token[:info]
+ screen_name = data["nickname"]
+ github_user_id = auth_token["uid"]
+
+ session[:authentication] = {
+ github_user_id: github_user_id,
+ github_screen_name: screen_name
+ }
+
+ user_info = GithubUserInfo.where(:github_user_id => github_user_id).first
+
+ @data = {
+ username: screen_name,
+ auth_provider: "Github"
+ }
+
+ if user_info
+ if user_info.user.active
+ log_on_user(user_info.user)
+ @data[:authenticated] = true
+ else
+ @data[:awaiting_activation] = true
+ # send another email ?
+ end
+ else
+ @data[:name] = screen_name
+ end
+ end
+
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 42fdf3cc7..dc5156d85 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -177,6 +177,10 @@ class UsersController < ApplicationController
if auth[:facebook].present? and FacebookUserInfo.find_by_facebook_user_id(auth[:facebook][:facebook_user_id]).nil?
FacebookUserInfo.create!(auth[:facebook].merge(user_id: user.id))
end
+
+ if auth[:github_user_id] && auth[:github_screen_name] && GithubUserInfo.find_by_github_user_id(auth[:github_user_id]).nil?
+ GithubUserInfo.create(:user_id => user.id, :screen_name => auth[:github_screen_name], :github_user_id => auth[:github_user_id])
+ end
end
diff --git a/app/models/github_user_info.rb b/app/models/github_user_info.rb
new file mode 100644
index 000000000..7f2b4c56d
--- /dev/null
+++ b/app/models/github_user_info.rb
@@ -0,0 +1,3 @@
+class GithubUserInfo < ActiveRecord::Base
+ belongs_to :user
+end
\ No newline at end of file
diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb
index e5be8ac52..ec7679792 100644
--- a/app/models/site_setting.rb
+++ b/app/models/site_setting.rb
@@ -116,6 +116,10 @@ class SiteSetting < ActiveRecord::Base
setting(:facebook_app_id, '')
setting(:facebook_app_secret, '')
+ client_setting(:enable_github_logins, false)
+ setting(:github_client_id, '')
+ setting(:github_client_secret, '')
+
setting(:enforce_global_nicknames, true)
setting(:discourse_org_access_key, '')
setting(:enable_s3_uploads, false)
diff --git a/app/models/user.rb b/app/models/user.rb
index 564aa480f..8e6b377f5 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -21,6 +21,7 @@ class User < ActiveRecord::Base
has_many :user_visits
has_many :invites
has_one :twitter_user_info
+ has_one :github_user_info
belongs_to :approved_by, class_name: 'User'
validates_presence_of :username
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
index 41e4c8d4d..838006e8a 100644
--- a/config/initializers/omniauth.rb
+++ b/config/initializers/omniauth.rb
@@ -27,4 +27,8 @@ Rails.application.config.middleware.use OmniAuth::Builder do
SiteSetting.twitter_consumer_key,
SiteSetting.twitter_consumer_secret
+ provider :github,
+ SiteSetting.github_client_id,
+ SiteSetting.github_client_secret
+
end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 241ca3d7e..d0f8bb480 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -248,6 +248,9 @@ en:
yahoo:
title: "Log In with Yahoo"
message: "Authenticating with Yahoo (make sure pop up blockers are not enabled)"
+ github:
+ title: "Log In with Github"
+ message: "Authenticating with Github (make sure pop up blockers are not enabled)"
composer:
saving_draft_tip: "saving"
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index fa4188200..4aa5add1d 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -314,6 +314,9 @@ en:
facebook_app_secret: "App secret for Facebook authentication, registered at https://developers.facebook.com/apps"
allow_import: "Allow import, which can replace ALL site data; leave false unless you plan to do data imports"
+ enable_github_logins: "Enable Github authentication, requires github_client_id and github_client_secret"
+ github_client_id: "Client id for Github authentication, registered at https://github.com/settings/applications"
+ github_client_secret: "Client secret for Github authentication, registered at https://github.com/settings/applications"
active_user_rate_limit_secs: "How frequently we update the 'last_seen_at' field, in seconds"
previous_visit_timeout_hours: "How long a visit lasts before we consider it the 'previous' visit, in hours"
diff --git a/db/migrate/20130226015336_add_github_user_info.rb b/db/migrate/20130226015336_add_github_user_info.rb
new file mode 100644
index 000000000..4887aa374
--- /dev/null
+++ b/db/migrate/20130226015336_add_github_user_info.rb
@@ -0,0 +1,13 @@
+class AddGithubUserInfo < ActiveRecord::Migration
+ def change
+ create_table :github_user_infos do |t|
+ t.integer :user_id, :null => false
+ t.string :screen_name, :null => false
+ t.integer :github_user_id, :null => false
+ t.timestamps
+ end
+
+ add_index :github_user_infos, [:github_user_id], :unique => true
+ add_index :github_user_infos, [:user_id], :unique => true
+ end
+end
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 39b4cd846..5951ff98a 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -1239,7 +1239,7 @@ CREATE TABLE categories (
--
CREATE SEQUENCE categories_id_seq
- START WITH 5
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -1324,7 +1324,7 @@ CREATE TABLE draft_sequences (
--
CREATE SEQUENCE draft_sequences_id_seq
- START WITH 20
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -1358,7 +1358,7 @@ CREATE TABLE drafts (
--
CREATE SEQUENCE drafts_id_seq
- START WITH 2
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -1391,7 +1391,7 @@ CREATE TABLE email_logs (
--
CREATE SEQUENCE email_logs_id_seq
- START WITH 3
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -1426,7 +1426,7 @@ CREATE TABLE email_tokens (
--
CREATE SEQUENCE email_tokens_id_seq
- START WITH 3
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -1479,6 +1479,39 @@ CREATE SEQUENCE facebook_user_infos_id_seq
ALTER SEQUENCE facebook_user_infos_id_seq OWNED BY facebook_user_infos.id;
+--
+-- Name: github_user_infos; Type: TABLE; Schema: public; Owner: -; Tablespace:
+--
+
+CREATE TABLE github_user_infos (
+ id integer NOT NULL,
+ user_id integer NOT NULL,
+ screen_name character varying(255) NOT NULL,
+ github_user_id integer NOT NULL,
+ created_at timestamp without time zone NOT NULL,
+ updated_at timestamp without time zone NOT NULL
+);
+
+
+--
+-- Name: github_user_infos_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE github_user_infos_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+--
+-- Name: github_user_infos_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE github_user_infos_id_seq OWNED BY github_user_infos.id;
+
+
--
-- Name: incoming_links; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
@@ -1639,7 +1672,7 @@ CREATE TABLE onebox_renders (
--
CREATE SEQUENCE onebox_renders_id_seq
- START WITH 2
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -1673,7 +1706,7 @@ CREATE TABLE post_action_types (
--
CREATE SEQUENCE post_action_types_id_seq
- START WITH 6
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -1804,7 +1837,7 @@ CREATE TABLE posts (
--
CREATE SEQUENCE posts_id_seq
- START WITH 16
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -1895,7 +1928,7 @@ CREATE TABLE site_settings (
--
CREATE SEQUENCE site_settings_id_seq
- START WITH 4
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -1927,7 +1960,7 @@ CREATE TABLE topic_allowed_users (
--
CREATE SEQUENCE topic_allowed_users_id_seq
- START WITH 3
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -2119,7 +2152,7 @@ CREATE TABLE topics (
--
CREATE SEQUENCE topics_id_seq
- START WITH 16
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -2225,7 +2258,7 @@ CREATE TABLE user_actions (
--
CREATE SEQUENCE user_actions_id_seq
- START WITH 40
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -2289,7 +2322,7 @@ CREATE TABLE user_visits (
--
CREATE SEQUENCE user_visits_id_seq
- START WITH 4
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -2356,7 +2389,7 @@ CREATE TABLE users (
--
CREATE SEQUENCE users_id_seq
- START WITH 3
+ START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
@@ -2688,6 +2721,13 @@ ALTER TABLE ONLY email_tokens ALTER COLUMN id SET DEFAULT nextval('email_tokens_
ALTER TABLE ONLY facebook_user_infos ALTER COLUMN id SET DEFAULT nextval('facebook_user_infos_id_seq'::regclass);
+--
+-- Name: id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY github_user_infos ALTER COLUMN id SET DEFAULT nextval('github_user_infos_id_seq'::regclass);
+
+
--
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
--
@@ -3174,6 +3214,14 @@ ALTER TABLE ONLY topics
ADD CONSTRAINT forum_threads_pkey PRIMARY KEY (id);
+--
+-- Name: github_user_infos_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
+--
+
+ALTER TABLE ONLY github_user_infos
+ ADD CONSTRAINT github_user_infos_pkey PRIMARY KEY (id);
+
+
--
-- Name: incoming_links_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
--
@@ -3926,6 +3974,20 @@ CREATE UNIQUE INDEX index_forum_thread_users_on_forum_thread_id_and_user_id ON t
CREATE INDEX index_forum_threads_on_bumped_at ON topics USING btree (bumped_at DESC);
+--
+-- Name: index_github_user_infos_on_github_user_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
+--
+
+CREATE UNIQUE INDEX index_github_user_infos_on_github_user_id ON github_user_infos USING btree (github_user_id);
+
+
+--
+-- Name: index_github_user_infos_on_user_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
+--
+
+CREATE UNIQUE INDEX index_github_user_infos_on_user_id ON github_user_infos USING btree (user_id);
+
+
--
-- Name: index_invites_on_email_and_invited_by_id; Type: INDEX; Schema: public; Owner: -; Tablespace:
--
@@ -4577,4 +4639,6 @@ INSERT INTO schema_migrations (version) VALUES ('20130213021450');
INSERT INTO schema_migrations (version) VALUES ('20130213203300');
-INSERT INTO schema_migrations (version) VALUES ('20130221215017');
\ No newline at end of file
+INSERT INTO schema_migrations (version) VALUES ('20130221215017');
+
+INSERT INTO schema_migrations (version) VALUES ('20130226015336');
\ No newline at end of file
diff --git a/docs/SOFTWARE.md b/docs/SOFTWARE.md
index 917883a1d..a13d104eb 100644
--- a/docs/SOFTWARE.md
+++ b/docs/SOFTWARE.md
@@ -27,6 +27,7 @@ The following Ruby Gems are used in Discourse:
* [omniauth-openid](https://github.com/intridea/omniauth-openid)
* [omniauth-facebook](https://github.com/mkdynamic/omniauth-facebook)
* [omniauth-twitter](https://github.com/arunagw/omniauth-twitter)
+* [omniauth-github](https://github.com/intridea/omniauth-github)
* [has_ip_address](https://rubygems.org/gems/has_ip_address)
* [vestal_versions](https://rubygems.org/gems/vestal_versions)
* [uglifier](https://rubygems.org/gems/uglifier)
diff --git a/spec/views/omniauth_callbacks/complete.html.erb_spec.rb b/spec/views/omniauth_callbacks/complete.html.erb_spec.rb
index 6c8d48b5a..098e79bc7 100644
--- a/spec/views/omniauth_callbacks/complete.html.erb_spec.rb
+++ b/spec/views/omniauth_callbacks/complete.html.erb_spec.rb
@@ -38,6 +38,18 @@ describe "users/omniauth_callbacks/complete.html.erb" do
rendered_data["awaiting_activation"].should eq(true)
end
+ it "renders github data " do
+ assign(:data, {:username =>"username", :auth_provider=>"Github", :awaiting_activation=>true})
+
+ render
+
+ rendered_data = JSON.parse(rendered.match(/window.opener.Discourse.authenticationComplete\((.*)\)/)[1])
+
+ rendered_data["username"].should eq("username")
+ rendered_data["auth_provider"].should eq("Github")
+ rendered_data["awaiting_activation"].should eq(true)
+ end
+
end